Ephemeral, isolated GitHub Actions runners powered by Qiniu Sandbox
中文 · Hosted Guide · Quick Start · Deploy to Qiniu LAS · Deployment Guide · Documentation · License · Community & Contributing
Qiniu Sandbox GitHub Runner provisions a clean Qiniu Sandbox for each GitHub Actions workflow job, registers a self-hosted runner just in time, and removes the runner and sandbox when the job ends. Teams keep the familiar GitHub Actions workflow while moving each job into a disposable environment.
The Qiniu CI Runner control plane is open source. Qiniu Sandbox, where workflow jobs execute, is a cloud service provided and operated by Qiniu.
- Ephemeral runners — one sandbox per job, automatically cleaned up after completion
- GitHub App auth — recommended production path with OAuth sign-in for the built-in web console
- Multi-database — SQLite (default), PostgreSQL, or MySQL for runtime state
- Concurrency control — global
max_concurrent_runnersand per-specmax_concurrencywith queue-based backpressure - Built-in web UI — admin console for runner requests, global runner specs, accounts, the platform Sandbox fallback, audit, matching, and diagnostics; ordinary-user console for job groups, logs, repository readiness, a platform Runner Spec catalog, scoped Sandbox management, and account/Organization custom Runner Specs
- Config obfuscation — sensitive values can be hidden from casual config inspection
- Retry & recovery — transient failures are retried with backoff; queued work and active remote runners are recovered after a service restart
GitHub webhook (workflow_job)
│
▼
┌─────────┐ create sandbox ┌──────────────────┐
│ runnerd │ ──────────────────────► │ Qiniu Sandbox │
│ (server) │ register runner │ (ephemeral VM) │
│ │ ──────────────────────► │ │
└─────────┘ │ GitHub Actions │
│ │ self-hosted │
│ job completed / timeout │ runner │
│◄────────────────────────────── │ │
│ stop & cleanup sandbox └──────────────────┘
▼
state DB (sqlite / postgres / mysql)
- GitHub sends a
workflow_job(queued) webhook to runnerd. - runnerd applies the repository allowlist, then matches the job labels against enabled Runner Specs.
- runnerd creates a Qiniu Sandbox instance and registers a self-hosted runner inside it.
- GitHub Actions dispatches the job to the runner; the job executes in the sandbox.
- When the job completes (or times out), runnerd removes the runner registration and stops the sandbox.
# 1. Build
task build
# 2. Create config from example
cp runnerd.yaml.example runnerd.yaml
# Edit runnerd.yaml: set database, GitHub App credentials, sandbox settings
# 3. Bootstrap the first admin (one-time, exits without starting the server)
./bin/runnerd --bootstrap-admin github:<github-user-id> --config runnerd.yaml
# 4. Start runnerd
./bin/runnerd --config runnerd.yaml- Open
http://<host>:25500/and sign in with GitHub OAuth. The public product landing page links to the same-origin/docsguides and the protected Jobs console at/jobs. On the first authenticated visit to/jobs, a six-step product tour introduces Jobs, Repositories, Settings, and Sandbox setup; it can be replayed from the account menu. - Open Repositories to review Runner readiness for the account or organization. Ready sources are shown without configuration controls. If Sandbox setup is missing and you can manage that scope, use Configure Sandbox to open the exact account or organization Preferences page and configure Sandbox Service credentials. Settings lists only your account and organizations where GitHub reports an active owner membership (
role: admin). Organization members, outside collaborators, and other repository-only users receive only read-only readiness and cannot browse that organization's configuration, Sandbox catalogs, or custom Runner Specs. Administrators can provide a fallback at/admin/sandbox_service. - Configure platform Runner Specs in Admin. Existing managed specs migrate with their labels and operator controls preserved; fresh installations require explicit creation. Enable catalog display only for verified public templates, whether referenced by name or ID. Standard and large template builds retain their regional release gates.
- Configure a GitHub webhook →
POST http://<host>:25500/webhooks/github. - Use the labels configured for an enabled Runner Spec, for example
runs-on: [qiniu, ubuntu-24.04]if an administrator has created a matching spec. Fresh installations do not create this example spec automatically.
Organization owners can open Settings → Fork sponsorship to let trusted personal forks use the organization's Sandbox service for managed Runner Specs. A policy is bound to the upstream repository's stable GitHub ID, starts disabled, has its own positive concurrency limit, and can require an exact fork approval, upstream write permission, or active organization membership. The Job and GitHub Runner remain owned by the fork; organization Cache S3, custom Runner Specs, physical template IDs, Runner Groups, credentials, and provider catalogs are never inherited. See Sponsor trusted forks with an organization Sandbox for the platform workflow and Organization-Sponsored Fork Runners for implementation details.
For local development, use task dev with runnerd.local.yaml. See docs/testing.md for detailed local setup including GitHub App creation and webhook forwarding.
runnerd reads ./runnerd.yaml by default, or the path passed with --config. See runnerd.yaml.example for a fully commented reference.
| Section | Description |
|---|---|
server |
Listen address, read/write/idle timeouts |
database |
Backend (sqlite / postgres / mysql) and DSN |
auth |
Session secret, encryption key, session TTL |
sandbox |
Sandbox lifecycle timeouts (create, run, stop) |
github |
Webhook secret, auth method (App / PAT / basic), OAuth, allowed repositories |
worker |
Lease, retry, and concurrency settings |
Key notes:
- Relative
database.dsnandgithub.app.private_key_filepaths resolve from the config file's directory. - Use SQLite for local and single-node deployments. PostgreSQL and MySQL are supported but multi-instance operation on a shared database has not been verified.
- CI creates fresh PostgreSQL and MySQL schemas and reruns migration against an existing catalog before exercising policy-free matching. See docs/testing.md for the opt-in local real-dialect command.
- Existing SQLite
runner_requestsandrunner_profilestables add missing model columns and indexes on startup without table recreation. This preserves historical runner values plus legacy profile rows and indexes. Creating missing indexes does not rewrite rows, but it can add brief startup I/O and lock contention on a large database; see docs/testing.md for migration and query-plan checks. - GitHub Enterprise Server is not supported; use a GitHub.com App.
- Configure exactly one GitHub auth method:
github.app,github.token, orgithub.basic_auth. - When
github.app.installation_idis omitted, runnerd resolves the installation dynamically per repository, allowing one App to serve multiple accounts.
Sensitive fields accept RUNNERD_ENC(v1:...) values to avoid plaintext in the config file:
read -r -s secret_value
printf '%s' "$secret_value" | ./bin/runnerd --obfuscate-config-value
unset secret_valueSupported fields: database.dsn, auth.session_secret, auth.encryption_key, github.webhook_secret, github.token, github.basic_auth.password, github.oauth.client_secret. These values are also masked as ****** in logs and serialized output.
Note: This hides plaintext from casual inspection only — the decoding key is embedded in the binary. It is not encryption against a host-level attacker.
Each user configures a Cache S3 Bucket, optional Prefix, AK, and SK in account or GitHub installation Preferences. The default prefix is gh-actions-cache. The S3 region and endpoint are derived from the selected Sandbox service region and are configured by the operator in runnerd.yaml under sandbox.regions. Because the configured endpoint may be private to the Sandbox network, runnerd only validates the configuration shape when saving it; bucket reachability and permissions are verified by the actual workflow in the Sandbox. AK/SK are encrypted in scoped state and are never returned to the browser or runner.
On every sandbox start, runnerd resolves the GitHub repository to its installation/account scope, verifies the Workflow Run trust context, and mints a Qiniu IAM federation token through the configured cache.sts_endpoint (default https://sts-ov.qiniuapi.com). Its requested lifetime is the configured Sandbox lifecycle plus five minutes for the post-job cache save step; no refresh mechanism is provided yet. It injects the token plus bucket/endpoint/prefix as AWS_* / RUNS_ON_S3_* environment variables in the Sandbox start script, so the scoped cache action can upload and restore caches directly to the user bucket without proxying bytes through runnerd.
Cache object keys are isolated by repository and workflow context:
<configured-prefix>/<owner>/<repo>/scopes/branch-<first-16-bytes-of-sha256(branch)-hex>/...
<configured-prefix>/<owner>/<repo>/scopes/pr-<number>/...
With the scoped qiniu/actions-cache@v5 action, runnerd injects ordered read prefixes plus one write prefix. A trusted branch searches its own scope and then the default-branch scope, and writes only its own scope. A pull request, including a Fork PR, searches its PR scope, base-branch scope, and default-branch scope in that order, and writes only its own PR scope; this matches GitHub's merge-ref cache isolation so a Fork cannot poison a base-branch cache. pull_request_target, workflow_run, issue_comment, and unverified metadata are default-branch read-only. Kodo list operations are scoped to authorized prefixes via kodo:prefix Condition, so cache key names outside the granted scopes are not enumerable across credentials.
sandbox:
regions:
- id: us-south-1
label: "United States · Dallas 1"
sandbox_api_url: https://us-south-1-sandbox.qiniuapi.com
s3_region: us-north-1
s3_endpoint: https://internal-s3-las-us-north-1-dal.qiniucs.com
cache:
sts_endpoint: https://sts-ov.qiniuapi.comsandbox.regions defines the public Sandbox region catalog exposed through GET /sandbox/regions; S3 mappings remain server-side because endpoints can be private. Each entry must include id, label, and sandbox_api_url. s3_region and s3_endpoint are optional and must be configured together; only regions with both fields support Cache S3. At least one region is required. For stronger cache isolation, use a dedicated bucket per GitHub installation. cache.sts_endpoint is the Qiniu IAM federation token endpoint used to mint short-lived credentials.
Use qiniu/actions-cache@v5 instead of actions/cache. No additional configuration is needed in the workflow — runnerd injects S3 credentials plus ordered read prefixes and a single write prefix as environment variables:
steps:
- uses: qiniu/actions-cache@v5
with:
path: |
~/.cache/go-build
~/go/pkg/mod
key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}
restore-keys: |
${{ runner.os }}-go-The upload/download concurrency can be tuned via environment variables (defaults shown):
env:
UPLOAD_QUEUE_SIZE: "16" # concurrent multipart upload parts
UPLOAD_PART_SIZE: "16" # part size in MiB
DOWNLOAD_QUEUE_SIZE: "16" # concurrent range-request downloads
DOWNLOAD_PART_SIZE: "16" # part size in MiB| Scope | Permission | Access | Purpose |
|---|---|---|---|
| Repository | Actions | Read-only | Query job/run status, list queued jobs; required for webhook events |
| Repository | Administration | Read & write | Repository-level runner registration (when spec has no runner_group) |
| Repository | Metadata | Read-only | Identify repositories and owners |
| Repository | Pull requests | Read-only | Show PR titles in job groups |
| Organization | Members | Read-only | Verify active organization owner role (role: admin) for organization Settings and scoped management |
| Organization | Self-hosted runners | Read & write | Organization-level runner registration (when spec sets runner_group) |
Set github.app.slug to show an "Install GitHub App" link in the user UI. Use github.allowed_repositories (patterns like owner/repo or owner/*) to restrict which repositories can use this runnerd instance.
github.oauth enables GitHub App OAuth login for the built-in console:
- Use the GitHub App's Client ID and Client Secret.
- Set the App callback URL to
http://<host>:<port>/auth/github/callback. - Set
auth.session_secret(session signing) andauth.encryption_key(user secret encryption) to separate random values.
First OAuth login creates a role: user account. Use --bootstrap-admin <github-user-id> to promote an account to admin.
In your GitHub App settings (Settings → Developer settings → GitHub Apps → your app → General), configure:
- Set the Webhook URL to
https://<your-runnerd-host>/webhooks/github. - Under Subscribe to events, check:
- Workflow jobs (
workflow_job) — required, triggers runner creation. - Workflow runs (
workflow_run) — optional, acts as a compensating signal for missedworkflow_jobevents.
- Workflow jobs (
- Save changes.
⚠️ Common pitfall: If no events are subscribed, GitHub will not send any webhooks and jobs will stay queued forever. This is configured in the GitHub App settings, not in the repository's webhook settings.
- Ensure the GitHub App webhook is configured as described in Webhook Events above, with the
webhook_secretmatchinggithub.webhook_secretin your config. - Use labels that match an enabled Runner Spec configured in Admin. For example, after configuring the corresponding public spec:
runs-on: [qiniu, ubuntu-24.04]The qiniu label is required by the standard spec examples. A custom spec can define
its own advertised and required labels instead.
runnerd handles queued, in_progress, and completed actions. For workflow_run, it lists all queued jobs in the run and enqueues any matching jobs not already seen.
New runner requests, including admission rejections, store the parsed GitHub context but not the raw webhook body. The legacy github_payload_json column and existing values remain available for historical metadata backfill; this change does not clean up old payloads, request history, or logs.
Runner specs are managed through the admin API and console — not through runnerd.yaml. Every enabled spec is eligible for repositories admitted by github.allowed_repositories; labels select the spec.
- Public-name binding: Admin configures a stable public template name. Runnerd resolves its physical ID through the request's effective Sandbox region. Publication in
/runner-specsis an explicit, validated choice. - Fixed-ID reference: Admin configures an explicit
template_id, which may refer to a public template. Admin uses one Template field; catalog display requires verified public visibility. New bindings and runtime startup require a nonzero effective default BuildID; a failed latest rebuild does not invalidate an existing default. Every platform spec's labels, priority and capacity are editable in Admin; the code no longer maintains a catalog. New binding/publication requires the configured admin Sandbox credentials; unchanged-binding policy edits remain available without provider access. - GitHub Runner Group: when a spec sets
runner_group, runnerd creates an organization-level runner in that GitHub group; otherwise it creates a repository-level runner. This is not the retired internal Runner Group model. Organization forms explain repository-level registration, offer a live group selector, and generategroup+labelsYAML. New/changed groups and re-enablement are validated before saving; startup checks group and exact repository access before provisioning. Admin platform specs retain manual names for their multiple organization contexts. See GitHub Runner groups.
⚠️ Personal accounts:runner_grouprequires the organization-level GitHub API. If the repository belongs to a personal account (not an organization), leaverunner_groupempty — otherwise the organization-group preflight will reject startup. Matching always enforcesrequired_labels ⊆ job_labels ⊆ labels. Migrated Ubuntu specs preserve theirqiniuand exact OS required labels; changing the catalog in Admin changes the workflow contract. Enablement and publication are separate controls.
Internal Runner Groups and Repository Policies have been removed. Their legacy
management APIs now return 404 Not Found, while old Admin bookmarks redirect
to Runner Specs. They are not part of supported configuration, matching, or
recovery behavior; any legacy database artifacts are ignored by current code.
The database is the single catalog authority. Startup migrates old managed rows once, preserves their operator settings and runtime behavior, and never restores edited/deleted specs. Legacy private specs keep their physical template IDs and clear unused public names so later edits remain valid. A fresh installation starts with an empty catalog. The visibility adjustment needs no new schema or data migration. Existing name/ID references and display flags stay unchanged; runtime keeps the existing name/ID behavior; this refactor adds no configurable Runner preparation, Docker or sponsorship policy. See Platform Runner Specs for fields, migration and validation.
See Public Runner Templates for supported workflow labels, publication status, and regional verification.
GET /api/public/runner-templates exposes enabled, displayed public-name references from the database without authentication, including validated large name references when configured. Fixed-ID specs can appear in the protected /runner-specs directory after publicness validation, but remain absent from this stable-name API. It returns stable template names, logical spec names and workflow labels, never physical IDs or credentials; the public projection is cached in each server process for 60 seconds, with concurrent cache fills coalesced. Successful Admin spec saves and deletes invalidate that process cache; browser caches may retain responses for 60 seconds. The credential-bound GET /user/sandbox/templates?region=<id> remains a separate scoped resource.
Ordinary users browse the read-only platform Runner Spec catalog at
/runner-specs. That page has no account/Organization selector or user-editable
availability and concurrency policy. Users manage only owned custom Specs under
/account/runner-specs or
/organizations/{login}/runner-specs. The authenticated /user/runner-specs
API combines published public platform specs and custom
specs owned by that account or owner-manageable Organization. Platform availability
and concurrency remain global Admin policy. Scoped custom specs use exact
normalized workflow labels, may override a global spec with the same label set,
and validate new or changed template IDs only with that scope's explicit or
legally inherited Sandbox credentials. runner_group is available only for
Organization custom specs. The response exposes a template ID only for the
caller's own scoped custom spec, never for a platform custom spec. A queued
request reloads and validates the same persisted source and scope immediately
before startup, so a spec disabled while waiting cannot launch a runner.
Admin creation controls platform execution separately from public visibility. Use a scoped custom spec when an environment must serve only one account or Organization.
For custom specs, template_id should point to a Qiniu Sandbox template containing the GitHub runner image. Template access is checked against the repository owner's effective Sandbox service shown under Repositories → Runner readiness at sandbox creation time.
The built-in web UI provides:
| Route | Description |
|---|---|
/admin/ |
Dashboard with runnerd runtime diagnostics and metrics |
/admin/accounts |
Account management — list, search, and change roles |
/admin/github_accounts |
GitHub App installation accounts reported live by GitHub |
/admin/github_accounts/{installation_id} |
One GitHub App installation and its currently authorized repositories |
/admin/runner_requests |
Runner request history with server-side filters, cursor-based infinite scrolling, global status metrics, controls, and exact lookup by Runner Name or internal request ID |
/runner_request_metrics |
Admin-only global Runner request status and Runner Spec counts; independent of list filters |
/admin/runner_requests/{id} |
One Runner request resource with persisted state, lifecycle timestamps and cleanup duration, a startup environment snapshot (Sandbox region, resolved physical template ID, template version, and preinstalled Runner version), a best-effort effective Runner version captured after any custom-template preflight or official self-update, typed termination source and optional process exit code, diagnostic findings, a retained terminal GitHub Job result with a historical live-lookup fallback, a bounded on-demand network probe for running Sandboxes, and a cursor-paged timeline that shows every control/stdout/stderr event and its optional stage directly in chronological order |
/admin/runner_specs |
Platform Runner Spec administration and public publication |
/runner-specs |
Read-only platform Runner Spec catalog and workflow labels |
/account/runner-specs and /organizations/{login}/runner-specs |
Custom Runner Specs owned by an account or owner-manageable Organization |
/organizations/{login}/fork-sponsorship |
Owner-only policies for organization-sponsored managed Runner execution in trusted forks |
/admin/sandbox_service |
Sandbox service configuration |
/admin/match |
Label-match preview against the current enabled Runner Specs |
/admin/audit |
Audit event history |
/admin/diagnostics |
runnerd runtime diagnostics with redacted summary, pprof discovery, and on-demand expvar |
/ is always the public Qiniu CI Runner product landing page. /docs and its fixed guide routes are public, same-origin, and available in English and Simplified Chinese. The ordinary-user Jobs homepage is /jobs; other protected routes include /repositories, PR job groups (/github/pulls/{owner}/{repo}/{number}/jobs), and account settings (/account/preferences, /account/sandbox-templates, /account/sandbox-instances), with matching /organizations/{login}/... routes. Opening a protected route without a session shows a focused GitHub sign-in page and returns to the original URL after OAuth.
Job details open Runner logs by default and retain the Web Console and request details. Jobs and admin request details share one event timeline: mixed control/stdout/stderr records, timestamps, stages, stream filters, older-page loading, and incremental refresh every five seconds while active. GET /user/runner_requests/{id}/events requires the same exact installation/repository authorization as Job details and returns the same event pages as the admin endpoint. In the Jobs panel, the job name links to the GitHub Job and the workflow name links to its Run. Standalone Job details provide View job on GitHub, falling back to the Workflow Run when its repository and Run ID are known. runnerd does not download or duplicate GitHub Actions logs. The retired /user/runner_requests/{id}/github-log endpoint returns 404.
Runner request lists return the newest 100 rows by default and cap pages at 500. They project only public runner-state fields instead of stored webhook payloads or Sandbox credentials. Admin polling uses the (queued_at DESC, id ASC) index; repository-authorized user polling queries each installation through (github_installation_id, queued_at DESC, id ASC) and merges the bounded results while preserving exact installation/repository access pairs.
| Symptom | Likely Cause | Fix |
|---|---|---|
| Job stays queued forever, no webhook in runnerd logs | GitHub App has no subscribed events | Go to GitHub App settings → Subscribe to Workflow jobs event |
runner_group_permission_denied (legacy: github registration token: status 404) |
Group lookup cannot access the owner organization, including personal-account owners or missing App permissions | Leave runner_group empty for personal repositories; for organizations, check the App installation and Self-hosted runners permission |
invalid signature in logs |
Webhook secret mismatch | Ensure github.webhook_secret matches the secret in GitHub App/repo webhook settings |
runner start deferred ... at capacity |
Global or per-spec concurrency limit reached | Wait for running jobs to finish, or increase max_concurrent_runners / spec max_concurrency |
| Sandbox creation fails | Repository owner has no effective Sandbox service | Open Repositories, select the account or organization, and complete Runner readiness; admins may also configure an eligible fallback at /admin/sandbox_service |
| GitHub reports that a self-hosted runner lost communication | The runner, Sandbox, or its network path stopped reporting heartbeats | Open Admin → Runner Requests, look up the Runner Name shown by GitHub (for example, e2b-101445685709), and inspect the request resource's findings and lifecycle timeline |
For a request that is still running, an administrator can run a fixed-target probe for the GitHub API, Ubuntu archive, or LLVM APT host from the request detail page. The probe is diagnostic evidence only: it is limited to 10 seconds, a 64 KiB download, and 64 KiB of combined command output; it is rate-limited to once per Sandbox/PID attempt every 30 seconds, retained in Run history, and never changes or extends the Runner lifecycle.
For detailed local debugging steps, see docs/testing.md.
The container image uses file-config only. Mount runnerd.yaml and any referenced secret files into the container:
docker run --rm -p 25500:25500 \
-v "$PWD/runnerd.yaml:/etc/runnerd/runnerd.yaml:ro" \
-v "$PWD/secrets:/etc/runnerd/secrets:ro" \
ghcr.io/qiniu/ci-runnertask deps # Install Go dependencies
task ui-deps # Install UI dependencies
task build # Build runnerd with embedded production UI
task ui-production-smoke # Execute the production UI bundle in Chromium
task dev # Start local dev (runnerd + Vite + smee)
task lint # Run linters
task test # Rebuild UI + run all tests (Go with race detection + Bun UI tests)
task docker-check # Verify the service Dockerfile
task release-check # Verify release buildFor focused UI tests, run cd ui && bun run test. Use task ui-production-smoke
after changing UI dependencies, Vite/Rollup configuration, or production asset
loading.
| Template | Description |
|---|---|
templates/github-runner-ubuntu-slim |
Ubuntu Slim x64 source with standard 20-GiB and large 80-GiB build configs |
templates/github-runner-ubuntu-22.04 |
Ubuntu 22.04 x64 source with standard 20-GiB and large 80-GiB build configs |
templates/github-runner-ubuntu-24.04 |
Ubuntu 24.04 x64 source with standard 20-GiB and large 80-GiB build configs |
templates/github-runner-ubuntu-26.04 |
Preview Ubuntu 26.04 x64 source with standard 20-GiB and large 80-GiB build configs |
The public ubuntu-latest-large Runner Spec is a logical label mapped to the
github-runner-ubuntu-24-04-large physical template; it does not add another
source directory or build target.
Run task template-python-test when changing Python/pipx installation; it uses
Docker and network access to verify isolation from apt-owned Python packages.
Run task template-check-all, then use task template-build-all to build all
eight templates sequentially, or use an individual task template-build-ubuntu-*
target for one real qshell Sandbox build. See
Public Runner Templates for publication and
cache-resume guidance after a remote build time limit, plus publication and
smoke commands. Shared setup code and the Actions Runner version pin live in
templates/common/. Build tasks verify the official Runner archive locally,
upload it as small COPY chunks, and verify it again before installation.
The pin remains the tested preinstalled baseline. Public-name specs use it and rely on regular template rebuilds. Private-ID specs resolve and verify GitHub's official Runner archive before
registration and replaces a stale writable copy before the current Job can be
accepted. Official self-update remains enabled after registration for both
paths.
The Actions Runner Update workflow checks GitHub's latest stable Runner every
Tuesday at 02:23 UTC and also supports manual dispatch. It accepts only the
canonical Linux x64 asset within the sixteen-chunk 256-MiB limit, verifies
the downloaded digest and byte count against GitHub's release metadata, updates
the shared pin and generated compatibility assertions, and passes
task template-check-all before creating or refreshing the single
automation/actions-runner-update pull request. Because a PR created with
GITHUB_TOKEN does not recursively trigger pull_request, the updater
explicitly dispatches the full Check workflow for that branch. This workflow
never builds, publishes, or unpublishes Sandbox templates. After merge, an
operator uses the existing local template-build-*, template-publish-*,
template-defaults-check, and template-smoke tasks for the two-region
promotion so long remote builds remain easy to inspect and production Sandbox
credentials never enter GitHub Actions.
A lower latest release is treated as a downgrade alert rather than a no-op. An
equal version is a no-op only when its GitHub-provided size and digest still
match the pin; metadata drift fails closed. Human review remains the provenance
boundary because the digest and asset metadata come from the same GitHub
release.
Template source validation requires Node.js 24, and template builds require
qshell 2.19.13 or newer. Standard configs request
disk_size_mb = 20480, while large configs request 81920 for new templates.
This setting is the minimum root disk size; the reported total can be larger.
Qshell does not send the setting on same-name
rebuilds. After the provider team's DiskMb is adjusted, the build tasks rebuild
the existing names and IDs in place without rejecting their stale pre-rebuild
totals. Publish and catalog checks require the rebuilt totals to meet the
configured lower bounds; a larger total is not a mismatch by itself.
Release smoke reads the corresponding TOML and requires the runtime root disk
size to meet its disk_size_mb lower bound.
The 2.337.0 baseline completed the two-region, eight-template rebuild, catalog,
standard workflow, and large workflow gates recorded in
Issue #93.
| Document | Description |
|---|---|
| Hosted site guides | Hosted quick start, runnerd deployment, workflow example, organization fork sponsorship, custom template lifecycle, troubleshooting, and managed labels |
| docs/testing.md | Local testing, GitHub App/OAuth setup, webhook forwarding, troubleshooting |
| docs/deployment-smoke.md | Production-style readiness checklist |
| docs/default-runner-templates.md | Public template labels, qshell release flow, regional smoke, and rollback |
| docs/runner-architecture-comparison.md | Architecture diagrams and comparison with ARC / Fireactions |
| docs/runner-implementation-review.md | Implementation status and schema migration notes |
Qiniu CI Runner is licensed under the Apache License 2.0.
Bug reports, feature ideas, documentation improvements, and code contributions are welcome.
- Report a bug or propose a feature.
- Open a Pull Request to improve the code or documentation.
- Scan the QR code below to join the community chat.
Scan the QR code to connect with maintainers and other Qiniu CI Runner users.
