Skip to content

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

Commit

ubuntu-latest follows GitHub: 4 vCPU in a public repository, 2 in a private one, billed as the machine it ran on (Closes #169)

GitHub's ubuntu-latest gives a public repository 4 vCPU and 16 GB, and a private one 2 vCPU and 8 GB. g1t gave every repository the 2 vCPU machine, so g1t's own workflows asked for g1t-4core by name, and its bill showed two machines. - `instance_for` takes whether the repository is public. With no machine named (`ubuntu-latest`, any other Linux label), a public repository gets the 4-core machine (standard-4: 4 vCPU, 12 GiB, 20 GB) and a private one the standard machine (standard-3: 2 vCPU, 8 GiB, 16 GB). A machine named in `runs-on` (`g1t-2core`, `g1t-4core`) is that machine in any repository. - 12 GiB is the most a Containers instance has without a raised account limit; GitHub's public machine has 16 GB. - The actions service reads visibility from the run's own event (`repository.private`, which every event carries), so it makes no extra call. An event that doesn't say is taken as private. - Billing: the label the plan resolves is the one the runner keeps on the job's meter, and the one billing prices the job by (`instance_named`). A public repository's ubuntu-latest job is charged as 4-core at $0.007 a minute. Usage stays owed until billing confirms it and is recorded once, as before. - g1t's workflows run on ubuntu-latest throughout. In this public repository that is 4 vCPU, as on GitHub. - The machine tables in the Actions, usage and billing, compute, Cloudflare and limitations docs say so. The open-source pool and the trial now say how many minutes they cover on each machine. Checked: - cargo test -p g1t-contracts -p g1t-billing -p g1t-actions-service (new: runs_on_picks_the_machine for public and private; a_runs_repository_is_public_only_when_its_event_says_so). - The runner's and the deploy tool's tests. - npx prettier --check .

G1t-Session:
ses_01m57b7r6jew3aqgyfmhw6yah6
syntaqxcommitted Parent5a992f0Browse files
14 files+141−690/14 viewed
+5−4
266266 name: The desktop app's Linux build
267267 needs: look
268268 if: ${{ needs.look.outputs.desktop-linux == 'true' }}
269− # The larger machine: linking Tauri on the small one dies with a bus error.
270− runs-on: g1t-4core
269+ # ubuntu-latest is 4 vCPU in this public repository, as on GitHub; linking
270+ # Tauri needs it (on 2 vCPU it dies with a bus error).
271+ runs-on: ubuntu-latest
271272 timeout-minutes: 60
272273 steps:
273274 - uses: actions/checkout@v5
310311 name: The desktop app's Windows build
311312 needs: look
312313 if: ${{ needs.look.outputs.desktop-windows == 'true' && vars.DESKTOP_WINDOWS_FROM_LINUX == 'true' && vars.DESKTOP_WINDOWS_RUNNER != 'true' }}
313− runs-on: g1t-4core
314+ runs-on: ubuntu-latest
314315 timeout-minutes: 60
315316 steps:
316317 - uses: actions/checkout@v5
374375 needs: look
375376 if: ${{ needs.look.outputs.cli == 'true' }}
376377 # The builder runs in Docker, which g1t's own machines give each job.
377− runs-on: g1t-4core
378+ runs-on: ubuntu-latest
378379 timeout-minutes: 60
379380 steps:
380381 - uses: actions/checkout@v5
+4−4
3838 jobs:
3939 rust:
4040 name: Rust
41− runs-on: g1t-4core
41+ runs-on: ubuntu-latest
4242 timeout-minutes: 45
4343 env:
4444 # Line tables, not full debug info: a panic still names its file and
158158
159159 desktop:
160160 name: Desktop app
161− # The larger machine, as the Rust job: linking Tauri on the small one
162− # ran out of room and the linker died with a bus error.
163− runs-on: g1t-4core
161+ # ubuntu-latest is 4 vCPU in this public repository, as on GitHub; linking
162+ # Tauri needs it (on 2 vCPU it ran out of room and died with a bus error).
163+ runs-on: ubuntu-latest
164164 timeout-minutes: 30
165165 steps:
166166 - uses: actions/checkout@v5
+2−2
1111 # Every platform builds in one job, in the rust-cross/cargo-zigbuild image,
1212 # pinned by digest in scripts/cli-release.mjs: the macOS builds link Apple's
1313 # Security framework (the keychain), and that image carries its SDK. It
14−# runs on g1t's own machines (g1t-4core), whose jobs have a Docker Engine of
14+# runs on g1t's own machines (ubuntu-latest, 4 vCPU here), whose jobs have a Docker Engine of
1515 # their own.
1616 name: CLI release
1717
3434 jobs:
3535 build:
3636 name: Build every platform
37− runs-on: g1t-4core
37+ runs-on: ubuntu-latest
3838 timeout-minutes: 60
3939 steps:
4040 - uses: actions/checkout@v5
+4−5
156156 # Runs when nothing before it failed: a migrate job skipped for having
157157 # nothing to apply is not a failure.
158158 if: ${{ !failure() && !cancelled() && needs.plan.outputs.has_core == 'true' && inputs.dry_run != true }}
159− # Rust builds and the runner's image get 4 vCPUs; everything else the
160− # standard machine.
161− runs-on: ${{ (matrix.rust || matrix.image) && 'g1t-4core' || 'ubuntu-latest' }}
159+ # ubuntu-latest: 4 vCPU in this public repository, as on GitHub.
160+ runs-on: ubuntu-latest
162161 environment:
163162 name: production
164163 url: https://g1t.sh
306305 name: edge (${{ matrix.group }})
307306 needs: [check, plan, migrate, core]
308307 if: ${{ !failure() && !cancelled() && needs.plan.outputs.has_edge == 'true' && inputs.dry_run != true }}
309− runs-on: ${{ (matrix.rust || matrix.image) && 'g1t-4core' || 'ubuntu-latest' }}
308+ runs-on: ubuntu-latest
310309 environment:
311310 name: production
312311 url: https://g1t.sh
321320 name: front (${{ matrix.group }})
322321 needs: [check, plan, migrate, core, edge]
323322 if: ${{ !failure() && !cancelled() && needs.plan.outputs.has_front == 'true' && inputs.dry_run != true }}
324− runs-on: ${{ (matrix.rust || matrix.image) && 'g1t-4core' || 'ubuntu-latest' }}
323+ runs-on: ubuntu-latest
325324 environment:
326325 name: production
327326 url: https://g1t.sh
+4−3
6363 linux:
6464 name: Linux
6565 needs: version
66− # The larger machine: linking Tauri on the small one dies with a bus error.
67− runs-on: g1t-4core
66+ # ubuntu-latest is 4 vCPU in this public repository, as on GitHub; linking
67+ # Tauri needs it (on 2 vCPU it dies with a bus error).
68+ runs-on: ubuntu-latest
6869 # Production's secrets, without a deployment: a release is not a deploy of
6970 # g1t.sh, and would otherwise show on its card as one in progress.
7071 environment:
168169 name: Windows, built on Linux
169170 needs: version
170171 if: vars.DESKTOP_WINDOWS_FROM_LINUX == 'true' && vars.DESKTOP_WINDOWS_RUNNER != 'true'
171− runs-on: g1t-4core
172+ runs-on: ubuntu-latest
172173 # Production's secrets, without a deployment: a release is not a deploy of
173174 # g1t.sh, and would otherwise show on its card as one in progress.
174175 environment:
+3−3
1111 # to make the release key the first time; CONTRIBUTING.md ("Deploying")
1212 # says how a release is made.
1313 #
14−# The image jobs run on g1t's own machines (g1t-4core), whose jobs have a
14+# The image jobs run on g1t's own machines (ubuntu-latest, 4 vCPU here), whose jobs have a
1515 # Docker Engine of their own (crates/runner/src/docker/engine.rs). arm64
1616 # images need QEMU's emulators registered with the kernel; each image job
1717 # tries that, and when the machine does not allow it, builds amd64 alone
126126 image:
127127 name: Container image
128128 needs: binaries
129− runs-on: g1t-4core
129+ runs-on: ubuntu-latest
130130 # Production's secrets, without a deployment: a release is not a deploy of
131131 # g1t.sh, and would otherwise show on its card as one in progress.
132132 environment:
183183 sandbox:
184184 name: Sandbox images
185185 needs: [binaries, image]
186− runs-on: g1t-4core
186+ runs-on: ubuntu-latest
187187 timeout-minutes: 60
188188 steps:
189189 - uses: actions/checkout@v5
+9−9
351351
352352 ### Machine sizes, time and storage
353353
354−| Limit | Value |
355−| ------------------------- | ----------------------------------------------------------------------------------------------------- |
356−| Largest machine | 4 vCPUs, 12 GiB of memory, 20 GB of disk (`g1t-4core`). No GPUs. |
357−| Standard machine | 2 vCPUs, 8 GiB of memory, 16 GB of disk (`ubuntu-latest`, every other hosted label, and `g1t-2core`). |
358−| One job on g1t's machines | 60 minutes. On a self-hosted runner, 24 hours. |
359−| One cache entry | 2 GiB, compressed. A larger one is not saved. |
360−| A repository's caches | 10 GiB together. Past it, the entries restored longest ago are removed. |
361−| One artifact | 5 GiB, zipped. Kept 14 days unless the repository says otherwise, at most 90. |
362−| A run's artifacts | 10 GiB together. |
354+| Limit | Value |
355+| ------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
356+| Largest machine | 4 vCPUs, 12 GiB of memory, 20 GB of disk (`g1t-4core`, and `ubuntu-latest` in a public repository). No GPUs. GitHub's machine for public repositories has 16 GB of memory. |
357+| Standard machine | 2 vCPUs, 8 GiB of memory, 16 GB of disk (`ubuntu-latest` and every other hosted label in a private repository, and `g1t-2core`). |
358+| One job on g1t's machines | 60 minutes. On a self-hosted runner, 24 hours. |
359+| One cache entry | 2 GiB, compressed. A larger one is not saved. |
360+| A repository's caches | 10 GiB together. Past it, the entries restored longest ago are removed. |
361+| One artifact | 5 GiB, zipped. Kept 14 days unless the repository says otherwise, at most 90. |
362+| A run's artifacts | 10 GiB together. |
363363
364364 The machine sizes are Cloudflare Containers' instance sizes. For more, use a
365365 [self-hosted runner](/guides/self-hosted-runners/). See
+8−5
7474 `runner` defines three Container classes, picked by `runs-on`, each a
7575 named Cloudflare instance type:
7676
77−| `runs-on` | Class | Size |
78−| ---------------------------------------------------- | ---------------- | ----------------------------------------------- |
79−| Any other hosted label, and every other kind of work | `AttemptSandbox` | `standard-3`: 2 vCPU, 8 GiB memory, 16 GB disk |
80−| `g1t-2core` | `Sandbox2Core` | `standard-3`: 2 vCPU, 8 GiB memory, 16 GB disk |
81−| `g1t-4core` | `Sandbox4Core` | `standard-4`: 4 vCPU, 12 GiB memory, 20 GB disk |
77+| `runs-on` | Class | Size |
78+| ---------------------------------------------------------------------------- | ---------------- | ----------------------------------------------- |
79+| Any other hosted label in a private repository, and every other kind of work | `AttemptSandbox` | `standard-3`: 2 vCPU, 8 GiB memory, 16 GB disk |
80+| `g1t-2core` | `Sandbox2Core` | `standard-3`: 2 vCPU, 8 GiB memory, 16 GB disk |
81+| `g1t-4core`, and any other hosted label in a public repository | `Sandbox4Core` | `standard-4`: 4 vCPU, 12 GiB memory, 20 GB disk |
8282
83+`ubuntu-latest` follows GitHub's hosted runners: the actions service
84+resolves it to `g1t-4core` when the run's repository is public (its
85+event's `repository.private`), and the job is billed as that machine.
8386 `g1t-2core` is kept as a name of the standard machine, so workflows that
8487 ask for it keep working; it keeps its class and its own `max_instances`
8588 in `services/runner/wrangler.jsonc`. The contracts' instance table
+17−10
554554
555555 ### Machine sizes
556556
557−A job runs on the standard machine unless its `runs-on` is `g1t-4core`:
557+`ubuntu-latest` gets what it gets on GitHub: 4 vCPUs in a public
558+repository, 2 in a private one. Any other Linux label is the same.
558559
559−| `runs-on` | vCPUs | Memory | Disk | A minute |
560−| -------------------------------------------- | ----- | ------ | ----- | -------- |
561−| `ubuntu-latest`, or any other Linux label | 2 | 8 GiB | 16 GB | $0.004 |
562−| `g1t-2core` (a name of the standard machine) | 2 | 8 GiB | 16 GB | $0.004 |
563−| `g1t-4core` | 4 | 12 GiB | 20 GB | $0.007 |
560+| `runs-on` | vCPUs | Memory | Disk | A minute |
561+| ----------------------------------------------------------------- | ----- | ------ | ----- | -------- |
562+| `ubuntu-latest`, or any other Linux label, in a public repository | 4 | 12 GiB | 20 GB | $0.007 |
563+| `ubuntu-latest`, or any other Linux label, in a private one | 2 | 8 GiB | 16 GB | $0.004 |
564+| `g1t-4core`, in any repository | 4 | 12 GiB | 20 GB | $0.007 |
565+| `g1t-2core`, in any repository | 2 | 8 GiB | 16 GB | $0.004 |
564566
567+GitHub's machine for public repositories has 16 GB of memory; g1t's has
568+12 GiB, the most its machines have.
569+
570+To choose a machine whatever the repository's visibility, name it:
571+
565572 ```yaml
566573 jobs:
567574 build:
568575 runs-on: g1t-4core
569576 ```
570577
571−`g1t-4core` is for heavier jobs: builds that compile, such as Rust or a
572−large TypeScript project, image builds and databases. `g1t-2core` is kept
573−as a name of the standard machine, so workflows that ask for it keep
574−working. The label can come from the matrix or the run's inputs
578+`g1t-4core` suits heavier jobs in a private repository: builds that
579+compile, such as Rust or a large TypeScript project, image builds and
580+databases. `g1t-2core` keeps a public repository's light jobs on the
581+smaller machine. The label can come from the matrix or the run's inputs
575582 (`runs-on: ${{ matrix.big && 'g1t-4core' || 'ubuntu-latest' }}`).
576583
577584 Each job is charged its time rounded up to the whole minute (61 seconds
+2−1
340340
341341 The standard sandbox is the instance type `standard-3` (2 vCPU, 8 GiB,
342342 16 GB), and so is `runs-on: g1t-2core`, in a class of its own; jobs that
343−ask for `runs-on: g1t-4core` get `standard-4` (4 vCPU, 12 GiB, 20 GB). At
343+ask for `runs-on: g1t-4core`, and `ubuntu-latest` jobs in a public
344+repository, get `standard-4` (4 vCPU, 12 GiB, 20 GB). At
344345 the `max_instances` in `services/runner/wrangler.jsonc` (20, 10 and 10),
345346 40 sandboxes at once hold 100 vCPU, 360 GiB of memory and 680 GB of disk,
346347 which your account's Containers limits for live instances must allow.
+15−9
102102 - **$10 of usage each month**, used first: everything g1t runs, at the
103103 [prices below](#what-it-costs) (runner minutes at their flat rate per
104104 machine, everything else at cost plus 20%). That is 2,500 runner minutes on the standard machine, or
105− about 1,428 on `g1t-4core`.
105+ about 1,428 on `g1t-4core` (which `ubuntu-latest` gets in a public
106+ repository).
106107 - **Everyone in the workspace** at one price, never per person.
107108 - **Unlimited** projects, previews and repositories.
108109 - Workflows, the merge queue,
244245
245246 Once its card is checked, a workspace gets **$5 of trial credit**, once. It
246247 pays for usage at the plan's prices: runner minutes for checks, workflows
247−and the merge queue (1,250 on the standard machine), and semantic search. It never pays for deployments.
248+and the merge queue (1,250 on the standard machine, about 714 on the
249+4-core one), and semantic search. It never pays for deployments.
248250
249251 - Each card gets one trial, whichever workspace it is checked in. Prepaid
250252 cards start none.
261263 ## The open-source pool
262264
263265 g1t sets aside **$25 a month** for public repositories, at most **$2 a
264−month** for any one repository: 6,250 and 500 runner minutes on the
265−standard machine. It pays for **checks, workflows and the merge queue on
266+month** for any one repository: about 3,571 and 285 minutes of
267+workflow jobs, which run on the 4-core machine in a public repository,
268+or 6,250 and 500 minutes of checks and merge queue runs on the standard
269+machine. It pays for **checks, workflows and the merge queue on
266270 public repositories**, after a card check. It does not pay
267271 for deployments, storage or embeddings.
268272
362366 queue run) is charged by the minute, at a fixed rate for the machine it
363367 ran on:
364368
365−| `runs-on` | Machine | vCPUs | Memory | Disk | A minute |
366−| ------------------------------------------------------ | ------------------- | ----- | ------ | ----- | -------- |
367−| `ubuntu-latest`, any other Linux label, or `g1t-2core` | Standard (`2-core`) | 2 | 8 GiB | 16 GB | $0.004 |
368−| `g1t-4core` | `4-core` | 4 | 12 GiB | 20 GB | $0.007 |
369+| `runs-on` | Machine | vCPUs | Memory | Disk | A minute |
370+| -------------------------------------------------------------------------------- | ------------------- | ----- | ------ | ----- | -------- |
371+| `ubuntu-latest` or any other Linux label in a private repository, or `g1t-2core` | Standard (`2-core`) | 2 | 8 GiB | 16 GB | $0.004 |
372+| `ubuntu-latest` or any other Linux label in a public repository, or `g1t-4core` | `4-core` | 4 | 12 GiB | 20 GB | $0.007 |
369373
370−Checks and the merge queue run on the standard machine. `g1t-2core` is
374+`ubuntu-latest` gets what it gets on GitHub: 4 vCPUs in a public
375+repository, 2 in a private one. A job is charged as the machine it ran
376+on. Checks and the merge queue run on the standard machine. `g1t-2core` is
371377 kept as a name of the standard machine, so workflows that ask for it keep
372378 working, at its rate.
373379
+32−11
10891089 /// Minutes before the job is stopped.
10901090 pub timeout_minutes: u32,
10911091 /// The machine its `runs-on` asked for, by label (`instance_for`):
1092− /// `g1t-2core` or `g1t-4core`; absent, the standard one.
1092+ /// `g1t-2core` or `g1t-4core`, which is also what `ubuntu-latest`
1093+ /// gets in a public repository; absent, the standard one.
10931094 #[serde(default)]
10941095 pub instance: Option<String>,
10951096 /// Whether the job may be given brokered secrets, so the runner sends
11161117 /// 16 GB of disk), `g1t-2core` is kept as a name of it so workflows that
11171118 /// ask for it keep working, and `g1t-4core` is standard-4 (4 vCPU, 12 GiB,
11181119 /// 20 GB).
1120+///
1121+/// `ubuntu-latest` and every other label not named here follow GitHub's
1122+/// hosted runners ([`instance_for`]): in a public repository the 4-core
1123+/// machine (GitHub's is 4 vCPU and 16 GB; 12 GiB is the most a Containers
1124+/// instance has without a raised limit), in a private one the standard
1125+/// machine (GitHub's is 2 vCPU and 8 GB).
11191126 #[derive(Clone, Copy, Debug, PartialEq)]
11201127 pub struct InstanceType {
11211128 /// The `runs-on` label, or `standard` for the default.
11541161 }
11551162 }
11561163
1157−/// The default: what `ubuntu-latest` and every other hosted label get.
1164+/// The default in a private repository: what `ubuntu-latest` and every
1165+/// other hosted label get there, as on GitHub. Checks and the merge queue
1166+/// run on it too.
11581167 pub const STANDARD_INSTANCE: InstanceType = InstanceType {
11591168 label: "standard",
11601169 machine: "2-core",
12071216 if seconds <= 0 { 0 } else { (seconds + 59) / 60 }
12081217 }
12091218
1219+/// The label of the machine `ubuntu-latest` gets in a public repository:
1220+/// GitHub gives public repositories 4 vCPU.
1221+pub const PUBLIC_DEFAULT_LABEL: &str = "g1t-4core";
1222+
12101223 /// The machine a job's `runs-on` labels ask for: the dearest named (the
1211−/// later row when two cost the same), or the standard one. Labels compare
1212−/// without regard to case.
1213−pub fn instance_for(labels: &[String]) -> InstanceType {
1224+/// later row when two cost the same). With none named (`ubuntu-latest`,
1225+/// say), what GitHub gives: the 4-core machine in a public repository,
1226+/// the standard one in a private one. Labels compare without regard to
1227+/// case.
1228+pub fn instance_for(labels: &[String], public: bool) -> InstanceType {
12141229 INSTANCE_TYPES
12151230 .iter()
12161231 .filter(|instance| instance.label != STANDARD_INSTANCE.label && labels.iter().any(|label| label.trim().eq_ignore_ascii_case(instance.label)))
12171232 .max_by_key(|instance| instance.micros_per_minute)
12181233 .copied()
1219− .unwrap_or(STANDARD_INSTANCE)
1234+ .unwrap_or_else(|| if public { instance_named(PUBLIC_DEFAULT_LABEL).unwrap_or(STANDARD_INSTANCE) } else { STANDARD_INSTANCE })
12201235 }
12211236
12221237 /// An instance type by its label, if it is one.
17171732
17181733 #[test]
17191734 fn runs_on_picks_the_machine() {
1720− assert_eq!(instance_for(&labels(&["ubuntu-latest"])), STANDARD_INSTANCE);
1721− assert_eq!(instance_for(&labels(&[])).label, "standard");
1722− assert_eq!(instance_for(&labels(&["g1t-4core"])).label, "g1t-4core");
1723− assert_eq!(instance_for(&labels(&["ubuntu-latest", "G1T-2Core"])).label, "g1t-2core");
1735+ // As on GitHub: ubuntu-latest is 2 vCPU in a private repository, 4 in a public one.
1736+ assert_eq!(instance_for(&labels(&["ubuntu-latest"]), false), STANDARD_INSTANCE);
1737+ assert_eq!(instance_for(&labels(&["ubuntu-latest"]), true).machine, "4-core");
1738+ assert_eq!(instance_for(&labels(&["ubuntu-24.04"]), true).vcpu, 4.0);
1739+ assert_eq!(instance_for(&labels(&[]), false).label, "standard");
1740+ assert_eq!(instance_for(&labels(&[]), true).label, PUBLIC_DEFAULT_LABEL);
1741+ // A machine asked for by name is that machine, public or not.
1742+ assert_eq!(instance_for(&labels(&["g1t-4core"]), false).label, "g1t-4core");
1743+ assert_eq!(instance_for(&labels(&["ubuntu-latest", "G1T-2Core"]), false).label, "g1t-2core");
1744+ assert_eq!(instance_for(&labels(&["ubuntu-latest", "g1t-2core"]), true).machine, "2-core");
17241745 // Both named: the later one.
1725− assert_eq!(instance_for(&labels(&["g1t-2core", "g1t-4core"])).label, "g1t-4core");
1746+ assert_eq!(instance_for(&labels(&["g1t-2core", "g1t-4core"]), false).label, "g1t-4core");
17261747 assert_eq!(instance_named("g1t-2core").map(|i| i.vcpu), Some(2.0));
17271748 assert_eq!(instance_named("g1t-4core").map(|i| i.vcpu), Some(4.0));
17281749 assert_eq!(instance_named("standard"), Some(STANDARD_INSTANCE));
+1−1
4141 { label: "g1t-4core", machine: "4-core", sandboxClass: "Sandbox4Core", container: "standard-4", vcpu: 4, memoryGib: 12, diskGb: 20, microsPerMinute: 7000 },
4242 ];
4343
44−/** The default: what `ubuntu-latest` and every other hosted label get. */
44+/** The default in a private repository: what `ubuntu-latest` and every other hosted label get there, as on GitHub (`instance_for` in crates/contracts/src/actions.rs gives a public repository `g1t-4core`). */
4545 export const STANDARD_INSTANCE: InstanceType = INSTANCE_TYPES[0]!;
4646
4747 /** An instance type by its label; the standard one for anything else. */
+35−2
505505 env.filter(|env| env.deploys)
506506 }
507507
508+/// Whether a run's repository was public when the run was made, from its
509+/// event's `repository.private`: private when the event doesn't say.
510+fn run_is_public(run: &RunRow) -> bool {
511+ run.info().event.get("repository").and_then(|repository| repository.get("private")).and_then(Value::as_bool) == Some(false)
512+}
513+
508514 /// The machine a job's `runs-on` asks for (`instance_for`), for the
509−/// runner: none for the standard one.
515+/// runner: none for the standard one. `ubuntu-latest` follows GitHub: the
516+/// 4-core machine in a public repository. Billing charges the job as the
517+/// machine named here, so what it ran on is what it pays for.
510518 fn start_instance(run: &RunRow, job: &JobRow) -> Option<String> {
511519 let spec = match job.callee() {
512520 Some((_, spec, _)) => spec,
526534 },
527535 _ => Vec::new(),
528536 };
529− let instance = g1t_contracts::actions::instance_for(&labels);
537+ let instance = g1t_contracts::actions::instance_for(&labels, run_is_public(run));
530538 (instance != g1t_contracts::actions::STANDARD_INSTANCE).then(|| instance.label.to_owned())
531539 }
532540
32533261 assert_eq!(runner["name"], "g1t");
32543262 }
32553263 }
3264+
3265+#[cfg(test)]
3266+mod machines {
3267+ use serde_json::json;
3268+
3269+ use super::{RunInfo, RunRow, run_is_public};
3270+
3271+ fn run(event: serde_json::Value) -> RunRow {
3272+ let info = serde_json::to_string(&RunInfo { repository: "acme/web".into(), event, ..RunInfo::default() }).unwrap();
3273+ serde_json::from_value(json!({
3274+ "id": "run_1", "workflow_id": "wf_1", "repo_id": "rep_1", "repo": "acme/web", "path": ".g1t/workflows/ci.yml", "name": "CI",
3275+ "title": "CI", "number": 1, "attempt": 1, "event": "push", "git_ref": "refs/heads/main", "sha": "abc", "status": "queued",
3276+ "source": "", "info": info, "inputs": "{}", "trusted": 1, "created_at": "2026-10-18T00:00:00Z",
3277+ }))
3278+ .unwrap()
3279+ }
3280+
3281+ #[test]
3282+ fn a_runs_repository_is_public_only_when_its_event_says_so() {
3283+ assert!(run_is_public(&run(json!({ "repository": { "private": false } }))));
3284+ assert!(!run_is_public(&run(json!({ "repository": { "private": true } }))));
3285+ // An event that doesn't say is taken as private: the standard machine.
3286+ assert!(!run_is_public(&run(json!({}))));
3287+ }
3288+}

Comments

Sign in to comment.