123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268 |
- #!/bin/bash
- # git-packaging-hooks - git hooks to semi-automate releases and distro packaging
- #
- # Copyright 2017 bill-auger <https://github.com/bill-auger/git-packaging-hooks/issues>
- #
- # git-packaging-hooks is free software: you can redistribute it and/or modify
- # it under the terms of the GNU General Public License version 3 as published by
- # the Free Software Foundation, either version 3 of the License, or
- # (at your option) any later version.
- #
- # git-packaging-hooks is distributed in the hope that it will be useful,
- # but WITHOUT ANY WARRANTY; without even the implied warranty of
- # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- # GNU General Public License for more details.
- #
- # You should have received a copy of the GNU General Public License version 3
- # along with git-packaging-hooks. If not, see <http://www.gnu.org/licenses/>.
- readonly HOOKS_PATH=$(git config --local core.hooksPath)
- readonly COMMON_DEFS_FILE=$HOOKS_PATH/common.sh.inc
- source $COMMON_DEFS_FILE
- [ ! -f $COMMON_DEFS_FILE ] && TraceError "missing $COMMON_DEFS_FILE - aborting commit" && exit 1
- if (($IS_STAGING_BRANCH))
- then TraceStage "running staging-specific post-commit hooks"
- # set "release" tag
- for revision_tag in $REVISION_TAGS
- do TraceStep "removing un-merged revision tag '$revision_tag'"
- git tag --delete $revision_tag > /dev/null
- done
- if [ ! -f $TAGS_FILE ]
- then TraceStep "adding revision tag '$VERSION_STRING'"
- git tag $VERSION_STRING
- else declare -a orphaned_tags=( $(cat $TAGS_FILE | sort | uniq) )
- orphaned_minor_tag=${orphaned_tags[0]}
- orphaned_rev_tag=${orphaned_tags[1]}
- orphaned_other_tags=${orphaned_tags[@]:2}
- [ "$orphaned_minor_tag" ] && TraceStep "restoring minor version tag '$orphaned_minor_tag'"
- [ "$orphaned_rev_tag" ] && TraceStep "adding revision tag '$orphaned_rev_tag'"
- [ "$orphaned_other_tags" ] && TraceStep "restoring other tags '$orphaned_other_tags'"
- for orphaned_tag in "${orphaned_tags[@]}" ; do git tag $orphaned_tag ; done
- rm $TAGS_FILE
- fi
- # re-configure autotools, rebuild, install, and verify
- TraceStep "re-configuring autotools"
- sudo make uninstall 2&> /dev/null
- make distclean 2&> /dev/null
- autoreconf --force --install
- TraceStep "verifying re-build/install"
- ./configure 2&> /dev/null
- make -j$N_MAKE_JOBS 2&> /dev/null
- sudo make install 2&> /dev/null
- make installcheck 2&> /dev/null
- sudo make uninstall 2&> /dev/null
- make distclean 2&> /dev/null
- # commit automated changes, and ensure signed
- git add --all
- git diff --exit-code --cached > /dev/null && is_index_clean=1 || is_index_clean=0
- git verify-commit --raw HEAD 2> /dev/null && has_trusted_signature=1 || has_trusted_signature=0
- (($is_index_clean )) || TraceStep "amending commit with automated changes"
- (($has_trusted_signature)) || TraceStep "amending commit to ensure signature exists"
- (($is_index_clean)) && (($has_trusted_signature)) || \
- git commit --gpg-sign --amend --reuse-message=HEAD > /dev/null
- TraceStage "completed staging-specific post-commit hooks"
- elif (($IS_PACKAGING_BRANCH))
- then (($IS_AMEND_COMMIT)) && exit 0
- TraceStage "running packaging-specific post-commit hooks"
- # implode tarball
- TraceStep "imploding tarball"
- rm $TARBALL_FILE $TARBALL_FILE.sig $PKGBUILD_FILE.sig 2> /dev/null
- git archive --prefix=$TARBALL_INNER_DIR/ --output=$TARBALL_FILE $VERSION_STRING
- # generate tarball metadata
- TraceStep "generating checksums"
- TARBALL_MD5SUM="$( md5sum $TARBALL_FILE | cut --delimiter=' ' --fields=1)"
- TARBALL_SHA1SUM="$( sha1sum $TARBALL_FILE | cut --delimiter=' ' --fields=1) "
- TARBALL_SHA256SUM="$(sha256sum $TARBALL_FILE | cut --delimiter=' ' --fields=1)"
- FILE_SIZE=$( wc --bytes $TARBALL_FILE | cut --delimiter=' ' --fields=1)
- # PKGBUILD_MD5SUMS="'$TARBALL_MD5SUM' SKIP SKIP"
- PKGBUILD_MD5SUMS="'$TARBALL_MD5SUM'"
- # inject tarball metadata into packaging files
- TraceStep "preparing packaging files"
- for dsc_file in ${DSC_FILES[@]}
- do echo "Checksums-Sha1:" >> $dsc_file
- echo " $TARBALL_SHA1SUM $FILE_SIZE $DEB_TARBALL_FILENAME" >> $dsc_file
- echo "Checksums-Sha256:" >> $dsc_file
- echo " $TARBALL_SHA256SUM $FILE_SIZE $DEB_TARBALL_FILENAME" >> $dsc_file
- echo "Files:" >> $dsc_file
- echo " $FAUX_DSC_MD5SUM $FAUX_DSC_SIZE $DEB_TARBALL_FILENAME" >> $dsc_file
- echo " $FAUX_DSC_MD5SUM $FAUX_DSC_SIZE $DEB_DIFFBALL_FILENAME" >> $dsc_file
- done
- sed --in-place "s/^md5sums=.*$/md5sums=( $PKGBUILD_MD5SUMS )/" $PKGBUILD_FILE
- # set uniform commit message and ensure signed
- git commit --gpg-sign --amend --allow-empty --message="$GIT_COMMIT_MSG" > /dev/null
- # sign tarball and PKGBUILD
- gpg --detach-sign --yes $TARBALL_FILE
- gpg --detach-sign --yes $PKGBUILD_FILE
- ### github steps ###
- # create upstream tarball
- TraceStep "pushing staging branch, packaging branch, and revision tag to github"
- git push --force $REMOTE_NAME $STAGING_BRANCH $PACKAGING_BRANCH $VERSION_STRING 2> /dev/null
- # destroy any existing github "tag release" with same tag
- TraceStep "querying existing github \"tag release\" '$VERSION_STRING'"
- resp_json=$(curl $CURL_RESP_ARGS $GITHUB_API_URL/tags/$VERSION_STRING)
- release_id=$(echo $resp_json | grep '"assets_url":' | sed "$RELEASEID_REGEX")
- error_resp=$(echo $resp_json | grep '"message": "Not Found"')
- if [ -n "$(echo $release_id | sed 's/[^0-9]//g')" -a -z "$error_resp" ]
- then TraceStep "deleting existing github \"tag release\" - id: '$release_id'"
- resp_status=$(curl --request DELETE \
- --header "Authorization: token $GITHUB_AUTH_TOKEN" \
- --header "Content-Type: application/json" \
- --header "Accept: application/json" \
- $CURL_STATUS_ARGS \
- $GITHUB_API_URL/$release_id )
- if [ "$resp_status" == "204" ]
- then TraceStep "deleted github \"tag release\" - id: '$release_id'"
- else TraceStep "failed to delete github \"tag release\" - id: '$release_id'" ; exit 1 ;
- fi
- fi
- # create github "tag release"
- TraceStep "creating github \"tag release\" '$VERSION_STRING'"
- resp_status=$(curl --request POST --data "$GITHUB_RELEASE_JSON" \
- --header "Authorization: token $GITHUB_AUTH_TOKEN" \
- --header "Content-Type: application/json" \
- --header "Accept: application/json" \
- $CURL_STATUS_ARGS \
- $GITHUB_API_URL )
- if [ "$resp_status" == "201" ]
- then TraceStep "created github \"tag release\" '$VERSION_STRING'"
- else TraceStep "failed to create github \"tag release\" '$VERSION_STRING'" ; exit 1 ;
- fi
- # ensure the new github "tag release" is accessible via the API
- TraceStep "confirming existence of new github \"tag release\" '$VERSION_STRING'"
- resp_json=$(curl $CURL_RESP_ARGS $GITHUB_API_URL/tags/$VERSION_STRING)
- release_id=$( echo $resp_json | grep '"assets_url":' | sed "$RELEASEID_REGEX")
- upload_url=$( echo $resp_json | grep '"upload_url":' | sed "$UPLOADURL_REGEX")
- error_resp=$( echo $resp_json | grep '"message": "Not Found"' )
- if [ -n "$(echo $release_id | sed 's/[^0-9]//g')" -a -z "$error_resp" ]
- then TraceStep "confirmed existence of new github \"tag release\" - id: '$release_id'"
- else TraceStep "failed to fetch new github \"tag release\" '$VERSION_STRING'" ; exit 1 ;
- fi
- # upload signatures to github "tag release"
- for upload_file in ${UPLOAD_FILES[@]}
- do filename=$(basename $upload_file)
- TraceStep "uploading '$filename' to github \"tag release\" '$VERSION_STRING'"
- resp_status=$(curl --request POST --data-binary "@$upload_file" \
- --header "Authorization: token $GITHUB_AUTH_TOKEN" \
- --header "Content-Type: text/plain" \
- --header "Accept: application/json" \
- $CURL_STATUS_ARGS \
- ${upload_url}?name=$filename )
- if [ "$resp_status" == "201" ]
- then TraceStep "uploaded '$upload_file'"
- else TraceStep "failed to upload '$upload_file'" ; exit 1 ;
- fi
- done
- # download and verify github "tag release" tarball and PKGBUILD
- TraceStep "downloading remote tarball, PKGBUILD, and signatures"
- curl $CURL_FETCH_ARGS $TARBALL_URL ; curl $CURL_FETCH_ARGS $PKGBUILD_URL ;
- curl $CURL_FETCH_ARGS $TARBALL_SIG_URL ; curl $CURL_FETCH_ARGS $PKGBUILD_SIG_URL ;
- for remote_file in ${REMOTE_FILENAMES[@]}
- do if [ -f $remote_file -a "$(stat --printf='%s' $remote_file)" != "9" ] # 'Not Found'
- then TraceStep "downloaded $remote_file"
- else TraceStep "failed to download $remote_file"
- # source $(git config --local core.hooksPath)/debug-remote-files.sh.inc
- exit 1
- fi
- done
- if gpg --verify --verify-options no-show-photos ./$TARBALL_FILENAME.sig 2> /dev/null && \
- diff $TARBALL_FILE ./$TARBALL_FILENAME > /dev/null && \
- diff $TARBALL_FILE.sig ./$TARBALL_FILENAME.sig > /dev/null && \
- gpg --verify --verify-options no-show-photos ./PKGBUILD.sig 2> /dev/null && \
- diff $PKGBUILD_FILE ./PKGBUILD > /dev/null && \
- diff $PKGBUILD_FILE.sig ./PKGBUILD.sig > /dev/null
- then TraceStep "verified remote tarball, PKGBUILD, and signatures"
- else TraceStep "failed to verify remote tarball, PKGBUILD, or signatures"
- # source $(git config --local core.hooksPath)/debug-remote-files.sh.inc
- exit 1
- fi
- ### OBS steps ###
- # copy OBS files to local OSC build directory and trigger remote builds
- TraceStep "populating OSC build directory"
- cd $OSC_DIR/ && rm ./*
- for obs_file in ${OBS_FILES[@]}
- do cp $obs_file $OSC_DIR/
- osc add ./$(basename $obs_file) > /dev/null
- done
- TraceStep "triggering OSC remote builds"
- osc checkin --message=$OSC_COMMIT_MSG > /dev/null
- # cleanup transient files
- TraceStep "cleaning up transient files"
- cd $PROJECT_DIR
- for transient_file in ${CLEANUP_FILES[@]} ; do rm $transient_file ; done ;
- git clean $GIT_CLEAN_OPTIONS &> /dev/null
- ### debian steps ###
- # rename tarball and prepare working tree for debain
- rm -rf ../${DEBIAN_NAME}*${VERSION}*
- mv $TARBALL_FILE ../$DEB_TARBALL_FILENAME
- [ "$DEB_BUILD_TOOL" == 'gbp' -a ! -f debian/gbp.conf ] && cp $HOOKS_PATH/gbp.conf debian/
- # build/validate debian package
- TraceStep "building debian package with '$"$DEB_BUILD_TOOL"'"
- case "$DEB_BUILD_TOOL" in
- 'debuild') debuild --unsigned-changes --unsigned-source
- deb_file=$(ls ../${DEBIAN_NAME}_${VERSION}-*_${DEB_BUILD_ARCH}.deb 2> /dev/null)
- sudo piuparts --save=$CHROOTBALL --basetgz=$CHROOTBALL \
- --distribution=$DEB_BUILD_DIST --arch=$DEB_BUILD_ARCH \
- --mirror="$DEBOOTSTRAP_REPO" $deb_file
- (($?)) && echo "piuparts failed for '$deb_file'" && exit 1
- ;;
- 'sbuild') sudo sbuild-createchroot --make-sbuild-tarball=$CHROOTBALL $DEB_BUILD_DIST \
- `mktemp --directory` "$DEBOOTSTRAP_REPO"
- sbuild --dist=$DEB_BUILD_DIST --arch=$DEB_BUILD_ARCH \
- --run-piuparts --piuparts-opts="--basetgz=$CHROOTBALL"
- ;;
- 'gbp') DIST=$DEB_BUILD_DIST ARCH=$DEB_BUILD_ARCH git-pbuilder create --extrapackages 'eatmydata' &> $LOG_FILE
- DIST=$DEB_BUILD_DIST ARCH=$DEB_BUILD_ARCH git-pbuilder update --extrapackages 'eatmydata' &> $LOG_FILE || true
- [ ! -d $PIUPARTS_CHROOT ] && echo "could not create chroot '$PIUPARTS_CHROOT'" && exit 1
- gbp buildpackage --git-dist=$DEB_BUILD_DIST --git-arch=$DEB_BUILD_ARCH \
- --git-pbuilder --git-tag --git-retag --git-notify=off &> $LOG_FILE
- deb_file=$(ls ../${DEBIAN_NAME}_${VERSION}-*_${DEB_BUILD_ARCH}.deb 2> /dev/null)
- [ ! -f "$deb_file" ] && echo "package creation failed" && exit 1
- TraceStep "testing debian package install/uninstall"
- sudo piuparts --distribution=$DEB_BUILD_DIST --arch=$DEB_BUILD_ARCH \
- --existing-chroot=$PIUPARTS_CHROOT $deb_file &> $LOG_FILE
- (($?)) && echo "piuparts failed for '$deb_file'" && exit 1
- debian_version=debian/$(dpkg-parsechangelog --show-field version)
- debian_tag=$(git tag --points-at HEAD)
- [ "$debian_version" != "$debian_tag" ] && TraceError "improper debian tag" && exit 1
- TraceStep "pushing debian tag to github"
- git push --force $REMOTE_NAME $debian_tag 2> /dev/null
- ;;
- esac
- TraceStage "completed packaging-specific post-commit hooks"
- fi
|