-
Notifications
You must be signed in to change notification settings - Fork 13
Description
We are using floating tags in most of our workflows, we should harden this with hash-pins to strengthen our supply chain.
List of PRs
- Pin Github Actions actions to their hashes docs#804
- Add Dependabot configuration hub-lite#89
- Pin Github Actions actions to their hashes island-dispatch#13
- Pin Github Actions actions to their hashes midi-app-controller#117
- Pin Github Actions actions to their hashes napari#8140
- Pin Github Actions actions to their hashes napari-animation#243
- Pin Github Actions actions to their hashes napari-console#45
- Pin Github Actions actions to their hashes napari-graph#15
- Pin Github Actions actions to their hashes napari-plugin-checks#9
- Pin Github Actions actions to their hashes napari-plugin-engine#65
- Pin Github Actions actions to their hashes napari-plugin-manager#163
- Pin Github Actions actions to their hashes napari-plugin-template#82
- Pin Github Actions actions to their hashes napari-release-tools#30
- Pin Github Actions actions to their hashes napari-scipy2025-workshop#33
- Pin Github Actions actions to their hashes napari-sphinx-theme#191
- Pin Github Actions actions to their hashes napari-svg#53
- Pin Github Actions actions to their hashes napari-tiff#51
- Pin Github Actions actions to their hashes napari-workshop-template#47
- Pin Github Actions actions to their hashes napari-xarray#5
- Pin Github Actions actions to their hashes npe2#394
- Pin Github Actions actions to their hashes npe2api#60
- Pin GHA actions to hashes #268
- Pin Github Actions actions to their hashes pins#8
- Pin Github Actions actions to their hashes update-checker#6
- Pin Github Actions actions to their hashes weather-report#40
Method used
I usually apply https://www.npmjs.com/package/pin-github-action for a couple of workflows, but this tool has an issue: it won't pin to the strictest version available (e.g. it will stay in v4 instead of choosing v4.1.3, which will configure Dependabot differently). For more info, see this issue: mheap/pin-github-action#192.
So instead I asked Gemini to write a script to do the same in Python, with the strictest-pin-available approach. After a couple of prompts, something usable was available. I fixed the logic for the comments. The script is available at https://gist.github.com/jaimergp/7e657e86a5c1a491905d37bcef6d3e55.
The script, however, is not perfect. It uses ruamel.yaml
to parse YAML and its comments, and the roundtrip is not perfect. In some cases, whitespace differences were introduced, so I had to clean those up manually. However, this SO answer plus a little bit of regex-y search+replace ((.* uses: .*)
-> $1
) in my IDE automated most of it. After all, I did want to review all the modified workflows, so I coupled this cleaning-up to the review.
So, the overall script looked something like this (this is not how I ran it, but this is how I would have run it if I knew about the shortcomings after the first attempts). Click to unfold!
Bash script
#!/bin/bash
set -ex
# 1. (Fork and) clone all repos in the napari org
# napari-repos.txt is obtained with 'gh repo list napari', removed the napari/ part so we only get the repo name;
# I omitted napari.github.io and the archived ones too; this could have been done with a CLI flag, but well...
# Oh, and place 'packaging' the first so we can rely on its dependabot.yml file
for repo in $(cat napari-repos.txt); do
echo napari/$repo
if [[ -d $repo ]]; then
continue
fi
gh repo fork --clone --default-branch-only napari/${repo}
cd $repo
git checkout main
git pull upstream main
if [[ ! -f .github/dependabot.yml ]];
cp ../packaging/.github/dependabot.yml .github/dependabot.yml
fi
cd ..
done
# 2. Run the Python script that will process the tags into commented hashes
# We do this for ALL workflows at once (across all repos) to maximize the
# cache hits (many workflows share many actions like actions/checkout)
GITHUB_TOKEN=XXXXX uv run pinner.py */.github/workflows/*.yml
# Steps 3 and 3b could have been avoided with a better YAML roundtrip logic in pinner.py
# like a regex-y search replace for ` uses: +\S+`, but well :shrug:
# 3. Clean up the whitespace diffs
for repo in $(cat napari-repos.txt); do
cd $repo
git diff -U0 -w --no-color --ignore-blank-lines | git apply --cached --ignore-whitespace --unidiff-zero - && git checkout .
cd ..
done
# 3b. Go to your IDE and review all the diffs, fixing issues as they appear
code .
# 4. Commit all the changes and send the PRs
for repo in $(cat napari-repos.txt); do
cd $repo
if env PAGER=cat git diff --check; then
git checkout -b pin-gha
git add .
git commit -m "Pin Github Actions actions to their hashes"
git push
fi
gh repo set-default napari/$repo
gh pr create --title "Pin Github Actions actions to their hashes" --body "Part of https://github.com/napari/packaging/issues/259" | tee -a ../prs.txt
cd ..
done