chore(openjpeg): update OpenJPEG submodule to upstream v2.5.4 #176
Workflow file for this run
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: PR checks | |
| # Pipeline: builds run as a per-package parallel matrix (wasm compiles are | |
| # the slow part), then a single test job runs the whole vitest workspace | |
| # against the built dists. BOTH CodSpeed instruments now live in bench.yml, | |
| # which waits for THIS workflow's dist artifacts and benches the packages | |
| # the PR touched: the simulation gate first, then the advisory walltime job | |
| # after it. | |
| # | |
| # Toolchain bumps (emsdk image tag below, root package.json/pnpm-lock.yaml, | |
| # this workflow itself) force the FULL pipeline including a full bench sweep. | |
| # Expect such a PR to also need: | |
| # 1. tools/dist-size/baseline.json regenerated from that PR's own CI | |
| # artifacts: gh run download <run-id> --pattern 'dist-*' -d tmp/ then | |
| # node tools/dist-size/check.js --update --artifacts tmp/ (commit diff) | |
| # 2. possibly regenerated lossy decode goldens (openjpeg .91, charls .81, | |
| # openjphjs corpus SHAs) IF the lossless tests still pass — see | |
| # tools/fixture-verification/README.md before touching any golden. | |
| # | |
| # CodSpeed's first-class GHA integration replaces the manual codspeed-bench | |
| # job from CircleCI: `CodSpeedHQ/action` installs valgrind, sets up | |
| # instrumentation, and uploads results in one step. | |
| on: | |
| pull_request: | |
| push: | |
| # Run pushes on main only: each merge seeds a fresh CodSpeed baseline | |
| # (without a main run, PR comments stay stuck on "Congrats! CodSpeed | |
| # is installed" with no before/after deltas). PR branches are already | |
| # covered by the pull_request event — running push on them too meant | |
| # every commit was built/tested/benched TWICE and uploaded two | |
| # CodSpeed measurements per commit, each on a randomly allocated | |
| # runner CPU (GitHub mixes Intel 8370C and AMD EPYC 7763 hardware), | |
| # which is a prime source of "Different runtime environments detected" | |
| # warnings on comparisons. | |
| branches: | |
| - main | |
| # 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. | |
| # | |
| # Keyed per-commit off a PR, the same way bench.yml is, and because of the same | |
| # incident. On a push `head_ref` is empty, so `github.head_ref || github.ref` | |
| # put every main push into the single group | |
| # `pr-checks-PR checks-refs/heads/main` with cancel-in-progress: true. The | |
| # release workflow's version commit -- pushed about five minutes after the | |
| # merge that triggered it -- entered that group and CANCELLED the merge | |
| # commit's run, then skipped its own jobs through the detect-changes guard | |
| # below. GitHub applies concurrency when a run is QUEUED, before it evaluates | |
| # any `if:`, so a run that goes on to do nothing still cancels its | |
| # predecessor: | |
| # | |
| # 18:33 c9ffa62 fix(release): preflight the registry... cancelled | |
| # 18:39 c44693e chore(release): publish skipped | |
| # | |
| # On c9ffa62 that killed `codspeed-walltime` at 18:39:11 with every other job | |
| # already green. The cost is not one lost job: the CodSpeed check is computed | |
| # from the FIRST upload a commit produces and is never re-evaluated, so | |
| # cancelling walltime hands the check to the simulation bench instead. The two | |
| # instruments differ by 5-15x on wasm decode (see BENCHMARKING.md), so | |
| # c9ffa62 stored a simulation-sourced number for a benchmark whose predecessor | |
| # had stored a walltime-sourced one, and the check reported `JPEG XL Lossless | |
| # (.110)` as 158.5 ms -> 991.8 ms on a diff that touches only tools/release/ | |
| # and workflows. | |
| # | |
| # c9ffa62 fixed this in bench.yml but not here, and the bench.yml fix is not | |
| # sufficient on its own: bench.yml's gate waits on THIS workflow's build | |
| # artifacts, so a run cancelled here starves the bench there. | |
| # | |
| # Keying non-PR runs by github.sha gives every main commit its own group, so no | |
| # main push can cancel another. cancel-in-progress stays true for | |
| # pull_request, where superseding an in-flight run with a newer push is | |
| # exactly what is wanted. See bench.yml's concurrency comment for why | |
| # per-commit keying is needed rather than cancel-in-progress: false alone -- a | |
| # group holds one running run and at most one PENDING run, and queueing a | |
| # third evicts the pending one whatever cancel-in-progress says. | |
| concurrency: | |
| group: pr-checks-${{ github.workflow }}-${{ github.event_name == 'pull_request' && github.head_ref || github.sha }} | |
| cancel-in-progress: ${{ github.event_name == 'pull_request' }} | |
| # Job-level permissions where a job needs more (detect-changes reads the PR's | |
| # changed files). | |
| permissions: | |
| contents: read | |
| jobs: | |
| detect-changes: | |
| # Skip the release workflow's own version commit -- it changes only | |
| # package.json versions, CHANGELOGs and the lockfile, and was built and | |
| # tested as its parent. Every job below needs this one, so skipping it | |
| # skips the run. | |
| # | |
| # Subject-anchored rather than the `[skip ci]` this replaces: GitHub's | |
| # keyword scan reads the whole commit message, so a squash merge whose body | |
| # merely QUOTED `[skip ci]` disabled every workflow on main (PR #89, which | |
| # is how a release fix shipped no release). The author clause keeps a human | |
| # commit that happens to open with the same subject from skipping CI. See | |
| # release.yml's build job for the full reasoning. | |
| if: >- | |
| github.event_name != 'push' | |
| || !(startsWith(github.event.head_commit.message, 'chore(release): publish') | |
| && github.event.head_commit.author.email == '41898282+github-actions[bot]@users.noreply.github.com') | |
| # Decide what this run needs to do. Two outputs: | |
| # packages — what to build (and therefore what the test job can rely | |
| # on). dicom-codec's integration tests decode through EVERY sibling | |
| # codec's dist, and the in-test CI guards fail loudly when a dist is | |
| # missing (no more silently-skipped suites), so any package change | |
| # builds the full set. Docs-only changes still skip everything. | |
| # bench — only the packages that actually changed. CodSpeed benches | |
| # run under valgrind (the slowest thing in CI), and a PR only needs | |
| # deltas for what it touched; main re-benches everything to keep | |
| # full baselines. No job in THIS workflow consumes it any more — | |
| # both bench jobs live in bench.yml, whose gate job computes the | |
| # same scope from the PR's changed-file list. It is kept because | |
| # the two lists must agree: keep TOOLCHAIN_PATHS below in sync with | |
| # the path lists in bench.yml's gate job, and this output is what | |
| # makes a divergence visible in this run's own log. | |
| # | |
| # Bounded like every other job here: without an explicit timeout a job that | |
| # wedges runs to GitHub's 6-hour default. 13s typical, so 10 is ~45x | |
| # headroom — this job's only slow part is the fetch-depth: 0 checkout. | |
| timeout-minutes: 10 | |
| runs-on: ubuntu-latest | |
| outputs: | |
| packages: ${{ steps.list.outputs.packages }} | |
| bench: ${{ steps.list.outputs.bench }} | |
| 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 libjxl openjpeg openjphjs little-endian big-endian dicom-codec) | |
| ALL_JSON=$(printf '%s\n' "${ALL[@]}" | jq -R . | jq -s -c .) | |
| # 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 | |
| echo "Baseline run ($EVENT_NAME on $REF): forcing all packages" | |
| echo "packages=$ALL_JSON" >> "$GITHUB_OUTPUT" | |
| echo "bench=$ALL_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") | |
| # Toolchain files affect how EVERY package is built, tested or | |
| # measured. A change here (e.g. an emsdk bump in this workflow, or | |
| # a vitest upgrade in the root lockfile) must run the full | |
| # pipeline with a full bench sweep — previously such PRs matched | |
| # no package path and skipped CI entirely. tools/ entries count | |
| # too: browser-smoke drives the browser-smoke job, the test suites | |
| # import reference derivations from tools/fixture-verification/gen/, | |
| # and tools/ci/ holds the flock wrapper the bench command actually | |
| # execs — a change to any of them must not land with CI skipped. | |
| # Note this forces a FULL bench sweep, which on the shared nashua box | |
| # holds the mutex for the duration; that is the same trade already | |
| # made for .github/workflows/ changes, and both are rare. | |
| TOOLCHAIN_PATHS=( | |
| ".github/workflows/" | |
| "package.json" | |
| "pnpm-lock.yaml" | |
| "pnpm-workspace.yaml" | |
| "vitest.workspace.mjs" | |
| "babel.config.json" | |
| "tools/ci/" | |
| "tools/csp/" | |
| "tools/dist-size/" | |
| "tools/browser-smoke/" | |
| "tools/fixture-verification/" | |
| # tools/release/ decides what gets versioned and published. Without | |
| # it here, a PR touching only the release scripts matched no path, | |
| # got any=false and skipped every job — so their first execution | |
| # would be a live release, partway through mutating manifests. | |
| "tools/release/" | |
| ) | |
| for p in "${TOOLCHAIN_PATHS[@]}"; do | |
| if ! git diff --quiet "$BASE"..HEAD -- "$p"; then | |
| echo "Toolchain change detected in $p: forcing all packages (build/test/bench)" | |
| echo "packages=$ALL_JSON" >> "$GITHUB_OUTPUT" | |
| echo "bench=$ALL_JSON" >> "$GITHUB_OUTPUT" | |
| echo "any=true" >> "$GITHUB_OUTPUT" | |
| exit 0 | |
| fi | |
| done | |
| 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 'bench=[]' >> "$GITHUB_OUTPUT" | |
| echo "any=false" >> "$GITHUB_OUTPUT" | |
| else | |
| bench_json=$(printf '%s\n' "${changed[@]}" | jq -R . | jq -s -c .) | |
| echo "Changed: $bench_json — building all packages, benching changed only" | |
| echo "packages=$ALL_JSON" >> "$GITHUB_OUTPUT" | |
| echo "bench=$bench_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) }} | |
| # The matrix leg that motivated this: `build (big-endian)` wedged on PR #70 | |
| # and sat in_progress for 80+ minutes while its nine siblings finished in | |
| # 58-239s, because nothing bounded it. fail-fast is off (deliberately — one | |
| # package's failure should not hide another's), so a wedged leg keeps the | |
| # whole run, and every job downstream of it, pending until GitHub's 6-hour | |
| # default fires. | |
| # | |
| # 20 is ~5x the slowest observed leg (libjxl, 239s) and leaves room for a | |
| # cold emsdk image pull. | |
| timeout-minutes: 20 | |
| runs-on: ubuntu-latest | |
| container: | |
| image: emscripten/emsdk:3.1.74 | |
| steps: | |
| - name: Install cmake + C++ build deps | |
| # Digest-checked rather than piped straight into tar; same pin as | |
| # release.yml's build job. From | |
| # https://cmake.org/files/v3.17/cmake-3.17.4-SHA-256.txt. | |
| env: | |
| CMAKE_TARBALL: cmake-3.17.4-Linux-x86_64.tar.gz | |
| CMAKE_SHA256: 126cc8356907913787d4ff35237ae1854c09b927a35dbe5270dd571ae224bdd3 | |
| # NO `set -euo pipefail` here. The emsdk image has no bash, so GitHub | |
| # runs every step in this container job as `sh -e {0}` and dash rejects | |
| # `-o pipefail` outright ("Illegal option -o pipefail", exit 2). It is | |
| # not needed either: `-e` is already on, and the digest check below is | |
| # the LAST command in its pipeline, so its failure is what the shell | |
| # sees. Same applies to release.yml's build job. | |
| run: | | |
| apt-get update | |
| apt-get -y install build-essential git | |
| # /tmp, not the workspace: this step runs before actions/checkout. | |
| wget -q -O "/tmp/${CMAKE_TARBALL}" "https://cmake.org/files/v3.17/${CMAKE_TARBALL}" | |
| echo "${CMAKE_SHA256} /tmp/${CMAKE_TARBALL}" | sha256sum -c - | |
| tar --strip-components=1 -xzf "/tmp/${CMAKE_TARBALL}" -C /usr/local | |
| rm -f "/tmp/${CMAKE_TARBALL}" | |
| apt-get autoremove -y | |
| apt-get clean -y | |
| rm -rf /var/lib/apt/lists/* | |
| - uses: actions/checkout@v4 | |
| # Shallow checkout: builds only need the working tree (full history | |
| # is only required by detect-changes for the merge-base diff). | |
| - uses: actions/setup-node@v4 | |
| # The emsdk image bundles node 20.18.0 — end of life since 2026-04-30, | |
| # and it fails this repo's engines.node check (needs >=24) anyway. Put node | |
| # 24 on PATH for pnpm/webpack; emscripten is unaffected — emcc invokes | |
| # the node binary pinned in its own .emscripten config, not the one on | |
| # PATH. | |
| with: | |
| node-version: '24' | |
| - name: Provide pnpm via Corepack | |
| # `corepack prepare --activate` with no argument installs exactly the | |
| # version in the root package.json "packageManager" field, so CI and | |
| # local dev never drift. | |
| run: | | |
| corepack enable pnpm | |
| corepack prepare --activate | |
| pnpm --version | |
| - 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 node_modules cache | |
| id: modules-cache | |
| uses: actions/cache@v4 | |
| with: | |
| path: | | |
| node_modules | |
| packages/*/node_modules | |
| # The key covers EVERY input to `pnpm install`, not just the lockfile, | |
| # because a hit skips the install step below — and with it the | |
| # --frozen-lockfile check. Specifically: | |
| # - pnpm-workspace.yaml: the lockfile's settings block records only | |
| # autoInstallPeers and excludeLinksFromLockfile, so changing | |
| # nodeLinker, allowBuilds, frozenLockfile or linkWorkspacePackages | |
| # leaves the lockfile byte-identical while changing the layout | |
| # installed. Keying on the lockfile alone, the cache would hit and | |
| # CI would keep testing the previous node_modules tree. | |
| # - package.json + packages/*/package.json: a manifest edit that has | |
| # not been reflected in the lockfile must reach the install step so | |
| # --frozen-lockfile can reject it, rather than being masked by a | |
| # stale cache entry. The root manifest also carries the | |
| # packageManager pin, so a pnpm bump invalidates too. | |
| # Keep the same hashFiles(...) inputs in all four pnpm-modules keys. | |
| # | |
| # This job's prefix is `build` rather than `node<major>` because it | |
| # installs inside the emsdk container; the other three install on | |
| # ubuntu-latest under setup-node and carry the node major in the key | |
| # so a node bump forces a fresh install instead of restoring a tree | |
| # built against the previous V8/ABI. BUMP THAT DISCRIMINATOR WITH THE | |
| # node-version PINS — bench.yml's key hashes only the lockfile and | |
| # workspace config, so nothing else in a node-only bump invalidates it. | |
| key: pnpm-modules-build-${{ runner.os }}-${{ runner.arch }}-${{ hashFiles('package.json', 'packages/*/package.json', 'pnpm-lock.yaml', 'pnpm-workspace.yaml') }} | |
| - name: Install dependencies | |
| if: steps.modules-cache.outputs.cache-hit != 'true' | |
| run: pnpm install --frozen-lockfile | |
| - name: Build | |
| run: cd "packages/${{ matrix.package }}" && pnpm 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: | |
| # One job for the whole vitest workspace: per-package test jobs spent far | |
| # more on runner setup (checkout, node, artifact download, install) than on | |
| # the few seconds of vitest itself, and dicom-codec's suite needs every | |
| # sibling dist anyway. CI=true (set by GitHub) arms the in-test guards: a | |
| # missing dist FAILS its suite instead of silently skipping. | |
| needs: [detect-changes, build] | |
| if: needs.detect-changes.outputs.any == 'true' | |
| # 53s typical. Generous enough for the openjpeg corpus suite on a slow | |
| # runner without letting a hung vitest worker burn six hours. | |
| timeout-minutes: 15 | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| with: | |
| # Full history + tags so the release dry-run at the end of this job | |
| # can walk back to each package's last `<name>@<version>` tag. | |
| fetch-depth: 0 | |
| fetch-tags: true | |
| # Do not leave GITHUB_TOKEN in .git/config. This job installs | |
| # dependencies and runs the release scripts against PR code; none of | |
| # that needs an authenticated remote, only local history and tags. | |
| persist-credentials: false | |
| - uses: actions/setup-node@v4 | |
| with: | |
| node-version: '24' | |
| - name: Provide pnpm via Corepack | |
| run: | | |
| corepack enable pnpm | |
| corepack prepare --activate | |
| pnpm --version | |
| - 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 node_modules cache | |
| id: modules-cache | |
| uses: actions/cache@v4 | |
| with: | |
| path: | | |
| node_modules | |
| packages/*/node_modules | |
| # Manifests + workspace config in the key — see the build job's cache | |
| # step for why the lockfile alone is not enough. | |
| key: pnpm-modules-node24-${{ runner.os }}-${{ runner.arch }}-${{ hashFiles('package.json', 'packages/*/package.json', 'pnpm-lock.yaml', 'pnpm-workspace.yaml') }} | |
| - name: Install dependencies | |
| if: steps.modules-cache.outputs.cache-hit != 'true' | |
| run: pnpm install --frozen-lockfile | |
| - name: CSP-safe source | |
| # The companion to the check each wasm build.sh runs on its own dist/: | |
| # that one covers emscripten's output, this one covers the source we | |
| # write. dicom-codec's `main` is src/index.js, so consumers bundle it | |
| # directly and a strict CSP judges it the same way. | |
| # | |
| # Needs nothing from the build matrix — it is plain node over the | |
| # working tree — but lives here rather than in its own job because it | |
| # takes milliseconds and a job's worth of runner setup would dwarf it. | |
| run: pnpm run csp:source | |
| - name: Test | |
| run: pnpm exec vitest run | |
| - name: Release dry-run | |
| # Exercises the release scripts on every PR. They are otherwise only | |
| # ever executed by a live release — after the 8-job build matrix, and | |
| # partway through mutating manifests, which is a poor place to discover | |
| # a syntax error or a bad tag walk. Mutates nothing and publishes | |
| # nothing. | |
| # | |
| # release:preflight re-checks the topological order and that every | |
| # package shipping dist/ actually has one, then asks the registry | |
| # whether each package can actually be published. A package that is not | |
| # on npm at all is only a WARNING here — the PR adding a codec is | |
| # exactly when it legitimately does not exist yet — but it is the | |
| # warning that was missing when libjxl was merged in #88 and broke the | |
| # next four releases. In the release workflow the same finding is fatal. | |
| run: | | |
| set -euo pipefail | |
| pnpm run release:plan | |
| pnpm run release:preflight | |
| dist-size: | |
| # Binary-size regression gate: compares every shipped dist artifact | |
| # (js/wasm/mem, raw and gzip) against the ground truth committed in | |
| # tools/dist-size/baseline.json and fails if anything grows beyond | |
| # max(1%, 1 KiB). Intentional size changes update the baseline in the | |
| # same PR (node tools/dist-size/check.js --update) so growth is always | |
| # a visible, reviewed diff. | |
| needs: [detect-changes, build] | |
| if: needs.detect-changes.outputs.any == 'true' | |
| # 47s typical: download the dist artifacts, measure, compare. | |
| timeout-minutes: 10 | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: actions/setup-node@v4 | |
| # check.js needs no dependencies (fs/path/zlib only), so this is purely | |
| # to stop the gate running on whatever node the runner image happens to | |
| # ship — which drifts, and has been below this repo's engines.node floor. | |
| with: | |
| node-version: '24' | |
| - name: Download all built dists | |
| uses: actions/download-artifact@v4 | |
| with: | |
| pattern: dist-* | |
| path: tmp/ | |
| - name: Check dist sizes against baseline | |
| run: node tools/dist-size/check.js --artifacts tmp | |
| browser-smoke: | |
| # Decodes every build variant in headless Chromium and hash-compares | |
| # against the RAW references — catches emscripten glue regressions that | |
| # only manifest in browsers (wasm URL resolution, MIME/streaming | |
| # compile, fetch loading), which is where emsdk bumps break first. | |
| # Advisory while it beds in; promote to blocking once proven stable. | |
| needs: [detect-changes, build] | |
| if: needs.detect-changes.outputs.any == 'true' | |
| continue-on-error: true | |
| timeout-minutes: 15 | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: actions/setup-node@v4 | |
| with: | |
| node-version: '24' | |
| - name: Provide pnpm via Corepack | |
| run: | | |
| corepack enable pnpm | |
| corepack prepare --activate | |
| pnpm --version | |
| - 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 node_modules cache | |
| id: modules-cache | |
| uses: actions/cache@v4 | |
| with: | |
| path: | | |
| node_modules | |
| packages/*/node_modules | |
| # Manifests + workspace config in the key — see the build job's cache | |
| # step for why the lockfile alone is not enough. | |
| key: pnpm-modules-node24-${{ runner.os }}-${{ runner.arch }}-${{ hashFiles('package.json', 'packages/*/package.json', 'pnpm-lock.yaml', 'pnpm-workspace.yaml') }} | |
| - name: Install dependencies | |
| if: steps.modules-cache.outputs.cache-hit != 'true' | |
| run: pnpm install --frozen-lockfile | |
| - name: Cache Playwright chromium | |
| id: pw-cache | |
| uses: actions/cache@v4 | |
| with: | |
| path: ~/.cache/ms-playwright | |
| key: playwright-chromium-${{ runner.os }}-${{ hashFiles('pnpm-lock.yaml', 'pnpm-workspace.yaml') }} | |
| - name: Install chromium | |
| if: steps.pw-cache.outputs.cache-hit != 'true' | |
| run: pnpm exec playwright-core install chromium | |
| - name: Browser smoke decode | |
| run: node tools/browser-smoke/run.js | |
| # codspeed-walltime lived here until it was moved to bench.yml, so that it | |
| # runs AFTER the simulation bench rather than beside it. See that job's | |
| # comment for why the ordering decides which instrument GitHub reports. |