Skip to content

feat(ci): build the scratchpad image on a GitHub-hosted runner with OIDC (ENG-2000) - #526

Draft
lucas-koontz wants to merge 2 commits into
stagingfrom
feat/eng-2000-hosted-scratchpad-build
Draft

lucas-koontz wants to merge 2 commits into
stagingfrom
feat/eng-2000-hosted-scratchpad-build

Conversation

@lucas-koontz

@lucas-koontz lucas-koontz commented Oct 4, 2026 •

Copy link
Copy Markdown
Contributor

User story

As an anton maintainer who merges to staging and main
I want the scratchpad image to build on a GitHub-hosted runner with an AWS role for its own tier
So that pull requests, staging pushes and releases keep publishing the worker image without a self-hosted runner

Why this matters

When an engineer opens a pull request or merges to staging or main, anton builds the scratchpad image, the sandbox pod image. Until now that build ran on a self-hosted runner, although GitHub recommends GitHub-hosted runners for public repositories like this one. Now it runs on ubuntu-latest and pushes with a short-lived AWS role that the job assumes through GitHub's OpenID Connect (OIDC) tokens. Pull request and staging images land in a new dev-tier repository, minds-anton-scratchpad-dev, and only a build from main pushes to minds-anton-scratchpad. The role's AWS account comes from an organization secret, so this public repository names no account id.

Test plan

Each line is a test in tests/test_fork_build_gate.py unless it says otherwise.

  • A pull request from a branch in this repo builds with no GitHub environment, assumes gha-anton-ecr-dev and pushes to minds-anton-scratchpad-dev.
  • A push to staging builds in the staging environment with gha-anton-ecr-dev. A push to main builds in the prod environment with gha-anton-ecr-prod and pushes to minds-anton-scratchpad.
  • The build names its AWS account only through the AWS_DEV_ACCOUNT_ID organization secret, both release pipelines pass that secret and no other, and no workflow names an account id.
  • Negative: a fork pull request skips the build, and the run summary says Build skipped: fork pull request.
  • Negative: a release pipeline that passes an environment other than staging or production fails the gate before the build starts.
  • Negative: a job that can mint an OIDC token, in a workflow an outside account can start, fails the test unless it carries the gate's condition.
  • Not run yet: a real build. It fails at the role step until the cloud roles and the secret exist.

Ships with

Part of ENG-2000.

  • Before the merge, the operator sets the AWS_DEV_ACCOUNT_ID organization secret for this repository, and creates its staging and prod environments: staging admits the staging branch and prod admits main. Neither environment exists yet.
  • Merge into staging after our infrastructure change applies and mindsdb/github-actions#71 merges, together with mindsdb/cowork#1117 and mindsdb/cowork-server#621, outside the weekly freeze.

The scratchpad image build runs on ubuntu-latest and pushes with a
short-lived AWS role it assumes through GitHub OIDC. GitHub recommends
GitHub-hosted runners for public repositories.

- Pull requests name no environment, assume gha-anton-ecr-dev and push
  to minds-anton-scratchpad-dev.
- Staging builds name the staging environment, assume gha-anton-ecr-dev
  and push to minds-anton-scratchpad-dev.
- Main builds name the prod environment, assume gha-anton-ecr-prod and
  push to minds-anton-scratchpad.

The gate job still skips fork pull requests. Its new target step picks
the environment, role and repository for each way in, and fails on any
other caller input. build-push-ecr runs with builder: local, so the
image builds on the runner itself. release.yml and publish-staging.yml
grant id-token: write on the calling job only. Third-party actions in
the build workflow are pinned by commit.

The gate tests run the target step for each way in. They also pin the
build job's wiring: the hosted runner, its own id-token grant, the role
step before the push, and each caller's grant. A new sweep requires the
gate on every job that can mint an OIDC token in a workflow an outside
account can start, and the runner sweep now covers the same workflows.
The actionlint config that declared the mdb-dev and mdb-prod labels is
gone, so actionlint flags any new use of them. The README and the
release docs page say where each build lands.

Work by Lucas Koontz for "Take the public repos off the credentialed
runner group and require devops to release a privileged run".

Refs: ENG-2000

This branch has not been deployed

No deployments
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