ci: pin actions to commit SHAs and add shellcheck (#3126)

* ci: pin actions to commit SHAs and add shellcheck

Pin actions/github-script in catalog-assign.yml to a full commit SHA; all
other workflows were already pinned. Add a repo-wide regression test that
every workflow `uses:` ref is pinned to a 40-char commit SHA.

Add a shellcheck job to lint.yml (--severity=error over scripts/bash/*.sh)
and document the local command in CONTRIBUTING.md.

* ci: use repo-standard actions/checkout v7.0.0 in shellcheck job

* ci: shellcheck all tracked shell scripts

Assisted-by: Codex (model: GPT-5, autonomous)

* ci: address workflow hygiene review feedback

Assisted-by: Codex (model: GPT-5, autonomous)
This commit is contained in:
Pascal THUET
2026-06-24 22:08:16 +02:00
committed by GitHub
parent b577e6c137
commit e5df517ddc
4 changed files with 64 additions and 1 deletions

View File

@@ -19,7 +19,7 @@ jobs:
permissions:
issues: write
steps:
- uses: actions/github-script@v9
- uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9
with:
script: |
const issue = context.payload.issue;

View File

@@ -42,3 +42,15 @@ jobs:
globs: |
'**/*.md'
!extensions/**/*.md
shellcheck:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
# shellcheck is preinstalled on ubuntu-latest runners.
# Start at --severity=error to block real bugs without flagging style
# (notably SC2155). Tighten in a follow-up after cleanup.
- name: Run shellcheck on shell scripts
run: git ls-files -z -- '*.sh' | xargs -0 shellcheck --severity=error

View File

@@ -113,6 +113,16 @@ uv pip install -e ".[test]"
> `specify_cli` to this checkout's `src/`. This matches the gotcha documented in
> `AGENTS.md` (Common Pitfalls).
#### Shell scripts
```bash
git ls-files -z -- '*.sh' | xargs -0 shellcheck --severity=error
```
The CI `lint.yml` `shellcheck` job currently reports and blocks only
error-severity findings. Warnings such as SC2155 are intentionally outside this
job until a follow-up cleanup tightens the threshold.
### Manual testing
#### Testing setup

View File

@@ -0,0 +1,41 @@
"""Static checks for repository GitHub Actions workflows."""
from __future__ import annotations
import re
from pathlib import Path
REPO_ROOT = Path(__file__).resolve().parent.parent
WORKFLOWS_DIR = REPO_ROOT / ".github" / "workflows"
# Match both the dedicated-step form (` uses: x@sha`) and the
# inline shorthand (` - uses: x@sha`) used in catalog-assign.yml.
USES_RE = re.compile(r"^\s*(?:-\s*)?uses:\s*(?P<ref>\S+)", re.MULTILINE)
PINNED_SHA_RE = re.compile(r"@[0-9a-f]{40}$", re.IGNORECASE)
def test_github_actions_are_pinned_to_full_commit_shas():
unpinned_refs = []
workflows = sorted(
list(WORKFLOWS_DIR.glob("*.yml")) + list(WORKFLOWS_DIR.glob("*.yaml"))
)
assert workflows
for workflow in workflows:
workflow_text = workflow.read_text(encoding="utf-8")
for match in USES_RE.finditer(workflow_text):
uses_ref = match.group("ref")
if uses_ref.startswith(("./", "../")):
continue
if PINNED_SHA_RE.search(uses_ref):
continue
unpinned_refs.append(f"{workflow.relative_to(REPO_ROOT)}: {uses_ref}")
assert unpinned_refs == []
def test_pinned_action_ref_accepts_uppercase_hex_sha():
assert PINNED_SHA_RE.search(
"actions/example@0123456789ABCDEF0123456789ABCDEF01234567"
)