2df78f33fb
* fix: provision Python test deps for bug-test workflow * test: anchor bug-test workflow domain assertions Address CodeQL py/incomplete-url-substring-sanitization alerts (14-17) by anchoring the PyPI domain assertions to their structural context: the `network.allowed` YAML list items in the source and the quoted JSON entries in the compiled lock. This defeats the incomplete-URL-substring pattern and strengthens the test to confirm the domains are real allowlist entries rather than incidental substrings. Assisted-by: GitHub Copilot (model: Claude Opus 4.8, supervised) Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 7b54442f-ccc5-4be1-a05c-b360889670e5 * fix: provision test deps without creating a project lock Replace `uv sync --extra test` with `uv pip install --system -e ".[test]"` in the bug-test provisioning step. `uv sync` writes a root `uv.lock` (and `.venv`) into the working tree. This repository intentionally has no `uv.lock`/`[tool.uv]` (uv.lock is gitignored), so the sync produced an untracked lockfile before the agent checks out the fix ref in Step 2. `uv pip install` installs the test extra into the runner's Python without generating a project lock, keeping the working tree clean before the fix checkout. The editable install means the agent's `python3 -m pytest` runs against the checked-out fix code. Recompiled the lock and updated the assertions accordingly. Assisted-by: GitHub Copilot (model: Claude Opus 4.8, supervised) Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 7b54442f-ccc5-4be1-a05c-b360889670e5 * chore(workflows): sync gh-aw action-pin metadata to latest across all workflows Dependabot bumps the third-party action `uses:` pins (and header comments) directly, but does not update gh-aw's own metadata: the per-file `gh-aw-manifest` JSON blob and the shared `.github/aw/actions-lock.json` pin cache. As a result the executing pins were already uniform and current (checkout v7.0.1, setup-node v7.0.0) while the manifest/cache metadata still recorded checkout v6.0.3 / setup-node v6.4.0. This is a latent downgrade hazard: a plain `gh aw compile` reads the stale cache and can silently revert the `uses:` lines back to the older pins, undoing Dependabot's bumps and breaking lockstep. Sync all four pin surfaces (uses / header comment / manifest / cache) to the current pins so every workflow agrees and a future recompile is a no-op: - actions-lock.json: checkout v6.0.3 -> v7.0.1, setup-node v6.4.0 -> v7.0.0, and add the setup-python v7.0.0 + setup-uv v9.0.0 entries now used by bug-test. - gh-aw-manifest blobs in the 5 non-bug-test lock files: checkout + setup-node bumped to match their own uses lines (bug-test was already current). No workflow body changes; only pin metadata. `uses:` pins are unchanged. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 7b54442f-ccc5-4be1-a05c-b360889670e5 Assisted-by: GitHub Copilot (model: Claude Opus 4.8, supervised) --------- Co-authored-by: root <kinsonnee@gmail.com> Co-authored-by: Manfred Riem <15701806+mnriem@users.noreply.github.com> Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 7b54442f-ccc5-4be1-a05c-b360889670e5
95 lines
3.4 KiB
Python
95 lines
3.4 KiB
Python
"""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"
|
|
)
|
|
|
|
|
|
def test_community_bundle_submission_automation_is_wired():
|
|
source = WORKFLOWS_DIR / "add-community-bundle.md"
|
|
compiled = WORKFLOWS_DIR / "add-community-bundle.lock.yml"
|
|
assignment = WORKFLOWS_DIR / "catalog-assign.yml"
|
|
|
|
assert source.is_file()
|
|
assert compiled.is_file()
|
|
source_text = source.read_text(encoding="utf-8")
|
|
assignment_text = assignment.read_text(encoding="utf-8")
|
|
|
|
assert "names: [bundle-submission]" in source_text
|
|
assert "bundles/catalog.community.json" in source_text
|
|
assert "docs/community/bundles.md" in source_text
|
|
assert "verified: false" in source_text
|
|
assert "allowed-files:" in source_text
|
|
assert "bundle-submission" in assignment_text
|
|
|
|
|
|
def test_bug_test_workflow_provisions_python_dependencies():
|
|
source = WORKFLOWS_DIR / "bug-test.md"
|
|
compiled = WORKFLOWS_DIR / "bug-test.lock.yml"
|
|
|
|
assert source.is_file()
|
|
assert compiled.is_file()
|
|
source_text = source.read_text(encoding="utf-8")
|
|
compiled_text = compiled.read_text(encoding="utf-8")
|
|
|
|
setup_uv = (
|
|
"astral-sh/setup-uv@c771a70e6277c0a99b617c7a806ffedaca235ff9 # v9.0.0"
|
|
)
|
|
setup_python = (
|
|
"actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0"
|
|
)
|
|
|
|
assert " - pypi.org" in source_text
|
|
assert " - files.pythonhosted.org" in source_text
|
|
assert setup_uv in source_text
|
|
assert setup_python in source_text
|
|
assert 'run: uv pip install --system -e ".[test]"' in source_text
|
|
|
|
assert '"pypi.org"' in compiled_text
|
|
assert '"files.pythonhosted.org"' in compiled_text
|
|
checkout_index = compiled_text.index("- name: Checkout repository")
|
|
uv_index = compiled_text.index("- name: Setup uv")
|
|
python_index = compiled_text.index("- name: Set up Python")
|
|
sync_index = compiled_text.index("- name: Install Python test dependencies")
|
|
agent_index = compiled_text.index("- name: Execute GitHub Copilot CLI")
|
|
assert checkout_index < uv_index < python_index < sync_index < agent_index
|
|
assert setup_uv in compiled_text
|
|
assert setup_python in compiled_text
|
|
assert 'run: uv pip install --system -e ".[test]"' in compiled_text
|