ci: offload lightweight workflows from hetzner lane#2547
Conversation
|
Note
|
| Cohort / File(s) | Summary |
|---|---|
Workflow Runner Standardization .github/workflows/ci-queue-hygiene.yml, .github/workflows/pr-auto-response.yml, .github/workflows/pr-check-stale.yml, .github/workflows/pr-check-status.yml, .github/workflows/pr-intake-checks.yml, .github/workflows/pr-label-policy-check.yml, .github/workflows/pr-labeler.yml, .github/workflows/sync-contributors.yml, .github/workflows/workflow-sanity.yml |
Unified runs-on specifications across all jobs to [self-hosted, Linux, X64, aws-india] by removing blacksmith-2vcpu-ubuntu-2404 and hetzner runner labels. No workflow logic or steps altered. |
Estimated code review effort
🎯 2 (Simple) | ⏱️ ~10 minutes
Possibly related PRs
- ci: remove blacksmith deps and restore self-hosted cache stack #2118: Modifies the same GitHub Actions workflow runner labels and removes Blacksmith runner references across multiple workflows.
- CI: move maintenance workflows to hosted runners #2201: Modifies the same CI workflow jobs (pr-check-stale, pr-check-status, sync-contributors) but makes opposite configuration changes.
- fix(ci): reduce Actions queue saturation on self-hosted lanes #2330: Modifies the same
.github/workflows/ci-queue-hygiene.ymlfile with related runner configuration updates.
Suggested labels
type: ci
Suggested reviewers
- theonlyhennygod
🚥 Pre-merge checks | ✅ 2 | ❌ 1
❌ Failed checks (1 warning)
| Check name | Status | Explanation | Resolution |
|---|---|---|---|
| Description check | The PR description is largely incomplete relative to the template. Critical sections are missing: Label Snapshot, Change Metadata, Linked Issue, Supersede Attribution, Validation Evidence, Security Impact, Privacy/Data Hygiene, Compatibility, i18n, Human Verification, Side Effects, Agent Collaboration, Rollback Plan, and Risks/Mitigations. | Complete all required sections per the description template: add risk/size/scope labels, change type/primary scope, linked issues, security/privacy assessments, validation commands, human verification details, and rollback plan. |
✅ Passed checks (2 passed)
| Check name | Status | Explanation |
|---|---|---|
| Title check | ✅ Passed | The title 'ci: offload lightweight workflows from hetzner lane' directly and clearly summarizes the main change: redirecting lightweight workflows away from Hetzner runners to reduce contention. |
| Docstring Coverage | ✅ Passed | No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check. |
✏️ Tip: You can configure your own custom pre-merge checks in the settings.
✨ Finishing Touches
🧪 Generate unit tests (beta)
- Create PR with unit tests
- Post copyable unit tests in a comment
- Commit unit tests in branch
ci/hetzner-selfhost
Comment @coderabbitai help to get the list of available commands and usage tips.
PR intake checks found warnings (non-blocking)Fast safe checks found advisory issues. CI lint/test/build gates still enforce merge quality.
Action items:
Detected Linear keys: none Run logs: https://github.com/zeroclaw-labs/zeroclaw/actions/runs/22576677189 Detected blocking line issues (sample):
Detected advisory line issues (sample):
Workflow files changed in this PR:
|
There was a problem hiding this comment.
Actionable comments posted: 9
🧹 Nitpick comments (2)
.github/workflows/sec-vorpal-reviewdog.yml (1)
94-94: Add a rollback note for this security-workflow runner cutover.Please include a brief fallback plan (e.g., revert to prior runner labels) in PR/workflow notes in case queueing or compatibility regresses.
Based on learnings "Applies to .github/workflows/** : For workflow changes, include threat/risk notes and rollback strategy; update
docs/actions-source-policy.mdwhen GitHub Actions sources change".🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In @.github/workflows/sec-vorpal-reviewdog.yml at line 94, Add a brief rollback/fallback plan to the PR and the workflow metadata explaining how to revert the runner cutover: mention reverting the runs-on labels array (the line with runs-on: [self-hosted, Linux, X64, aws-india, blacksmith-2vcpu-ubuntu-2404, hetzner]) back to the prior labels, expected validation steps, and a short timeline for monitoring; also update docs/actions-source-policy.md to record the change and the rollback procedure so reviewers have the threat/risk notes and a clear reversion path..github/workflows/sync-contributors.yml (1)
20-20: Add explicit Actions allowlist-impact note in PR notes.Line 20 is a workflow routing change; please add a short PR note confirming whether Actions sources changed (and if not, state “no allowlist/docs impact” explicitly) to keep workflow-governance auditability clear.
As per coding guidelines: “For.github/workflows/**changes, include Actions allowlist impact in PR notes and updatedocs/actions-source-policy.mdwhen sources change.”🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In @.github/workflows/sync-contributors.yml at line 20, The PR changed the workflow routing in .github/workflows/sync-contributors.yml by modifying the runs-on specification (the runs-on key), but the PR notes lack the required Actions allowlist impact statement; update the PR description to explicitly state whether the Actions sources changed—if they did, add the exact source changes and update docs/actions-source-policy.md accordingly, otherwise add the sentence “no allowlist/docs impact” to the PR notes to satisfy workflow-governance auditability.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In @.github/workflows/ci-change-audit.yml:
- Around line 61-66: The "Setup Python" workflow step currently only prints
python3 --version and doesn't enforce a minimum version; add an explicit guard
in that step to verify python3 is >= 3.9 and exit with a clear error if not
(e.g., run a shell check using python3 -c "import sys; assert sys.version_info
>= (3,9), ..." or print an error and exit non-zero). Keep the existing set -euo
pipefail and ensure the check runs before any audit scripts so older Python
versions fail early with a descriptive message.
In @.github/workflows/ci-run.yml:
- Line 27: The workflow uses the same runner labels for both lightweight and
heavy jobs; update the jobs named changes, docs-only, non-rust, docs-quality,
lint-feedback, license-file-owner-guard, and ci-required in
.github/workflows/ci-run.yml to use a distinct lightweight runner pool label
(e.g., replace the current runs-on array [self-hosted, Linux, X64, aws-india,
blacksmith-2vcpu-ubuntu-2404, hetzner] with a dedicated lightweight label such
as [self-hosted, Linux, X64, aws-india, blacksmith-light-1vcpu] or a shared tag
like [self-hosted, lightweight]) so short jobs don’t contend with heavy
workloads; additionally ensure workflow linting is actually executed on PRs by
adding or enabling an actionlint job that runs the repository’s actionlint.yaml
(or invoking actionlint as a step in the CI workflow) and make it a required
check so you can provide verification that actionlint ran for this PR.
In @.github/workflows/pages-deploy.yml:
- Line 25: Remove the "hetzner" runner label from the runs-on arrays for the
build and deploy jobs in pages-deploy.yml so the workflows no longer require
Hetzner-constrained runners; locate the runs-on arrays used by the "build" job
(currently containing [self-hosted, Linux, X64, aws-india,
blacksmith-2vcpu-ubuntu-2404, hetzner]) and the "deploy" job and delete the
"hetzner" entry from each array, keeping the remaining labels intact.
In @.github/workflows/pr-auto-response.yml:
- Line 30: The workflow's risk assessment is inaccurate and missing required PR
docs: confirm that the job named labeled-routes (which currently runs on
pull_request_target with runs-on: [self-hosted, Linux, X64, aws-india]) is
either moved to GitHub-hosted runners or reconfigured to use a strictly isolated
ephemeral self-hosted pool to eliminate external-PR execution risk; update the
review text to clarify that contributor-tier-issues is gated by
github.event_name == 'issues' (so it isn't exposed to external PRs); and add the
required PR documentation fields from .github/pull_request_template.md—Security
Impact (list new permissions like issues: write, pull-requests: write on
external events), Side Effects / Blast Radius (affected subsystems and
guardrails), and a concrete Rollback Plan (fast rollback command/path); finally,
check docs/actions-source-policy.md and update it if any new Actions were
introduced.
In @.github/workflows/pr-check-stale.yml:
- Line 20: The PR must include a short governance note explaining Actions
allowlist impact and rollback/threat considerations for the workflow change that
modifies the runner selection (the runs-on array such as "runs-on: [self-hosted,
Linux, X64, aws-india]"); add a sentence stating whether this is "no source
changes" for the allowlist, and a concise threat/risk + rollback strategy (how
to revert the workflow or disable the runner if issues occur). Also update
docs/actions-source-policy.md if GitHub Actions sources or runner origins
change, and confirm any added observability logs are non-sensitive before
including them in the PR description.
In @.github/workflows/pub-release.yml:
- Around line 171-174: The workflow comment claims GNU Linux artifacts are kept
on Ubuntu 22.04 for a GLIBC baseline, but the matrix runner uses the label
"blacksmith-2vcpu-ubuntu-2404" which actually sets the baseline to Ubuntu 24.04
(glibc 2.39+); fix by either updating the comment to state Ubuntu 24.04 as the
baseline or change the runner label to the Ubuntu 22.04 equivalent (e.g.,
replace "blacksmith-2vcpu-ubuntu-2404" with the 22.04 runner label) so the
comment and the "blacksmith-2vcpu-ubuntu-2404" entry are consistent.
In @.github/workflows/sec-audit.yml:
- Around line 519-524: The "Setup Python 3.11" step currently only runs `python3
--version` and doesn't enforce the Python >=3.11 requirement, so add an explicit
runtime version check in that step (before running
scripts/ci/unsafe_policy_guard.py) that invokes python3 to verify
sys.version_info >= (3,11) and exits non-zero with a clear message if the check
fails; update the step containing `python3 --version` (the "Setup Python 3.11"
step) to perform this check so the workflow fails fast when Python is too old.
In @.github/workflows/test-e2e.yml:
- Line 33: The runs-on label array currently requires a runner that matches all
labels (runs-on: [self-hosted, Linux, X64, aws-india,
blacksmith-2vcpu-ubuntu-2404, hetzner]), which is overly restrictive; update the
workflow to avoid conjunctive provider labels by either splitting into separate
jobs (one job per provider label like aws-india, blacksmith-2vcpu-ubuntu-2404,
hetzner), using a job matrix/strategy to iterate provider labels, or
implementing conditional routing that selects the proper runs-on per-provider,
and ensure changes reference the runs-on array and the provider label tokens
('aws-india', 'blacksmith-2vcpu-ubuntu-2404', 'hetzner') so jobs are
schedulable.
In @.github/workflows/test-self-hosted.yml:
- Around line 13-14: The workflow name "Runner Health / self-hosted aws-india"
is out of sync with the runs-on labels; update the YAML `name:` value to reflect
the broader `runs-on:` set (e.g., include aws-india,
blacksmith-2vcpu-ubuntu-2404, hetzner or use "multi-region/multi-label") so the
`name:` consistently describes the targeted runner lane; change the `name:`
string where it appears above the `runs-on:` entry in this workflow.
---
Nitpick comments:
In @.github/workflows/sec-vorpal-reviewdog.yml:
- Line 94: Add a brief rollback/fallback plan to the PR and the workflow
metadata explaining how to revert the runner cutover: mention reverting the
runs-on labels array (the line with runs-on: [self-hosted, Linux, X64,
aws-india, blacksmith-2vcpu-ubuntu-2404, hetzner]) back to the prior labels,
expected validation steps, and a short timeline for monitoring; also update
docs/actions-source-policy.md to record the change and the rollback procedure so
reviewers have the threat/risk notes and a clear reversion path.
In @.github/workflows/sync-contributors.yml:
- Line 20: The PR changed the workflow routing in
.github/workflows/sync-contributors.yml by modifying the runs-on specification
(the runs-on key), but the PR notes lack the required Actions allowlist impact
statement; update the PR description to explicitly state whether the Actions
sources changed—if they did, add the exact source changes and update
docs/actions-source-policy.md accordingly, otherwise add the sentence “no
allowlist/docs impact” to the PR notes to satisfy workflow-governance
auditability.
ℹ️ Review info
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (33)
.github/actionlint.yaml.github/workflows/ci-canary-gate.yml.github/workflows/ci-change-audit.yml.github/workflows/ci-provider-connectivity.yml.github/workflows/ci-queue-hygiene.yml.github/workflows/ci-reproducible-build.yml.github/workflows/ci-rollback.yml.github/workflows/ci-run.yml.github/workflows/ci-supply-chain-provenance.yml.github/workflows/deploy-web.yml.github/workflows/docs-deploy.yml.github/workflows/feature-matrix.yml.github/workflows/nightly-all-features.yml.github/workflows/pages-deploy.yml.github/workflows/pr-auto-response.yml.github/workflows/pr-check-stale.yml.github/workflows/pr-check-status.yml.github/workflows/pr-intake-checks.yml.github/workflows/pr-label-policy-check.yml.github/workflows/pr-labeler.yml.github/workflows/pub-docker-img.yml.github/workflows/pub-prerelease.yml.github/workflows/pub-release.yml.github/workflows/sec-audit.yml.github/workflows/sec-codeql.yml.github/workflows/sec-vorpal-reviewdog.yml.github/workflows/sync-contributors.yml.github/workflows/test-benchmarks.yml.github/workflows/test-e2e.yml.github/workflows/test-fuzz.yml.github/workflows/test-self-hosted.yml.github/workflows/workflow-sanity.ymlDockerfile
| - name: Setup Python | ||
| uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5 | ||
| with: | ||
| python-version: "3.12" | ||
| shell: bash | ||
| run: | | ||
| set -euo pipefail | ||
| python3 --version | ||
|
|
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
# First, let's read the complete workflow file to understand the full context
cat -n .github/workflows/ci-change-audit.ymlRepository: zeroclaw-labs/zeroclaw
Length of output: 7138
🏁 Script executed:
# Check if docs/actions-source-policy.md exists
ls -la docs/actions-source-policy.md 2>&1 || echo "File not found"Repository: zeroclaw-labs/zeroclaw
Length of output: 144
🏁 Script executed:
# Search for Python version requirements in the repository
rg "python" -i -B2 -A2 --type-list | head -20
rg "python.*3\.\d+" -i --type yaml --type bash --type shRepository: zeroclaw-labs/zeroclaw
Length of output: 484
🏁 Script executed:
# Check git history to see what the previous version looked like
git diff HEAD -- .github/workflows/ci-change-audit.yml | head -100Repository: zeroclaw-labs/zeroclaw
Length of output: 48
🏁 Script executed:
# Check Python version requirements in the audit scripts
head -30 scripts/ci/ci_change_audit.pyRepository: zeroclaw-labs/zeroclaw
Length of output: 935
🏁 Script executed:
# Check other Python scripts referenced
head -20 scripts/ci/tests/test_*.py 2>/dev/null | head -40
head -20 scripts/ci/emit_audit_event.py 2>/dev/nullRepository: zeroclaw-labs/zeroclaw
Length of output: 1581
🏁 Script executed:
# Read the actions source policy file
cat docs/actions-source-policy.mdRepository: zeroclaw-labs/zeroclaw
Length of output: 3607
🏁 Script executed:
# Search for any Python version specifications in repo config
rg "python" -i docs/ .github/ --max-count 5Repository: zeroclaw-labs/zeroclaw
Length of output: 8460
🏁 Script executed:
# Check actual Python version requirements in the audit scripts
grep -n "list\[" scripts/ci/ci_change_audit.py scripts/ci/emit_audit_event.pyRepository: zeroclaw-labs/zeroclaw
Length of output: 1121
🏁 Script executed:
# Check what Python version the self-hosted runners provide
# Look for any runner config or documentation
fd -t f "runner" -e yml -e yaml -e md | xargs grep -l "python\|version" 2>/dev/null | head -5Repository: zeroclaw-labs/zeroclaw
Length of output: 181
🏁 Script executed:
# Verify type hints used in scripts
rg "-> (list|dict|str|int|bool|None)" scripts/ci/*.py -A1 -B1 | head -50Repository: zeroclaw-labs/zeroclaw
Length of output: 470
Add explicit Python version check to prevent runtime syntax errors
The setup step only logs the Python version without enforcing a minimum. The audit scripts use Python 3.9+ syntax (e.g., list[str] type hints), which will fail if a runner has an older Python version installed. Add an explicit version guard to prevent silent failures.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In @.github/workflows/ci-change-audit.yml around lines 61 - 66, The "Setup
Python" workflow step currently only prints python3 --version and doesn't
enforce a minimum version; add an explicit guard in that step to verify python3
is >= 3.9 and exit with a clear error if not (e.g., run a shell check using
python3 -c "import sys; assert sys.version_info >= (3,9), ..." or print an error
and exit non-zero). Keep the existing set -euo pipefail and ensure the check
runs before any audit scripts so older Python versions fail early with a
descriptive message.
| changes: | ||
| name: Detect Change Scope | ||
| runs-on: ubuntu-22.04 | ||
| runs-on: [self-hosted, Linux, X64, aws-india, blacksmith-2vcpu-ubuntu-2404, hetzner] |
There was a problem hiding this comment.
❓ Verification inconclusive
Script executed:
# First, check the workflow file exists and get its size
wc -l .github/workflows/ci-run.ymlRepository: zeroclaw-labs/zeroclaw
Repository: zeroclaw-labs/zeroclaw
Exit code: 0
stdout:
452 .github/workflows/ci-run.yml
Script executed:
# Extract the jobs and their runs-on configuration around the flagged lines
# Lines 27, 262, 271, 280, 339, 365, 383
for line in 27 262 271 280 339 365 383; do
echo "=== Context around line $line ==="
sed -n "$((line-2)),$((line+2))p" .github/workflows/ci-run.yml
echo ""
doneRepository: zeroclaw-labs/zeroclaw
Repository: zeroclaw-labs/zeroclaw
Exit code: 0
stdout:
=== Context around line 27 ===
changes:
name: Detect Change Scope
runs-on: [self-hosted, Linux, X64, aws-india, blacksmith-2vcpu-ubuntu-2404, hetzner]
outputs:
docs_only: ${{ steps.scope.outputs.docs_only }}
=== Context around line 262 ===
needs: [changes]
if: needs.changes.outputs.docs_only == 'true'
runs-on: [self-hosted, Linux, X64, aws-india, blacksmith-2vcpu-ubuntu-2404, hetzner]
steps:
- name: Skip heavy jobs for docs-only change
=== Context around line 271 ===
needs: [changes]
if: needs.changes.outputs.docs_only != 'true' && needs.changes.outputs.rust_changed != 'true'
runs-on: [self-hosted, Linux, X64, aws-india, blacksmith-2vcpu-ubuntu-2404, hetzner]
steps:
- name: Skip Rust jobs for non-Rust change scope
=== Context around line 280 ===
needs: [changes]
if: needs.changes.outputs.docs_changed == 'true'
runs-on: [self-hosted, Linux, X64, aws-india, blacksmith-2vcpu-ubuntu-2404, hetzner]
timeout-minutes: 15
steps:
=== Context around line 339 ===
if: github.event_name == 'pull_request'
needs: [changes, lint, docs-quality]
runs-on: [self-hosted, Linux, X64, aws-india, blacksmith-2vcpu-ubuntu-2404, hetzner]
permissions:
contents: read
=== Context around line 365 ===
needs: [changes]
if: github.event_name == 'pull_request'
runs-on: [self-hosted, Linux, X64, aws-india, blacksmith-2vcpu-ubuntu-2404, hetzner]
permissions:
contents: read
=== Context around line 383 ===
if: always()
needs: [changes, lint, workspace-check, package-check, test, build, docs-only, non-rust, docs-quality, lint-feedback, license-file-owner-guard]
runs-on: [self-hosted, Linux, X64, aws-india, blacksmith-2vcpu-ubuntu-2404, hetzner]
steps:
- name: Enforce required status
Script executed:
# Get the full structure to understand job names and their runners
# Extract job definitions with their runs-on values
rg -n "^\s{2}[a-zA-Z0-9_-]+:\s*$" .github/workflows/ci-run.yml | head -20Repository: zeroclaw-labs/zeroclaw
Repository: zeroclaw-labs/zeroclaw
Exit code: 0
Script executed:
# Extract runs-on configurations with context
rg -B 5 "runs-on:" .github/workflows/ci-run.yml | head -80Repository: zeroclaw-labs/zeroclaw
Repository: zeroclaw-labs/zeroclaw
Exit code: 0
stdout:
CARGO_TERM_COLOR: always
jobs:
changes:
name: Detect Change Scope
runs-on: [self-hosted, Linux, X64, aws-india, blacksmith-2vcpu-ubuntu-2404, hetzner]
--
lint:
name: Lint Gate (Format + Clippy + Strict Delta)
needs: [changes]
if: needs.changes.outputs.rust_changed == 'true'
runs-on: [self-hosted, Linux, X64, aws-india, blacksmith-2vcpu-ubuntu-2404, hetzner]
--
workspace-check:
name: Workspace Check
needs: [changes]
if: needs.changes.outputs.rust_changed == 'true'
runs-on: [self-hosted, Linux, X64, aws-india, blacksmith-2vcpu-ubuntu-2404, hetzner]
--
package-check:
name: Package Check (${{ matrix.package }})
needs: [changes]
if: needs.changes.outputs.rust_changed == 'true'
runs-on: [self-hosted, Linux, X64, aws-india, blacksmith-2vcpu-ubuntu-2404, hetzner]
--
test:
name: Test
needs: [changes]
if: needs.changes.outputs.rust_changed == 'true'
runs-on: [self-hosted, Linux, X64, aws-india, blacksmith-2vcpu-ubuntu-2404, hetzner]
--
build:
name: Build (Smoke)
needs: [changes]
if: needs.changes.outputs.rust_changed == 'true'
runs-on: [self-hosted, Linux, X64, aws-india, blacksmith-2vcpu-ubuntu-2404, hetzner]
--
docs-only:
name: Docs-Only Fast Path
needs: [changes]
if: needs.changes.outputs.docs_only == 'true'
runs-on: [self-hosted, Linux, X64, aws-india, blacksmith-2vcpu-ubuntu-2404, hetzner]
--
non-rust:
name: Non-Rust Fast Path
needs: [changes]
if: needs.changes.outputs.docs_only != 'true' && needs.changes.outputs.rust_changed != 'true'
runs-on: [self-hosted, Linux, X64, aws-india, blacksmith-2vcpu-ubuntu-2404, hetzner]
--
docs-quality:
name: Docs Quality
needs: [changes]
if: needs.changes.outputs.docs_changed == 'true'
runs-on: [self-hosted, Linux, X64, aws-india, blacksmith-2vcpu-ubuntu-2404, hetzner]
--
lint-feedback:
name: Lint Feedback
if: github.event_name == 'pull_request'
needs: [changes, lint, docs-quality]
runs-on: [self-hosted, Linux, X64, aws-india, blacksmith-2vcpu-ubuntu-2404, hetzner]
--
license-file-owner-guard:
name: License File Owner Guard
needs: [changes]
if: github.event_name == 'pull_request'
runs-on: [self-hosted, Linux, X64, aws-india, blacksmith-2vcpu-ubuntu-2404, hetzner]
--
await script({ github, context, core });
ci-required:
name: CI Required Gate
Script executed:
# Validate YAML syntax using basic Python YAML parser
python3 << 'EOF'
import yaml
import sys
try:
with open('.github/workflows/ci-run.yml', 'r') as f:
yaml.safe_load(f)
print("YAML syntax: VALID ✓")
except yaml.YAMLError as e:
print(f"YAML syntax: INVALID ✗")
print(f"Error: {e}")
sys.exit(1)
EOFRepository: zeroclaw-labs/zeroclaw
Repository: zeroclaw-labs/zeroclaw
Exit code: 0
stdout:
YAML syntax: VALID ✓
Script executed:
# Get a complete picture of ALL jobs and their runners to verify the architectural claim
cat .github/workflows/ci-run.yml | sed -n '/^jobs:/,/^[^ ]/p' | grep -E "^\s{4}[a-zA-Z0-9_-]+:|runs-on:" | paste - - | sed 's/\t/ -> /'Repository: zeroclaw-labs/zeroclaw
Repository: zeroclaw-labs/zeroclaw
Exit code: 0
stderr:
/bin/bash: line 2: paste: command not found
Script executed:
# Identify which jobs are "heavy" (compile/test) vs "lightweight" (metadata/fast-path)
# by examining their actual steps and dependencies
cat .github/workflows/ci-run.yml | grep -E "name:|runs-on:|if:|steps:" -A 1 | head -100Repository: zeroclaw-labs/zeroclaw
Repository: zeroclaw-labs/zeroclaw
Exit code: 0
stdout:
name: CI Run
--
name: Detect Change Scope
runs-on: [self-hosted, Linux, X64, aws-india, blacksmith-2vcpu-ubuntu-2404, hetzner]
outputs:
--
steps:
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
--
- name: Detect docs-only changes
id: scope
--
name: Lint Gate (Format + Clippy + Strict Delta)
needs: [changes]
if: needs.changes.outputs.rust_changed == 'true'
runs-on: [self-hosted, Linux, X64, aws-india, blacksmith-2vcpu-ubuntu-2404, hetzner]
timeout-minutes: 75
--
steps:
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
--
- name: Self-heal Rust toolchain cache
shell: bash
--
- name: Ensure C toolchain
shell: bash
--
- name: Ensure C toolchain for Rust builds
run: ./scripts/ci/ensure_cc.sh
- name: Ensure cargo component
shell: bash
--
- name: Run rust quality gate
run: ./scripts/ci/rust_quality_gate.sh
- name: Run strict lint delta gate
env:
--
name: Workspace Check
needs: [changes]
if: needs.changes.outputs.rust_changed == 'true'
runs-on: [self-hosted, Linux, X64, aws-india, blacksmith-2vcpu-ubuntu-2404, hetzner]
timeout-minutes: 45
steps:
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
- name: Self-heal Rust toolchain cache
shell: bash
--
- name: Check workspace
run: cargo check --workspace --locked
--
name: Package Check (${{ matrix.package }})
needs: [changes]
if: needs.changes.outputs.rust_changed == 'true'
runs-on: [self-hosted, Linux, X64, aws-india, blacksmith-2vcpu-ubuntu-2404, hetzner]
timeout-minutes: 25
--
steps:
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
- name: Self-heal Rust toolchain cache
shell: bash
--
- name: Check package
run: cargo check -p ${{ matrix.package }} --locked
--
name: Test
needs: [changes]
if: needs.changes.outputs.rust_changed == 'true'
runs-on: [self-hosted, Linux, X64, aws-india, blacksmith-2vcpu-ubuntu-2404, hetzner]
timeout-minutes: 120
--
steps:
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
- name: Ensure C toolchain
shell: bash
--
- name: Self-heal Rust toolchain cache
shell: bash
--
- name: Ensure C toolchain for Rust builds
run: ./scripts/ci/ensure_cc.sh
- name: Ensure cargo component
shell: bash
--
- name: Run tests with flake detection
shell: bash
--
- name: Publish flake probe summary
if: always()
shell: bash
--
- name: Upload flake probe artifact
if: always()
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
--
name: test-flake-probe
path: artifacts/flake-probe.*
--
name: Build (Smoke)
needs: [changes]
Script executed:
# Check if there are any PR notes or lint evidence files
find . -name "*lint*" -o -name "*actionlint*" | head -20Repository: zeroclaw-labs/zeroclaw
Repository: zeroclaw-labs/zeroclaw
Exit code: 0
stdout:
./.github/actionlint.yaml
./.github/workflows/scripts/lint_feedback.js
./.markdownlint-cli2.yaml
./firmware/zeroclaw-esp32-ui/ui/main.slint
Script executed:
# Check for any validation scripts or CI configuration that would run workflow linting
find . -path "./node_modules" -prune -o -path "./.git" -prune -o -name "*.js" -o -name "*.sh" | grep -i "lint\|action\|workflow" | head -20Repository: zeroclaw-labs/zeroclaw
Repository: zeroclaw-labs/zeroclaw
Exit code: 0
stdout:
./.github/workflows/scripts/ci_human_review_guard.js
./.github/workflows/scripts/ci_license_file_owner_guard.js
./.github/workflows/scripts/lint_feedback.js
./.github/workflows/scripts/pr_auto_response_contributor_tier.js
./.github/workflows/scripts/pr_auto_response_labeled_routes.js
./.github/workflows/scripts/pr_check_status_nudge.js
./.github/workflows/scripts/pr_intake_checks.js
./.github/workflows/scripts/pr_labeler.js
./.github/workflows/scripts/test_benchmarks_pr_comment.js
Script executed:
# Look at the complete workflow structure to understand job dependencies and timeouts
# This will help confirm which are heavy vs lightweight
rg -A 2 "timeout-minutes:" .github/workflows/ci-run.ymlRepository: zeroclaw-labs/zeroclaw
Repository: zeroclaw-labs/zeroclaw
Exit code: 0
stdout:
timeout-minutes: 75
env:
CARGO_HOME: ${{ github.workspace }}/.ci-rust/${{ github.run_id }}-${{ github.run_attempt }}-${{ github.job }}/cargo
--
timeout-minutes: 45
steps:
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
--
timeout-minutes: 25
strategy:
fail-fast: false
--
timeout-minutes: 120
env:
CARGO_HOME: ${{ github.workspace }}/.ci-rust/${{ github.run_id }}-${{ github.run_attempt }}-${{ github.job }}/cargo
--
timeout-minutes: 90
env:
CARGO_HOME: ${{ github.workspace }}/.ci-rust/${{ github.run_id }}-${{ github.run_attempt }}-${{ github.job }}/cargo
--
timeout-minutes: 15
steps:
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
Script executed:
# Examine the actionlint config to understand what workflow linting checks would apply
cat ./.github/actionlint.yamlRepository: zeroclaw-labs/zeroclaw
Repository: zeroclaw-labs/zeroclaw
Exit code: 0
stdout:
self-hosted-runner:
labels:
- Linux
- X64
- racknerd
- aws-india
- blacksmith-2vcpu-ubuntu-2404
- hetzner
Script executed:
# Create a summary showing which jobs are lightweight vs heavy based on actual step complexity and timeouts
python3 << 'EOF'
import re
with open('.github/workflows/ci-run.yml', 'r') as f:
content = f.read()
# Extract job names with their timeouts and conditional runs
jobs_pattern = r'^\s{4}([a-zA-Z0-9_-]+):\s*$'
timeout_pattern = r'timeout-minutes:\s*(\d+)'
name_pattern = r'name:\s*(["\']?)([^"\']*)\1'
condition_pattern = r'if:\s*(.+?)$'
jobs = re.findall(jobs_pattern, content, re.MULTILINE)
print("JOB CLASSIFICATION:")
print("=" * 70)
heavy_jobs = {'lint', 'workspace-check', 'package-check', 'test', 'build'}
lightweight_jobs = {'changes', 'docs-only', 'non-rust', 'docs-quality', 'lint-feedback', 'license-file-owner-guard', 'ci-required'}
for job in jobs:
job_section = re.search(f' {job}:\n(.*?)(?=\n [a-zA-Z0-9_-]+:|$)', content, re.DOTALL)
if job_section:
section = job_section.group(1)
timeout_match = re.search(timeout_pattern, section)
timeout = timeout_match.group(1) if timeout_match else "default"
category = "HEAVY (compile/test)" if job in heavy_jobs else "LIGHTWEIGHT (fast-path/metadata)" if job in lightweight_jobs else "OTHER"
print(f"{job:35} {category:35} timeout: {timeout} min")
EOFRepository: zeroclaw-labs/zeroclaw
Repository: zeroclaw-labs/zeroclaw
Exit code: 0
stdout:
JOB CLASSIFICATION:
======================================================================
push OTHER timeout: default min
pull_request OTHER timeout: default min
merge_group OTHER timeout: default min
changes LIGHTWEIGHT (fast-path/metadata) timeout: default min
lint HEAVY (compile/test) timeout: 75 min
workspace-check HEAVY (compile/test) timeout: 45 min
package-check HEAVY (compile/test) timeout: 25 min
test HEAVY (compile/test) timeout: 120 min
build HEAVY (compile/test) timeout: 90 min
docs-only LIGHTWEIGHT (fast-path/metadata) timeout: default min
non-rust LIGHTWEIGHT (fast-path/metadata) timeout: default min
docs-quality LIGHTWEIGHT (fast-path/metadata) timeout: 15 min
lint-feedback LIGHTWEIGHT (fast-path/metadata) timeout: default min
license-file-owner-guard LIGHTWEIGHT (fast-path/metadata) timeout: default min
ci-required LIGHTWEIGHT (fast-path/metadata) timeout: default min
Lightweight fast-path/governance jobs still contend on the same runner pool as heavy workloads
All jobs—including lightweight jobs like changes, docs-only, non-rust, docs-quality, lint-feedback, license-file-owner-guard, and ci-required—use the identical runner labels [self-hosted, Linux, X64, aws-india, blacksmith-2vcpu-ubuntu-2404, hetzner]. This means lightweight jobs (with 0–15 min timeouts) and heavy compilation/test jobs (with 25–120 min timeouts) compete for the same execution slots, defeating the architectural goal of offloading lightweight workflows to a separate lane.
Lines affected: 27, 262, 271, 280, 339, 365, 383
Additionally, while actionlint.yaml exists in the repository, provide evidence that workflow linting checks were run on this PR.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In @.github/workflows/ci-run.yml at line 27, The workflow uses the same runner
labels for both lightweight and heavy jobs; update the jobs named changes,
docs-only, non-rust, docs-quality, lint-feedback, license-file-owner-guard, and
ci-required in .github/workflows/ci-run.yml to use a distinct lightweight runner
pool label (e.g., replace the current runs-on array [self-hosted, Linux, X64,
aws-india, blacksmith-2vcpu-ubuntu-2404, hetzner] with a dedicated lightweight
label such as [self-hosted, Linux, X64, aws-india, blacksmith-light-1vcpu] or a
shared tag like [self-hosted, lightweight]) so short jobs don’t contend with
heavy workloads; additionally ensure workflow linting is actually executed on
PRs by adding or enabling an actionlint job that runs the repository’s
actionlint.yaml (or invoking actionlint as a step in the CI workflow) and make
it a required check so you can provide verification that actionlint ran for this
PR.
| jobs: | ||
| build: | ||
| runs-on: ubuntu-latest | ||
| runs-on: [self-hosted, Linux, X64, aws-india, blacksmith-2vcpu-ubuntu-2404, hetzner] |
There was a problem hiding this comment.
🧩 Analysis chain
🌐 Web query:
GitHub Actions runs-on array labels AND OR semantics matching
💡 Result:
Web search failed: Server error: no LLM provider could handle the message
🏁 Script executed:
# First, let's check if the workflow file exists and validate YAML syntax
fd pages-deploy.yml .github/workflows/ 2>/dev/null || echo "File not found, will search more broadly"Repository: zeroclaw-labs/zeroclaw
Length of output: 100
🏁 Script executed:
# Search for the workflow file
find . -name "pages-deploy.yml" -o -name "pages*.yml" 2>/dev/null | head -20Repository: zeroclaw-labs/zeroclaw
Length of output: 102
🏁 Script executed:
# Read the workflow file to see the actual content and validate YAML
cat -n .github/workflows/pages-deploy.ymlRepository: zeroclaw-labs/zeroclaw
Length of output: 1871
🏁 Script executed:
# Validate YAML syntax using Python
python3 << 'EOF'
import sys
try:
import yaml
with open('.github/workflows/pages-deploy.yml', 'r') as f:
yaml.safe_load(f)
print("✓ YAML syntax is valid")
except yaml.YAMLError as e:
print(f"✗ YAML syntax error: {e}")
sys.exit(1)
except Exception as e:
print(f"✗ Error: {e}")
sys.exit(1)
EOFRepository: zeroclaw-labs/zeroclaw
Length of output: 88
🏁 Script executed:
# Search for any documentation or comments about runner labels in the repo
rg -i "label|runs-on|hetzner|aws-india" docs/ README.md 2>/dev/null | head -30Repository: zeroclaw-labs/zeroclaw
Length of output: 3612
🏁 Script executed:
# Check git history or comments that might explain the label strategy
git log --oneline --all -S "hetzner" -- .github/workflows/pages-deploy.yml 2>/dev/null | head -10 || echo "No git history available"Repository: zeroclaw-labs/zeroclaw
Length of output: 195
🏁 Script executed:
# Search for runner configuration or documentation
find . -name "*runner*" -o -name "*action*" -type f 2>/dev/null | grep -E "\.(md|yml|yaml|json)$" | head -20Repository: zeroclaw-labs/zeroclaw
Length of output: 486
🏁 Script executed:
# Check for actions-source-policy.md mentioned in coding guidelines
find . -path "*/docs/actions-source-policy.md" 2>/dev/nullRepository: zeroclaw-labs/zeroclaw
Length of output: 97
🏁 Script executed:
# Look for other workflow files to see how they use labels
rg "runs-on" .github/workflows/ -A 1 | head -40Repository: zeroclaw-labs/zeroclaw
Length of output: 2590
Remove hetzner label to complete lightweight workflow offload
Commit df535f8 targets offloading lightweight workflows from Hetzner, but pages-deploy.yml still requires the hetzner label at lines 25 and 56. This directly contradicts the stated offload goal. In GitHub Actions, array labels use AND semantics—keeping hetzner ensures the workflow runs only on Hetzner-constrained runners. Compare with workflow-sanity.yml and sync-contributors.yml, which already removed the label for similar lightweight workloads.
Suggested fix
- runs-on: [self-hosted, Linux, X64, aws-india, blacksmith-2vcpu-ubuntu-2404, hetzner]
+ runs-on: [self-hosted, Linux, X64, aws-india, blacksmith-2vcpu-ubuntu-2404]Applied to both the build job (line 25) and deploy job (line 56).
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| runs-on: [self-hosted, Linux, X64, aws-india, blacksmith-2vcpu-ubuntu-2404, hetzner] | |
| runs-on: [self-hosted, Linux, X64, aws-india, blacksmith-2vcpu-ubuntu-2404] |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In @.github/workflows/pages-deploy.yml at line 25, Remove the "hetzner" runner
label from the runs-on arrays for the build and deploy jobs in pages-deploy.yml
so the workflows no longer require Hetzner-constrained runners; locate the
runs-on arrays used by the "build" job (currently containing [self-hosted,
Linux, X64, aws-india, blacksmith-2vcpu-ubuntu-2404, hetzner]) and the "deploy"
job and delete the "hetzner" entry from each array, keeping the remaining labels
intact.
| (github.event_name == 'issues' && | ||
| (github.event.action == 'opened' || github.event.action == 'reopened')) | ||
| runs-on: ubuntu-22.04 | ||
| runs-on: [self-hosted, Linux, X64, aws-india] |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# 1. Read the workflow file to verify pull_request_target trigger and runs-on at specific lines
echo "=== Checking .github/workflows/pr-auto-response.yml ==="
cat -n .github/workflows/pr-auto-response.yml | head -100
echo ""
echo "=== Extracted triggers and runs-on at lines 30, 49, 80 ==="
sed -n '1,10p; 25,35p; 45,55p; 75,85p' .github/workflows/pr-auto-response.yml | cat -nRepository: zeroclaw-labs/zeroclaw
Length of output: 6019
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# 2. Check if docs/actions-source-policy.md exists
echo "=== Checking docs/actions-source-policy.md ==="
if [ -f "docs/actions-source-policy.md" ]; then
wc -l docs/actions-source-policy.md
echo "File exists. Content:"
head -50 docs/actions-source-policy.md
else
echo "File does not exist"
fi
# 3. Check if .github/pull_request_template.md exists
echo ""
echo "=== Checking .github/pull_request_template.md ==="
if [ -f ".github/pull_request_template.md" ]; then
wc -l .github/pull_request_template.md
echo "File exists. Content:"
cat .github/pull_request_template.md
else
echo "File does not exist"
fiRepository: zeroclaw-labs/zeroclaw
Length of output: 5863
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# 3. Verify other workflows with pull_request_target + self-hosted combination
echo "=== Checking all workflows for pull_request_target + self-hosted pattern ==="
for workflow in .github/workflows/*.yml .github/workflows/*.yaml; do
if [ -f "$workflow" ]; then
if grep -q "pull_request_target" "$workflow" && grep -q "self-hosted" "$workflow"; then
echo "⚠️ Found both in: $workflow"
echo "Triggers:"
grep -n "pull_request_target" "$workflow" | head -3
echo "Runs-on:"
grep -n "self-hosted" "$workflow" | head -3
echo ""
fi
fi
doneRepository: zeroclaw-labs/zeroclaw
Length of output: 786
Refine self-hosted execution risk assessment and include required PR documentation.
The workflow does expose a risk, but only partially as stated: the labeled-routes job (line 80) runs on pull_request_target events with self-hosted runners. However, contributor-tier-issues (line 30) runs exclusively on issues events (not external PRs) due to its condition github.event_name == 'issues', so that job is not vulnerable to the stated risk.
For labeled-routes, the combination of self-hosted execution with pull_request_target events (which respond to untrusted external PRs) increases blast radius. Either migrate to GitHub-hosted runners or use a tightly isolated ephemeral self-hosted pool.
Additionally, per the PR template requirements in .github/pull_request_template.md, this workflow change must include:
- Security Impact: document new permissions/capabilities (issues: write, pull-requests: write on external events)
- Side Effects / Blast Radius: affected subsystems and guardrails
- Rollback Plan: concrete fast rollback command/path
Also verify if docs/actions-source-policy.md requires updating if new Actions are introduced in this workflow.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In @.github/workflows/pr-auto-response.yml at line 30, The workflow's risk
assessment is inaccurate and missing required PR docs: confirm that the job
named labeled-routes (which currently runs on pull_request_target with runs-on:
[self-hosted, Linux, X64, aws-india]) is either moved to GitHub-hosted runners
or reconfigured to use a strictly isolated ephemeral self-hosted pool to
eliminate external-PR execution risk; update the review text to clarify that
contributor-tier-issues is gated by github.event_name == 'issues' (so it isn't
exposed to external PRs); and add the required PR documentation fields from
.github/pull_request_template.md—Security Impact (list new permissions like
issues: write, pull-requests: write on external events), Side Effects / Blast
Radius (affected subsystems and guardrails), and a concrete Rollback Plan (fast
rollback command/path); finally, check docs/actions-source-policy.md and update
it if any new Actions were introduced.
| issues: write | ||
| pull-requests: write | ||
| runs-on: ubuntu-22.04 | ||
| runs-on: [self-hosted, Linux, X64, aws-india] |
There was a problem hiding this comment.
Add workflow-governance notes to PR description.
Please add a short PR note for: (1) Actions allowlist impact (no source changes if true), and (2) threat/risk + rollback strategy for these workflow-routing changes.
Based on learnings: "For workflow changes, include threat/risk notes and rollback strategy; update docs/actions-source-policy.md when GitHub Actions sources change; keep observability non-sensitive."
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In @.github/workflows/pr-check-stale.yml at line 20, The PR must include a short
governance note explaining Actions allowlist impact and rollback/threat
considerations for the workflow change that modifies the runner selection (the
runs-on array such as "runs-on: [self-hosted, Linux, X64, aws-india]"); add a
sentence stating whether this is "no source changes" for the allowlist, and a
concise threat/risk + rollback strategy (how to revert the workflow or disable
the runner if issues occur). Also update docs/actions-source-policy.md if GitHub
Actions sources or runner origins change, and confirm any added observability
logs are non-sensitive before including them in the PR description.
| - name: Setup Python 3.11 | ||
| uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5 | ||
| with: | ||
| python-version: "3.11" | ||
| shell: bash | ||
| run: | | ||
| set -euo pipefail | ||
| python3 --version | ||
|
|
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
# First, let's read the specific lines in question
head -n 524 .github/workflows/sec-audit.yml | tail -n 20Repository: zeroclaw-labs/zeroclaw
Length of output: 794
🏁 Script executed:
# Let's also check the full workflow file structure to understand context
wc -l .github/workflows/sec-audit.ymlRepository: zeroclaw-labs/zeroclaw
Length of output: 101
🏁 Script executed:
# Check if the file exists and examine the problematic section more carefully
if [ -f ".github/workflows/sec-audit.yml" ]; then
sed -n '510,535p' .github/workflows/sec-audit.yml
fiRepository: zeroclaw-labs/zeroclaw
Length of output: 1107
🏁 Script executed:
# Check for Python scripts in scripts/ci/ to understand version requirements
fd -t f '\.py$' scripts/ci/ 2>/dev/null | head -20Repository: zeroclaw-labs/zeroclaw
Length of output: 769
🏁 Script executed:
# Look for shebang or version requirements in the audit-related scripts
find . -name "*.py" -path "*/scripts/ci/*" -exec grep -l "python\|version_info\|sys.version" {} \; 2>/dev/null | head -10Repository: zeroclaw-labs/zeroclaw
Length of output: 416
🏁 Script executed:
# Check the unsafe_policy_guard.py script for Python version requirements
head -30 ./scripts/ci/unsafe_policy_guard.pyRepository: zeroclaw-labs/zeroclaw
Length of output: 692
🏁 Script executed:
# Check for project-level Python version requirements
if [ -f "pyproject.toml" ]; then
grep -A 5 "python\|version" pyproject.toml | head -20
fiRepository: zeroclaw-labs/zeroclaw
Length of output: 48
🏁 Script executed:
# Check for requirements files
fd -t f 'requirements.*\.txt|pyproject.toml|setup.py|setup.cfg' . --max-depth 3 2>/dev/null | grep -E "(requirements|pyproject|setup)" | head -10Repository: zeroclaw-labs/zeroclaw
Length of output: 89
🏁 Script executed:
# Validate YAML syntax of the workflow file
if command -v yamllint &>/dev/null; then
yamllint .github/workflows/sec-audit.yml 2>&1 || true
fiRepository: zeroclaw-labs/zeroclaw
Length of output: 6958
🏁 Script executed:
# Check Python version available on ubuntu-2404 (latest Ubuntu 24.04)
# by looking at GitHub documentation or comments in the repo
grep -r "python\|3\.1[0-9]" .github/workflows/ --include="*.yml" --include="*.yaml" | grep -i "version\|uses.*python\|ubuntu" | head -20Repository: zeroclaw-labs/zeroclaw
Length of output: 207
"Setup Python 3.11" step does not enforce Python 3.11 requirement
Lines 519–524 only print python3 --version without enforcing the Python 3.11+ requirement. The next step executes scripts/ci/unsafe_policy_guard.py, which requires Python 3.11+ due to its use of tomllib (available only in Python 3.11+). The step will fail later at script execution rather than at version setup, making the step name misleading. Add an explicit version check to fail fast if Python < 3.11.
Suggested fix
- - name: Setup Python 3.11
+ - name: Verify Python 3.11+
shell: bash
run: |
set -euo pipefail
- python3 --version
+ python3 - <<'PY'
+import sys
+assert sys.version_info >= (3, 11), f"Python 3.11+ required, got {sys.version}"
+print(sys.version)
+PY📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| - name: Setup Python 3.11 | |
| uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5 | |
| with: | |
| python-version: "3.11" | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| python3 --version | |
| - name: Verify Python 3.11+ | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| python3 - <<'PY' | |
| import sys | |
| assert sys.version_info >= (3, 11), f"Python 3.11+ required, got {sys.version}" | |
| print(sys.version) | |
| PY |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In @.github/workflows/sec-audit.yml around lines 519 - 524, The "Setup Python
3.11" step currently only runs `python3 --version` and doesn't enforce the
Python >=3.11 requirement, so add an explicit runtime version check in that step
(before running scripts/ci/unsafe_policy_guard.py) that invokes python3 to
verify sys.version_info >= (3,11) and exits non-zero with a clear message if the
check fails; update the step containing `python3 --version` (the "Setup Python
3.11" step) to perform this check so the workflow fails fast when Python is too
old.
| integration-tests: | ||
| name: Integration / E2E Tests | ||
| runs-on: ubuntu-22.04 | ||
| runs-on: [self-hosted, Linux, X64, aws-india, blacksmith-2vcpu-ubuntu-2404, hetzner] |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
# First, check the YAML syntax of the workflow file
cd .github/workflows
cat -n test-e2e.yml | head -50Repository: zeroclaw-labs/zeroclaw
Length of output: 2156
🏁 Script executed:
# Verify YAML syntax with yamllint if available, or use python
python3 -c "
import yaml
try:
with open('.github/workflows/test-e2e.yml', 'r') as f:
yaml.safe_load(f)
print('✓ YAML syntax is valid')
except yaml.YAMLError as e:
print(f'✗ YAML syntax error: {e}')
"Repository: zeroclaw-labs/zeroclaw
Length of output: 88
🏁 Script executed:
# Check what the current runs-on configuration looks like
rg -n 'runs-on:' .github/workflows/test-e2e.yml -A 1Repository: zeroclaw-labs/zeroclaw
Length of output: 192
🏁 Script executed:
# Search for all workflows with similar provider label patterns
rg -n 'runs-on:.*\[.*aws-india' .github/workflows/ --type yaml
rg -n 'runs-on:.*\[.*blacksmith-2vcpu-ubuntu-2404' .github/workflows/ --type yaml
rg -n 'runs-on:.*hetzner' .github/workflows/ --type yamlRepository: zeroclaw-labs/zeroclaw
Length of output: 21964
Fix conjunctive provider labels in runs-on across workflows.
Line 33 requires a runner with all labels (aws-india + blacksmith-2vcpu-ubuntu-2404 + hetzner) simultaneously. In GitHub Actions, this is an AND match, creating overly restrictive scheduling that likely makes jobs unschedulable. This pattern appears in 80+ occurrences across 30+ workflow files, suggesting a systemic configuration issue.
Consider using label alternatives to support your offload strategy:
- Use separate jobs with disjunctive scheduling (each provider separately)
- Use conditional job routing instead of label conjunctions
- Verify runner labels match the intended lane design
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In @.github/workflows/test-e2e.yml at line 33, The runs-on label array currently
requires a runner that matches all labels (runs-on: [self-hosted, Linux, X64,
aws-india, blacksmith-2vcpu-ubuntu-2404, hetzner]), which is overly restrictive;
update the workflow to avoid conjunctive provider labels by either splitting
into separate jobs (one job per provider label like aws-india,
blacksmith-2vcpu-ubuntu-2404, hetzner), using a job matrix/strategy to iterate
provider labels, or implementing conditional routing that selects the proper
runs-on per-provider, and ensure changes reference the runs-on array and the
provider label tokens ('aws-india', 'blacksmith-2vcpu-ubuntu-2404', 'hetzner')
so jobs are schedulable.
| name: Runner Health / self-hosted aws-india | ||
| runs-on: [self-hosted, aws-india] | ||
| runs-on: [self-hosted, Linux, X64, aws-india, blacksmith-2vcpu-ubuntu-2404, hetzner] |
There was a problem hiding this comment.
Update job name to match the new runner lane.
Line 13 still implies only aws-india, but Line 14 now targets a broader label set. This makes health-check dashboards/logs slightly misleading.
✏️ Proposed rename
- name: Runner Health / self-hosted aws-india
+ name: Runner Health / self-hosted multi-lane📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| name: Runner Health / self-hosted aws-india | |
| runs-on: [self-hosted, aws-india] | |
| runs-on: [self-hosted, Linux, X64, aws-india, blacksmith-2vcpu-ubuntu-2404, hetzner] | |
| name: Runner Health / self-hosted multi-lane | |
| runs-on: [self-hosted, Linux, X64, aws-india, blacksmith-2vcpu-ubuntu-2404, hetzner] |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In @.github/workflows/test-self-hosted.yml around lines 13 - 14, The workflow
name "Runner Health / self-hosted aws-india" is out of sync with the runs-on
labels; update the YAML `name:` value to reflect the broader `runs-on:` set
(e.g., include aws-india, blacksmith-2vcpu-ubuntu-2404, hetzner or use
"multi-region/multi-label") so the `name:` consistently describes the targeted
runner lane; change the `name:` string where it appears above the `runs-on:`
entry in this workflow.
df535f8 to
7c10e2f
Compare
Summary
self-hosted, Linux, X64, aws-india)self-hosted, Linux, X64, aws-india, blacksmith-2vcpu-ubuntu-2404, hetzner)Why
Validation
gcp-usrunners can absorb lightweight jobsHost-side Ops Applied (already live)
henny-2/henny-3: runner CPU affinity defaults updated to0-6(~90% target) instart-runners.shandenforce-cpuset.shhenny-1: existinggithub-runners.slicequota verified atCPUQuotaPerSecUSec=7.200000s(90% of 8 vCPU)Summary by CodeRabbit