Hello, I finally have something working to manage git-buildpackage from tags. The debian/changelog is not updated on the branch.
The procedure is the following: You on your workstation: ------------------------ 1. upstream release a new version 2. merge upstream in your debian packaging branch 3. create a "build request tag"[1] 4. push the tag on a central repository The post-receive hook on a central git repository: -------------------------------------------------- 1. check for specific tag names 2. launch a build.command[2] in background My build-deb build.command on a central git repository: ------------------------------------------------------- 1. check tag name 2. "clone -l" in a temporary directory 3. switch to last tagged debian package, if any 4. merge the "build request tag" 5. update debian/changelog[3] 6. run git-buildpackage 7. tag new version 6. push the new tag (as we are on temporary clone) 7. send report by mail 8. clean (done by a trap on EXIT) TODO: * Use "git-dch --snapshot" if distribution name contains "experimental" For version to be incremented in debian/changelog we need to tag snapshots too. We could keep only one snapshot tag by removing the previous one. We could remove the previous snapshot tag when doing non snapshot build (no using experimental in distribution name) * As above, but for --bpo, --nmu, etc * Remove debian/changelog from the development branch, will be possible if I can close #669171[4] Thanks. Footnotes: [1] default to something like "build/<vendor>/<distribution>" [2] Included build-deb [3] This part require a patch[5] for git-dch to set the distribution name based on the tag name [4] http://bugs.debian.org/669171 [5] http://bugs.debian.org/646684 -- Daniel Dehennin Récupérer ma clef GPG: gpg --keyserver pgp.mit.edu --recv-keys 0x7A6FE2DF
#!/bin/bash #------------------------------------------------------------------------ # Inspired by the post-receive-email hook # Copyright (c) 2007 Andy Parkins # # build-hook - Run a command after receiving a build request tag # Copyright (C) 2012 Daniel Dehennin <daniel.dehen...@baby-gnu.org> # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program 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 # along with this program. If not, see <http://www.gnu.org/licenses/>. #------------------------------------------------------------------------ # Usage: command line: build-hook <refname> <oldrev> <newrev> # # Usage: hook script: echo <oldrev> <newrev> <refname> | build-hook # # This script can be be run from command line or as a hook script. # # It check for a build tag and run an external command in background. # # The tag must match the build.tag-regex git configuration # # Config # ------ # build.tag-regex # Extended regular expression (as in regex(7)) to match build # request tags. The value must match the <vendor>/<distribution> # part used to determine the distribution name. # Default value: 'refs/tags/build/[^/]+/.+' # build.command # Run that command in the background with the following arguments: # <refname> <oldrev> <newrev> # The standard and error outputs are both redirected to /dev/null. # No default value set -e die() { echo -e "$@" >&2; exit 1; } function usage() { perl -lne 'print substr($_, 2) if /^# Usage/../^$/' < "${0}"; exit 1; } [ "${1}" = "-h" -o "${1}" = "--help" ] && usage BUILD_CMD=$(git config build.command || /bin/true) BUILD_TAG_REGEX=$(git config build.tag-regex || echo -n 'refs/tags/build/[^/]+/.+') function check-build-request() { # --- Arguments refname="${1}" # NB: no quote arround right operand of =~ if ! [[ "${refname}" =~ ${BUILD_TAG_REGEX} ]] then # Not a build request return 1 fi oldrev=$(git rev-parse "${2}" 2>/dev/null) newrev=$(git rev-parse "${3}" 2>/dev/null) # --- Interpret # 0000->1234 (create) # 1234->2345 (update) # 2345->0000 (delete) if expr "${oldrev}" : '0*$' >/dev/null then change_type="create" else if expr "${newrev}" : '0*$' >/dev/null then change_type="delete" else change_type="update" fi fi # --- Get the revision types newrev_type=$(git cat-file -t "${newrev}" 2> /dev/null || true) # oldrev_type=$(git cat-file -t "${oldrev}" 2> /dev/null || true) case "${change_type}" in create|update) rev="${newrev}" rev_type="${newrev_type}" ;; delete) return 1 ;; esac # The revision type tells us what type the commit is, combined with # the location of the ref we can decide between # - working branch # - tracking branch # - unannoted tag # - annotated tag # Only take care of tags short_refname="${refname##refs/tags/}" case "${rev_type}" in commit) # un-annotated tag refname_type="tag" ;; tag) # annotated tag refname_type="annotated tag" ;; *) # Can not happen? return 1 ;; esac if [ -n "${BUILD_CMD}" ] then echo "Spool a build from ${refname_type} '${short_refname}'" else die "No 'build.command' git configuration defined" fi } # --- Main loop # Allow dual mode: run from the command line just like the update hook, or # if no arguments are given then run as a hook script if [ -n "${1}" -a -n "${2}" -a -n "${3}" ]; then # Check if this is a build request and run the source builder command check-build-request $@ && "${BUILD_CMD}" $@ > /dev/null 2>&1 & else while read oldrev newrev refname do check-build-request "${refname}" "${oldrev}" "${newrev}" || continue "${BUILD_CMD}" "${refname}" "${oldrev}" "${newrev}" > /dev/null 2>&1 & done fi
#!/bin/bash #------------------------------------------------------------------------ # Inspired by the post-receive-email hook # Copyright (c) 2007 Andy Parkins # # build-deb - Run git-buildpackage from a tag name # Copyright (C) 2012 Daniel Dehennin <daniel.dehen...@baby-gnu.org> # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program 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 # along with this program. If not, see <http://www.gnu.org/licenses/>. #------------------------------------------------------------------------ # Usage: build-source <refname> <oldrev> <newrev> # # Run "git buildpackage" on a build request tag. # # The tag must match the build.tag-regex git configuration # # The <distribution> part of the <refname> will get the slash "/" # transformed to dashes "-": # # - build/debian/unstable -> unstable # - build/debian/wheezy/proposed/updates -> whezzy-proposed-updates # - build/debian/wheezy/proposed-updates -> whezzy-proposed-updates # # The build is done against the last builded package tag reachable. # # Config # ------ # build.home # Base directory where a temporary directory is created in which # the build occurs. # Default value: '${HOME}/build' # build.tag-regex # Extended regular expression (as in regex(7)) to match build # request tags. The value must match the <vendor>/<distribution> # part used to determine the distribution name. # Default value: 'refs/tags/build/[^/]+/.+' # build.mail # If 'true', send a mail of the log file # No default value # build.mail-from # Set the From header of the mail report # No default value # build.mail-to # Set the To header of the mail report # No default value # build.mail-cc-tag-author # If set to 'true', when 'build.mail-to' is defined send a carbon # copy to the author of the tag. # No default value # # Mandatory dependencies: # ----------------------- # * bash # * perl # * cut # * git # * git-buildpackage # * gbp-config: http://bugs.debian.org/672854#35 # * dpkg-parsechangelog # * mktemp # # Optional dependencies: # ---------------------- # * mailx or heirloom-mailx if the 'build.mail-from' or # 'build.mail-cc-tag-author' options are set set -e die() { echo -e "$@" >&2; exit 1; } function usage() { if [ -n "$@" ] then echo -e "Error: $@\n" >&2 fi perl -lne 'print substr($_, 2) if /^# Usage/../^$/' < "${0}" exit 1 } [ "${1}" = "-h" -o "${1}" = "--help" ] && usage BUILD_CMD='git-buildpackage' BUILD_TAG_REGEX=$(git config build.tag-regex || echo -n 'refs/tags/build/[^/]+/.+') BUILD_HOME=$(git config build.home || echo -n "${HOME}/build") function check-build-request() { # --- Arguments refname="${1}" if ! [[ "${refname}" =~ ${BUILD_TAG_REGEX} ]] then usage fi oldrev=$(git rev-parse "${2}" 2>/dev/null) newrev=$(git rev-parse "${3}" 2>/dev/null) # --- Interpret # 0000->1234 (create) # 1234->2345 (update) # 2345->0000 (delete) if expr "${oldrev}" : '0*$' >/dev/null then change_type="create" else if expr "$newrev" : '0*$' >/dev/null then change_type="delete" else change_type="update" fi fi # --- Get the revision types newrev_type=$(git cat-file -t "${newrev}" 2> /dev/null || true) oldrev_type=$(git cat-file -t "${oldrev}" 2> /dev/null || true) case "${change_type}" in create|update) rev="${newrev}" rev_type="${newrev_type}" ;; delete) die "${0} should not be called when deleting objects:\n\n" \ "change_type: '${change_type}'\n" \ "refname: '${refname}'\n" \ "oldrev: '${oldrev}'\n" \ "oldrev type: '${oldrev_type}'\n" \ "newrev: '${newrev}'" ;; esac # The revision type tells us what type the commit is, combined with # the location of the ref we can decide between # - working branch # - tracking branch # - unannoted tag # - annotated tag short_refname="${refname##refs/tags/}" case "${rev_type}" in commit) # un-annotated tag refname_type="tag" tag_author=$(git cat-file -p "${refname}" | perl -lane 'print join(" ", @F[1..@F-3]) if $F[0] eq "committer"') ;; tag) # annotated tag refname_type="annotated tag" tag_author=$(git cat-file -p "${refname}" | perl -lane 'print join(" ", @F[1..@F-7]) if $F[0] eq "tagger"') ;; *) # Can not happen? die "${0} must be called only for a build request:\n\n" \ "change_type: '${change_type}'\n" \ "refname: '${refname}'\n" \ "oldrev: '${oldrev}'\n" \ "oldrev type: '${oldrev_type}'\n" \ "newrev: '${newrev}'" \ "newrev type: '${newrev_type}'\n" ;; esac # TODO Get tag message without GPG signature # TAG=$(git tag -v ${refname}) # TAG_MSG=$(echo ${TAG} | tail -n +5) author_name=$(echo "${tag_author}" | perl -pe 's/\s<[^>]+>.*//xms') author_email=$(echo "${tag_author}" | perl -pe 's/[^<]+<([^>]+)>.*/$1/xms') # Do it here to send mail to author BUILD_CMD=$(type -p "${BUILD_CMD}") test -x "${BUILD_CMD}" \ || die "Build command '${BUILD_CMD}' not found or not executable" return 0 } function prepare-clone() { unset GIT_DIR PROJECT=$(basename $(pwd)) PROJECT="${PROJECT%.git}" test -d "${BUILD_HOME}" || mkdir -p "${BUILD_HOME}" \ || die "Can not create directory '${BUILD_HOME}'" test -w "${BUILD_HOME}" || die "Build directory '${BUILD_HOME}' is not writable" # Require a push url to publish tag PUSH_URL=$(git config build.push-url || die "No 'build.push-url' configuration: abort") BUILD_ROOT=$(mktemp -d "${BUILD_HOME}/${PROJECT}-XXXXXX") BUILD_DIR="${BUILD_ROOT}/${PROJECT}" cat >&2 <<EOF ┌──────────────────────────────────────────────────────────────────────────────┐ │ Prepare new clone │ └──────────────────────────────────────────────────────────────────────────────┘ EOF git clone -l $(pwd) "${BUILD_DIR}" >&2 } function deb-get-last-pkg() { local refname="${1}" cat >&2 <<EOF ┌──────────────────────────────────────────────────────────────────────────────┐ │ Get last debian package │ └──────────────────────────────────────────────────────────────────────────────┘ EOF git checkout -b tmp-XXXXXX "${refname}" local deb_tag_fmt=$(gbp-config git-buildpackage debian-tag | cut -d':' -f2-) local deb_tag_prefix="${deb_tag_fmt%\%*}" local last_pkg=$(git describe --abbrev=0 --match "${deb_tag_prefix}"\*) if [ -z "${last_pkg}" ] then echo "Unable to get last package, use ${refname}" >&2 last_pkg="${refname}" else echo "Use last package from '${last_pkg}'" >&2 fi echo "${last_pkg}" } function deb-get-distribution() { local short_refname="${1}" # Get the disribution from tag name (build/<vendor>/<base name>/<release>) # For example: build/debian/wheezy/proposed/updates cat >&2 <<EOF ┌──────────────────────────────────────────────────────────────────────────────┐ │ Get distribution │ └──────────────────────────────────────────────────────────────────────────────┘ EOF # strip build/ local dist="${short_refname#*/}" # strip vendor/ dist="${dist#*/}" # replace / with - dist="${dist//\//-}" echo "Set distribution to '${dist}'" >&2 echo "${dist}" } function main() { LOG_FILE=$(mktemp --tmpdir "build-deb-XXXXXX.log") exec 2> "${LOG_FILE}" # --- Arguments refname="${1}" oldrev=$(git rev-parse "${2}" 2>/dev/null) newrev=$(git rev-parse "${3}" 2>/dev/null) cat >&2 <<EOF ┌──────────────────────────────────────────────────────────────────────────────┐ │ Build source package │ └──────────────────────────────────────────────────────────────────────────────┘ Build request from: ${tag_author} Tag: ${short_refname} EOF prepare-clone cd "${BUILD_DIR}" local last_pkg=$(deb-get-last-pkg "${refname}") local build_branch=$(gbp-config git-buildpackage debian-branch | cut -d':' -f2-) test -z "${build_branch}" && die "Unable to get build branch" local dist=$(deb-get-distribution "${short_refname}") test -z "${dist}" && die "Unable to get distribution name" cat >&2 <<EOF ┌──────────────────────────────────────────────────────────────────────────────┐ │ Merge new package │ └──────────────────────────────────────────────────────────────────────────────┘ EOF git checkout -b "${build_branch}" "${last_pkg}" 1>&2 \ || die "Unable to switch to build branch '${build_branch}' from '${last_pkg}'" git merge --no-edit --no-ff -m "New upstream release by ${author_name}" "${refname}" >&2 cat >&2 <<EOF ┌──────────────────────────────────────────────────────────────────────────────┐ │ Update debian/changelog │ └──────────────────────────────────────────────────────────────────────────────┘ EOF git-dch -a debian/ >&2 || die "Unable to update debian/changelog" git add "debian/changelog" >&2 || die "Unable to add debian/changelog to git stagging area" local changes=$(dpkg-parsechangelog) local deb_version=$(echo $changes | awk '/^Version/ {print $2}') git commit -a -m "${author_name}: New version ${deb_version} for ${dist}." >&2 echo -e "\nChanges:" >&2 echo -e "=======:\n" >&2 echo "${changes}" >&2 cat >&2 <<EOF ┌──────────────────────────────────────────────────────────────────────────────┐ │ git-buildpackage build │ └──────────────────────────────────────────────────────────────────────────────┘ EOF git buildpackage >&2 || die "Unable to build debian source package" cat >&2 <<EOF ┌──────────────────────────────────────────────────────────────────────────────┐ │ git-buildpackage tag new version │ └──────────────────────────────────────────────────────────────────────────────┘ EOF git buildpackage --git-tag-only >&2 || die "Unable to create new tag" local new_version=$(git describe --tags --exact-match || die "No release tag created") cat >&2 <<EOF ┌──────────────────────────────────────────────────────────────────────────────┐ │ Publish new tag │ └──────────────────────────────────────────────────────────────────────────────┘ EOF echo "Push '${new_version} to '${PUSH_URL}${PROJECT}'" >&2 git push "${PUSH_URL}${PROJECT}" "${new_version}" >&2 || die "Unable to push new version tag" NEW_VERSION=$(git ls-remote --tags "${PUSH_URL}${PROJECT}" "${new_version}") } function clean() { local mail_from local mail_to local mail_cc cat >&2 <<EOF ┌──────────────────────────────────────────────────────────────────────────────┐ │ Cleaning │ └──────────────────────────────────────────────────────────────────────────────┘ EOF # We may fail to early if [ -n "${LOG_FILE}" ] then # Block new build request of last was not successful if [ -n "${NEW_VERSION}" ] then git tag -d "${short_refname}" >&2 git push "${PUSH_URL}${PROJECT}" ":${refname}" >&2 fi if [ -f "${LOG_FILE}" ] && git config build.mail then mail_from=$(git config build.mail-from || /bin/true) test -n "${mail_from}" && mail_from="-r ${mail_from}" mail_to=$(git config build.mail-to || /bin/true) if [ -n "${mail_to}" ] then if [[ $(git config build.mail-cc-tag-author) =~ ^t|T ]] then mail_cc="-S autocc=${author_email}" fi else mail_to="${author_email}" fi mail -s "[${PROJECT}] Build debian source package" \ "${mail_from}" "${mail_cc}" "${mail_to}" < "${LOG_FILE}" \ || /bin/true # Be sure to delete ${BUILD_ROOT} fi cd "${HOME}" rm -f "${LOG_FILE}" rm -rf "${BUILD_ROOT}" fi } trap clean EXIT # --- Main loop if [ -n "$1" -a -n "$2" -a -n "$3" ]; then # Check if this is a build request and run it check-build-request $@ && main $@ else usage "Invalid argument" fi
pgp4UdtN9Ov9T.pgp
Description: PGP signature
_______________________________________________ vcs-pkg-discuss mailing list vcs-pkg-discuss@lists.alioth.debian.org http://lists.alioth.debian.org/cgi-bin/mailman/listinfo/vcs-pkg-discuss