Update GitHub Actions workflow and add Dependabot config#63
Update GitHub Actions workflow and add Dependabot config#63JohnRDOrazio wants to merge 2 commits intoopensourcecatholic:masterfrom
Conversation
- Pin actions/checkout, actions/cache, and peaceiris/actions-gh-pages to full commit SHAs (with version comments) to harden the supply chain and make updates reviewable - Bump actions to current major versions (checkout v6, cache v5, actions-gh-pages v4), resolving the "Set up job" failure caused by actions/cache@v1 running on a retired Node runtime - Bump the Ruby container from 3.2.2 to 3.4.9 (latest 3.x) - Add .github/dependabot.yml with weekly updates for github-actions and bundler ecosystems so pinned SHAs and gem versions stay current Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The workflow container was bumped from 3.2.2 to 3.4.9, but the rest of the repo still pointed at 3.2.2. Three follow-ups: - Update .ruby-version from 3.2.2 to 3.4.9 so local tooling (rbenv, asdf, chruby) matches the CI container. - Regenerate Gemfile.lock under Ruby 3.4.9. The old lockfile was BUNDLED WITH 2.2.22, which is incompatible with Ruby 3.4's DidYouMean API; the new one is BUNDLED WITH 2.6.9. Gem versions were resolved fresh. - Expand the actions/cache key to include .ruby-version so that future Ruby bumps invalidate the gem cache, avoiding silent ABI mismatches between cached native extensions and a new Ruby runtime. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
@mkasberg could you take a look at this too, seeing you have taken care of some of the maintenance here? |
|
if auto-merge is enabled in the repo settings, we can also add an auto-merge workflow for dependabot bumps (at least minor version bumps), which can take away some of the maintenance headache. I've been implementing a similar workflow on a bunch of my projects, and it works wonderfully. I prevent auto-merge for major version bumps so that I can see the open PR and act on anything if the major version bump requires any changes to anything. |
| steps: | ||
| - uses: actions/checkout@v2 | ||
| - uses: actions/cache@v1 | ||
| - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 |
There was a problem hiding this comment.
I'd rather not hit a specific commit, because that makes it a little more annoying to 'follow master' — future versions of checkout/cache could break things, and we wouldn't know until at some point we're forced to update dependencies.
There was a problem hiding this comment.
I see dependabot maybe manages the deps though?
There was a problem hiding this comment.
yes dependabot will automatically open PRs for version bumps, following this same schema of pinning to the SHA and adding a human readable comment for the corresponding version (major.minor.patch). Basically it's the same as pinning to the version number except it's more secure, and dependabot takes care of keeping them up to date.
A good followup (which I can open later, if "auto-merge" is enabled in the repo settings), is a workflow that will automatically merge minor version bumps from dependabot (minor version bumps won't break anything), while for major version bumps dependabot would open the PR but it wouldn't automatically merge, we would merge it manually to ensure nothing breaks.
But even better is to have an automatic build step on dependabot major bumps PRs that ensures the build is clean, and only if that build test passes would we merge (or auto-merge).
There was a problem hiding this comment.
basically I had never touched the "enable auto-merge" setting on any of my projects until recently, because I was afraid that it would automatically merge open PRs without being able to review them. But I just discovered in the past week or two that it actually just enables the possibility of auto-merge, it doesn't actually auto-merge; if enabled though, you can add another workflow that will auto-merge dependabot PRs, and you can choose if it auto-merges all dependabot PRs or only minor version bump PRs. And you can place conditions such as "does this build cleanly?"
There was a problem hiding this comment.
I guess I'm fine with either approach; actions/foo is managed by GitHub so I'm not terribly worried about the sha changing, especially on a static site like this.
| steps: | ||
| - uses: actions/checkout@v2 | ||
| - uses: actions/cache@v1 | ||
| - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 |
There was a problem hiding this comment.
I guess I'm fine with either approach; actions/foo is managed by GitHub so I'm not terribly worried about the sha changing, especially on a static site like this.
| - package-ecosystem: github-actions | ||
| directory: / | ||
| schedule: | ||
| interval: weekly |
There was a problem hiding this comment.
I don't actually want to review dependabot PRs weekly though, and we really have no reason to for a static site. I'd rather bump everything (manually, without dependabot) once a year.
There was a problem hiding this comment.
Bump manually without dependabot, for minor version bumps? The problem with bumping it manually without dependabot opening a PR, is that it won't get bumped manually and then things start to break (as is currently the case). We all have lots of projects on our hands, and something that needs looking into once a year probably means nobody will look into it. But if dependabot opens the PR, then you at least get notified "hey there's something to look into here". Setting up a workflow to auto-merge minor version bumps means we wouldn't even have to look at it weekly: minor version bumps just get merged and you hardly notice. For GitHub actions, that won't break anything. Major version bumps can be merged manually: dependabot will check weekly but of course there won't be a weekly major version bump, it'll still only happen maybe once a year. And at least you get notified...
There was a problem hiding this comment.
Setting up a workflow to auto-merge minor version bumps means we wouldn't even have to look at it weekly: minor version bumps just get merged and you hardly notice. For GitHub actions, that won't break anything.
That's why I usually like pinning to major versions, and each build will automatically have the latest release in that version (e.g. v1, v2, etc.).
Can Dependabot pin to major versions instead of to commit hashes? That would be easiest for me. You start to see failures immediately if a minor fix in the major version causes it—though for GitHub Actions, there was only one time in the 300+ repos I maintain that a minor action change caused any grief.
There was a problem hiding this comment.
the best way to prevent a failure, is to add a build job to any PR that touches anything that determines the build (see PR #65 for that). So a dependabot PR that attempts to bump the minor version of an action, will still have to await a successful build action before it can be merged, and that's the best way of knowing whether a bumped action could break a build, you catch it before it is even merged to the codebase.
I don't feel very strongly about this and I am happy to revert to major version strings instead of SHAs, but SHAs are now recommended as the best security practice. I think ChatGPT will sum it up better than I could explain:
1) What SHA pinning actually gives you (and why it’s strongly recommended)
Pinning a GitHub Action to a full commit SHA instead of a tag like
@v3is fundamentally about supply-chain security and determinism:Security (the real reason)
- Tags are mutable: an attacker (or compromised maintainer account) can retarget
v3to malicious code.- A commit SHA is immutable → you are guaranteed to run exactly the code you reviewed. ([Well-Architected]1)
- This directly mitigates “poisoned release/tag” attacks and secret exfiltration risks. ([The GitHub Blog]2)
Reproducibility
- Your CI runs the same code every time, no surprises from upstream changes.
- Builds become deterministic (same inputs → same result).
Stability
- No accidental breaking changes from upstream minor/major releases.
- You control when upgrades happen instead of being surprised by them.
Policy enforcement
- GitHub can now enforce SHA pinning at org/repo level; workflows fail if not pinned. ([The GitHub Blog]2)
👉 Bottom line: SHA pinning trades automatic updates for control + security. That’s not optional anymore in serious pipelines.
2) The downside (and why you need automation)
Pinned SHAs do not move automatically, so:
- You will go stale if you don’t update them.
- You can miss bug fixes or security patches.
That’s why GitHub explicitly recommends pairing pinning with an updater (Dependabot or similar). ([Well-Architected]1)
3) Will Dependabot still open PRs with SHA pinning?
Yes — but with an important nuance:
✔ Yes, Dependabot still works with SHA-pinned actions
- It scans workflows, resolves tags → SHAs, and opens PRs updating the pinned commit. ([Adaptive Enforcement Lab]3)
- It can also include/update the version comment (
# v4.1.7) alongside the SHA. ([GitHub Docs]4)✔ It still detects new releases
- Version updates: PRs when a new version is released
- Security updates: PRs when a vulnerability is fixed ([GitHub Docs]5)
❗ But: semver semantics become less visible
You’re pinning a commit, not
v3/v4, so:
- Dependabot doesn “bump
v3 → v4” in the YAML.- It updates the underlying SHA to one corresponding to a newer release.
In practice:
- uses: actions/checkout@<old-sha> # v4.1.0→ Dependabot PR:
- uses: actions/checkout@<new-sha> # v4.2.0
4) Minor vs major bumps specifically
Yes, Dependabot will still open PRs for both minor and major updates, but:
- It’s not “bumping a version string” anymore
- It’s proposing a new SHA tied to a newer release (minor or major)
You can still control behavior:
- Ignore majors, allow only minor/patch via config (
update-types) ([GitHub Docs]6)- Group updates, schedule them, etc.
5) The correct mental model
Think of it this way:
Without pinning:
“Always run latest matching version” (unsafe, non-deterministic)With SHA pinning + Dependabot:
“Run a frozen version, and let a bot propose upgrades explicitly”That’s the winning combination.
Final verdict
- SHA pinning is non-negotiable for security-critical workflows
- Dependabot still works perfectly with it
- You don’t lose updates — you just review them instead of silently consuming them
If anything, SHA pinning + Dependabot is the best practice baseline today.
And then enabling an auto-merge workflow for minor version bumps, results basically in the same situation as pinning to a major version. Pinning to a major version, you don't have control over any of the minor version bumps, they are transparent. Pinning to a SHA and allowing auto-merge of minor version bumps, they're basically still transparent but with the added security that there is no poisoning, AND you can add the test build workflow that guarantees it won't break anything.
There was a problem hiding this comment.
There may be a way to configure dependabot to keep things up to date without too much regular interaction. I guess I'd be open to exploring that, but I still don't think we need it. If we do explore it, I'd prefer it in a separate, isolated PR.
I do want version tags for workflows, not SHAs. I understand the argument ChatGPT is making. The advice is reasonable, and in a different context SHAs might be the preferred approach. It's not my preferred approach here:
- We don't have any secrets to protect. This is a static site in an open source repo. We're not even running any servers.
- SHA pinning is only valuable to the extent that you trust the SHA. If dependabot is updating automatically, you're vulnerable to a supply chain attack again anyway, so by automatically updating SHAs (without any other kind of review or validation) you've lost the value of SHA pinning.
I have a more minimal PR here that gets the build working. It makes the minimal changes needed to fix the build - update actions/cache, and add a PR test workflow to validate the change. We can also update other things (ruby version, jekyll version, etc), but I'd prefer to do so in separate, smaller, isolated PRs.
There was a problem hiding this comment.
SHA pinning is only valuable to the extent that you trust the SHA.
That is true, but my understanding of dependabot is that it doesn't do any blind version bumps, but does some security checks to ensure that the bump is valid and not poisoned, considering it also takes care of opening PRs for security fixes on dependencies. I think some trust can be placed in Dependabot? Having that extra security check on the pinned SHA makes it nearly impossible to get a bad bump; whereas linking to major versions means neither we nor dependabot has any control over the version bumps.
In any case, not a big deal, one way or the other, as long as we get the build working again.
There was a problem hiding this comment.
#68 is merged, so the build should be working again!
There was a problem hiding this comment.
Yeah, main thing is getting the build working.
I mainly like not having 'noise' in the commits (e.g. keeping up with commits, Dependabot going a bit crazy there), especially for a project that's mostly in maintenance mode (at least architecturally).
And security through commit hashes instead of tags is a dubious argument, I'd seriously argue the point with ChatGPT, but then in the end it would probably tell me I'm right, because it just loves making me feel good about whatever I decide haha.
There was a problem hiding this comment.
I notice that when people ask AI an opinion on an issue, and they already have a bit of an opinion themselves, AI will often tend to let them hear what they want to hear. But if instead of asking for an opinion or an argument in favor of or against something, you ask simply to summarize the situation with the latest best practices based on documentation, it does a pretty good job at that.
The main reference document here is:
https://docs.github.com/en/actions/reference/security/secure-use#using-third-party-actions
But this really does matter more when you are dealing with third party actions. The actions curated by GitHub can generally be considered secure.
Closes #64.
Summary
The
Build & Deploy to GitHub Pagesworkflow has been failing at theSet up jobstep becauseactions/cache@v1runs on a Node runtime that GitHub has retired. This PR brings the workflow up to date, aligns the rest of the repo with the new Ruby version, and adds Dependabot so things stay current going forward.Changes
Workflow actions — pinned to full commit SHAs
Pinning SHAs (with a trailing
# vX.Y.Zcomment so the version is still visible) protects against a maintainer's tag being repointed at malicious code, and is the approach recommended by GitHub's own hardening guide. Each SHA was verified against the action's own repo before pinning.actions/checkout@v2→v6.0.2(de0fac2…)actions/cache@v1→v5.0.5(27d5ce7…)peaceiris/actions-gh-pages@v3→v4.0.0(4f9cc66…)Ruby bump — 3.2.2 → 3.4.9
Bumping the Ruby container required three coordinated changes so the repo stays internally consistent:
container:ingithub-pages.yml—ruby:3.2.2-bookworm→ruby:3.4.9-bookworm.ruby-version—3.2.2→3.4.9, so local tooling (rbenv, asdf, chruby) matches CIGemfile.lock— regenerated under Ruby 3.4.9. The old lockfile wasBUNDLED WITH 2.2.22, which is incompatible with Ruby 3.4'sDidYouMeanAPI; the new lockfile isBUNDLED WITH 2.6.9with gem versions resolved fresh. Smoke-tested locally withbundle exec jekyll buildin a realruby:3.4.9-bookwormcontainer — build succeeds.Cache key — include
.ruby-versionPreviously the cache key was
${{ runner.os }}-gems-${{ hashFiles('**/Gemfile.lock') }}. A Ruby ABI change (e.g. 3.2 → 3.4) with an unchanged Gemfile.lock would restore gems with native extensions compiled against the old Ruby — likely to crash at load. Expanded the key tohashFiles('**/Gemfile.lock', '.ruby-version')so future Ruby bumps invalidate the cache cleanly.Dependabot (
.github/dependabot.yml)Weekly update schedules for two ecosystems:
github-actions— so pinned SHAs get bumped automatically rather than silently going stalebundler— so Gemfile gems (Jekyll, Nokogiri, etc.) keep receiving updates, consistent with prior Dependabot PRs on this repoNote: Dependabot does not touch
.ruby-versionor thecontainer:key in workflows. Future Ruby bumps remain a manual action — done in a single PR that updates the workflow,.ruby-version, and regeneratesGemfile.locktogether, as this PR does.Test plan
Build & Deploy to GitHub Pagesaction succeeds onmaster🤖 Generated with Claude Code