fix(ci): harden GitHub Actions workflows (#1221) - #1228
Conversation
|
The docs for this PR live here. All of your documentation changes will be reflected on that endpoint. The docs are available until 30 days after the last update. |
There was a problem hiding this comment.
Alignment Review Report
Scope: mechanical supply-chain hardening — pins GitHub Actions to full commit SHAs (with version comments) in .github/workflows/publish-pypi.yml and .github/workflows/publish-testpypi.yml. No Python or runtime code is touched.
Automated Checks
- Lint: FAIL (hook exit 1) — not attributable to this PR. In this fresh environment the hook builds a new
.venvand resolvesruff 0.16.8(repo pinsruff>=0.14.0), which then reports 56 pre-existing Python files undersrc/,tests/, andenvs/as "would reformat".ruff/usortdo not process YAML, and this PR changes only workflow.ymlfiles, so it introduces zero lint findings. - Debug code: CLEAN for this PR.
check-debug.shflags only pre-existingprint/TODOitems insrc/(CLI, harbor, docstring examples); none are in the two changed workflow files.
Open RFCs Context
All RFCs are Draft or In Review (000, 001, 002, 003, 004, 005, 008, 010, 011, 012), but every one concerns environment/runtime design (abstractions, env-spec, MCP, rubrics, agentic harnesses, auto-validation, echo-env, catalog discovery, harbor capture). None govern CI/CD or GitHub Actions, so none are relevant to this change.
Tier 1: Fixes Required
None. I independently verified every pin against authoritative GitHub tag data (git/ref/tags, dereferencing annotated tags to commits):
| Action | Pinned SHA | Comment | Result |
|---|---|---|---|
actions/checkout |
3d3c42e…90b1 |
v7.0.1 | MATCH |
actions/setup-python |
5fda3b9…4b97 |
v7.0.0 | MATCH |
actions/upload-artifact |
043fb46…6a0a |
v7.0.1 | MATCH |
actions/download-artifact |
3e5f45b…1e7c |
v8.0.1 | MATCH |
The floating major tags that were replaced (checkout@v7, setup-python@v7, download-artifact@v8) currently resolve to exactly these SHAs, so the pins are behavior-preserving; version comments are accurate. This is consistent with the "No credential exposure" security invariant and the existing persist-credentials: false on checkout. No syntax errors, no secrets, no debug code introduced.
Tier 2: Alignment Discussion
Principle Conflicts
None identified. The change is CI-only and engages none of the runtime principles/invariants (Gymnasium API, client-server separation, rewards-in-environment, MCP/WebSocket dual boundary, container isolation).
RFC Conflicts
None identified.
Informational (non-blocking follow-ups)
pypa/gh-action-pypi-publish@release/v1remains a moving branch ref in both publish workflows — the most trust-sensitive step, since it performs the actual PyPI publish. The PR description already acknowledges this is tracked separately and intentionally left for a human decision. Noted, not a blocker.- Several other workflows still use floating action tags (e.g.
docker-build.yml,openspiel_base_build.yml,test.yml,package-ci.yml,deploy-hf-env.yml,manage-hf-collection.yml), including third-partydocker/*andastral-sh/setup-uv. These are out of scope for this PR (which targets only the two flagged files); a follow-up could extend the samepinactpinning repo-wide.
Summary
- 0 mechanical issues to fix (Tier 1)
- 0 alignment points for human review (Tier 2)
- 0 RFC conflicts to discuss
Verdict: correct, verified, behavior-preserving CI hardening. The only items are two acknowledged, out-of-scope follow-ups noted above.
Sent by Cursor Automation: Pre-review
There was a problem hiding this comment.
Content review at d21c2734. This supersedes #1224, which GitHub auto-closed when I merged its base #1221. Same branch, same tree, but now correctly based on main, so it will actually run Tests, Package CI, and lint — none of which could run while the base was a Dependabot branch.
Pins verified against upstream
| Action | Pinned SHA | Resolves to |
|---|---|---|
actions/checkout |
3d3c42e5aac5ba805825da76410c181273ba90b1 |
v7.0.1 |
actions/setup-python |
5fda3b95a4ea91299a34e894583c3862153e4b97 |
v7.0.0 |
actions/upload-artifact |
043fb46d1a93c77aae656e7c1c64a875d1fc6a0a |
v7.0.1 |
actions/download-artifact |
3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c |
v8.0.1 |
I resolved each tag through the GitHub API; all four match. The diff is confined to publish-pypi.yml and publish-testpypi.yml and is purely mechanical tag-to-SHA replacement across ten uses: lines. No job, trigger, permission, environment, or secret binding changes, and the v7.0.1 upload-artifact pin from #1221 is preserved.
Needs a decision I should not make
Both pypa/gh-action-pypi-publish@release/v1 invocations remain on a mutable branch ref. Those are the two jobs holding id-token: write against the PyPI and TestPyPI Trusted Publishers, so they are the most security-sensitive refs in the repository and the two findings the bot still reports as HIGH. Pinning them is a release-credential boundary decision and needs the release owner, against a specific reviewed commit rather than the moving branch. I have requested @burtenshaw as reviewer for that reason.
Recommended timing: merge after Thursday's v0.6.0 publish, not before.
The 0.6.0 candidate has already been validated end to end through publish-testpypi.yml as it stands on main today, including a real TestPyPI upload with upload-artifact@v7.0.1. Landing this now would change the publish path after that validation and leave no cycle to re-exercise it before the release. Merging immediately afterwards gives these pins a full TestPyPI run before they matter, and there is no urgency in the gap: every ref this PR replaces is an official major-version tag, not a third-party one.
The branch is currently BEHIND main; it needs a refresh and terminal green CI before it is mergeable either way.
Sent by Cursor Automation: Release
OpenEnv 0.6.0 Breaking change - `--llm-endpoint` / OpenAIClient now take a full base URL; the implicit port 8000 is gone. `http://localhost` means port 80; use `http://localhost:8000` or `--llm-port 8000` for the old behavior (#1189, landed via #1237). New - NovitaSandboxProvider: run an OpenEnv server in a Novita AI sandbox over wss://, from a registry image or a local Dockerfile; install with `pip install openenv[novita]` (#1191). - RFC 008 Level 2 validation building blocks: manifest-v2, report-v2 and runtime-plan schemas, the severity-v2 policy, and DockerValidationProvider (#1178, #1179). The `openenv validate` CLI is unchanged in this release. Fixes - A failed `new_session()` no longer leaves the provider's container or sandbox running (#1145). Repository and environment images (not in the wheel) - coding_env `additional_imports` now extends the default safe-import allowlist (#1147). - Environment lockfile security updates: anyio 4.14.2 and soupsieve 2.9.2 (#1196, #1197, #1201, #1202). - CI hardening: per-job GITHUB_TOKEN scopes and SHA-pinned actions (#1221, #1223, #1225, #1226, #1228, #1239, #1240); validation-lab toolchain pins (#1229, #1230, #1231); docs navigation and Miles integration docs (#1219, #1220). Known, accepted for this release: Novita provider debt (unbraced $ARG ordering in Dockerfile flattening, a tbench2 example readiness leak); fixes follow in #1235. Validated: exact-head CI 13/13 on 0034202; TestPyPI 0.6.0.dev141 (run 35854754769) byte-identical to the release wheel apart from Version; clean wheel/sdist install, CLI, and Echo reset/step smoke.


Automated hardening of the workflow files flagged on #1221.
Targets
main. Files changed, and what changed them:.github/workflows/publish-pypi.yml— action pins.github/workflows/publish-testpypi.yml— action pinsFixed by this PR:
unpinned-action(pinact) — .github/workflows/publish-pypi.yml:31unpinned-action(pinact) — .github/workflows/publish-pypi.yml:69unpinned-action(pinact) — .github/workflows/publish-pypi.yml:101unpinned-action(pinact) — .github/workflows/publish-pypi.yml:120unpinned-action(pinact) — .github/workflows/publish-pypi.yml:139unpinned-action(pinact) — .github/workflows/publish-pypi.yml:172unpinned-action(pinact) — .github/workflows/publish-testpypi.yml:34unpinned-action(pinact) — .github/workflows/publish-testpypi.yml:39unpinned-action(pinact) — .github/workflows/publish-testpypi.yml:116unpinned-action(pinact) — .github/workflows/publish-testpypi.yml:135This does not fix everything. 2 further finding(s) (2 high) need a decision this bot should not make for you. They are in the security channel with their locations — deliberately not repeated here, since this repository may be public and they are not fixed yet.
Pinning changes come from
pinactand are mechanical. Any other change was generated by Claude — read it before merging.Note
Low Risk
Mechanical action pinning only; publish behavior is unchanged, though some release workflow actions may still be unpinned outside this diff.
Overview
Pins third-party GitHub Actions in the PyPI and TestPyPI release workflows to immutable commit SHAs (with version comments), replacing floating refs like
@v7and@v8.Affected steps include checkout, setup-python, upload-artifact, and download-artifact in
publish-pypi.yml(build, publish, GitHub release, and post-release bump jobs) and the matching build/publish jobs inpublish-testpypi.yml. Workflow logic and release steps are unchanged; this is supply-chain hardening from pinact.Note:
pypa/gh-action-pypi-publish@release/v1is still tag-based in both workflows (called out separately in #1221 as not addressed here).Reviewed by Cursor Bugbot for commit d21c273. Bugbot is set up for automated code reviews on this repo. Configure here.