Skip to content

ci: lint workflows with actionlint and zizmor, and let Dependabot update npm - #12

Merged
Mearman merged 3 commits into
mainfrom
ci-linters
Oct 3, 2026
Merged

Mearman merged 3 commits into
mainfrom
ci-linters

Conversation

@Mearman

@Mearman Mearman commented Oct 3, 2026

Copy link
Copy Markdown
Member

Adds Actionlint and Zizmor jobs to CI, copied from monorepo-template: actionlint 1.7.12 and shellcheck 0.11.0 downloaded at pinned versions and checked against SHA-256 digests per runner architecture, and zizmor 1.30.1 through uvx, offline. Both run on the runner determine-runner selects and are joined into Required Checks, so the required check name is unchanged. .github/actionlint.yaml lists exadev-runners and the Blacksmith label determine-runner runs on and falls back to; .github/zizmor.yml requires a commit SHA for every action outside ExaDev (ExaDev/* may use a tag) and disables self-repository, whose $/ syntax actionlint still rejects (rhysd/actionlint#711).

Findings on the existing workflow, before this change:

  • zizmor artipacked on the commitlint, lint, typecheck, mutation and package checkouts: fixed with persist-credentials: false. None of them pushes; the release job's checkout already had it and is untouched.
  • zizmor template-injection on echo '${{ toJSON(needs) }}' in Required Checks: the JSON now arrives through env.
  • zizmor adhoc-packages on the release job's npm install -g npm@11.20.0 and on the package job's npm install of the packed tarball with cosmiconfig@<major>: ignored inline on each line. The first is an exact, deliberately chosen pin and the release job's behaviour is unchanged; the second is the lockfile-free consumer install the job exists to test. zizmor only reads an ignore comment as a YAML comment, not inside a multi-line run: script, so that install moves into a step of its own with the same command and working directory.
  • actionlint: nothing.

With the configs from this branch, both commands as CI runs them fail on a deliberately bad workflow in a scratch repository (tag-pinned actions/checkout@v4, unknown runner label, ${{ github.event.pull_request.title }} in run:, an unquoted variable): actionlint exits 1 (runner-label, expression, shellcheck SC2086) and zizmor exits 14 (unpinned-uses, template-injection, artipacked, excessive-permissions).

Dependabot also gets an npm entry with the same weekly schedule, grouped minor and patch updates and the same cooldown: default-days: 7 as the github-actions entry, matching the seven-day minimum release age local installs use. The cooldown keys are checked against GitHub's Dependabot options reference (https://docs.github.com/en/code-security/reference/supply-chain-security/dependabot-options-reference, archived at https://web.archive.org/web/20261001095248/https://docs.github.com/en/code-security/reference/supply-chain-security/dependabot-options-reference): default-days and exclude are supported for npm, and cooldown never delays security updates.

Jobs that never push no longer leave the job token in .git/config,
where any later step or uploaded artefact could read it.
The release job's checkout already opted out and is unchanged.

The Required Checks job printed toJSON(needs) inside a single-quoted echo,
so a quote in any job output would end the string and run as shell.
It now reaches the script through env.
Nothing stopped a tag-pinned third-party action, an unknown runner label
or a script injection from coming back into the workflows.
Actionlint (with shellcheck) and zizmor now run as their own jobs on the
runner determine-runner selects, and Required Checks waits on both.

Both tools are pinned: actionlint and shellcheck by version and SHA-256
per runner architecture, zizmor through uvx at an exact version, offline.
.github/actionlint.yaml lists the fleet and Blacksmith runner labels.
.github/zizmor.yml requires a commit SHA for every action outside ExaDev
and disables self-repository, whose `$/` syntax actionlint rejects.

adhoc-packages is ignored inline on the release job's pinned npm upgrade and on the
package job's tarball install, which moves to a step of its own because zizmor
reads ignore comments only as YAML comments, not inside a multi-line script.
The npm entry mirrors the github-actions one: weekly, minor and patch
updates grouped, and a seven-day cooldown matching the minimum release age
local installs enforce.
@Mearman
Mearman marked this pull request as ready for review October 3, 2026 13:09
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 3, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
🔒 Security Review ✅ Completed 2026-10-03T13:15:00.716092Z afeeb7c Draft marked ready
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@Mearman
Mearman merged commit 851040b into main Oct 3, 2026
26 of 28 checks passed
@Mearman
Mearman deleted the ci-linters branch October 3, 2026 13:15
@github-actions

github-actions Bot commented Oct 3, 2026

Copy link
Copy Markdown

🎉 This PR is included in version 1.1.5 🎉

The release is available on:

Your semantic-release bot 📦🚀

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

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant