chore(ci): take fork-reachable jobs off the self-hosted runners (ENG-2017) - #88
Merged
mindsdb-devops merged 4 commits intoAug 28, 2026
Merged
Conversation
…2017) test_on_pr runs on pull_request and installed the pull request's own requirements.txt on mdb-dev, so an approved fork PR ran its own code on a pod in the newdev cluster. Move the matrix to ubuntu-latest. The hosted image carries builds for 3.8 through 3.11, so the matrix is unchanged. The CLA workflow moves to the shared reusable in the same change, which takes it off mdb-dev and pins the third-party action it runs. Refs: ENG-2017
7 tasks
…017) Both URLs the org uses for this document are rename redirects that resolve to the same repository and serve byte-identical content. A redirect is fine until somebody creates a repository at the old name, and this is the page a contributor reads before agreeing to it. Name the repository that actually holds the file. Refs: ENG-2017
…2017)
The allowlist moved into mindsdb/github-actions and is bots only. This repo
carried one of six hand-maintained copies naming people, and 11 of the 25 names
across those copies had already left the org while still being exempt from
signing. Staff sign like everybody else now. A bot cannot sign, so the two that
actually open pull requests in this org stay exempt in the reusable.
Dropping the line also drops two defects that rode inside it. `bot*` compiled to
an unanchored `new RegExp("bot.*").test(login)`, so it exempted any login
containing "bot", `robotnik` and `sabotage` included. And `Stpmax` never matched
the real login `StpMax`, because non-wildcard entries are compared with a
case-sensitive `===`.
Needs mindsdb/github-actions#56 first, which gives the input a default.
This repo accepts pull requests from outside contributors and had no CODEOWNERS at all, so a workflow change here needed no particular reviewer. Everything under .github/ decides what runs in CI, on which runner, and with which secrets in scope, which is a trust boundary rather than product code. Auto-request only for now. Making it a hard gate needs require_code_owner_reviews in branch protection, which this repo does not have; that rides ENG-2013's org ruleset.
mindsdb-devops
approved these changes
Aug 28, 2026
mindsdb-devops
deleted the
chore/eng-2017-fork-jobs-off-self-hosted-runners
branch
August 28, 2026 00:33
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to subscribe to this conversation on GitHub.
Already have an account?
Sign in.
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
User story
As an engineer who reviews external contributions to this repository
I want approving CI on a stranger's pull request to be a harmless act
So that a plausible-looking patch cannot execute its own code on a pod inside our clusters
Why this matters
test_on_pr.ymlruns onpull_requestwithruns-on: mdb-dev, which is a pod inside our newdev EKS cluster and not a GitHub VM. It checks out the pull request's head and runspip install -r requirements.txtagainst it. A fork owns that file, so an approved fork pull request installed and executed whatever it named, on a pod holding a Kubernetes identity, an AWS role and a filesystem other repositories' credentialed jobs write into.Separately,
cla.ymlran onmdb-devtoo. Its triggers,pull_request_targetandissue_comment, run in base-repo context, so GitHub's fork-approval gate never applied and any account could start that pod with no human in the loop.What happens today
flowchart TD F["Fork pull request"] --> APP{"Someone with push clicks Approve and run"} APP --> J["test job on mdb-dev"] J --> CO["Checks out the fork's tree"] CO --> PI["pip install -r requirements.txt, fork-controlled"]What should happen
flowchart TD F["Fork pull request"] --> APP{"Someone with push clicks Approve and run"} APP --> J["test job on ubuntu-latest"] J --> CO["Checks out the fork's tree"] CO --> PI["pip install runs on a disposable VM"]Acceptance criteria
test_on_pr.ymlno longer requestsmdb-dev.mdb-devand skips outright for a comment that is not a CLA comment.deploy.ymlandtest_on_deploy.ymlare untouched. They are release-triggered, not fork-reachable, and moving the publish job is a separate piece of work.clabranch, is unchanged.How to test
testmatrix runs onubuntu-latestfor all four Python versions and that no self-hosted job is offered a runner.Notes for the reviewer
The allowlist is gone from this file, and staff now sign like everybody else. Fifteen repositories carried six different hand-maintained copies naming 25 people between them, and 11 of those 25 had already left the org while still being exempt from signing. It now defaults in the reusable and is bots only:
dependabot[bot]andmindsdb-release-train[bot], the two that actually open pull requests in this org. A bot cannot post the agreement sentence, so without an exemption its pull request is red forever.Dropping the line also drops two live defects that rode inside it.
bot*compiled to an unanchorednew RegExp("bot.*").test(login), so it exempted any login containing "bot", includingrobotnikandsabotage; anyone could opt out of the CLA by choosing a username. AndStpmaxnever matched the real loginStpMax, because non-wildcard entries use a case-sensitive===. Needs mindsdb/github-actions#56, which gives the input its default..github/gets a code owner. This repo had no CODEOWNERS, so a change to what runs in CI, on which runner, and with which secrets in scope needed no particular reviewer, on a repo that accepts outside pull requests. Auto-request only for now: a hard gate needsrequire_code_owner_reviewsin branch protection, which this repo does not set and which rides ENG-2013's org ruleset. Faking it here would be a file that looks like a control and is not one.The green
CLAssistantrow on this pull request does not exercise this change.pull_request_targetloads the workflow from the base branch, so the check that passed here is the copy this PR replaces, running onmdb-dev. The new job cannot test itself on its own pull request; it is exercised on the first pull request opened after this merges.The
on:andpermissions:blocks swap places, which is why the diff looks bigger than it is. Every converted wrapper now reads name, permissions, triggers, job, in that order. No trigger and no scope changes as a result of the move itself.The matrix is unchanged, which needed checking rather than assuming. Python 3.8 has been end of life since 2024 and is not in the ubuntu-24.04 image, so the obvious worry is that
ubuntu-latestdrops half the matrix. I readactions/python-versions' manifest: 3.8, 3.9, 3.10 and 3.11 all publish ubuntu-24.04 x64 builds, sosetup-pythonresolves every one of them. Worth knowing thatubuntu-latestwill move to 26.04, and 3.8 and 3.9 have no 26.04 builds; that is a future matrix decision, not this one.deploy.ymlstill runs onmdb-devand this PR leaves it there. It publishes to PyPI with the sharedPYPI_PASSWORDorg secret, it is triggered byworkflow_runoff a release, and a fork cannot reach it. Moving it is the trusted-publishing work, which is its own ticket.The CLA change is the same one landing in nine sibling repositories, replacing a hand-rolled job with the reusable
anton,coworkandcowork-serveralready call. The reusable is hardened in the anchor PR: the action pinned to a commit, the event filter moved from the step to the job, theruns-oninput deleted, andactions: writereduced toactions: read.The agreement link names the canonical repository rather than a redirect. Every URL the org used for this document was a rename redirect. They all resolve to the same file and serve byte-identical content, so nothing changes for a reader today. A redirect stops being harmless the moment somebody creates a repository at the old name, and this is the page a contributor reads before agreeing to it.
Verified locally
actionlinton both changed filesdeploy.ymlandtest_on_deploy.yml, which this PR does not touch.actions/python-versionsversions-manifest.jsonlists ubuntu-24.04 x64 builds for 3.8.16+, 3.9.23+, 3.10.19+ and 3.11.14+. So the matrix survives the move with no edit.mindsdb/github-actions@main:ubuntu-latest, and after the anchor PR the input does not exist.clabranch, 10 signers, unchanged by this PR.Ships with
One behaviour across eleven repositories, one pull request each. The anchor is
mindsdb/github-actions, which hardens the shared CLA reusable this repo nowcalls. No
Deploys:line and no pull request environment: nothing here bringsone up.
Merge order: the anchor first, and that is a requirement rather than a
preference. This wrapper grants
actions: read, and untilmindsdb/github-actions#55 merges the reusable still declares
actions: write.A called workflow's permissions are enforced when its file is loaded, so a
callee naming a scope its caller has not granted rejects the whole run as a
startup_failurewith zero jobs, and there is no job left to report it. Therun is red, the CLA gate is down, and nothing announces either.
Refs: ENG-2017