-
-
Notifications
You must be signed in to change notification settings - Fork 8
206 lines (197 loc) · 8.65 KB
/
Copy pathci.yml
File metadata and controls
206 lines (197 loc) · 8.65 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
197
198
199
200
201
202
203
204
205
206
# Zaparoo Frontend
# Copyright (c) 2026 Wizzo Pty Ltd and the Zaparoo Project contributors.
# SPDX-License-Identifier: LicenseRef-PolyForm-Noncommercial-1.0.0
name: CI
on:
push:
branches: [main]
pull_request:
branches: [main]
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
permissions:
contents: read
# Consumer jobs (rust-lint, rust-test, desktop-build) pull the lint image
# from GHCR; that pull requires read scope even though the publishing
# `ensure-lint-image` job overrides to `packages: write` below. Setting
# an explicit `permissions:` block strips defaults, so without this
# line the consumer jobs would only get `contents: read` and `docker
# pull` would fail with "denied" against any private package version.
packages: read
env:
# CI doesn't reuse incremental metadata across runs — it only bloats the
# cached `target/` and slows the Swatinem post-cache upload.
CARGO_INCREMENTAL: 0
# Strip debug info from test binaries to keep `target/` small for caching.
CARGO_PROFILE_TEST_DEBUG: 0
CARGO_TERM_COLOR: always
jobs:
# Resolve the lint image tag from `scripts/lint/VERSION` and make sure
# that tag exists on GHCR before downstream jobs try to spin up
# containers from it. PRs that bump `scripts/lint/VERSION` therefore
# self-bootstrap: the very
# first CI run for the bump publishes the image, then re-runs and
# downstream jobs reuse it. The dedicated `lint-image-build.yml`
# workflow still publishes multi-arch images on pushes to main; this
# job only ever produces linux/amd64 (CI's runner arch).
ensure-lint-image:
name: Ensure lint image
runs-on: ubuntu-latest
# Only this job pushes to GHCR — downstream jobs pull via container
# credentials, which use the same GITHUB_TOKEN but don't need write.
permissions:
contents: read
packages: write
outputs:
image: ${{ steps.resolve.outputs.image }}
version: ${{ steps.resolve.outputs.version }}
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
- id: resolve
env:
OWNER: ${{ github.repository_owner }}
run: |
VERSION=$(tr -d '[:space:]' < scripts/lint/VERSION)
OWNER_LC=$(printf '%s' "$OWNER" | tr '[:upper:]' '[:lower:]')
IMAGE="ghcr.io/${OWNER_LC}/zaparoo-lint:${VERSION}"
{
printf 'version=%s\n' "$VERSION"
printf 'image=%s\n' "$IMAGE"
} >> "$GITHUB_OUTPUT"
- uses: docker/login-action@c99871dec2022cc055c062a10cc1a1310835ceb4 # v4
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- id: check
run: |
if docker manifest inspect ${{ steps.resolve.outputs.image }} >/dev/null 2>&1; then
echo "exists=true" >> "$GITHUB_OUTPUT"
echo "Lint image ${{ steps.resolve.outputs.image }} already published"
else
echo "exists=false" >> "$GITHUB_OUTPUT"
echo "Lint image ${{ steps.resolve.outputs.image }} missing — building"
fi
# Fork PRs cannot push to GHCR (GITHUB_TOKEN is read-only), so a
# scripts/lint/VERSION bump from a fork would fail mid-`docker push` with
# an opaque "denied: forbidden". Fail fast here with a useful
# message instead. Maintainer-branch PRs (head.repo.fork == false)
# fall through to the existing build/push steps.
- if: steps.check.outputs.exists != 'true' && github.event.pull_request.head.repo.fork == true
run: |
echo "::error::Lint image ${{ steps.resolve.outputs.image }} is not yet published. Fork PRs cannot push to GHCR — ask a maintainer to land the scripts/lint/VERSION bump from the main repo first."
exit 1
- if: steps.check.outputs.exists != 'true' && github.event.pull_request.head.repo.fork != true
uses: docker/setup-buildx-action@bb05f3f5519dd87d3ba754cc423b652a5edd6d2c # v4
- if: steps.check.outputs.exists != 'true' && github.event.pull_request.head.repo.fork != true
uses: docker/build-push-action@53b7df96c91f9c12dcc8a07bcb9ccacbed38856a # v7.3.0
with:
context: .
file: Dockerfile.lint
# Single-arch build is intentional. Multi-arch publish (amd64 +
# arm64 for Apple Silicon contributors) is the dedicated
# `lint-image-build.yml` workflow's job; CI runners are amd64.
platforms: linux/amd64
push: true
tags: ${{ steps.resolve.outputs.image }}
cache-from: type=gha,scope=lint
cache-to: type=gha,scope=lint,mode=max
rust-lint:
name: Rust lint (fmt + clippy + deny)
needs: ensure-lint-image
runs-on: ubicloud-standard-8
container:
image: ${{ needs.ensure-lint-image.outputs.image }}
credentials:
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
defaults:
run:
working-directory: rust
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
- uses: Swatinem/rust-cache@e18b497796c12c097a38f9edb9d0641fb99eee32 # v2
with:
workspaces: rust
# Lint image version contributes to cache key — different image
# versions can ship different rustc / Qt / clang, so reusing
# target/ across image versions risks dangling object refs.
prefix-key: "v0-rust-${{ needs.ensure-lint-image.outputs.version }}"
env-vars: "CARGO CC CFLAGS CXX CMAKE RUST"
- name: rustfmt
run: cargo fmt --all --check
- name: clippy
run: cargo clippy --workspace --all-targets -- -D warnings
- name: cargo-deny
run: cargo deny check
rust-test:
name: Rust tests (nextest)
needs: ensure-lint-image
runs-on: ubicloud-standard-8
container:
image: ${{ needs.ensure-lint-image.outputs.image }}
credentials:
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
defaults:
run:
working-directory: rust
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
- uses: Swatinem/rust-cache@e18b497796c12c097a38f9edb9d0641fb99eee32 # v2
with:
workspaces: rust
prefix-key: "v0-rust-${{ needs.ensure-lint-image.outputs.version }}"
env-vars: "CARGO CC CFLAGS CXX CMAKE RUST"
- name: nextest
run: cargo nextest run --workspace
desktop-build:
# Folds the old `cpp-lint` job in: clang-tidy needs compile_commands.json
# and the autogen/moc outputs that the desktop build already produces, so
# running lint as the final step of the same job avoids building twice.
name: Desktop build + ctest + lint
needs: ensure-lint-image
runs-on: ubicloud-standard-8
container:
image: ${{ needs.ensure-lint-image.outputs.image }}
credentials:
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
- uses: Swatinem/rust-cache@e18b497796c12c097a38f9edb9d0641fb99eee32 # v2
with:
workspaces: rust
prefix-key: "v0-desktop-${{ needs.ensure-lint-image.outputs.version }}"
env-vars: "CARGO CC CFLAGS CXX CMAKE RUST"
# ccache wraps clang/gcc invocations; CMake's compiler-launcher hooks pick it up
# via CMAKE_{C,CXX}_COMPILER_LAUNCHER set on the configure command line
# below. Lint image version is part of the cache key because Qt
# include paths are baked into preprocessed translation units.
- name: Set up ccache
uses: hendrikmuhs/ccache-action@d62db5f07c26379fc4b4e0916f098a92573c3b03 # v1.2.23
with:
key: desktop-build-${{ needs.ensure-lint-image.outputs.version }}
max-size: 500M
- name: Configure
run: >
cmake --preset desktop-debug
-DCMAKE_C_COMPILER_LAUNCHER=ccache
-DCMAKE_CXX_COMPILER_LAUNCHER=ccache
- name: Build
run: cmake --build --preset desktop-debug
- name: Test
run: ctest --preset desktop-debug
- name: Lint (clang-format + clang-tidy + qmllint)
run: cmake --build build --target lint
- name: Check translations are up to date
run: bash scripts/check-translations-updated.sh build
- name: Upload frontend binary
if: failure()
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: frontend-debug-${{ github.run_id }}
path: build/bin/frontend
if-no-files-found: warn
retention-days: 7