Nokogiri CI Pins Keep Dependabot and Zizmor Aligned
Nokogiri is a Ruby HTML and XML parser with native extension build paths, so its CI is part of the product surface. This recent activity was not about a parser API; it was about updating pinned GitHub Actions while keeping Dependabot comment parsing compatible, with actions/cache, actionlint, and zizmor at the center.
Pinned actions stay current
Only two commits landed in the window, with 7 files changed and a near even diffstat of 36 insertions and 37 deletions. That is a clue. This was maintenance work, but maintenance on the path that tells users whether a native gem still builds across Ruby versions, platforms, and downstream projects. The GitHub Actions group bump moved actions/cache from v4.3.0 to v6.1.0 across the main CI jobs.
It also moved actionlint from v1.7.11 to v1.7.12 and zizmor-action from v0.5.2 to v0.5.7. These are not runtime gem dependencies. They decide whether CI can tell maintainers the truth.
That matters more in Nokogiri than in a small pure Ruby library. The project compiles native code, pulls libxml2 and libxslt through several build paths, and keeps a broad matrix alive. A stale cache action can make failures look like build problems. A stale workflow scanner can make security exceptions drift until review becomes archaeology.
The touched workflow files are the ones you would expect:
ci.ymlcarries the main Ruby and platform matrixdownstream.ymlchecks projects that consume Nokogiriupstream.ymlkeeps source library paths under test
The main thing for contributors is boring but useful. The project still pins actions by SHA, and the version comment beside the pin remains a human hint. That is a decent balance. The runner fetches an exact object, while reviewers still see which release the object represents.
Dependabot needs comments in the right place
The more interesting commit is the comment order fix for Dependabot. Dependabot only updates the version comment when that comment is the last thing on a uses: line. Nokogiri had lines where the version comment came before a zizmor suppression, so the hash could move while the readable version stayed stale.
That is not a dramatic bug. It is worse in the usual way: small, silent, and easy to forget. The maintainers changed 17 uses: lines so the zizmor directive comes before the version comment. The scanner still sees the ignore reason, and Dependabot gets the format it expects.
- uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0 # zizmor: ignore[cache-poisoning] -- reason
+ uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # zizmor: ignore[cache-poisoning] -- reason # v4.3.0
The practical rule is simple: if you edit a SHA pinned action line in Nokogiri, leave the # vX.Y.Z style marker last. Put zizmor suppressions before it, with the reason still attached. It looks fussy until the next automated update works without a human fixing stale comments by hand.
Downstream CI stays on the same path
The action bump also touches downstream.yml, which is worth reading if you maintain a gem that sits near Nokogiri. That workflow clones and tests consumers such as loofah, rails-html-sanitizer, sanitize, ruby-saml, and mechanize against the local Nokogiri checkout.
One small line disappeared there: an explicit gem install bundler -v ">= 2.3.22" before bundle install. The rest of the job still removes Bundler from downstream gemspecs when needed, adds the local Nokogiri checkout with bundle add nokogiri --path=".." --skip-install, installs dependencies, and runs each downstream suite.
There is no claim in the commit that this changes supported Ruby behavior, so treat it as CI cleanup tied to the action update. The useful signal is that downstream testing remains part of the same maintenance sweep. When the project adjusts cache tooling, it checks the path where a Nokogiri change would break real consumers, not only its own unit tests.
Generated workflow text is kept in sync
The same Dependabot compatibility fix updates rakelib/docker.rake. That file contains the template used by the docker:pipeline task for generated CI image workflow content.
This is the part that often gets missed in repos with generated workflow files. Editing the checked in workflow is not enough if a generator can recreate the old text later. Nokogiri moved the comment order in the template too, so the next regeneration should keep the Dependabot friendly layout.
For contributors, the lesson is to search both workflow files and generators when changing CI line formats. A one line scanner suppression can have a second copy in a Rake task, a script, or a template. Missing it makes the next generated diff look like someone reversed your cleanup. Nobody needs that kind of entertainment from CI.
How to prepare
Application users do not need to change Nokogiri code for this activity. This was CI infrastructure work. Still, it is useful if you contribute patches or maintain a fork with similar workflow hardening.
- Keep
# vX.Y.Zas the final comment on SHA pinneduses:lines - Keep
zizmorsuppressions specific, especially for cache poisoning and unpinned image exceptions - If a downstream job fails after cache changes, check
portsandports/archivescache keys before chasing parser behavior
The bigger point is not the exact actions/cache version. It is that Nokogiri is keeping automated updates, workflow linting, and security scanning able to coexist. That is unglamorous repo work, but for a native gem with many consumers, boring CI is a feature.