#!/bin/bash # mkupdate-with-scores # # This script generates, tests, and publishes rule updates for stable release # versions. It does the following: # # - retrieves the latest gernerated scores for new active.list rules # - checks out the trunk revision of code that those scores were generated for # - generates an update tarball and associated sha1 and asc files # - checks out each of the 3.3 stable release tagged versions, builds and # installs that version (in a tmp dir) and then installs the above generated # update using sa-update --install to make sure it works with each version # - if all goes well, it copies the update files to the update www directory, # updates the dns zone files and schedules (using the at queue) an update # of the zone soa and rndc reload using the tick_zone_serial script # # This script is similar to the run_part2 script used for trunk rule updates. set -e set -x umask 022 UPDATEDIR=/var/www/buildbot.spamassassin.org/updatestage DNSDIR=/var/named/updates.spamassassin.org.d KEYDIR=/home/updatesd/key UPDATE_BUILD_DIR=0 # if $1 is present redirect output files to a test directory structure if [ $1 ]; then UPDATEDIR=$1$UPDATEDIR DNSDIR=$1$DNSDIR # make the test directory structure mkdir -p $UPDATEDIR mkdir -p $DNSDIR fi if [ $2 ]; then KEYDIR=$2 fi if [ $3 ]; then UPDATE_BUILD_DIR=1 fi echo "UPDATEDIR=$UPDATEDIR" echo "DNSDIR=$DNSDIR" echo "KEYDIR=$KEYDIR" test_version() { SA_VERSION=$1 SA_SVN_TAG=$2 # to heck with dealing with svn update failures rm -rf release_$SA_VERSION # test the release on the version(s) of spamassassin the update is meant for svn co https://svn.apache.org/repos/asf/spamassassin/$SA_SVN_TAG release_$SA_VERSION cd release_$SA_VERSION perl Makefile.PL PREFIX=$TMPDIR/release_$SA_VERSION < /dev/null make make install set +e ./sa-update -D --install $TMPDIR/${REVISION}.tar.gz STATUS=$? set -e cd .. rm -rf release_$SA_VERSION $TMPDIR/release_$SA_VERSION return $STATUS } update_dns_record() { SA_VERSION=$1 UPDATE_REVISION=$2 # turn "3.2.0" into "0.2.3" RVERS=`echo $SA_VERSION | perl -pe 's/^(\d+)\.(\d+)\.(\d+)$/$3.$2.$1/'` DNS_RECORD="$RVERS TXT \"$UPDATE_REVISION\"" echo "DNS Record: $DNS_RECORD" DNSFILE="$DNSDIR/$SA_VERSION" mkdir $TMPDIR/dns-backup set +e cp $DNSFILE $TMPDIR/dns-backup/. set -e # set -e should catch any errors here echo $DNS_RECORD > $DNSFILE.mkupdate-with-scores.new mv $DNSFILE.mkupdate-with-scores.new $DNSFILE return 0 } revert_dns_record() { SA_VERSION=$1 DNSFILE="$DNSDIR/$SA_VERSION" set +e cp $TMPDIR/dns-backup/$SA_VERSION $DNSFILE set -e } copy_update_paranoid() { SRC=$1 DST=$2 set +e cp $SRC $DST diff -u $SRC $DST if [ $? -ne 0 ]; then set -e return 1 fi set -e return 0 } make_rule_update_from_trunk() { # to heck with dealing with svn update failures rm -rf trunk trunk-rulesrc-scores # get the latest scores for new rules svn co https://svn.apache.org/repos/asf/spamassassin/trunk/rulesrc/scores trunk-rulesrc-scores # get the revision number of the rules # TODO: have the script that make 72_scores.cf include a revision number #REVISION=`head -1 trunk-rulesrc-scores/72_scores.cf | cut -d" " -f6` REVISION=`head -1 trunk-rulesrc-scores/scores-set* | cut -d" " -f9 | sort -rn | head -1` svn co --revision=$REVISION https://svn.apache.org/repos/asf/spamassassin/trunk trunk cd trunk if [ $UPDATE_BUILD_DIR ]; then svn up build fi perl Makefile.PL PREFIX=$TMPDIR/trunk < /dev/null make cd .. cp trunk-rulesrc-scores/72_scores.cf trunk/rules/72_scores.cf # note: one of set0 or set1 stats might be incorrect (not all of their rules # are included in the update) I can't remember if we eliminate dropped # rules in generate-new-scores or not (we run the sets in a particular # order for some reason) cp trunk-rulesrc-scores/stats-set0 trunk/rules/STATISTICS-set0-72_scores.cf.txt cp trunk-rulesrc-scores/stats-set1 trunk/rules/STATISTICS-set1-72_scores.cf.txt cp trunk-rulesrc-scores/stats-set2 trunk/rules/STATISTICS-set2-72_scores.cf.txt cp trunk-rulesrc-scores/stats-set3 trunk/rules/STATISTICS-set3-72_scores.cf.txt cd trunk/rules # remove files we don't want to ship in updates # remember that 3KB == 1GB of traffic on the mirrors as of Jan 1, 2010 set +e rm 70_sandbox.cf 70_inactive.cf rm STATISTICS-set?.txt set -e mkdir -p $TMPDIR/trunk/etc/mail/spamassassin #cp *.pre *.cf *.txt languages user_prefs.template $TMPDIR/trunk/etc/mail/spamassassin/. ../spamassassin --lint -D tar cvf - *.cf *.txt languages user_prefs.template | gzip -9 > $TMPDIR/${REVISION}.tar.gz cd ../.. shasum $TMPDIR/${REVISION}.tar.gz > $TMPDIR/${REVISION}.tar.gz.sha1 gpg --batch --homedir $KEYDIR -bas $TMPDIR/${REVISION}.tar.gz || exit $? } TMPDIR="/tmp/sa-mkupdate-$$" rm -rf $TMPDIR mkdir $TMPDIR cd $TMPDIR # generate a rule update using rules from trunk at a revision # that we have generated scores for make_rule_update_from_trunk # test to make sure it works with sa-update --install UPDATED_VERSIONS=0 MINOR_VERS=0 for (( MINOR_VERS=0; 1; MINOR_VERS++ )); do set +e svn info https://svn.apache.org/repos/asf/spamassassin/tags/spamassassin_release_3_3_$MINOR_VERS | grep Revision VERSION_EXISTS=$? set -e if [ $VERSION_EXISTS -ne 0 ]; then break; fi test_version 3.3.$MINOR_VERS tags/spamassassin_release_3_3_$MINOR_VERS \ && update_dns_record "3.3.$MINOR_VERS" "$REVISION" && UPDATED_VERSIONS=$((UPDATED_VERSIONS+1)) done # we just assume that the next stable version is the branch's current version test_version 3.3.$MINOR_VERS branches/3.3 \ && update_dns_record "3.3.$MINOR_VERS" "$REVISION" && UPDATED_VERSIONS=$((UPDATED_VERSIONS+1)) echo "VERSIONS UPDATE PASSED ON: $UPDATED_VERSIONS" # publish update if [ $UPDATED_VERSIONS -gt 0 ]; then # be careful, we want to make sure that the DNS records are always in a good state; # even if we end up exiting unexpectedly due to an error EXIT=0 ( copy_update_paranoid "$TMPDIR/$REVISION.tar.gz" "$UPDATEDIR/$REVISION.tar.gz" && copy_update_paranoid "$TMPDIR/$REVISION.tar.gz.asc" "$UPDATEDIR/$REVISION.tar.gz.asc" && copy_update_paranoid "$TMPDIR/$REVISION.tar.gz.sha1" "$UPDATEDIR/$REVISION.tar.gz.sha1" && chmod 544 $UPDATEDIR/$REVISION.tar.gz* ) || EXIT=5 # copying the update files went wrong, revert dns and exit if [ $EXIT -gt 0 ]; then for (( I=0; I<=$MINOR_VERS; I++ )); do revert_dns_record "3.3.$I" done exit $EXIT fi # schedule dns commit/reload atq job # note that we're probably not going to be able to commit the DNS changes # until the update tarball mirrors have had time to sync since the ASF # name servers will probably update and reload via a commit hook trigger or # on a set interval # delete any existing jobs in at queue 'n' used for named reloads for JOB in `at -l -q n | cut -d" " -f1`; do atrm $JOB; done # schedule a job to tick the zone serial and reload named in 16 minutes # (mirror rsyncs are done every 15 minutes) cd echo "/export/home/updatesd/svn/spamassassin/build/mkupdates/tick_zone_serial" | at -q n now + 16min fi cd rm -rf $TMPDIR