Manual pipelines and runner boundaries
Golf can run a bounded shell subset of GitHub Actions and GitLab configuration on registered Docker workers. This is an implemented development capability, not full Actions or GitLab Runner compatibility. Cloudflare execution, reusable workflows, remote actions, service containers, secrets and production deployment remain separate work.
Run a supported workflow
- Open a repository’s Settings → Workflows (
/repositories/{owner}/{name}/settings/workflows). Inspection resolves one immutable commit and discovers direct.github/workflows/*.yml/*.yamlor root.gitlab-ci.ymlfiles. - Review the compatibility result. Only a validated supported configuration can offer Run workflow. Your current repository permission must allow writing; archived repositories and mirrors cannot dispatch.
- Have the authorized administrators configure the applicable instance, organization and repository execution ceilings. Policies start disabled. Enabled parent scopes do not bypass narrower child restrictions.
- Register an eligible worker and an operator-approved Linux image by immutable digest. An arbitrary image name or workflow label does not grant runner authority.
- Choose Run workflow. Inspect the resulting run and bounded logs; cancel through the run controls when needed. A response lost during dispatch requires inspecting recorded runs before a separate deliberate dispatch. Golf does not automatically resend it.
Current policy controls cover disabled/all/selected repository eligibility and exact workflow selection, with immutable repository IDs and durable revisions/epochs. Instance settings require an explicitly enrolled Golf administrator password session. Organization settings require native ownership; repository settings require native administration. Eligibility is checked at dispatch, worker assignment, heartbeat and result publication. Independent native credentials are not governed by a Golf-only organization creation policy.
Supported execution subset
| Format | Implemented subset | Excluded examples |
|---|---|---|
| Actions | One input-free workflow_dispatch job; approved Linux runner mapping; named run steps with supported default, bash or sh shell | uses, expressions, environment expansion, dependencies, matrices, multi-job graphs |
| GitLab | One digest-pinned image matching the operator-approved image; one job with string script commands and optional stage | Includes, variables, rules, services, dependencies, before/after scripts and native GitLab runner coordination |
Unsupported or invalid configuration fails visibly; Golf does not silently ignore unsupported behavior. Commands are private execution input and do not appear in the inspection catalogue. See the authoritative execution compatibility contract for the exact accepted syntax.
The worker receives a verified source snapshot, not a full Git checkout. The normalized tar is bounded to 16 MiB, 4,096 entries and 8 MiB per file. Links, unsafe paths and nonregular entries are rejected. Repository Git metadata, submodules and LFS hydration are not resolved by this snapshot path.
Actions steps execute as separate shell processes; GitLab script commands share one fail-fast script context. Jobs run as nonroot with a read-only container root, dropped capabilities, no external network and bounded runtime, CPU, memory, process count and output. Source copying makes the job workspace writable inside the container; there is no host extraction or host command execution. Untrusted job code can still modify its own workspace.
Durability and isolation
Golf stores the bound repository/owner identity, exact commit/blob/path, compiled plan, source hash, policy epochs and idempotency input hash before durable queueing. Manual runs bind the current user/session; push-origin runs separately bind their event/grant/credential authority, with no synthetic browser session. Leases and attempt capabilities are short-lived and distinct from browser or provider credentials. Cancellation, expired leases, authority loss and policy revocation fence further results. Logs are bounded, ordered and attempt-bound. Completed evidence does not grant later access: run reads and logs require current repository authority and immutable identity matching.
Source bundles can stay in PostgreSQL or use configured private RustFS/S3/R2-compatible storage. Stored profile-backed bundles retain their immutable connection version, so an activation change cannot silently rebind existing runs to a new destination.
Actual isolated qualification covers Actions/GitLab shell success and exit failure, cancellation and policy revocation, restart durability, conditional object writes and cleanup. Exact source revisions, image digests and test counts live in the implementation ledger. This does not establish broad engine parity, R2 service qualification, Kubernetes execution, high availability or large-scale capacity.
Push intake is separate from automatic execution
The new native HMAC push intake records authenticated bounded deliveries; its native receipt/replay proof passed on Docker Desktop. This proves intake rather than automatic execution. Current manual runs still require their real user session. Automatic CI is not enabled by accepting an event: it requires exact input deduplication, explicit push eligibility, supported trigger compilation and the same current native authority/policy/lease fences used for worker results. Repository automation grants now store explicit durable personal delegation, and the new opt-in automatic push slice integrates materialization and unattended run admission in disposable development stacks. Disposable native qualification has passed; the retained local runtime now runs schema021 with an explicitly scoped private demo. There is no synthetic browser session or administrator-token fallback. See the local automation design. Outbound CI/Slack/email notifications are a separate planned consumer.
Push-trigger compiler foundation
The read-only catalogue now recognizes a bounded push shape separately from operational execution. Actions accepts scalar on: push or on: workflow_dispatch, or an event mapping with empty push and/or input-free workflow_dispatch. A push mapping may specify 1–50 distinct exact branch names. Pattern characters, tag/path/ignore filters, expressions, event sequences and other events are rejected. The push compiler matches only a full refs/heads/{branch} reference; tags and nonmatching branches do not yield a plan.
A push-only Actions file cannot be manually dispatched: Run workflow still requires explicit workflow_dispatch. GitLab's existing single-job pinned-image script can compile for branch pushes only without rules, only/except, workflow definitions or includes. Provider event variables/context are not implemented. Unsupported fields fail the whole configuration rather than being skipped. Commands remain private plan input.
Compilation itself neither consumes stored deliveries nor dispatches a job. The automatic push integration separately binds those plans to current event/grant/policy authority. The workflow configuration contract defines the exact catalogue and source boundaries.
Independent push permission
The push-policy increment gives each instance, organization and repository ceiling an independent pushAllowed value, defaulting to false. In Edit execution policy, Automatic push execution is separate from Manual dispatch; allowing one does not allow the other. All applicable repository eligibility and exact workflow restrictions still apply. Saving the push permission starts no run and does not replay old events.
Permission is one prerequisite rather than operational readiness: an automatic attempt also requires a current repository-bound automation grant, supported push-trigger compilation, exact event/commit/workflow deduplication and qualified worker/source authority. The automatic integration now has separate disposable native evidence; the retained local schema021 runtime now has a deliberately scoped private demo. A denied or missing parent ceiling cannot be overridden by a repository setting or event payload. Existing read-only clients cannot gain policy mutation authority by invoking another API/MCP surface.