Skip to content

Update GitHub Actions workflow and add Dependabot config#63

Closed
JohnRDOrazio wants to merge 2 commits intoopensourcecatholic:masterfrom
JohnRDOrazio:update-ci-workflow
Closed

Update GitHub Actions workflow and add Dependabot config#63
JohnRDOrazio wants to merge 2 commits intoopensourcecatholic:masterfrom
JohnRDOrazio:update-ci-workflow

Conversation

@JohnRDOrazio
Copy link
Copy Markdown
Contributor

@JohnRDOrazio JohnRDOrazio commented Apr 22, 2026

Closes #64.

Summary

The Build & Deploy to GitHub Pages workflow has been failing at the Set up job step because actions/cache@v1 runs 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.Z comment 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@v2v6.0.2 (de0fac2…)
  • actions/cache@v1v5.0.5 (27d5ce7…)
  • peaceiris/actions-gh-pages@v3v4.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: in github-pages.ymlruby:3.2.2-bookwormruby:3.4.9-bookworm
  • .ruby-version3.2.23.4.9, so local tooling (rbenv, asdf, chruby) matches CI
  • Gemfile.lock — regenerated 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 lockfile is BUNDLED WITH 2.6.9 with gem versions resolved fresh. Smoke-tested locally with bundle exec jekyll build in a real ruby:3.4.9-bookworm container — build succeeds.

Cache key — include .ruby-version

Previously 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 to hashFiles('**/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 stale
  • bundler — so Gemfile gems (Jekyll, Nokogiri, etc.) keep receiving updates, consistent with prior Dependabot PRs on this repo

Note: Dependabot does not touch .ruby-version or the container: key in workflows. Future Ruby bumps remain a manual action — done in a single PR that updates the workflow, .ruby-version, and regenerates Gemfile.lock together, as this PR does.

Test plan

  • Merge and confirm the Build & Deploy to GitHub Pages action succeeds on master
  • Confirm Dependabot opens its first PRs within a week (or trigger manually from Insights → Dependency graph → Dependabot)

🤖 Generated with Claude Code

JohnRDOrazio and others added 2 commits April 22, 2026 21:09
- 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>
@JohnRDOrazio
Copy link
Copy Markdown
Contributor Author

@mkasberg could you take a look at this too, seeing you have taken care of some of the maintenance here?

@JohnRDOrazio
Copy link
Copy Markdown
Contributor Author

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
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see dependabot maybe manages the deps though?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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).

Copy link
Copy Markdown
Contributor Author

@JohnRDOrazio JohnRDOrazio Apr 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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?"

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Comment thread .github/dependabot.yml
- package-ecosystem: github-actions
directory: /
schedule:
interval: weekly
Copy link
Copy Markdown
Collaborator

@mkasberg mkasberg Apr 24, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copy link
Copy Markdown
Contributor Author

@JohnRDOrazio JohnRDOrazio Apr 24, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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...

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copy link
Copy Markdown
Contributor Author

@JohnRDOrazio JohnRDOrazio Apr 24, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 @v3 is fundamentally about supply-chain security and determinism:

Security (the real reason)

  • Tags are mutable: an attacker (or compromised maintainer account) can retarget v3 to 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.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copy link
Copy Markdown
Contributor Author

@JohnRDOrazio JohnRDOrazio Apr 25, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

#68 is merged, so the build should be working again!

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copy link
Copy Markdown
Contributor Author

@JohnRDOrazio JohnRDOrazio Apr 25, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

CI workflow failing: actions/cache@v1 runs on a retired Node runtime

3 participants