forked from tobi/walgit
-
-
Notifications
You must be signed in to change notification settings - Fork 0
196 lines (177 loc) · 8.4 KB
/
Copy pathci.yml
File metadata and controls
196 lines (177 loc) · 8.4 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
name: CI
# The repository had no build/test workflow: only pages.yml (a site deploy). A workspace that did
# not compile reached main because nothing ran cargo on push. This runs `just ci` — the same
# tiers AGENTS.md documents (warnings, clippy, test, e2e) — so CI and a contributor's laptop cannot drift.
# The tier definitions live in the justfile, never duplicated here.
on:
push:
branches: [main]
pull_request:
workflow_dispatch:
concurrency:
group: ci-${{ github.ref }}
# Superseded PR pushes are worth cancelling; main is not. A cancelled main run takes
# publish-canary down with it (run-level cancellation ignores job-level concurrency),
# and that commit's immutable sha- tag would then never exist.
cancel-in-progress: ${{ github.ref != 'refs/heads/main' }}
# Least privilege by default: only publish-canary needs a write scope, and it asks for it itself.
permissions:
contents: read
env:
CARGO_TERM_COLOR: always
jobs:
build-test:
name: warnings + test
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4.4.0
# prost-build does not vendor protoc; without it the proto crate fails with NotFound.
- name: Install protoc
run: sudo apt-get update && sudo apt-get install -y protobuf-compiler
# No toolchain version here on purpose: rust-toolchain.toml pins it (and its components).
# `rustup show` installs exactly that, so the pin has one home.
- name: Install the pinned Rust toolchain
run: rustup show && cargo --version && git --version
- uses: Swatinem/rust-cache@6323deb102c322ba6fcbdcafc7e3dddab59af2b6 # v2.9.2
- uses: taiki-e/install-action@e67fa11c4b9316fa714ddf0abed07a0c3143b95b # v2.87.4
with:
tool: just
- uses: pnpm/action-setup@b906affcce14559ad1aafd4ab0e942779e9f58b1 # v4.3.0
with:
version: 10
- uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
with:
node-version: 24
cache: pnpm
cache-dependency-path: web/pnpm-lock.yaml
# Required, not cosmetic: build.rs only writes a placeholder index.html, and api_v1's
# v1_surface_and_browser_lane asserts /repos.js and /repos.mjs are served 200. Also runs
# oxlint --deny-warnings and tsc --noEmit, so the web gate is covered here too.
- name: Build the SPA and the SDK
run: just web-build
- run: just warnings
- run: just clippy
- run: just test
e2e:
name: e2e
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4.4.0
- name: Install protoc
run: sudo apt-get update && sudo apt-get install -y protobuf-compiler
- name: Install the pinned Rust toolchain
run: rustup show && cargo --version && git --version
- uses: Swatinem/rust-cache@6323deb102c322ba6fcbdcafc7e3dddab59af2b6 # v2.9.2
- uses: taiki-e/install-action@e67fa11c4b9316fa714ddf0abed07a0c3143b95b # v2.87.4
with:
tool: just
- uses: pnpm/action-setup@b906affcce14559ad1aafd4ab0e942779e9f58b1 # v4.3.0
with:
version: 10
- uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
with:
node-version: 24
cache: pnpm
cache-dependency-path: web/pnpm-lock.yaml
- name: Build the SPA and the SDK
run: just web-build
- run: just e2e
- run: just sim
- run: just smoke
# publish-canary needs this job, so its verdict decides whether a main commit is published:
# a moving tag here could pass a contract that did not hold. Pinned like the publishing job,
# for the same reason, even though this job itself holds nothing but a read token.
spec:
name: bounded contract checks
runs-on: ubuntu-latest
timeout-minutes: 20
steps:
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4.4.0
- name: Install spec runner dependencies
run: sudo apt-get update && sudo apt-get install -y ripgrep
- uses: actions/setup-java@cf277c60eb25467037889841efdb72551f06f6c3 # v4.9.1
with:
distribution: temurin
java-version: 21
- uses: taiki-e/install-action@e67fa11c4b9316fa714ddf0abed07a0c3143b95b # v2.87.4
with:
tool: just
- run: just spec
- uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
if: always()
with:
name: spec-evidence
path: target/test-logs/spec-*
# Canary image publish. Lives in this workflow, not a separate one, so `needs` gates it on the
# same green run that just tested the commit: a red main never produces a canary tag, and there
# is no workflow_run indirection re-deriving the SHA from an event payload.
#
# ghcr.io/<owner>/walgit:canary moving tag, always the newest green main
# ghcr.io/<owner>/walgit:sha-<40> immutable, what a rollback or a bug report pins to
#
# Re-running a run on the same commit is safe, and it does NOT touch an existing sha- tag: the
# build is not bit-reproducible, so republishing that tag would repoint what a rollback pinned to
# at a digest nobody chose. A re-run moves `canary` only; the sha- tag is written once, ever.
publish-canary:
name: publish canary image
needs: [build-test, e2e, spec]
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
runs-on: ubuntu-latest
permissions:
contents: read
# The only write scope this workflow needs; GITHUB_TOKEN carries nothing else.
packages: write
steps:
# This job holds a token that can write packages, so its actions are pinned to commit SHAs:
# a moving tag would let an upstream compromise reach the registry. The other jobs read only.
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4.4.0
with:
# Nothing here runs git again; leaving the token in .git/config only widens the blast radius.
persist-credentials: false
- uses: docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f # v3.12.0
- uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 # v3.7.0
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
# GHCR rejects an uppercase path, and github.repository carries the owner's real casing.
- name: Resolve the image name
id: image
run: echo "name=ghcr.io/${GITHUB_REPOSITORY,,}" >> "$GITHUB_OUTPUT"
# "Immutable" has to mean it: if this commit already has a sha- tag, leave it at the digest
# it already points to and let this run move `canary` alone.
- name: Decide whether the rollback tag is still unwritten
id: rollback
run: |
if docker buildx imagetools inspect "${{ steps.image.outputs.name }}:sha-${GITHUB_SHA}" >/dev/null 2>&1; then
echo "unwritten=false" >> "$GITHUB_OUTPUT"
else
echo "unwritten=true" >> "$GITHUB_OUTPUT"
fi
# format=long, not short: a seven-character prefix is a namespace that collides, and the
# collision would silently move an older commit's immutable tag onto a newer image. Both tags
# and the OCI source/revision labels come from one place rather than hand-built strings.
- name: Derive tags and labels
id: meta
uses: docker/metadata-action@c299e40c65443455700f0fdfc63efafe5b349051 # v5.10.0
with:
images: ${{ steps.image.outputs.name }}
tags: |
type=raw,value=canary
type=sha,format=long,prefix=sha-,enable=${{ steps.rollback.outputs.unwritten }}
- name: Build and push
uses: docker/build-push-action@10e90e3645eae34f1e60eeb005ba3a3d33f178e8 # v6.19.2
with:
context: .
file: Containerfile
platforms: linux/amd64
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
# The build stage never copies .git, so this ARG is the binary's only build identity:
# without it walgit-server/build.rs falls back to "dev" and every image reports the same
# version on /healthz. Full 40 chars: build.rs takes the value verbatim.
build-args: |
WALGIT_BUILD_SHA=${{ github.sha }}
cache-from: type=gha
cache-to: type=gha,mode=max