Skip to content

ci: run devtools verify on the sinnix-prime self-hosted runner - #4584

Merged
Sinity merged 1 commit into
masterfrom
ci/self-hosted-verify
Sep 3, 2026
Merged

ci: run devtools verify on the sinnix-prime self-hosted runner#4584
Sinity merged 1 commit into
masterfrom
ci/self-hosted-verify

Conversation

@Sinity

@Sinity Sinity commented Sep 3, 2026

Copy link
Copy Markdown
Owner

Summary

Adds .github/workflows/verify.yml: a verify job on pull_request and
merge_group that runs nix develop --command devtools verify on the
workstation runner and uploads .cache/verify/current-run.json.

Problem

Per-PR hosted CI runs only the quick gate (.github/workflows/ci.yml gates the
test job behind if: github.event_name != 'pull_request'). A green PR check
therefore does not mean tests ran, and every merge relies on someone verifying
locally. A merge queue cannot replace the publication sweep without a required
check that carries real test evidence.

Solution

The runner is [self-hosted, sinnix-prime], registered by sinnix branch
feat/github-runner (services.github-runners.polylogue, non-ephemeral,
Slice = sinnixd-work.slice, work directory under /realm/state).

  • concurrency: { group: pytest, cancel-in-progress: false } — the host has one
    pytest slot; serialising in GitHub means a queued run waits there instead of
    holding a runner blocked on the slot, and a run already proving a revision is
    never discarded.
  • clean: false on checkout keeps the runner's gitignored state — the testmon
    datafile and the devshell venv — so a run selects rather than reseeding. The
    seed step only fills in a datafile the runner does not have yet, copying from
    the primary checkout; a missing seed reports a full run rather than refusing.
  • pytest itself goes through the host's pueue pytest group automatically
    (devtools/pytest_slot.py), so the job plane's memory ceiling applies where
    the work runs.

Verification

nix develop --command devtools verify --quick

12 gates ok (format, lint, mypy, generated-surfaces, layering, patterns,
doc-commands, schema-versioning, oracle-integrity, consumer-reachability,
timestamp-doctrine, schema-privacy).

The verify job cannot execute until the operator mints the runner token and
the sinnix change is deployed; this PR adds the workflow only.

Making the check required

Not done here. After the runner has reported verify at least once:

gh api --method PATCH repos/Sinity/polylogue/branches/master/protection/required_status_checks \
  -H "Accept: application/vnd.github+json" \
  -F strict=false \
  -f "checks[][context]=verify"

Residual risk

  • The runner is a shared workstation with a persistent work directory; a
    workflow change could read or write host state outside the checkout. Branch
    protection on master is the control.
  • clean: false means stale untracked files survive between runs. devtools verify reports an interpreter or package change as a full run, so a poisoned
    venv shows up as a slow run, not a false green.

🤖 Generated with Claude Code

https://claude.ai/code/session_01YGi8wLWGR2HYBh8p8fXFXz

Per-PR hosted CI runs only the quick gate, so a green PR check does not mean
tests ran. This workflow runs the selected `devtools verify` on the
workstation runner, on pull_request and merge_group, and uploads the run
receipt.

`concurrency: pytest` with cancel-in-progress false serialises against the
host's single pytest slot in GitHub rather than in a held runner, and never
discards a run already proving a revision.

`clean: false` on checkout keeps the runner's gitignored state -- the testmon
datafile and the devshell venv -- so a run selects instead of reseeding; the
seed step only fills in a datafile the runner does not yet have, and a missing
seed reports a full run rather than refusing.

Verification: nix develop --command devtools verify --quick (12 gates ok).
The job itself cannot run until the runner is registered (sinnix
feat/github-runner) and made required.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YGi8wLWGR2HYBh8p8fXFXz
@Sinity
Sinity merged commit 854baa3 into master Sep 3, 2026
1 of 4 checks passed
@coderabbitai

coderabbitai Bot commented Sep 3, 2026

Copy link
Copy Markdown

Important

  • 🔍 Trigger review

This repository does not receive automatic reviews because it has fewer than 10 stars.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Team

Run ID: 8a70094e-4a6f-4c2c-b183-643cb519edaf


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@Sinity
Sinity deleted the ci/self-hosted-verify branch September 3, 2026 04:46
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Sep 3, 2026

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review Completed 2026-09-03T04:52:41.810712Z e353603 PR opened
ℹ️ 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" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: e353603d5a

ℹ️ 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".

fi

- name: Verify
run: nix develop --command devtools verify

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Keep pull-request code off the persistent workstation

When a pull request changes flake.nix or devtools, this step evaluates and executes that untrusted revision directly as the self-hosted runner user. The read-only GitHub token does not restrict filesystem access, and branch protection does not sandbox feature-branch code, so such a PR can read or modify workstation state and persist code in the ignored .venv retained by clean: false; use an isolated ephemeral runner or require an explicit trust gate before dispatching to this host. This is especially incompatible with the repository's requirement to keep operator archives and other private local state outside public artifacts.

AGENTS.md reference: AGENTS.md:L13-L17

Useful? React with 👍 / 👎.

# GitHub rather than holding a runner while blocked on the slot, and a run that
# is already proving a revision is never discarded.
concurrency:
group: pytest

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Avoid canceling pending merge-queue verification runs

With one run active and another pending in this repository-wide pytest group, a third pull-request or merge-group event replaces and cancels the existing pending run even though cancel-in-progress is false. For example, an incoming PR synchronization can cancel a queued merge-group check, leaving that merge candidate with a canceled required verify result instead of test evidence; remove this concurrency group or scope it per ref and let the already-mandatory host pueue slot serialize pytest.

AGENTS.md reference: AGENTS.md:L147-L149

Useful? React with 👍 / 👎.

fi

- name: Verify
run: nix develop --command devtools verify

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Fail when dependency synchronization does not complete

When a PR changes pyproject.toml or uv.lock and the devshell's uv sync --frozen fails, the shell hook only prints dependency sync INCOMPLETE and still runs this command from the retained old .venv. Because the installed-package identity remains unchanged, testmon can continue selecting against the old environment and the required check can pass without ever testing the dependency versions declared by the PR; add a CI provisioning step that fails the job, or make the shell hook failure fatal in this workflow.

Useful? React with 👍 / 👎.

fi

- name: Verify
run: nix develop --command devtools verify

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Cancel the queued pytest task when the Actions job stops

If this job is manually canceled or reaches its 120-minute timeout while pytest is active, devtools.pytest_slot._queue stops waiting but never cancels the task already submitted to the user pueue daemon. That detached pytest therefore keeps using this persistent workspace after Actions starts another job and checks out a different revision into it, corrupting both the test result and the shared testmon graph; the workflow needs cancellation cleanup that terminates the submitted pueue task before releasing the runner workspace.

AGENTS.md reference: AGENTS.md:L147-L149

Useful? React with 👍 / 👎.

if [ -f .cache/testmon/testmondata ]; then
echo "runner already has a datafile; keeping it"
elif [ -f "$seed" ]; then
cp "$seed" .cache/testmon/testmondata

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Copy the seed only while the testmon database is quiescent

On the runner's first invocation, this plain file copy occurs before devtools verify acquires the host pytest slot, so a local managed pytest run can be writing the source SQLite datafile at the same time. A page-level copy during that commit can leave the runner with a corrupt graph; verify then reports graph_unusable, and every later seed step keeps the bad destination instead of replacing it. Take the seed through SQLite's backup mechanism or perform and validate the copy while holding the same host slot used by writers.

AGENTS.md reference: AGENTS.md:L141-L149

Useful? React with 👍 / 👎.

fi

- name: Verify
run: nix develop --command devtools verify

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Run a fallback when testmon selects no tests

This invokes the default affected-test mode, and devtools converts a zero-test selection into the blocking pytest_no_tests_selected result. A documentation-only PR can therefore never obtain this required check from an up-to-date graph; likewise, after the PR run advances the persistent graph, a single-PR merge-group tree with identical file contents selects nothing and fails even though the same revision was just proven. Use --all for the required merge-queue check or explicitly provide a non-vacuous fallback for an empty affected selection.

AGENTS.md reference: AGENTS.md:L141-L145

Useful? React with 👍 / 👎.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant