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.

g1t.sh
132 linesCodeBlameRaw
1# Releases the self-hosted runner, g1t-runner (crates/runner): builds it for
2# Linux, macOS and Windows on x64 and arm64, signs the release, publishes it
3# to g1t.sh/downloads/runner/ (the g1t-downloads R2 bucket), and pushes its
4# container image. Runners already out there update themselves to it.
5#
6# A release is a tag `runner-v<version>`, where the version is the one in
7# crates/runner/Cargo.toml; or run it by hand. scripts/runner-release.mjs
8# does the work, and its header says how to make the release key the first
9# time; CONTRIBUTING.md ("Deploying") says how a release is made.
10name: Runner release
11
12on:
13 push:
14 tags: ["runner-v*"]
15 workflow_dispatch:
16
17permissions:
18 contents: read
19
20concurrency:
21 group: runner-release
22 cancel-in-progress: false
23
24env:
25 CLOUDFLARE_ACCOUNT_ID: ${{ vars.CLOUDFLARE_ACCOUNT_ID }}
26 WRANGLER_SEND_METRICS: "false"
27
28jobs:
29 binaries:
30 name: Build, sign and publish
31 runs-on: ubuntu-latest
32 # Production's secrets, without a deployment: a release is not a deploy of
33 # g1t.sh, and would otherwise show on its card as one in progress.
34 environment:
35 name: production
36 deployment: false
37 timeout-minutes: 60
38 steps:
39 - uses: actions/checkout@v5
40 - name: The tag names this version
41 if: startsWith(github.ref, 'refs/tags/runner-v')
42 run: |
43 version="$(sed -n 's/^version = "\(.*\)"/\1/p' crates/runner/Cargo.toml | head -1)"
44 [ "runner-v$version" = "${GITHUB_REF_NAME}" ] || { echo "::error::The tag is ${GITHUB_REF_NAME}, but crates/runner is $version"; exit 1; }
45 - name: Install zig and cargo-zigbuild
46 run: |
47 # The runner's Debian marks its Python as externally managed (PEP 668); zig goes under ~/.local anyway.
48 pip install --user --break-system-packages ziglang==0.13.0
49 echo "$HOME/.local/bin" >> "$GITHUB_PATH"
50 cargo install --locked cargo-zigbuild
51 - uses: actions/cache@v4
52 with:
53 path: |
54 ~/.cargo/registry
55 target
56 key: runner-release-${{ hashFiles('Cargo.lock') }}
57 - name: Build Linux and Windows
58 # The macOS targets need Apple's SDK to link (the Security and
59 # CoreFoundation frameworks), which zig does not carry, so they are
60 # left out until this builds in the rust-cross/cargo-zigbuild image
61 # as the CLI's release does (scripts/cli-release.mjs). A Mac runner
62 # keeps the version it has, since the manifest names no file for it.
63 env:
64 G1T_RUNNER_RELEASE_KEY: ${{ vars.RUNNER_RELEASE_PUBLIC_KEY }}
65 RUNNER_AGENT_IMAGE: ${{ vars.RUNNER_AGENT_IMAGE }}
66 run: node scripts/runner-release.mjs build --targets linux-x64,linux-arm64,windows-x64
67 - name: Sign
68 env:
69 RUNNER_RELEASE_KEY: ${{ secrets.RUNNER_RELEASE_KEY }}
70 G1T_RUNNER_RELEASE_KEY: ${{ vars.RUNNER_RELEASE_PUBLIC_KEY }}
71 run: |
72 node scripts/runner-release.mjs sign
73 node scripts/runner-release.mjs verify
74 # npm's downloads, kept between runs: an install reads them first
75 # and asks the registry only for what changed, so a dropped
76 # connection to it rarely stops the job.
77 - name: Cache npm's downloads
78 uses: actions/cache@v4
79 with:
80 path: ~/.npm
81 key: npm-${{ runner.os }}-${{ hashFiles('package-lock.json') }}
82 restore-keys: npm-${{ runner.os }}-
83 - name: Install Wrangler
84 run: npm ci --prefer-offline --workspaces=false --no-audit --no-fund
85 - name: Publish to g1t.sh/downloads/runner
86 env:
87 CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }}
88 run: node scripts/runner-release.mjs publish
89 - uses: actions/upload-artifact@v4
90 with:
91 name: linux-binaries
92 path: |
93 target/runner-release/*/g1t-runner-linux-x64
94 target/runner-release/*/g1t-runner-linux-arm64
95
96 image:
97 name: Container image
98 needs: binaries
99 # Builds for arm64 as well as amd64, which needs QEMU's emulators
100 # registered on the machine: a self-hosted runner's, for now.
101 runs-on: [self-hosted, docker]
102 # Production's secrets, without a deployment: a release is not a deploy of
103 # g1t.sh, and would otherwise show on its card as one in progress.
104 environment:
105 name: production
106 deployment: false
107 timeout-minutes: 30
108 # Its token pushes the image to g1t's registry.
109 permissions:
110 contents: read
111 packages: write
112 steps:
113 - uses: actions/checkout@v5
114 - uses: actions/download-artifact@v4
115 with:
116 name: linux-binaries
117 path: release
118 - name: Build and push for amd64 and arm64
119 # To g1t's own registry, where flagon-io keeps it public.
120 env:
121 IMAGE: g1t.sh/flagon-io/g1t-runner
122 run: |
123 version="$(sed -n 's/^version = "\(.*\)"/\1/p' crates/runner/Cargo.toml | head -1)"
124 echo "${{ secrets.G1T_TOKEN }}" | docker login g1t.sh -u g1t --password-stdin
125 for arch in amd64 arm64; do
126 mkdir -p "context-$arch"
127 cp deploy/runner/Dockerfile "context-$arch/"
128 name="g1t-runner-linux-$([ "$arch" = amd64 ] && echo x64 || echo arm64)"
129 cp release/*/"$name" "context-$arch/g1t-runner"
130 docker buildx build --platform "linux/$arch" -t "$IMAGE:$version-$arch" --push "context-$arch"
131 done
132 docker buildx imagetools create -t "$IMAGE:$version" -t "$IMAGE:latest" "$IMAGE:$version-amd64" "$IMAGE:$version-arm64"