-
Notifications
You must be signed in to change notification settings - Fork 23
242 lines (232 loc) · 9.34 KB
/
Copy pathpr-checks.yml
File metadata and controls
242 lines (232 loc) · 9.34 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
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
name: PR checks
# Per-package parallel pipeline: each codec is built, tested, and benchmarked
# independently. The matrix mirrors what CircleCI was doing — every entry
# runs concurrently, any failure fails the workflow.
#
# CodSpeed's first-class GHA integration replaces the manual codspeed-bench
# job from CircleCI: `CodSpeedHQ/action@v3` installs valgrind, sets up
# instrumentation, and uploads results in one step.
on:
pull_request:
push:
# Run on every branch including main so each merge to main seeds a
# fresh CodSpeed baseline. Without a main run, PR comments stay stuck
# on "Congrats! CodSpeed is installed" with no before/after deltas.
branches:
- "**"
# workflow_dispatch lets CodSpeed trigger a backtest run from the
# dashboard (to seed initial perf data after the repo is connected).
workflow_dispatch:
# Cancel in-flight runs when a new push lands on the same PR / branch.
concurrency:
group: pr-checks-${{ github.workflow }}-${{ github.head_ref || github.ref }}
cancel-in-progress: true
permissions:
contents: read
pull-requests: write # CodSpeed action posts a sticky PR comment
id-token: write # OIDC token used by CodSpeedHQ/action for auth
jobs:
detect-changes:
# Build the matrix dynamically from the set of packages that actually
# changed since main. Mirrors CircleCI's --since main skip logic. On a
# PR where every README was touched (this branch) the list is the full
# 8 packages; on a docs-only PR the build matrix is empty.
runs-on: ubuntu-latest
outputs:
packages: ${{ steps.list.outputs.packages }}
any: ${{ steps.list.outputs.any }}
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- id: list
name: List changed packages
env:
EVENT_NAME: ${{ github.event_name }}
REF: ${{ github.ref }}
run: |
set -e
ALL=(charls libjpeg-turbo-8bit libjpeg-turbo-12bit openjpeg openjphjs little-endian big-endian dicom-codec)
# Baseline runs: on a manual dispatch or any commit landing on
# main, build/test/bench every package. The "diff vs main" trick
# only makes sense on PR/feature branches — when HEAD === main,
# `git diff origin/main..HEAD` is empty and would skip CodSpeed
# entirely, leaving the dashboard with no baseline data.
if [ "$EVENT_NAME" = "workflow_dispatch" ] || [ "$REF" = "refs/heads/main" ]; then
json=$(printf '%s\n' "${ALL[@]}" | jq -R . | jq -s -c .)
echo "Baseline run ($EVENT_NAME on $REF): forcing all packages"
echo "packages=$json" >> "$GITHUB_OUTPUT"
echo "any=true" >> "$GITHUB_OUTPUT"
exit 0
fi
git fetch --no-tags --depth=50 origin main || true
BASE=$(git merge-base origin/main HEAD || echo "origin/main")
changed=()
for pkg in "${ALL[@]}"; do
if ! git diff --quiet "$BASE"..HEAD -- "packages/$pkg/"; then
changed+=("$pkg")
fi
done
if [ ${#changed[@]} -eq 0 ]; then
echo "No packages changed since $BASE."
echo 'packages=[]' >> "$GITHUB_OUTPUT"
echo "any=false" >> "$GITHUB_OUTPUT"
else
json=$(printf '%s\n' "${changed[@]}" | jq -R . | jq -s -c .)
echo "Changed packages: $json"
echo "packages=$json" >> "$GITHUB_OUTPUT"
echo "any=true" >> "$GITHUB_OUTPUT"
fi
build:
needs: detect-changes
if: needs.detect-changes.outputs.any == 'true'
strategy:
fail-fast: false
matrix:
package: ${{ fromJson(needs.detect-changes.outputs.packages) }}
runs-on: ubuntu-latest
container:
image: emscripten/emsdk:3.1.74
steps:
- name: Install yarn + cmake + C++ build deps
run: |
npm install --global yarn@1.22.22
apt-get update
apt-get -y install build-essential git
wget -qO- "https://cmake.org/files/v3.17/cmake-3.17.4-Linux-x86_64.tar.gz" \
| tar --strip-components=1 -xz -C /usr/local
apt-get autoremove -y
apt-get clean -y
rm -rf /var/lib/apt/lists/*
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Allow git to operate on the workspace
# The container runs as root but the workspace is owned by the
# checkout action's user, which makes git complain about
# `dubious ownership`. Mark it safe.
run: git config --global --add safe.directory "$GITHUB_WORKSPACE"
- name: Init submodules for this package
run: |
if [ -d "packages/${{ matrix.package }}/extern" ]; then
git submodule update --init --recursive "packages/${{ matrix.package }}/extern"
else
echo "No extern/ submodule for ${{ matrix.package }}; skipping."
fi
- name: Restore yarn cache
uses: actions/cache@v4
with:
path: ~/.cache/yarn
key: yarn-${{ hashFiles('yarn.lock') }}
restore-keys: yarn-
- name: Install dependencies
run: yarn install --frozen-lockfile
- name: Build
run: cd "packages/${{ matrix.package }}" && yarn run build:ci
- name: Ensure dist exists (no-op packages still need a placeholder)
run: mkdir -p "packages/${{ matrix.package }}/dist"
- name: Upload dist
uses: actions/upload-artifact@v4
with:
name: dist-${{ matrix.package }}
path: packages/${{ matrix.package }}/dist
if-no-files-found: ignore
retention-days: 7
test:
needs: [detect-changes, build]
if: needs.detect-changes.outputs.any == 'true'
strategy:
fail-fast: false
matrix:
package: ${{ fromJson(needs.detect-changes.outputs.packages) }}
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '22'
- name: Download all built dists
uses: actions/download-artifact@v4
with:
pattern: dist-*
path: tmp/
- name: Replay dists into packages/<pkg>/dist
# actions/download-artifact lands each artifact in tmp/<name>/.
# Move each into its proper packages/<pkg>/dist location so vitest
# finds them, mirroring how CircleCI workspace persist worked.
run: |
set -e
for d in tmp/dist-*; do
[ -d "$d" ] || continue
pkg=$(basename "$d" | sed 's/^dist-//')
mkdir -p "packages/$pkg/dist"
shopt -s dotglob nullglob
cp -r "$d"/* "packages/$pkg/dist/" 2>/dev/null || true
done
ls packages/*/dist 2>/dev/null | head
- name: Restore yarn cache
uses: actions/cache@v4
with:
path: ~/.cache/yarn
key: yarn-${{ hashFiles('yarn.lock') }}
restore-keys: yarn-
- name: Install dependencies
run: yarn install --frozen-lockfile
- name: Test
run: cd "packages/${{ matrix.package }}" && yarn run test:ci
codspeed-bench:
needs: [detect-changes, build]
if: needs.detect-changes.outputs.any == 'true'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '22'
- name: Download all built dists
uses: actions/download-artifact@v4
with:
pattern: dist-*
path: tmp/
- name: Replay dists into packages/<pkg>/dist
run: |
set -e
for d in tmp/dist-*; do
[ -d "$d" ] || continue
pkg=$(basename "$d" | sed 's/^dist-//')
mkdir -p "packages/$pkg/dist"
shopt -s dotglob nullglob
cp -r "$d"/* "packages/$pkg/dist/" 2>/dev/null || true
done
- name: Restore yarn cache
uses: actions/cache@v4
with:
path: ~/.cache/yarn
key: yarn-${{ hashFiles('yarn.lock') }}
restore-keys: yarn-
- name: Install dependencies
run: yarn install --frozen-lockfile
- name: Run CodSpeed benchmarks
# CodSpeedHQ/action@v4 sets up CPU simulation (Cachegrind-based
# instruction counting on a modeled CPU + cache hierarchy), runs
# the inner command under valgrind, uploads to codspeed.io, and
# posts/updates a sticky PR comment with the per-bench deltas.
# Authenticates via GitHub OIDC (id-token: write above) so no
# CODSPEED_TOKEN secret is needed.
#
# mode: simulation (vs walltime) — we chose simulation because:
# - deterministic: <1% run-to-run drift (verified across 3
# runs of identical source)
# - free CI minutes (walltime needs CodSpeed macro-runners)
# - regression-detection signal is strong even though the
# headline numbers are MODELED instruction-time, not real
# wall-clock (JS-loop benches inflate 30-100x vs production
# V8 due to no JIT under Cachegrind; wasm decode kernels
# inflate ~5-15x; pure native ~1x)
# See BENCHMARKING.md at the repo root for the full measurement
# model, how to read the cold/warm bench split, and what the
# CodSpeed dashboard warnings mean.
uses: CodSpeedHQ/action@v4
with:
mode: simulation
run: yarn run bench