Using git-describe output for version pinning
The fact that tj-actions/changed-files
was compromised is kind of old news at this point, but I had an insight the other day about this problem and its remediation that I haven't seen mentioned yet.
To recap - the issue is that many GitHub Actions users were doing something like uses: tj-actions/changed-files@$TAG
, but the commit that $TAG
actually points at can be changed (which isn't a behavior specific to GitHub Actions, for what it's worth). The solution is to do something like uses: tj-actions/changed-files@$COMMIT_SHA
. This gets us the same commit every time, but now we have the problem of not being able to see at a glance which version $COMMIT_SHA
refers to! One solution to that would be to add a simple comment:
uses: tj-actions/changed-files@ed68ef82c095e0d48ec87eccea555d944a631a4c # v46.0.5
...but the problem with this solution is nothing makes you keep that comment up-to-date when you change the commit SHA, so they can (and often do) end up diverging.
So I was thinking "oh man, wouldn't it be nice if a Git revision could specify the expected commit SHA, along with an annotation for the intended tag?"
...and then I remembered that's exactly what git describe
gives us!
For those of you who aren't familiar, git describe
outputs a "human-readable name based on an available ref" - it's often in the format $TAG-$NUM_COMMITS_PAST_TAG-g$COMMIT_SHA
. So to use our earlier example, ed68ef82c095e0d48ec87eccea555d944a631a4c
becomes v46.0.5-0-ged68ef82c095e0d48ec87eccea555d944a631a4c
. And this format is understood by git rev-parse, so it's understood by all Git commands, as well as uses
clauses in GitHub Actions.
To get this kind of revision for a given tag, you just need to use git describe --long --abbrev=40 $TAG
- the --long
is so git describe
doesn't just give you the name of the tag, and the --abbrev=40
is to get the full commit SHA.
However, there is a small caveat: unfortunately, while the $COMMIT_SHA
part does get verified (which is, in my opinion, the important part!), the $TAG
and $NUM_COMMITS_PAST_TAG
parts are ignored - so you could still have the problem where you just change the $COMMIT_SHA
part and it no longer matches $TAG
. But, since it's part of the actual workflow YAML rather than just a comment, it would be easier to write a linter for this, and whipping up a script to verify those parts would be trivial. GitHub themselves could even add this to Actions!