Skip to content

ci: run jobs on gcrunner - #18

Merged
levivannoort merged 3 commits into
mainfrom
ci/gcrunner
Oct 13, 2026
Merged

levivannoort merged 3 commits into
mainfrom
ci/gcrunner

Conversation

@levivannoort

@levivannoort levivannoort commented Oct 13, 2026 •

Copy link
Copy Markdown
Member

What

GitHub-hosted runners don't start jobs for this repository while it's private ("The job was not started because recent account payments have failed or your spending limit needs to be increased"), so CI hasn't run since 2026-10-12. This moves the CI workflows to Appwrite's gcrunner runners, as appwrite/appwrite uses: an ephemeral Compute Engine VM per job.

Workflow Runner
Lint and test, Workflow lint, Renovate generate c3d-standard-4
Install (each scenario, and Install result) c3d-standard-4: the 4 vCPUs and 16 GB of a public GitHub runner, double what the private runners had
Nightly end-to-end c3d-standard-8
Security scan, Upstream drift c3d-standard-4
Release, Scorecard unchanged, GitHub-hosted
  • Labels follow appwrite/appwrite's ci.yml: gcrunner=<run id>-<job>-<index>/machine=<type>, unique per job. The machine is set in the label, so no .github/gcrunner.yml is needed; c3d is the family Appwrite's runners already use.
  • Pull requests from forks ask for ubuntu-latest (same expression as appwrite/appwrite). This is not a security boundary (hansi-codes, below): a fork PR runs its own copy of the workflow and can ask for gcrunner, and gcrunner provisions any queued job with a gcrunner label. No risk while the repository is private (GitHub doesn't run fork PR workflows there by default); before it goes public, see Before going public.
  • Release and Scorecard stay on GitHub-hosted runners: Scorecard only publishes results from them, and the release's provenance attestation should name GitHub's runners rather than a self-hosted VM. Both only run once the repository is public, where hosted runners are free.
  • CONTRIBUTING.md explains the runners.

skip-changelog: CI only.

Before going public

One of these has to be in place, or a fork PR can run arbitrary code on a VM in Appwrite's GCP project:

  • Repository admin: Settings → Actions → General → Approval for running fork pull request workflows → Require approval for all external contributors. Runs from forks then wait for a maintainer, who must not approve one that changes runs-on. The stopgap; CONTRIBUTING.md says this.
  • gcrunner: refuse jobs from fork pull requests: appwrite-labs/gcrunner#26, merged and deployed. The real fix; also covers appwrite/appwrite.

Testing

  • actionlint and zizmor (1.30.1, the repository's config) are clean.
  • This pull request's own checks are the real test: it changes lint.yaml, actions-lint.yaml and test-install.yaml, so Lint and test, Workflow lint and Install all run on gcrunner. If they stay queued, the gcrunner GitHub App isn't installed on this repository yet (an org owner adds it).
  • All checks passed on gcrunner: Lint and test (10), Workflow lint (2), Install (9 scenarios and Install result, twice). The Artifact Hub lint container failed as --user 1001 (the gcrunner runner user has another uid), fixed by running ah with docker run -u "$(id -u):$(id -g)".
  • Nightly end-to-end from this branch on c3d-standard-8: passed in 5 minutes, including a node-22 function built as a Kubernetes Job and executed on Docker-in-Docker.

After merging

#16 and #17 run their checks from their own branches, so rebase them on main to pick up the runners.

GitHub-hosted runners don't start jobs for this repository while it's
private ("recent account payments have failed or your spending limit needs
to be increased"), so nothing has run since 2026-10-12. Lint, Workflow lint,
Install, Nightly end-to-end, Security scan, Renovate generate and Upstream
drift now run on Appwrite's gcrunner runners (an ephemeral Compute Engine VM
per job), as appwrite/appwrite does: c3d-standard-8 for the nightly,
c3d-standard-4 for everything else, so the install jobs get the 4 vCPUs and
16 GB of a public GitHub runner.

Pull requests from forks fall back to ubuntu-latest, as in appwrite's ci.yml,
so code from outside the repository never runs on Appwrite's machines.
Release and Scorecard stay on GitHub-hosted runners: Scorecard only publishes
results from them, and the release's provenance should name GitHub's
runners. Both only run once the repository is public.
@levivannoort levivannoort added the skip-changelog Changes users won't notice: no CHANGELOG.md entry needed label Oct 13, 2026
@hansi-codes

hansi-codes Bot commented Oct 13, 2026 •

Copy link
Copy Markdown

🟢 Tier S · Ready to merge

The pull request moves selected CI workflows to Appwrite gcrunner VM runners while keeping Release and Scorecard on GitHub-hosted runners. It documents the runner setup and fork-approval caveat, runs Artifact Hub lint as the runner UID, and updates Renovate to track the lint image. The latest commit clarifies in CONTRIBUTING.md that the workflow runner expression is not a security boundary and describes the approval requirement before the repository becomes public.

Latest changes: The latest commit updates CONTRIBUTING.md to explain that fork-controlled workflows can request gcrunner and to document the approval guard required before the repository is public.

Verdict New comments Fixed Still open
💬 Commented 0 0 0
📂 Walkthrough · 9
File Change
.github/workflows/actions-lint.yaml Routes workflow lint jobs to gcrunner except for fork pull requests.
.github/workflows/e2e-nightly.yaml Moves nightly end-to-end testing to a c3d-standard-8 gcrunner.
.github/workflows/lint.yaml Routes lint and test jobs to gcrunner and runs Artifact Hub lint as the runner UID.
.github/workflows/renovate-generate.yaml Moves Renovate generation to a c3d-standard-4 gcrunner.
.github/workflows/security-scan.yaml Moves security scans to c3d-standard-4 gcrunners.
.github/workflows/test-install.yaml Routes install scenarios and the result job to gcrunner except for fork pull requests.
.github/workflows/upstream-drift.yaml Moves upstream drift checks to a c3d-standard-4 gcrunner.
CONTRIBUTING.md Documents gcrunner usage, GitHub-hosted exceptions, and the fork-workflow approval guard before the repository becomes public.
renovate.json Updates Renovate's Docker image matcher to track the Trivy and Artifact Hub lint images.

Reviewed the commits since 77c7304 · Details · Comment @hansi-codes review to re-run, or mention @hansi-codes with a question.

@hansi-codes hansi-codes 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.

⛔ Tier F · 1 blocking finding to address. Summary

Comment thread .github/workflows/lint.yaml
As a job container with --user 1001, ah couldn't write the runner's files on
gcrunner, whose runner user has another uid (EACCES on
_runner_file_commands). docker run with the runner's own uid works on any
runner. Renovate keeps the image current through the Trivy image's custom
manager, now matching AH_IMAGE too.
A pull request runs its own copy of the workflow, so a fork can rewrite
runs-on and ask for gcrunner, which doesn't check where a job comes from.
Say so, and name the guard for a public repository: maintainer approval of
every fork pull request's workflow runs.
@levivannoort
levivannoort merged commit 5d6af31 into main Oct 13, 2026
22 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

skip-changelog Changes users won't notice: no CHANGELOG.md entry needed

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant