Skip to content

Run Dependabot pull requests on GitHub-hosted runners - #553

Merged
leynos merged 1 commit into
mainfrom
dependabot-hosted-runners
Oct 25, 2026
Merged

leynos merged 1 commit into
mainfrom
dependabot-hosted-runners

Conversation

@leynos

@leynos leynos commented Oct 19, 2026 •

Copy link
Copy Markdown
Owner

Part of DF12-89

Rollout of the pattern in leynos/typos-config-builder#152 (reviewed and merged): Dependabot pull requests on a public repository run on GitHub-hosted runners, not Ubicloud. User decision of 19 October 2026.

Change

Every Ubicloud runs-on that has the fork fallback gains the Dependabot arm, in the pilot's shape:

runs-on: >-
  ${{ (github.event.pull_request.head.repo.fork
  || github.event.pull_request.user.login == 'dependabot[bot]')
  && 'ubuntu-latest' || 'ubicloud-standard-N' }}
  • pull_request.user.login (the author), not github.actor, which changes on a re-run.
  • Pushes to main have no pull_request payload and stay on Ubicloud, so main's caches stay warm.
  • runner_placement_test.py reads the combined condition and requires it on both ci.yml lanes; runner_labels_test.py uses the new expression. Wildside is heavy: its build job took 70m32s cold on standard-8 and 86m46s on standard-4 against a 90-minute cap, and a Dependabot build is cold on ubuntu-latest (4 vCPU). After merge I will measure one real Dependabot run; if it fails for a runner reason (timeout, disk, memory) the follow-up PR keeps that job on Ubicloud with a comment giving the run URL, per the packet. Bespoke contract, so this PR takes the full review gate.
  • docs/developers-guide.md records the reason and the cold-cache consequence.

Check script row (before)

["wildside", "pending", "3 ubicloud jobs, 1 lacking the arm"] from ~/docs/jm5-dependabot-runners/bin/check.py on origin/HEAD before this change.

Gates

pytest --doctest-modules tests/workflow_contracts: 584 passed; the 22 failures are the typedoc documentation-gate tests (documentation_gate*_test.py), which need the workspace's installed Node tooling and fail identically without this change. The runner contracts pass. mdtablefix --check clean.

Mutation proof

Mutation Result
ci.yml: user.login replaced by actor (all jobs) killed
ci.yml: Dependabot arm removed (first job) killed
contract tests/workflow_contracts/runner_placement_test.py: `HOSTED_CONDITION: typ.Final[str] = f"({FORK_FIELD}

Merge class

Mechanical rollout of the pilot's shape (same expression, same form of contract change, docs paragraph, mutation proof), per the lead's ruling of 19 October.

Overlapping open PRs

These open PRs touch the same kind of files; per the standing rulings they do not hold this PR and are left untouched:

Summary by Sourcery

Route Dependabot pull requests to GitHub-hosted runners while preserving Ubicloud execution for trusted events.

New Features:

  • Run Dependabot pull-request jobs on GitHub-hosted runners while retaining Ubicloud runners for other workflows.

Enhancements:

  • Extend runner contract validation to require the combined fork-or-Dependabot placement condition.

Documentation:

  • Document the Dependabot runner selection and its cold-cache implications for contributors.

Tests:

  • Update workflow contract tests to validate the Dependabot-aware runner expression.

Selector proof

Selector proof: natural Dependabot runs on ubuntu-latest, all green: https://github.com/leynos/actix-v2a/actions/runs/39958329992, https://github.com/leynos/typos-config-builder/actions/runs/39990740324, https://github.com/leynos/agentland/actions/runs/39965006591; and a main push staying on ubicloud-standard-2: https://github.com/leynos/typos-config-builder/actions/runs/39181228629.

@coderabbitai

coderabbitai Bot commented Oct 19, 2026 •

Copy link
Copy Markdown
Contributor

Review in Change Stack →

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

No actionable comments were generated in the recent review.

ℹ️ Recent review info
⚙️ Run configuration
  • Configuration used: Organization UI
  • Review profile: ASSERTIVE
  • Plan: Team
  • Run ID: 451145a9-ced8-4941-a6b2-e9b7d126853c
📥 Commits

Reviewing files that changed from the base of the PR and between cbdb5ac and 8fde08a.

📒 Files selected for processing: 4
  • .github/workflows/ci.yml
  • docs/developers-guide.md
  • tests/workflow_contracts/runner_labels_test.py
  • tests/workflow_contracts/runner_placement_test.py
🔗 Linked repositories identified

CodeRabbit considers these linked repositories for cross-repo context during reviews:

Included review availability: This review used your included allowance. 5 included reviews remain after this review. Your included PR review attempts over the past 7 days set your current allowance at 10 reviews per hour.

Summary

Route fork and Dependabot pull requests to ubuntu-latest. Keep other events, including pushes to main, on ubicloud-standard-8.

Changes

  • Detect Dependabot with github.event.pull_request.user.login == 'dependabot[bot]'.
  • Update runner placement and label contract tests.
  • Document cold-cache implications in docs/developers-guide.md.
  • Follow the reviewed pilot pattern from typos-config-builder PR #152.

Validation

  • pytest --doctest-modules tests/workflow_contracts: 584 passed.
  • mdtablefix --check: passed.
  • 22 typedoc documentation-gate tests failed due to missing workspace Node tooling; the failures are unchanged by this PR.
  • Mutation checks killed mutations for Dependabot detection and runner placement.

Walkthrough

Build and coverage jobs now use ubuntu-latest for pull requests from forks or authored by Dependabot. Other events retain ubicloud-standard-8. The developer guide and workflow contract tests describe and check this selection.

Changes

Runner selection

Layer / File(s) Summary
Update workflow runner selection
.github/workflows/ci.yml
The build and coverage jobs select ubuntu-latest for fork or Dependabot-authored pull requests. Other events use ubicloud-standard-8.
Document and test runner selection
docs/developers-guide.md, tests/workflow_contracts/*
The guide explains the conditions and distinguishes the pull request author from the triggering actor. The contract tests check the runner labels and the combined condition. The runner-expression parser now accepts parenthesised compound conditions.

Suggested labels: Issue

Priority: Low

Change: Feature

Merge Risk: Minimal · up to 8fde0

The change is ready to merge with no concrete current-head risk identified.

Pre-merge checks: Passed 14 · Failed 1

Failed Failed checks: 1 warning

Check name Status Explanation Resolution
Title check Warning The title accurately describes the main change. However, the description references DF12-89, and the title does not include the required issue reference. Add the referenced issue identifier to the title, for example: "Run Dependabot pull requests on GitHub-hosted runners (DF12-89)" or the required GitHub issue format if available.
Passed Passed checks: 14 passed
Check name Status Explanation
Docstring Coverage Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 1 functions across 2 files. (2 skipped: 2 …
Linked Issues check Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check Passed Check skipped because no linked issues were found for this pull request.
Testing (Overall) Passed The new runner-selection behaviour has substantive contract coverage. tests/workflow_contracts/runner_placement_test.py:113-123, 172-212 discovers every Ubicloud lane reachable from a pull_request…
User-Facing Documentation Passed Treat this check as not applicable. The pull request changes only CI runner selection and workflow contract tests; it does not change Wildside server behaviour, an API, a CLI, or an end-user interface…
Developer Documentation Passed The CI runner change is a tooling and build-placement change, and the pull request documents it in docs/developers-guide.md:236-263. The guide records the hosted-runner condition for fork and Depend…
Module-Level Documentation Passed Pass. The pull request changes two Python modules, and both have clear module-level docstrings. runner_labels_test.py documents the reader's purpose, behaviour, and use by placement contracts (lines…
Testing (Unit And Behavioural) Passed Pass the testing check. The updated workflow contract reads the committed workflow and parametrizes every Ubicloud job reachable from a pull request (tests/workflow_contracts/runner_placement_test.py:…
Testing (Property / Proof) Passed The change does not require property-based testing. It adds a small Boolean condition with two predicates: fork status and exact Dependabot author login. The meaningful input space is a short, auditab…
Testing (Compile-Time / Ui) Passed PASS — The pull request changes GitHub Actions YAML, Markdown, and Python contract tests only. It introduces no Rust or TypeScript compile-time behaviour, so no trybuild-equivalent test applies. The r…
Unit Architecture Passed PASS — The change introduces no query, command, storage, network, clock, or process operation. It updates declarative runs-on expressions in .github/workflows/ci.yml:60-63, 677-680 and keeps the r…
Domain Architecture Passed PASS — The pull request changes only GitHub Actions runner selection, workflow-contract tests, and developer documentation. It does not change domain models, commands, repositories, adapters, transpor…
Observability Passed Accept the change. It alters CI runner placement, not production service behaviour. GitHub Actions exposes the selected runner, job duration, status, and failure logs. Existing ci.yml diagnostics al…
Description check Passed The pull request description directly matches the changes. It describes routing Dependabot and fork pull requests to GitHub-hosted runners, preserving Ubicloud runners for other events, updating contr…
Full details: Docstring Coverage

Explanation

Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 1 functions across 2 files. (2 skipped: 2 unsupported.)

Full details: Testing (Overall)

Explanation

The new runner-selection behaviour has substantive contract coverage. tests/workflow_contracts/runner_placement_test.py:113-123, 172-212 discovers every Ubicloud lane reachable from a pull_request, parses its complete runs-on expression, and requires the exact (github.event.pull_request.head.repo.fork || github.event.pull_request.user.login == 'dependabot[bot]') condition with ubuntu-latest as the hosted arm and an Ubicloud fallback. This rejects the plausible incorrect implementations of using github.actor, omitting the Dependabot arm, swapping the labels, or leaving a lane unchanged. tests/workflow_contracts/runner_labels_test.py:21-30 also verifies that the expression reader returns both labels. The tests therefore exercise the changed workflow configuration rather than only checking mocks or test setup.

Full details: User-Facing Documentation

Explanation

Treat this check as not applicable. The pull request changes only CI runner selection and workflow contract tests; it does not change Wildside server behaviour, an API, a CLI, or an end-user interface. The internal CI guidance is documented in docs/developers-guide.md (lines 228-254), while the repository policy reserves docs/users-guide.md for users who apply the project rather than modify its internals (lines 103-118). No user-guide update or migration note is required.

Full details: Developer Documentation

Explanation

The CI runner change is a tooling and build-placement change, and the pull request documents it in docs/developers-guide.md:236-263. The guide records the hosted-runner condition for fork and Dependabot pull requests, the use of pull_request.user.login instead of github.actor, the non-pull-request fallback, and the cold-cache consequence. The reviewed diff adds no new ExecPlan or roadmap item, and no parallel locale documentation set is present. The change does not introduce an internal API or system architecture boundary that requires a separate design document or ADR.

Full details: Module-Level Documentation

Explanation

Pass. The pull request changes two Python modules, and both have clear module-level docstrings. runner_labels_test.py documents the reader's purpose, behaviour, and use by placement contracts (lines 1-13). runner_placement_test.py documents the runner-placement rule, its purpose, and its relationship to workflow triggers and coverage-main.yml (lines 1-24). The other changed files are YAML and Markdown, not modules.

Full details: Testing (Unit And Behavioural)

Explanation

Pass the testing check. The updated workflow contract reads the committed workflow and parametrizes every Ubicloud job reachable from a pull request (tests/workflow_contracts/runner_placement_test.py:113-145). It parses the complete runs-on expression and requires the fork condition, the pull_request.user.login == 'dependabot[bot]' arm, ubuntu-latest, and the Ubicloud fallback (lines 176-212). The runner-label tests cover the new expression and retain accepted-form and refusal-path cases (runner_labels_test.py:21-116). These tests exercise the workflow configuration boundary, not only private helpers or mocks.

Full details: Testing (Property / Proof)

Explanation

The change does not require property-based testing. It adds a small Boolean condition with two predicates: fork status and exact Dependabot author login. The meaningful input space is a short, auditable truth table, not a large range of states or orderings. The contract tests enumerate every reachable Ubicloud lane in runner_placement_test.py and assert the complete expression shape at lines 113-123 and 143-212. runner_labels_test.py also uses a focused parameterized case for the new expression at lines 21-30. No introduced lemma or proof assumption requires an exhaustive proof.

Full details: Testing (Compile-Time / Ui)

Explanation

PASS — The pull request changes GitHub Actions YAML, Markdown, and Python contract tests only. It introduces no Rust or TypeScript compile-time behaviour, so no trybuild-equivalent test applies. The runner changes are structured configuration, not rendered or UI-adjacent output. Focused assertions in tests/workflow_contracts/runner_labels_test.py:21-30 and tests/workflow_contracts/runner_placement_test.py:193-212 verify the labels, condition, and fallback arms directly; snapshots would add brittleness without testing a user-facing output.

Full details: Unit Architecture

Explanation

PASS — The change introduces no query, command, storage, network, clock, or process operation. It updates declarative runs-on expressions in .github/workflows/ci.yml:60-63, 677-680 and keeps the runner policy explicit through HOSTED_CONDITION and a focused parser assertion in tests/workflow_contracts/runner_placement_test.py:42-63, 193-209. The label test remains a pure input/output contract in tests/workflow_contracts/runner_labels_test.py:21-30. No new hidden dependency, mutation, or mixed responsibility is introduced.

Full details: Domain Architecture

Explanation

PASS — The pull request changes only GitHub Actions runner selection, workflow-contract tests, and developer documentation. It does not change domain models, commands, repositories, adapters, transport, persistence, or infrastructure-facing domain logic. The runner expressions remain in workflow configuration, so no domain boundary is introduced or weakened.

Full details: Observability

Explanation

Accept the change. It alters CI runner placement, not production service behaviour. GitHub Actions exposes the selected runner, job duration, status, and failure logs. Existing ci.yml diagnostics also record runner/image-scoped cache keys and cache hits in the step summary (lines 148-165 and 639-664), plus sccache statistics (lines 562-588). The pull request documents the expected cold-cache effect. No new service boundary, sensitive logging, unbounded metric label, or actionable alert requirement is introduced.

Full details: Description check

Explanation

The pull request description directly matches the changes. It describes routing Dependabot and fork pull requests to GitHub-hosted runners, preserving Ubicloud runners for other events, updating contract tests, and documenting the policy.

  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Forks and Dependabot take the hosted lane
Build and coverage follow the rule
Other events keep their managed runner
Tests check the labels and condition
The guide records how the choice is made

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

@sourcery-ai

sourcery-ai Bot commented Oct 19, 2026

Copy link
Copy Markdown

Reviewer's Guide

This PR rolls out the established runner-placement pattern so Dependabot pull requests on the public repository use ubuntu-latest, while normal trusted workflows remain on Ubicloud; documentation and contract tests are updated to specify and enforce the exact condition.

Sequence diagram for runner selection on pull requests

sequenceDiagram
    participant GitHub
    participant Workflow as ci.yml
    participant Runner
    GitHub->>Workflow: Trigger pull_request
    Workflow->>Workflow: Read pull_request.head.repo.fork
    Workflow->>Workflow: Read pull_request.user.login
    alt Fork or Dependabot author
        Workflow->>Runner: Select ubuntu-latest
    else Trusted non-Dependabot workflow
        Workflow->>Runner: Select ubicloud-standard-8
    end
Loading

Flow diagram for Dependabot runner placement

flowchart TD
    A[Pull request or workflow event] --> B{Fork pull request?}
    B -->|Yes| C[ubuntu-latest]
    B -->|No| D{"Author is dependabot[bot]?"}
    D -->|Yes| C
    D -->|No| E[ubicloud-standard-8]
    F[Push to main or manual dispatch] --> E
Loading

File-Level Changes

Change Details Files
Route Dependabot pull-request jobs to GitHub-hosted runners while preserving Ubicloud for trusted workloads.
  • Extended both applicable CI jobs’ runner expressions to select ubuntu-latest for forked pull requests or pull requests authored by dependabot[bot].
  • Used the pull-request author rather than github.actor, keeping reruns or pushes by other users from changing placement.
  • Preserved Ubicloud placement for pushes to main and manual dispatches, where no pull-request payload is present.
.github/workflows/ci.yml
Document the runner-placement policy and its operational trade-offs.
  • Explained the Dependabot-specific routing rationale and author-versus-actor distinction.
  • Documented the absent pull-request context behavior and cold-cache cost on hosted runners.
docs/developers-guide.md
Update workflow contract tests to enforce the combined fork-or-Dependabot condition.
  • Updated expected runner labels for the new expression.
  • Added shared condition constants and broadened expression parsing to support parenthesized conditions.
  • Required both paid CI lanes to use the exact hosted-runner condition.
tests/workflow_contracts/runner_labels_test.py
tests/workflow_contracts/runner_placement_test.py

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

codescene-access[bot]

This comment was marked as outdated.

@leynos
leynos marked this pull request as ready for review October 21, 2026 22:47
@sourcery-ai

sourcery-ai Bot commented Oct 21, 2026

Copy link
Copy Markdown

Sorry @leynos, you've used your own review budget of 250,000 diff characters for the last 7 days.

You can request another review in 21 hours and 12 minutes by commenting @sourcery-ai review. Upgrade to get a review now.

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 21, 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 ⚠️ Failed 2026-10-21T22:47:41.466435Z
We couldn’t complete this review. Comment @codex review to try again.
8fde08a Draft marked ready
🔒 Security Review ⚠️ Failed 2026-10-21T22:47:48.406646Z
We couldn’t complete this review. Comment @codex security review to try again.
8fde08a Draft marked ready
ℹ️ 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

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.
To continue using code reviews, add credits to your account and enable them for code reviews in your settings.

@chatgpt-codex-connector

Copy link
Copy Markdown

The account paying for this security review has reached its Codex usage limits. The payer can check the Codex usage dashboard. For personal accounts, using credits requires enabling “Use credits for security reviews” in Code review settings. If you do not manage the paying account, contact this repository's admins.

@coderabbitai coderabbitai Bot added the Issue label Oct 21, 2026
@buzzybee-df12

Copy link
Copy Markdown
Collaborator

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Oct 22, 2026 •

Copy link
Copy Markdown
Contributor
⚠️ Action not completed

Already reviewed the last commit. Use @coderabbitai full review to rerun a review of the entire changeset.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@pandalump

Copy link
Copy Markdown
Collaborator

Rebased onto main only because the squash merge of a branch whose workflow file diverged from main needs the workflow OAuth scope. Range-diff against the reviewed head (all =):

1:  8fde08ad = 1:  0d571f2f Place Dependabot pull requests on GitHub-hosted runners

codescene-access[bot]

This comment was marked as outdated.

GitHub-hosted minutes cost nothing on a public repository, so a pull request
authored by dependabot[bot] now falls back to ubuntu-latest like a fork's.
The expression tests pull_request.user.login rather than github.actor, which
changes when someone re-runs or pushes. A push to main has no pull_request
payload and stays on Ubicloud, so main still writes the cache.

`runner_placement_test.py` reads the combined condition and requires it on both `ci.yml` lanes; `runner_labels_test.py` uses the new expression. Wildside is heavy: its `build` job took 70m32s cold on standard-8 and 86m46s on standard-4 against a 90-minute cap, and a Dependabot build is cold on `ubuntu-latest` (4 vCPU). After merge I will measure one real Dependabot run; if it fails for a runner reason (timeout, disk, memory) the follow-up PR keeps that job on Ubicloud with a comment giving the run URL, per the packet. Bespoke contract, so this PR takes the full review gate.
@leynos
leynos force-pushed the dependabot-hosted-runners branch from 0d571f2 to eed9d3d Compare October 24, 2026 23:08
@buzzybee-df12

Copy link
Copy Markdown
Collaborator

Rebased onto main after the audit fix (#562) landed. Range-diff against the reviewed head (all =). #559 touches the same runs-on lines; whichever merges second keeps both changes.

1:  0d571f2f = 1:  eed9d3d5 Place Dependabot pull requests on GitHub-hosted runners

@leynos
leynos merged commit e7ab91e into main Oct 25, 2026
8 checks passed
@leynos
leynos deleted the dependabot-hosted-runners branch October 25, 2026 10:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants