Route Linux CI to Hetzner runner - #1
Conversation
Use the self-hosted Hetzner runner for Linux CI while keeping macOS and Windows on GitHub-hosted runners, and gate external PR usage behind maintainer approval.
|
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: a02d6ad792
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| if: >- | ||
| github.event_name == 'push' || | ||
| github.event.pull_request.head.repo.full_name == github.repository || | ||
| contains(github.event.pull_request.labels.*.name, 'run-hetzner-ci') |
There was a problem hiding this comment.
Fail unapproved fork PRs instead of silently skipping Linux CI
For fork PRs that are opened or synchronized without run-hetzner-ci, this job-level guard evaluates false, so Test Linux is skipped; GitHub reports skipped jobs as successful, which means an external PR can look green without running the Linux test suite. The same guard is repeated on Clippy and Format, so the label gate should either run a safe fallback/check that fails or stays pending until approval, or otherwise avoid marking the Linux CI requirements as passed before they actually run.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Addressed in 4689ebd: added a GitHub-hosted Self-hosted runner approval gate that fails unapproved external PRs unless run-hetzner-ci is present, so skipped Hetzner jobs cannot make an unapproved fork PR appear green.
There was a problem hiding this comment.
Updated in 2169aa6: tokensave is a public repo, and standard GitHub-hosted Linux runners are free for public repositories, so this PR no longer routes Linux CI to Hetzner or skips Linux checks for external PRs.
Keep the handler-level annotation regression test aligned with tools that already declare readOnlyHint=false.
Avoid racing the detached startup catch-up sync before asserting that a new file is stale.
Restart CI after refreshing the self-hosted runner image and resources.
Track the local Cursor MCP config needed for this branch's tokensave tooling.
Add an explicit GitHub-hosted gate so external PRs cannot appear green before maintainers approve Hetzner Linux CI.
Keep standard GitHub-hosted Linux CI for the public tokensave fork, where hosted runner minutes are free.
The MCP fact_store add path (and its fact_feedback sibling) awaited the memory store with no bound, so a slow or contended operation could pin the transport open indefinitely (observed: ~100% CPU, 9+ min, no return). Measured the add path with a tempdir profile: per-add latency is flat from add #1 through #600 (~50ms each in a debug build), so the vectorization is NOT O(n) over existing facts and there is no busy-spin in the write path. The hangs are a contention/lock-starvation class, not an algorithmic blow-up, so the correct fix is a defensive backstop. Wrap the whole store-touching operation (open + dispatch, including the holographic encode, the serialized write, and any digest refresh) in a 30s per-operation deadline that degrades an elapsed operation to a typed, retryable ProjectRoute problem (reason_code memory_operation_deadline_exceeded) instead of an unbounded transport hang. Tests: deadline passes fast results through unchanged, an elapsed deadline surfaces the typed retryable problem, a real tempdir add completes within the deadline, plus an ignored manual probe documenting the flat add scaling. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The MCP fact_store add path (and its fact_feedback sibling) awaited the memory store with no bound, so a slow or contended operation could pin the transport open indefinitely (observed: ~100% CPU, 9+ min, no return). Measured the add path with a tempdir profile: per-add latency is flat from add #1 through #600 (~50ms each in a debug build), so the vectorization is NOT O(n) over existing facts and there is no busy-spin in the write path. The hangs are a contention/lock-starvation class, not an algorithmic blow-up, so the correct fix is a defensive backstop. Wrap the whole store-touching operation (open + dispatch, including the holographic encode, the serialized write, and any digest refresh) in a 30s per-operation deadline that degrades an elapsed operation to a typed, retryable ProjectRoute problem (reason_code memory_operation_deadline_exceeded) instead of an unbounded transport hang. Tests: deadline passes fast results through unchanged, an elapsed deadline surfaces the typed retryable problem, a real tempdir add completes within the deadline, plus an ignored manual probe documenting the flat add scaling. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Bump the grafeo fork pin bdd5dbdf -> 3c995681, the head of ScriptedAlchemy/grafeo#1 after its review: close() now checkpoints once a raw store handle escapes (WAL-bypassing count-neutral mutations can no longer be dropped by the clean-close skip), the Dict marker mapping is versioned as CompactStore section v4, dropping a property index reaches the compact base, neighbors() filters base edge tombstones, and the tiered arena accepts exact-fit values while typing over-aligned allocations. Builds at this pin keep reading v3 graph stores and write v4 sections at the next checkpoint; binaries still on an older pin fail closed on a v4 store with the typed unsupported-version error, so rebuild stale lanes rather than sharing a store across pins.
Summary
run-hetzner-cilabel.Test plan
git diff --checkfor the workflow change./home/zack/github-runner/entrypoint.shwithbash -n./home/zack/github-runner/docker-compose.ymlwithdocker compose configand image build.all_external_contributors.Notes
hetzner,linux, andx64labels.run-hetzner-cilabel before Linux jobs use the self-hosted runner.