chore(deps-dev): bump eslint from 9.39.5 to 10.7.0 in /ui #219
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: ci | |
| on: | |
| push: | |
| branches: [main] | |
| pull_request: | |
| permissions: | |
| contents: read | |
| jobs: | |
| server: | |
| # Self-hosted watcher-runners (meshed) so the cargo build uses the shared | |
| # in-cluster sccache redis. The runners now carry a postgres sidecar (cluster | |
| # repo: charts/actions/runners/values-watcher.yaml) reachable at localhost:5432, | |
| # so the ARC-can't-run-a-service-container reason for staying hosted is gone. | |
| runs-on: watcher-runners | |
| env: | |
| DATABASE_URL: postgres://watcher:watcher@localhost:5432/watcher | |
| # sccache → shared in-cluster redis (cluster repo: charts/sccache). Reachable | |
| # only through Linkerd mTLS (the watcher runner identity is admitted); it | |
| # carries no credentials, so it lives here rather than a secret. | |
| # CARGO_INCREMENTAL=0 — sccache can't cache incremental artefacts. | |
| RUSTC_WRAPPER: sccache | |
| SCCACHE_REDIS: redis://sccache-redis.dev.svc.cluster.local:6379 | |
| CARGO_INCREMENTAL: "0" | |
| defaults: | |
| run: | |
| working-directory: server | |
| steps: | |
| - uses: actions/checkout@v7 | |
| - uses: dtolnay/rust-toolchain@stable | |
| with: | |
| components: rustfmt, clippy | |
| - uses: Swatinem/rust-cache@v2 | |
| with: | |
| cache-targets: false | |
| workspaces: server | |
| # Stable key shared across branches/PRs (not the per-branch default), so a | |
| # PR's first run restores main's warm target/ instead of compiling cold. | |
| shared-key: watcher-server | |
| - name: Install sccache | |
| # --force: rust-cache restores cargo's "already installed" metadata on a warm | |
| # cache, but not the binary, so a plain binstall skips and sccache is absent | |
| # from PATH (RUSTC_WRAPPER then fails). Force a real install every run. | |
| run: cargo binstall --no-confirm --force sccache | |
| # The postgres sidecar boots in parallel with the runner container; block until | |
| # it accepts TCP before building/testing. bash /dev/tcp avoids needing a client. | |
| - name: Wait for postgres sidecar | |
| run: | | |
| for i in $(seq 1 60); do | |
| (echo > /dev/tcp/127.0.0.1/5432) >/dev/null 2>&1 && { echo "postgres up after ${i}s"; exit 0; } | |
| sleep 1 | |
| done | |
| echo "postgres sidecar never came up" >&2; exit 1 | |
| - run: cargo fmt --check | |
| # clippy replaces a standalone `cargo build`: it's check-speed (no codegen) and | |
| # gates the compile too, while `cargo test` below does the actual codegen. Only | |
| # the workspace crate runs through clippy-driver; deps still compile via sccache. | |
| # -D warnings matches the repo's warnings-as-errors policy. | |
| - run: cargo clippy --locked --all-targets -- -D warnings | |
| - run: cargo test --locked # ingest->query integration test against the sidecar DB | |
| - name: sccache stats | |
| if: always() | |
| run: sccache --show-stats | |
| ui: | |
| runs-on: watcher-runners | |
| defaults: | |
| run: | |
| working-directory: ui | |
| steps: | |
| - uses: actions/checkout@v7 | |
| - uses: actions/setup-node@v6 | |
| with: | |
| node-version: 22 | |
| cache: npm | |
| cache-dependency-path: ui/package-lock.json | |
| - run: npm ci | |
| # Accessibility floor (JEF-431): eslint-plugin-jsx-a11y gates keyboard- | |
| # operable rows, labeled charts, and no silent-live tables from regressing. | |
| - run: npm run lint | |
| # Runtime a11y route-smoke (JEF-442) runs inside `npm test`: each top-level | |
| # route is mounted (jsdom, API mocked) and scanned by axe-core, failing on | |
| # serious/critical structural violations. Complements the static lint above — | |
| # it catches ARIA that only resolves against the rendered tree. | |
| - run: npm test | |
| - run: npm run build | |
| # One image now: the server builds the UI and embeds it (rust-embed), so there | |
| # is no separate watcher-ui image. Build context is the repo root. | |
| # | |
| # Native per-arch on the self-hosted runner (watcher-runners), offloading to the | |
| # two in-cluster BuildKit builders — amd64 on `buildkit` (node-3), arm64 on | |
| # `buildkit-arm64` (an arm64 Pi) — each building NATIVELY, no QEMU. BuildKit | |
| # enforces mTLS, so we point the remote driver at the client cert the runner | |
| # already mounts (BUILDKIT_TLS_DIR) and verify each endpoint against its | |
| # servername; without the cert the gRPC handshake is rejected. The build also pushes a layer cache to GHA | |
| # (cache-from/to type=gha): paired with cargo-chef in the Dockerfile, the dep | |
| # compile becomes a portable layer any node can pull — unlike the per-node | |
| # BuildKit daemon cache, which a cold node can't reach. | |
| image: | |
| needs: [server, ui] | |
| if: github.ref == 'refs/heads/main' | |
| runs-on: watcher-runners | |
| permissions: | |
| contents: read | |
| packages: write | |
| id-token: write # keyless cosign signing (OIDC token -> Sigstore Fulcio) | |
| steps: | |
| - uses: actions/checkout@v7 | |
| - name: Connect to BuildKit (mTLS, native per-arch) | |
| # Two native builders share one CA (cluster: charts/actions/buildkit + | |
| # values-arm64.yaml): amd64 on `buildkit` (node-3), arm64 on `buildkit-arm64` | |
| # (an arm64 Pi). buildx --append joins them into one builder so each platform | |
| # builds NATIVELY and buildx merges the manifest — no QEMU (arm64 Rust under | |
| # QEMU ran for hours). The runner's existing client cert (BUILDKIT_TLS_DIR) | |
| # authenticates to both; each endpoint verifies its own server SAN via servername. | |
| env: | |
| BUILDKIT_ARM64_HOST: tcp://buildkit-arm64.dev.svc.cluster.local:1234 | |
| BUILDKIT_ARM64_TLS_SERVER_NAME: buildkit-arm64.dev.svc.cluster.local | |
| run: | | |
| for i in 1 2 3 4 5; do | |
| docker buildx rm watcher-remote >/dev/null 2>&1 || true | |
| if docker buildx create --name watcher-remote --use \ | |
| --driver remote --platform linux/amd64 \ | |
| --driver-opt cacert="$BUILDKIT_TLS_DIR/ca.crt",cert="$BUILDKIT_TLS_DIR/tls.crt",key="$BUILDKIT_TLS_DIR/tls.key",servername="$BUILDKIT_TLS_SERVER_NAME" \ | |
| "$BUILDKIT_HOST" \ | |
| && docker buildx create --name watcher-remote --append \ | |
| --driver remote --platform linux/arm64 \ | |
| --driver-opt cacert="$BUILDKIT_TLS_DIR/ca.crt",cert="$BUILDKIT_TLS_DIR/tls.crt",key="$BUILDKIT_TLS_DIR/tls.key",servername="$BUILDKIT_ARM64_TLS_SERVER_NAME" \ | |
| "$BUILDKIT_ARM64_HOST" \ | |
| && timeout 90 docker buildx inspect --bootstrap; then | |
| echo "connected to buildkit (amd64 + arm64, native)"; exit 0 | |
| fi | |
| echo "buildkit connect failed (attempt $i/5), retrying…"; sleep 10 | |
| done | |
| echo "could not reach buildkit"; exit 1 | |
| - uses: docker/login-action@v4 | |
| with: | |
| registry: ghcr.io | |
| username: ${{ github.actor }} | |
| password: ${{ secrets.GITHUB_TOKEN }} | |
| - uses: docker/metadata-action@v6 | |
| id: meta | |
| with: | |
| images: ghcr.io/${{ github.repository_owner }}/watcher-server | |
| tags: | | |
| type=raw,value=latest | |
| type=sha | |
| - uses: docker/build-push-action@v7 | |
| id: build | |
| with: | |
| context: . | |
| file: server/Dockerfile | |
| platforms: linux/amd64,linux/arm64 | |
| push: true | |
| tags: ${{ steps.meta.outputs.tags }} | |
| labels: ${{ steps.meta.outputs.labels }} | |
| # Portable layer cache on GitHub's Actions Cache (~10GB/repo, free). With | |
| # cargo-chef the dep-compile layer cache-hits here until Cargo.lock moves, | |
| # so a cold node skips it. mode=max also caches intermediate (build-stage) | |
| # layers, which is what carries the cook layer — at the cost of a larger | |
| # WAN transfer (see JEF-87 / measure in JEF-82). | |
| cache-from: type=gha | |
| cache-to: type=gha,mode=max | |
| provenance: true | |
| sbom: true | |
| - uses: sigstore/cosign-installer@v3 | |
| - name: Sign the image (keyless) | |
| # Sign by immutable digest, not tag. Keyless: GitHub's OIDC token is | |
| # exchanged for a short-lived Fulcio cert and the signature is recorded in | |
| # the Rekor transparency log — no private key to store. cosign reuses the | |
| # docker login above to push the signature to GHCR. | |
| env: | |
| DIGEST: ${{ steps.build.outputs.digest }} | |
| run: cosign sign --yes "ghcr.io/${{ github.repository_owner }}/watcher-server@${DIGEST}" |