diff --git a/.github/workflows/actions.lock b/.github/workflows/actions.lock index a9ba626..506d0dc 100644 --- a/.github/workflows/actions.lock +++ b/.github/workflows/actions.lock @@ -45,7 +45,6 @@ workflows: - 'anchore/sbom-action@v0.24.2' '.github/workflows/release-tag.yml': - 'actions/checkout@v7.0.1' - - 'actions/setup-go@v7.0.0' '.github/workflows/release.yml': - 'actions/checkout@v7.0.1' '.github/workflows/self-audit.yml': @@ -53,6 +52,9 @@ workflows: - 'actions/checkout@v7.0.1' - 'actions/setup-dotnet@v6.0.0' - 'actions/setup-go@v7.0.0' + '.github/workflows/test-go.yml': + - 'actions/checkout@v7.0.1' + - 'actions/setup-go@v7.0.0' '.github/workflows/update-codeql.yml': - 'actions/cache@v6.1.0' - 'actions/checkout@v7.0.1' diff --git a/.github/workflows/build-and-test-go.yml b/.github/workflows/build-and-test-go.yml index cc082df..5d31027 100644 --- a/.github/workflows/build-and-test-go.yml +++ b/.github/workflows/build-and-test-go.yml @@ -16,6 +16,7 @@ on: - '**/testdata/**' - 'scripts/**' - '.github/workflows/build-and-test-go.yml' + - '.github/workflows/test-go.yml' - 'go.mod' - 'go.sum' - 'Makefile' @@ -26,6 +27,7 @@ on: - '**/testdata/**' - 'scripts/**' - '.github/workflows/build-and-test-go.yml' + - '.github/workflows/test-go.yml' - 'go.mod' - 'go.sum' - 'Makefile' @@ -34,82 +36,43 @@ permissions: contents: read jobs: + # Each of these is test-go.yml, the job a release tests its tree with, so a release runs nothing + # that a pull request has not already run. checks: name: Build and Test - Checks - runs-on: ubuntu-latest - - steps: - - name: Build and Test - Checkout repository - uses: actions/checkout@v7.0.1 - - - name: Build and Test - Setup Go - uses: actions/setup-go@v7.0.0 - with: - go-version-file: go.mod - cache: true - - # First, because a duplicated package clause reads as a syntax error everywhere else and - # sends the reader looking in the wrong place. - - name: Build and Test - Check for corrupted writes - run: make check-corrupt - - - name: Build and Test - Check formatting - run: make fmt - - - name: Build and Test - Vet - run: make vet - - - name: Build and Test - Test the scripts - run: make script-test - - - name: Build and Test - Build the binary - run: make build + permissions: + contents: read + uses: ./.github/workflows/test-go.yml + with: + # check-corrupt first, because a duplicated package clause reads as a syntax error + # everywhere else and sends the reader looking in the wrong place. + targets: check-corrupt fmt vet script-test build + cache: true sqlite: name: Build and Test - Go (SQLite) - runs-on: ubuntu-latest - - steps: - - name: Build and Test - Checkout repository - uses: actions/checkout@v7.0.1 - - - name: Build and Test - Setup Go - uses: actions/setup-go@v7.0.0 - with: - go-version-file: go.mod - cache: true - - # Graphviz is a requirement: serve refuses to start without it, and the layout and figure - # tests fail rather than skip. - - name: Build and Test - Install Graphviz - run: sudo apt-get update && sudo apt-get install --yes --no-install-recommends graphviz - - - name: Build and Test - Run tests - run: make test-sqlite + permissions: + contents: read + uses: ./.github/workflows/test-go.yml + with: + targets: test-sqlite + cache: true postgres: name: Build and Test - Go (PostgreSQL) - runs-on: ubuntu-latest - - steps: - - name: Build and Test - Checkout repository - uses: actions/checkout@v7.0.1 - - - name: Build and Test - Setup Go - uses: actions/setup-go@v7.0.0 - with: - go-version-file: go.mod - cache: true - - # Docker is a requirement: the store suite runs on a PostgreSQL primary and physical standby in - # containers, and fails rather than skips without a daemon. Ubuntu runners have one. - - name: Build and Test - Run tests - run: make test-postgres + permissions: + contents: read + uses: ./.github/workflows/test-go.yml + with: + # Docker is a requirement: the store suite runs on a PostgreSQL primary and physical standby + # in containers, and fails rather than skips without a daemon. Ubuntu runners have one. + targets: test-postgres + cache: true # One name to require in branch protection, whichever jobs the run is split into. build-and-test-go: name: Build and Test - Go - runs-on: ubuntu-latest + runs-on: ubuntu-26.04 needs: [checks, sqlite, postgres] if: always() diff --git a/.github/workflows/build-and-test-ui.yml b/.github/workflows/build-and-test-ui.yml index e514e84..9b5643d 100644 --- a/.github/workflows/build-and-test-ui.yml +++ b/.github/workflows/build-and-test-ui.yml @@ -6,6 +6,7 @@ on: pull_request: paths: - '.github/workflows/build-and-test-ui.yml' + - 'scripts/setup-graphviz.sh' - '.node-version' - 'Makefile' # The populated run is only as good as what it runs against, and both of these decide that: @@ -28,6 +29,7 @@ on: branches: ['main'] paths: - '.github/workflows/build-and-test-ui.yml' + - 'scripts/setup-graphviz.sh' - '.node-version' - 'Makefile' - 'cmd/abom-corpus/**' @@ -55,7 +57,7 @@ jobs: # seconds rather than behind a toolchain neither of them uses. browser: name: Interface - Browser code - runs-on: ubuntu-latest + runs-on: ubuntu-26.04 steps: - name: Browser code - Checkout repository @@ -78,7 +80,7 @@ jobs: components: name: Interface - Components - runs-on: ubuntu-latest + runs-on: ubuntu-26.04 steps: - name: Components - Checkout repository @@ -110,7 +112,7 @@ jobs: # `dotnet publish` and a `go build` that together cost more than the tests it then runs. build: name: Interface - Build what the suite drives - runs-on: ubuntu-latest + runs-on: ubuntu-26.04 outputs: specs: ${{ steps.specs.outputs.specs }} @@ -189,7 +191,7 @@ jobs: suite: name: Interface - Browser suite (${{ matrix.spec }}) needs: build - runs-on: ubuntu-latest + runs-on: ubuntu-26.04 strategy: # Every shard reports. "Which spec files are broken" is the question a split suite exists to @@ -240,8 +242,8 @@ jobs: # Graphviz is a requirement: serve refuses to start without it, and the layout and figure # tests fail rather than skip. - - name: Browser suite - Install Graphviz - run: sudo apt-get update && sudo apt-get install --yes --no-install-recommends graphviz + - name: Browser suite - Setup Graphviz + run: scripts/setup-graphviz.sh # `-run` rather than `make e2e`: the binary, the interface and the data set were built once # and unpacked above, and rebuilding them here would be the whole saving spent again. @@ -261,7 +263,7 @@ jobs: name: Build and Test - Interface needs: [browser, build, components, suite] if: always() - runs-on: ubuntu-latest + runs-on: ubuntu-26.04 steps: - name: Interface - Summary diff --git a/.github/workflows/copilot-setup-steps.yml b/.github/workflows/copilot-setup-steps.yml index 72ae854..e23c494 100644 --- a/.github/workflows/copilot-setup-steps.yml +++ b/.github/workflows/copilot-setup-steps.yml @@ -23,6 +23,7 @@ on: - 'go.mod' - 'go.sum' - 'Makefile' + - 'scripts/setup-graphviz.sh' # Pins the PostgreSQL image the setup pulls. - 'scripts/with-postgres.py' - '**/codeql-pack.yml' @@ -42,6 +43,7 @@ on: - 'go.mod' - 'go.sum' - 'Makefile' + - 'scripts/setup-graphviz.sh' - 'scripts/with-postgres.py' - '**/codeql-pack.yml' - '**/codeql-pack.lock.yml' @@ -56,7 +58,7 @@ jobs: copilot-setup-steps: permissions: contents: read - runs-on: ubuntu-latest + runs-on: ubuntu-26.04 steps: - name: Copilot Setup - Checkout code @@ -139,8 +141,8 @@ jobs: # Graphviz is a requirement: serve refuses to start without it, and the layout and figure # tests fail rather than skip. - - name: Copilot Setup - Install Graphviz - run: sudo apt-get update && sudo apt-get install --yes --no-install-recommends graphviz + - name: Copilot Setup - Setup Graphviz + run: scripts/setup-graphviz.sh # `make test-postgres` runs the store suite in the PostgreSQL image the harness pins, and pulls it on # first use. The probe starts that image and removes its container; the image stays cached. diff --git a/.github/workflows/dependency-review.yml b/.github/workflows/dependency-review.yml index cfd4736..d39fb69 100644 --- a/.github/workflows/dependency-review.yml +++ b/.github/workflows/dependency-review.yml @@ -16,7 +16,7 @@ permissions: jobs: dependency-review: name: Dependency Review - runs-on: ubuntu-latest + runs-on: ubuntu-26.04 steps: - name: Dependency Review - Checkout repository diff --git a/.github/workflows/lint-go.yml b/.github/workflows/lint-go.yml index 65f79c6..dcb91f5 100644 --- a/.github/workflows/lint-go.yml +++ b/.github/workflows/lint-go.yml @@ -13,7 +13,7 @@ permissions: jobs: lint-go: name: Lint - Go - runs-on: ubuntu-latest + runs-on: ubuntu-26.04 steps: - name: Lint - Checkout repository diff --git a/.github/workflows/query-unit-tests.yml b/.github/workflows/query-unit-tests.yml index db92061..7ddb3f0 100644 --- a/.github/workflows/query-unit-tests.yml +++ b/.github/workflows/query-unit-tests.yml @@ -36,7 +36,7 @@ jobs: # here rather than at release time. versions: name: Query Unit Tests - Versions - runs-on: ubuntu-latest + runs-on: ubuntu-26.04 steps: - name: Versions - Checkout repository @@ -49,7 +49,7 @@ jobs: query-unit-tests: name: Query Unit Tests - runs-on: ubuntu-latest + runs-on: ubuntu-26.04 steps: - name: Query Unit Tests - Checkout repository diff --git a/.github/workflows/release-build.yml b/.github/workflows/release-build.yml index 1af5ceb..a199ef1 100644 --- a/.github/workflows/release-build.yml +++ b/.github/workflows/release-build.yml @@ -3,8 +3,9 @@ name: Release - Build # Called by release.yml only. Read-only: it tests the tagged commit, builds each platform's -# archive on that platform, and smoke-tests the uploaded bytes on that platform again. Nothing -# here signs or publishes, and nothing restores a cache another branch could have written. +# archive on that platform, and smoke-tests the uploaded bytes on that platform again, darwin/amd64 +# under Rosetta. Nothing here signs or publishes, and nothing restores a cache another branch could +# have written. on: workflow_call: @@ -57,8 +58,8 @@ jobs: # Graphviz is a requirement: serve refuses to start without it, and the layout and figure # tests fail rather than skip. - - name: Verify - Install Graphviz - run: sudo apt-get update && sudo apt-get install --yes --no-install-recommends graphviz + - name: Verify - Setup Graphviz + run: scripts/setup-graphviz.sh # `make verify` less lint, pins and the browser suite, which pull requests already run and # which need tools this job would otherwise install for nothing the archive contains. @@ -161,7 +162,10 @@ jobs: include: - { os: linux, arch: amd64, runner: ubuntu-22.04, codeql: linux64 } - { os: linux, arch: arm64, runner: ubuntu-22.04-arm, codeql: linux-arm64 } - - { os: darwin, arch: amd64, runner: macos-15-intel, codeql: osx64 } + # Under Rosetta on arm64: Homebrew has no Intel bottle for Graphviz or its dependencies, + # so an Intel runner would compile all of them before the smoke could start. The + # manifest check still requires the executable to report darwin/amd64. + - { os: darwin, arch: amd64, runner: macos-15, codeql: osx64 } - { os: darwin, arch: arm64, runner: macos-15, codeql: osx64 } steps: @@ -200,13 +204,17 @@ jobs: # Graphviz is a requirement the release notes name: serve refuses to start without `dot`, so # the archive is proven on a machine that has it, installed the way a user would. - - name: Smoke - Install Graphviz + - name: Smoke - Setup Graphviz + run: scripts/setup-graphviz.sh dot + + # An arm64 Mac runs the amd64 build only through Rosetta, which the image normally ships. + - name: Smoke - Install Rosetta + if: matrix.os == 'darwin' && matrix.arch == 'amd64' run: | - case "$RUNNER_OS" in - Linux) sudo apt-get update && sudo apt-get install --yes --no-install-recommends graphviz ;; - macOS) brew install graphviz ;; - *) echo "::error::no Graphviz install for $RUNNER_OS"; exit 1 ;; - esac + if ! arch -x86_64 /usr/bin/true 2>/dev/null; then + sudo softwareupdate --install-rosetta --agree-to-license + fi + arch -x86_64 /usr/bin/true - name: Smoke - Run run: | diff --git a/.github/workflows/release-tag.yml b/.github/workflows/release-tag.yml index 08619cd..bb23b0b 100644 --- a/.github/workflows/release-tag.yml +++ b/.github/workflows/release-tag.yml @@ -54,37 +54,19 @@ jobs: exit 1 fi + # The job pull requests run, on the tree with every pack set to the release version. Read-only + # whatever this workflow is granted, and uncached: a release restores nothing another branch + # could have written. test: name: Tag - Test the tree to be tagged needs: inspect if: needs.inspect.outputs.exists == 'false' - runs-on: ubuntu-26.04 - - steps: - - name: Test - Checkout repository - uses: actions/checkout@v7.0.1 - with: - persist-credentials: false - - - name: Test - Setup Go - uses: actions/setup-go@v7.0.0 - with: - go-version-file: go.mod - # A release restores nothing another branch could have written. - cache: false - - - name: Test - Set the release version - env: - VERSION: ${{ inputs.version }} - run: scripts/release-version.sh "$VERSION" - - # Graphviz is a requirement: serve refuses to start without it, and the layout and figure - # tests fail rather than skip. - - name: Test - Install Graphviz - run: sudo apt-get update && sudo apt-get install --yes --no-install-recommends graphviz - - - name: Test - Run the Go checks - run: make check-corrupt check-release-version fmt vet test + permissions: + contents: read + uses: ./.github/workflows/test-go.yml + with: + version: ${{ inputs.version }} + targets: check-corrupt check-release-version fmt vet test create: name: Tag - Create diff --git a/.github/workflows/self-audit.yml b/.github/workflows/self-audit.yml index db60dd3..a70330c 100644 --- a/.github/workflows/self-audit.yml +++ b/.github/workflows/self-audit.yml @@ -52,7 +52,7 @@ permissions: jobs: self-audit: name: Self Audit - ${{ matrix.name }} - runs-on: ubuntu-latest + runs-on: ubuntu-26.04 strategy: # Every language is reported, not just the first to fail. A cancelled sibling would hide @@ -169,7 +169,7 @@ jobs: # starts, under the repository's `require_lockfile` Actions policy. So this gates. action-pins: name: Self Audit - Action pins - runs-on: ubuntu-latest + runs-on: ubuntu-26.04 steps: - name: Action pins - Checkout repository diff --git a/.github/workflows/test-go.yml b/.github/workflows/test-go.yml new file mode 100644 index 0000000..fed7a0e --- /dev/null +++ b/.github/workflows/test-go.yml @@ -0,0 +1,81 @@ +# This workflow is managed by gh actions-lock. + +name: Test - Go + +# The Go tests, run the same way for a pull request as for a release: build-and-test-go.yml calls +# this for each of its jobs, and release-tag.yml for the tree it is about to tag, so a release fails +# on nothing a pull request has not already run on the same image. +# +# Called, never triggered, and given no secrets. The token can only read, the checkout keeps no +# credentials, and every input reaches the shell through the environment and is checked first. + +on: + workflow_call: + inputs: + targets: + description: 'The make targets to run, separated by spaces' + required: true + type: string + version: + description: 'A release version to set every pack to first, as tagging does' + required: false + type: string + default: '' + cache: + description: 'Restore and save the Go module and build caches' + required: false + type: boolean + default: false + +permissions: + contents: read + +jobs: + test: + name: make ${{ inputs.targets }} + runs-on: ubuntu-26.04 + + steps: + - name: Test - Checkout repository + uses: actions/checkout@v7.0.1 + with: + persist-credentials: false + + - name: Test - Setup Go + uses: actions/setup-go@v7.0.0 + with: + go-version-file: go.mod + # Off unless the caller turns it on: a release restores nothing another branch could + # have written. + cache: ${{ inputs.cache }} + + - name: Test - Set the release version + if: inputs.version != '' + env: + VERSION: ${{ inputs.version }} + run: scripts/release-version.sh "$VERSION" + + # Graphviz is a requirement: serve refuses to start without it, and the layout and figure + # tests fail rather than skip. + - name: Test - Setup Graphviz + run: scripts/setup-graphviz.sh + + # Target names only: an option or a variable assignment would change what make runs. + - name: Test - Run make + env: + TARGETS: ${{ inputs.targets }} + run: | + set -f + # shellcheck disable=SC2086 # one argument per target, with globbing off. + set -- $TARGETS + set +f + [ $# -gt 0 ] || { echo "::error::no make targets given"; exit 1; } + for target in "$@"; do + case "$target" in + -* | *[!A-Za-z0-9._-]*) + echo "::error::'$target' is not a make target" + exit 1 + ;; + esac + done + make "$@" diff --git a/.github/workflows/update-codeql.yml b/.github/workflows/update-codeql.yml index 6d6622f..33e93c4 100644 --- a/.github/workflows/update-codeql.yml +++ b/.github/workflows/update-codeql.yml @@ -20,7 +20,7 @@ jobs: # here, for the suites that pin upstream, and for the lock files. detect: name: Detect CodeQL CLI Update - runs-on: ubuntu-latest + runs-on: ubuntu-26.04 outputs: current: ${{ steps.check.outputs.current }} @@ -91,7 +91,7 @@ jobs: name: Check for an Existing Upgrade Branch needs: detect if: needs.detect.outputs.needed == 'true' - runs-on: ubuntu-latest + runs-on: ubuntu-26.04 outputs: exists: ${{ steps.look.outputs.exists }} @@ -135,7 +135,7 @@ jobs: name: Upgrade and Open a Pull Request needs: [detect, existing-branch] if: needs.detect.outputs.needed == 'true' && needs.existing-branch.outputs.exists != 'true' - runs-on: ubuntu-latest + runs-on: ubuntu-26.04 permissions: contents: write @@ -207,8 +207,8 @@ jobs: # Graphviz is a requirement: serve refuses to start without it, and the layout and figure # tests fail rather than skip. - - name: Upgrade - Install Graphviz - run: sudo apt-get update && sudo apt-get install --yes --no-install-recommends graphviz + - name: Upgrade - Setup Graphviz + run: bash scripts/setup-graphviz.sh - name: Upgrade - Verify run: make verify diff --git a/docs/deployment/source.md b/docs/deployment/source.md index 7dcd25f..1fac9f1 100644 --- a/docs/deployment/source.md +++ b/docs/deployment/source.md @@ -21,7 +21,7 @@ flowchart LR | .NET SDK | The major version named by `TargetFramework` in [the UI project](../../ui/Abom.WebAssembly.csproj). `dotnet --list-sdks` shows what is installed. No extra workloads are needed. | | GitHub CLI | [gh](https://cli.github.com/), for authentication and ownership verification. | | CodeQL | The version in [.codeql-version](../../.codeql-version), on `PATH`. See [install CodeQL](#install-codeql). | -| Graphviz | [Graphviz](https://graphviz.org/download/), with `dot` on `PATH`: `brew install graphviz` or `apt-get install graphviz`. Every details page draws its figure with it, and the Explorer's stable layout uses it. `serve` refuses to start without it and names the version it found. | +| Graphviz | [Graphviz](https://graphviz.org/download/), with `dot` on `PATH`: `brew install graphviz` or `apt-get install graphviz`. Every details page draws its figure with it, and the Explorer's stable layout uses it. `serve` refuses to start without it and names the version it found. On Ubuntu 26.04 and later, `make test` also needs the separately packaged neato layout plugin; run [setup-graphviz.sh](../../scripts/setup-graphviz.sh) as CI does, or install the available `libgvplugin-neato-layout*` package for your release. | These are the only requirements for serving and analyzing. Node, Playwright and golangci-lint are development tools. AI authoring and explicit lock verification have diff --git a/plans/tools/deployment.md b/plans/tools/deployment.md index d8eaa3a..b826ead 100644 --- a/plans/tools/deployment.md +++ b/plans/tools/deployment.md @@ -249,16 +249,19 @@ run in deployment environments: | Stage | Workflow and environment | What it writes | | --- | --- | --- | | Version | `release.yml` | Nothing; refuses a version that is not a release of the pinned CLI | -| Tag | `release-tag.yml`, `release-tag` | The tag, only for a dispatched version that has none, after the Go tests pass on the tree it tags. An existing tag is checked and never moved. | -| Build | `release-build.yml` | Nothing. Tests the tagged commit, builds each archive on its own platform's runner and smoke-tests the uploaded bytes there. | +| Tag | `release-tag.yml`, `release-tag` | The tag, only for a dispatched version that has none, after the Go tests pass on the tree it tags. They run in [test-go.yml](../../.github/workflows/test-go.yml), the job pull requests run. An existing tag is checked and never moved. | +| Build | `release-build.yml` | Nothing. Tests the tagged commit, builds each archive on its own platform's runner and smoke-tests the uploaded bytes there; darwin/amd64 is smoke-tested under Rosetta on arm64, because Homebrew has no Intel bottle for Graphviz. | | Draft | `release-publish.yml`, `release-draft` | Provenance attestations, then a draft release with the archives, SBOMs, `SHA256SUMS` and the attestation bundle | | Publish | `release-publish.yml`, `release` | Publishes the draft, after checking it holds exactly the staged assets | The [smoke test](../../scripts/release/smoke.sh) verifies the manifest against the extracted bytes and the executable's identity, starts the server from the archive root and reopens its database, then installs the shipped packs' dependencies and requires results from ABOM's own findings and -graph queries against the pinned CLI. Attestations name `release-publish.yml` as the signing -workflow. Artifact attestations on a private repository need GitHub Enterprise Cloud. +graph queries against the pinned CLI. Every job that needs Graphviz installs it with +[setup-graphviz.sh](../../scripts/setup-graphviz.sh), which adds the layout engines that Ubuntu +26.04 splits into a separate package and checks that each one draws. Attestations name +`release-publish.yml` as the signing workflow. Artifact attestations on a private repository need +GitHub Enterprise Cloud. The repository needs, once: the three environments, with `release-tag` limited to `main`, `release-draft` and `release` limited to `main` and `v*` tags, and required reviewers on `release` @@ -422,7 +425,10 @@ organization-wide crawl merely to validate the instructions. recorded floor with the pinned CodeQL, including the Xcode requirements on Apple silicon, before any floor appears in release documentation. Serving and analyzing need no Rosetta there, since ABOM traces no build and the Actions extractor is native; the floor run is what confirms it. The - candidates' archives are enough to start on. + candidates' archives are enough to start on. GitHub retires the `ubuntu-22.04` and + `ubuntu-22.04-arm` runner images in April 2027, after brownouts in which every job on them + fails, so the Linux archive and smoke rows need a new home first: an `ubuntu:22.04` container on + a supported runner keeps the glibc floor, and a newer image raises it. 4. **Exercise the actual download path.** Document download, provenance/checksum verification, extraction into a versioned user-writable prefix, PATH setup, configuration and startup. Use appropriate Linux/macOS verification commands and an expected repository/workflow with diff --git a/scripts/setup-graphviz.sh b/scripts/setup-graphviz.sh new file mode 100755 index 0000000..8e2d640 --- /dev/null +++ b/scripts/setup-graphviz.sh @@ -0,0 +1,73 @@ +#!/usr/bin/env bash +# +# Installs Graphviz with the layout engines given, and proves each one draws. +# +# setup-graphviz.sh [engine ...] default: every engine internal/layout may run +# +# Every workflow installs Graphviz through this, so a pull request installs it exactly as a release +# does. Its packaging differs by runner image: Ubuntu 26.04 splits the layout engines out of +# graphviz, and Homebrew has no Intel macOS bottle. serve itself needs only dot; the layout tests +# run every engine. +set -euo pipefail + +all="dot neato fdp sfdp twopi circo osage" +# shellcheck disable=SC2086 # split into one argument per engine. +[ $# -gt 0 ] || set -- $all + +# Each engine is then run by name, so nothing outside internal/layout's list is. +for engine in "$@"; do + case " $all " in + *" $engine "*) ;; + *) + echo "setup-graphviz: $engine is not one of: $all" >&2 + exit 2 + ;; + esac +done + +as_root() { + if [ "$(id -u)" -eq 0 ]; then + "$@" + else + sudo "$@" + fi +} + +case "$(uname -s)/$(uname -m)" in +Linux/*) + as_root apt-get update + # From Ubuntu 26.04 every engine but dot is a separate package that graphviz does not even + # recommend; before it, they ship inside graphviz's own library. + plugin=$(apt-cache pkgnames libgvplugin-neato-layout | + grep -E '^libgvplugin-neato-layout[0-9]+$' | sort -V | tail -n 1 || true) + # shellcheck disable=SC2086 # $plugin is one package name or nothing. + as_root apt-get install --yes --no-install-recommends graphviz $plugin + ;; +Darwin/arm64) + brew install graphviz + ;; +Darwin/x86_64) + # Homebrew builds no Intel bottle for Graphviz or anything it depends on, so this would compile + # that whole tree from source. An amd64 build runs on arm64 under Rosetta instead. + echo "setup-graphviz: Homebrew has no Intel macOS bottle for Graphviz; use an arm64 machine" >&2 + exit 1 + ;; +*) + echo "setup-graphviz: no Graphviz install for $(uname -s)/$(uname -m)" >&2 + exit 1 + ;; +esac + +# A missing engine is otherwise found minutes later, by a test, as a Graphviz error. +dot -V +missing="" +for engine in "$@"; do + if ! echo 'digraph { subgraph cluster_g { a } a -> b }' | "$engine" -Tplain >/dev/null; then + missing="$missing $engine" + fi +done +if [ -n "$missing" ]; then + echo "setup-graphviz: Graphviz cannot draw with:$missing" >&2 + exit 1 +fi +echo "setup-graphviz: draws with $*" diff --git a/ui/tests/e2e/package-lock.json b/ui/tests/e2e/package-lock.json index 989f5de..e247424 100644 --- a/ui/tests/e2e/package-lock.json +++ b/ui/tests/e2e/package-lock.json @@ -8,17 +8,20 @@ "name": "abom-e2e", "version": "0.0.0", "devDependencies": { - "@playwright/test": "1.56.1" + "@playwright/test": "1.61.1" + }, + "engines": { + "node": ">=24.0.0" } }, "node_modules/@playwright/test": { - "version": "1.56.1", - "resolved": "https://ms-feed-25.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/@playwright/test/-/test-1.56.1.tgz", - "integrity": "sha1-bjvz0MkMXPlL9kvbVv0VqAXIvT8=", + "version": "1.61.1", + "resolved": "https://ms-feed-25.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/@playwright/test/-/test-1.61.1.tgz", + "integrity": "sha1-SFaNwir3gZ5V+l6OO8ebfmo+ZnU=", "dev": true, "license": "Apache-2.0", "dependencies": { - "playwright": "1.56.1" + "playwright": "1.61.1" }, "bin": { "playwright": "cli.js" @@ -42,13 +45,13 @@ } }, "node_modules/playwright": { - "version": "1.56.1", - "resolved": "https://ms-feed-25.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/playwright/-/playwright-1.56.1.tgz", - "integrity": "sha1-YuO5nd6+0NR15ZNqFSyI5ovlX78=", + "version": "1.61.1", + "resolved": "https://ms-feed-25.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/playwright/-/playwright-1.61.1.tgz", + "integrity": "sha1-2MDAbrk8KJga/HR7rORTvb1QGLw=", "dev": true, "license": "Apache-2.0", "dependencies": { - "playwright-core": "1.56.1" + "playwright-core": "1.61.1" }, "bin": { "playwright": "cli.js" @@ -61,9 +64,9 @@ } }, "node_modules/playwright-core": { - "version": "1.56.1", - "resolved": "https://ms-feed-25.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/playwright-core/-/playwright-core-1.56.1.tgz", - "integrity": "sha1-JKZkgeXNM6BFYyIwqixPDLax2z0=", + "version": "1.61.1", + "resolved": "https://ms-feed-25.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/playwright-core/-/playwright-core-1.61.1.tgz", + "integrity": "sha1-PJmEEwfvu6vJ1yTEGojJFHBdFfw=", "dev": true, "license": "Apache-2.0", "bin": { diff --git a/ui/tests/e2e/package.json b/ui/tests/e2e/package.json index 16f6af2..68f2ff3 100644 --- a/ui/tests/e2e/package.json +++ b/ui/tests/e2e/package.json @@ -11,6 +11,6 @@ "test": "playwright test" }, "devDependencies": { - "@playwright/test": "1.56.1" + "@playwright/test": "1.61.1" } }