mirror of
https://github.com/github/spec-kit.git
synced 2026-07-03 12:28:06 +08:00
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:
41
tests/test_github_workflows.py
Normal file
41
tests/test_github_workflows.py
Normal 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"
|
||||
)
|
||||
Reference in New Issue
Block a user