GPG verifying git tags in a deployment script

We would like our deployment process to pull directly from our git repository, but only activate new changes if they are signed (via git tag -s) with a GPG signature. I've found very few examples out there of workflows that use GPG verification of git tags, so I'm not sure if there's a "best practice" for this sort of thing.

What we have so far looks like this:

# discard erroneous local changes
git reset --hard HEAD

# get changes
git fetch
start=$(git rev-parse FETCH_HEAD)

# get new tags
git fetch --tags

# find most recent release tag
tag=$(git describe --abbrev=0 --match "release-*" $start)

if git tag -v $tag; then
  git checkout $tag
  ...do stuff...
fi

Does this make sense? In particular, in order to avoid erroneous local changes from hosing the deployment process, is git reset --hard HEAD the right thing to do? Also, remembering FETCH_HEAD seems to be necessary, other wise tags subsequent to HEAD don't show up in the output of git describe. Is there another way to do this?

Alternatively, if you have a documented deployment workflow that uses signed tags for verification I would be interested in a link to that.


The title of the question is about signed tags in a deployment workflow, but what you are asking has very little to do with the signed tags. And in reality the only step that would be different is the verification of the tags, and you are already doing that.

git reset --hard HEAD is not going to clean out any untracked local files, which may very well ruin your build process. After git reset --hard you may want to also run git clean -d -x -f.

git fetch may fetch multiple branches, or it may not fetch what you would expect it to fetch. All the fetched branches would be added to .git/FETCH_HEAD so to avoid any surprises when using the FETCH_HEAD ref, I would recommend fetching your release branch explicitly. Something like git fetch $remote $branch.

You are asking if there is a "better" way of doing this, but personally I think this is good enough. If your goal is to avoid unnecessary fetching, then you could play with the output of git ls-remote but it is really not worth the effort.

Personally, for reproducible builds I would simply start the build in a clean directory every time. dir=$(mktemp -d); cd $dir; git init; git remote add ... and so on. This way you can also easily move this script to a different machine. To speed up the initial fetch you can tell the temporary directory to find git objects from the permanent local directory with a echo $permanent_git_directory/.git/objects > .git/objects/info/alternates (man gitrepository-layout for more info).