flagon-io/g1t

public

Where people and agents ship software together. The open-source git platform for the whole job: issues, agents, checks and deploys to the edge.

g1t/apps/docs/src/content/docs/guides/actions.md

311 lines15,783 bytesCodeBlame
1---
2title: GitHub Actions
3description: Your GitHub Actions workflows run on g1t as they are. Rename .github to .g1t and push.
4---
5
6g1t runs GitHub Actions workflows. They are written exactly as on GitHub,
7and kept in `.g1t/workflows/` instead of `.github/workflows/`.
8
9## Moving from GitHub
10
11```sh
12git mv .github .g1t
13git commit -m "Run our workflows on g1t"
14git push g1t main
15```
16
17That is the whole move. Everything in the folder comes along: workflows,
18local actions under `.g1t/actions/` and anything else you keep there.
19Workflows that still say `uses: ./.github/actions/setup` find it under
20`.g1t/` once `.github` is gone.
21
22g1t never reads `.github`. A repository mirrored to both places can keep
23`.github` for GitHub and `.g1t` for g1t, side by side.
24
25Then add your [secrets and variables](#secrets-and-variables): GitHub never
26gives their values out, so they cannot be copied across.
27
28## What runs
29
30| On GitHub | On g1t |
31| --- | --- |
32| `on:` `push` (branches, tags, paths), `pull_request`, `pull_request_target`, `issues`, `issue_comment`, `pull_request_review`, `schedule`, `workflow_dispatch`, `workflow_run`, `merge_group` | The same, from g1t's own pushes, pull requests, issues, comments and [merge queue](/guides/merge-queue/). |
33| `jobs`, `needs`, `if`, `outputs`, `env`, `defaults`, `timeout-minutes`, `continue-on-error` | The same. |
34| `strategy.matrix` with `include` and `exclude`, `fail-fast`, `max-parallel`, a matrix from `fromJSON(needs.…)` | The same. |
35| `concurrency` with `cancel-in-progress` | The same. |
36| `${{ }}` expressions: every operator, function and context | The same, including `hashFiles`, `success()`, `failure()`, `always()` and `cancelled()`. |
37| `run:` with `bash`, `sh`, `python` or a custom shell | The same. |
38| JavaScript actions (`uses: owner/repo@v7`) | Fetched from GitHub and run as they are, on Node 24, the runtime current actions declare. |
39| Composite actions | The same. |
40| Reusable workflows in the repository (`jobs.<id>.uses: ./.g1t/workflows/build.yml`) | The same: `with:` inputs, `on.workflow_call` outputs, and nesting up to four deep. `./.github/workflows/…` finds the workflow under `.g1t/` after the move. Their jobs read the repository's secrets and variables. |
41| `actions/checkout` | Checks out from g1t, with `ref`, `fetch-depth`, `path`, `repository`, `token` and `submodules`. |
42| `GITHUB_OUTPUT`, `GITHUB_ENV`, `GITHUB_PATH`, `GITHUB_STATE`, `GITHUB_STEP_SUMMARY` | The same. |
43| `::error::`, `::warning::`, `::notice::`, `::group::`, `::add-mask::` | The same: errors and warnings become annotations on the run. |
44| `secrets.*`, `vars.*`, `secrets.GITHUB_TOKEN` | The same. `secrets.G1T_TOKEN` is the workspace's own token for the run; `GITHUB_TOKEN` is its alias. |
45| `environment:` on a job | The job reads each key's row for that environment, as GitHub's environment secrets work. |
46| `actions/upload-artifact`, `actions/download-artifact` | Kept with the run for 14 days, passed between its jobs, and downloadable from the run's page. Up to 60 MB each. |
47| `actions/cache`, `actions/cache/restore`, `actions/cache/save` | Kept per repository, found by `key` or the newest under a `restore-keys` prefix. `path` takes globs and `!` exclusions. Up to 2 GB each; see [the cache](#the-cache). |
48
49The **Actions** page of a workflow says, under *How this runs on g1t*,
50anything in it that runs differently.
51
52### Not yet
53
54- **Windows and macOS on g1t's machines.** g1t's own runners are Linux; a
55 job with `runs-on: windows-latest` or `macos-latest` fails, and says so.
56 [Self-hosted runners](/guides/self-hosted-runners/) of any OS run them:
57 `runs-on: [self-hosted, windows]`.
58- **Docker** container actions, `services:` containers and `container:`.
59- **Reusable workflows from other repositories** (`uses: owner/repo/.github/workflows/x.yml@v1`); ones in the same repository work.
60- **The toolkit's own cache.** Actions that cache through GitHub's service
61 themselves, such as `actions/setup-node` with `cache: npm`, run without
62 it. Use `actions/cache` for the same effect.
63- **Environments' protection rules** (required reviewers, wait timers,
64 branch limits). A job with `environment:` gets that environment's
65 [values](/guides/secrets-and-variables/#a-value-per-environment), and runs
66 without waiting.
67
68## The runner
69
70Jobs run in a fresh sandbox each: Debian with Node 24, Python 3, Go, Rust,
71`build-essential`, `git`, `curl`, `jq` and passwordless `sudo`, in GitHub's
72layout (`/home/runner/work`, `RUNNER_TEMP`, `RUNNER_TOOL_CACHE`).
73`runner.os` is `Linux`. `ubuntu-latest`, `ubuntu-24.04`, `self-hosted` and
74other Linux labels all run here. Setup actions such as
75`actions/setup-node` and `actions/setup-python` install other versions as
76they do on GitHub.
77
78### Machine sizes
79
80A job runs on the standard machine unless its `runs-on` names a larger
81one:
82
83| `runs-on` | vCPUs | Memory | Disk |
84| --- | --- | --- | --- |
85| `ubuntu-latest`, or any other Linux label | 0.5 | 4 GiB | 8 GB |
86| `g1t-2core` | 2 | 8 GiB | 16 GB |
87| `g1t-4core` | 4 | 12 GiB | 20 GB |
88
89```yaml
90jobs:
91 build:
92 runs-on: g1t-4core
93```
94
95The label can come from the matrix or the run's inputs
96(`runs-on: ${{ matrix.big && 'g1t-4core' || 'ubuntu-latest' }}`). A
97larger machine costs what it costs g1t, plus the same margin as all
98sandbox time: see [usage and billing](/guides/usage-and-billing/#workflow-jobs-on-larger-machines).
99Builds that compile, such as Rust or a large TypeScript project, finish
100several times faster on one.
101
102A job runs for at most 60 minutes, whatever its `timeout-minutes`, and
103for less if the workspace's plan caps runs lower (a new workspace's first
104month, or the trial). A job stopped at its time cap fails saying so.
105
106### What a job can reach
107
108A job's network is restricted, as an agent's is (see
109[guardrails](/guides/guardrails/)): it reaches the hosts its project's
110guardrails allow, g1t itself, and what builds need, and nothing else.
111What builds need is the package registries (npm, PyPI, crates.io, the Go
112proxy, RubyGems, Packagist, NuGet, Maven and Gradle, Debian's mirrors),
113GitHub, where `uses:` actions and the setup actions' downloads come from,
114and the toolchains' download sites (`nodejs.org`, `go.dev`,
115`static.rust-lang.org`). A request anywhere else gets `403` with
116the reason. To reach another host, someone with the Maintain [role](/guides/access-and-roles/) or
117higher adds it to the project's
118allowed domains under **Settings → Guardrails**; a project whose guardrails
119turn the network restriction off runs its jobs with an open network.
120
121A host only workflows should reach, such as the API a deploy uploads to,
122goes in **Workflow-only domains** instead, limited to the workflows and
123environments that need it: `api.cloudflare.com | deploy.yml | production`
124lets only `deploy.yml`'s jobs with `environment: production` reach it.
125Agents never reach those hosts, and neither do runs of pull requests from
126forks. See [workflow-only domains](/guides/guardrails/#workflow-only-domains).
127
128g1t does not run cryptocurrency miners: a step that names one (`xmrig`,
129a `stratum+tcp://` pool, `--donate-level`) is not run, and a job that
130looks like it is mining is stopped. See
131[abuse and mining](/guides/guardrails/#abuse-and-mining).
132
133## The cache
134
135`actions/cache` keeps what a job saves for the repository's later jobs:
136
137| | |
138| --- | --- |
139| One entry | Up to 2 GB, compressed. A larger one is not saved, and the job goes on. |
140| A repository's entries | Up to 10 GB together. Saving past it removes the entries restored longest ago. |
141| How long | Until it has not been restored for 7 days, and at most 28 days after it was saved. |
142| Keys | Written once: saving under a key that exists does nothing. A restore finds its `key` exactly, else the newest entry whose key starts with one of its `restore-keys`. |
143| `path` | Files and folders; globs, `**` included; `~/` is the home folder; a line starting with `!` leaves matching paths out. |
144| Compression | zstd. |
145
146```yaml
147- uses: actions/cache@v4
148 with:
149 path: |
150 ~/.cargo/registry/cache
151 target/release
152 !target/**/incremental
153 key: cargo-${{ runner.os }}-${{ hashFiles('Cargo.lock') }}
154 restore-keys: cargo-${{ runner.os }}-
155```
156
157Each restore and save says on the job's log how large the entry was and
158how long it took. A workspace on the plan pays for what its caches hold
159(`Actions cache storage` on its statement), at R2's price plus the margin;
160see [usage and billing](/guides/usage-and-billing/#actions-cache).
161
162## Runs and logs
163
164Open a repository's **Actions** page, in its sidebar. Pick a workflow to
165see its runs, run it by hand if it has `workflow_dispatch`, or turn it off
166without touching its file.
167
168A run's page shows its jobs, each job's steps, and their logs as they are
169written. Groups fold, errors and warnings are marked, and secrets are
170replaced with `***`. **Cancel**, **Re-run all jobs** and **Re-run failed
171jobs** do what they say.
172
173## Pull requests
174
175A pull request's workflows run on each new head: when it is opened, when
176a commit is pushed to it, and, for one a g1t agent makes, when the agent
177marks it ready, which on g1t is when it first has code. Each head runs
178each workflow once.
179
180## Checks
181
182A pull request's checks are its workflows. Each workflow that runs on
183`pull_request` runs on every pull request's head, whoever opened it, a
184person or an agent, and its runs report a check named after the workflow:
185a workflow with `name: CI` reports `CI`, with the status context
186`CI / pull_request` (the workflow's name and the event).
187
188- **Which checks a merge needs** is up to the default branch's
189 [required status checks](/guides/pull-requests/#required-status-checks),
190 under **Settings → Branches and merging**. A required check that failed,
191 is still running or has not reported holds the merge. Checks that are not
192 required are shown on the pull request and never hold it.
193- **In a repository that merges through the [merge queue](/guides/merge-queue/)**,
194 workflows with `on: merge_group` run on each combined state the queue
195 builds, on the branch `g1t-queue/<entry>`, and the state lands only if
196 they and every required check pass on it. A workflow behind a required
197 check needs `merge_group` in its `on:`.
198- **A pull request a g1t agent is working on** goes back to the agent when
199 a check fails, with the end of each failed job's log. The agent reads the
200 run and its logs with the same tools you have, fixes the cause, and
201 pushes; the workflows run again. See
202 [seeing it through](/guides/g1t-agents/#seeing-it-through).
203
204```yaml
205name: CI
206
207on:
208 pull_request:
209 push:
210 branches: [main]
211 merge_group:
212```
213
214### Add CI
215
216A repository with no workflows has nothing that proves a change works, for
217people or for agents. Its pull requests, its **Branches and merging**
218settings and its **Actions** page say **This repository has no checks**,
219with an **Add CI** button. Anyone who can push to the repository can use it:
220
2211. Choose **Add CI**. g1t looks at the files at the repository's root and
222 writes a starter workflow with a job for each stack it finds, up to
223 three: Node (npm, pnpm, Yarn or Bun), Rust, Go, Python (pip or uv), Ruby,
224 Java (Maven or Gradle), .NET, or Make. Each job installs, lints where
225 the project says how, builds and tests. When it finds none, the job is a
226 placeholder that fails until you replace its last step with your own
227 commands.
2282. The workflow is committed as `.g1t/workflows/ci.yml` on a new branch,
229 `add-ci`, and opened as a pull request, by you. It is named `CI` and runs
230 on `pull_request`, on `push` to the default branch, and on `merge_group`.
2313. Change it on the pull request if the steps are not how your project
232 builds, and merge it.
2334. Once it has run, `CI` is offered under **Required status checks**.
234 Require it, so that nothing merges into the default branch unless it
235 passes.
236
237## Secrets and variables
238
239Secrets are read as `${{ secrets.KEY }}` and config as `${{ vars.KEY }}`,
240from the rows under **Settings → Secrets and variables** that are
241available to Workflows. A job with `environment: production` reads each
242key's Production row; other jobs read the rows for all environments. See
243[Secrets and variables](/guides/secrets-and-variables/) for how rows,
244environments and the workspace's rows work.
245
246Every trusted job also gets `${{ secrets.G1T_TOKEN }}`, the workspace's own
247token for the run, with `GITHUB_TOKEN` as its alias. A pull request's runs
248get secrets and the token only when its author has the Write
249[role](/guides/access-and-roles/) or higher on the repository, a member or
250an outside collaborator, or is g1t's agent. Anyone else's, such as one
251from a fork or by someone with Read or Triage, runs without secrets and
252with an empty token. See
253[who gets secrets](/guides/secrets-and-variables/#who-gets-secrets).
254
255## Who may run workflows
256
257What you can do with a repository's workflows follows your
258[role](/guides/access-and-roles/) on it:
259
260| | Needs |
261| --- | --- |
262| See workflows, runs and their logs | Read: on a public repository, anyone |
263| Run a workflow by hand, cancel or re-run a run | Write |
264| Enable or disable a workflow | Maintain |
265| The repository's secrets and variables, seeing them included | Admin |
266
267Jobs run in g1t's sandboxes, so they need the
268[g1t plan](/guides/usage-and-billing/#the-g1t-plan) or
269[the trial](/guides/usage-and-billing/#the-trial). On a public repository,
270[g1t's open-source pool](/guides/usage-and-billing/#the-open-source-pool)
271runs them too, after a card check, until the month's pool is spent.
272
273Before each job starts, g1t reserves what it may cost (its time limit at
274the sandbox price) with billing, and settles what it really cost when it
275ends; each job's sandbox is charged as
276[sandbox time](/guides/usage-and-billing/#sandbox-time), from the first
277second. A job billing refuses does not start: it is recorded as failed
278with "Not started:" and the reason, such as "Workflows run in g1t's
279sandboxes, which need a paid workspace", and what to do about it. The
280Actions page tells people with Write on a repository whose workspace
281cannot run jobs before the first run.
282
283## From the API
284
285The routes follow the standard Actions REST shape, so existing scripts
286usually work once they point at `https://api.g1t.sh`.
287
288| `workflow` action | Route |
289| --- | --- |
290| `list` | `GET /repos/{owner}/{repo}/actions/workflows` |
291| `list_runs` | `GET /repos/{owner}/{repo}/actions/runs`, with `workflow`, `branch`, `event`, `pull`, `head_sha` |
292| `get_run` | `GET /repos/{owner}/{repo}/actions/runs/{id}` |
293| `job_logs` | `GET /repos/{owner}/{repo}/actions/jobs/{job}/logs?after=` |
294| `dispatch` | `POST /repos/{owner}/{repo}/actions/workflows/{workflow}/dispatches` with `ref` and `inputs` |
295| `cancel` | `POST /repos/{owner}/{repo}/actions/runs/{id}/cancel` |
296| `rerun` | `POST …/runs/{id}/rerun`, or `…/rerun-failed-jobs` |
297| `update` | `PUT …/workflows/{workflow}/enable` and `…/disable` |
298| `list_actions_secrets`, `set_actions_secret`, `delete_actions_secret` | `GET`, `PUT` and `DELETE /repos/{owner}/{repo}/actions/secrets/{name}` |
299| `list_actions_variables`, `set_actions_variable`, `delete_actions_variable` | `GET` and `POST /repos/{owner}/{repo}/actions/variables`, `PATCH` and `DELETE …/variables/{name}` |
300
301Workspace secrets and variables are under
302`/workspaces/{workspace}/actions/secrets` and `…/variables`. The fields
303g1t adds (environments, who reads a row, linked repositories) are in
304[Secrets and variables](/guides/secrets-and-variables/#from-the-api).
305
306```sh
307curl -X POST https://api.g1t.sh/repos/acme/web/actions/workflows/ci.yml/dispatches \
308 -H "Authorization: Bearer $G1T_TOKEN" -H "Content-Type: application/json" \
309 -d '{"ref": "main", "inputs": {"environment": "staging"}}'
310```
311