From b4a78bc61fdbe014cd5ef625d3f026342e32e45a Mon Sep 17 00:00:00 2001 From: Denis Cornehl Date: Wed, 26 Aug 2026 19:02:32 +0200 Subject: [PATCH 1/3] refactor justfiles / test commands --- .github/workflows/ci.yml | 29 +- .github/workflows/commit-sqlx-changes.yml | 31 +- .github/workflows/docker.yml | 19 +- .gitignore | 1 + Justfile | 6 +- README.md | 121 ++++-- docker-compose.yml | 16 - dockerfiles/Dockerfile-gui-tests | 82 ---- docs/src/binaries/index-watcher.md | 2 +- docs/src/development/docker-commands.md | 90 ++++- docs/src/development/local-configuration.md | 39 ++ docs/src/development/troubleshooting.md | 21 +- docs/src/development/vendored-assets.md | 5 +- justfiles/book.just | 6 +- justfiles/cli.just | 138 +++---- justfiles/docker.just | 28 ++ justfiles/linting.just | 171 +++++++++ justfiles/services.just | 58 +-- justfiles/sqlx.just | 38 ++ justfiles/testing.just | 256 +++---------- justfiles/utils.just | 52 ++- package-lock.json | 400 ++++++++++++++++++++ 22 files changed, 1097 insertions(+), 512 deletions(-) delete mode 100644 dockerfiles/Dockerfile-gui-tests create mode 100644 justfiles/docker.just create mode 100644 justfiles/linting.just create mode 100644 justfiles/sqlx.just create mode 100644 package-lock.json diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 19a1a27bde..79223bec4f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -32,11 +32,8 @@ jobs: - name: Set up Docker Buildx uses: docker/setup-buildx-action@v4 - - name: run sqlx migration up & down - run: | - just sqlx-migrate-run \ - sqlx-check \ - sqlx-migrate-revert + - name: Test database migrations + run: just test-database-migrations - name: shut down test environment if: ${{ always() }} @@ -90,12 +87,28 @@ jobs: - name: Set up Docker Buildx uses: docker/setup-buildx-action@v4 + - name: Expose GitHub cache credentials + uses: crazy-max/ghaction-github-runtime@v4 + - uses: taiki-e/install-action@v2 with: - tool: just + tool: just,sqlx-cli - - name: Run GUI tests - run: just run-gui-tests + - uses: actions/setup-node@v6 + with: + node-version: 24 + cache: npm + + - name: Run end-to-end GUI tests + env: + # run all necessary admin commands from the docker images, as + # we would in prod. + DOCSRS_CLI_MODE: docker + # run the preparation / builds for the e2e tests not + # on the gh action host, but inside our builder docker image. + # Like this we know this works. + DOCSRS_BUILDER_CLI_MODE: docker + run: just prepare-gui-tests run-gui-tests-e2e - name: shut down test environment if: ${{ always() }} diff --git a/.github/workflows/commit-sqlx-changes.yml b/.github/workflows/commit-sqlx-changes.yml index 3e6763663a..8821cc2cb6 100644 --- a/.github/workflows/commit-sqlx-changes.yml +++ b/.github/workflows/commit-sqlx-changes.yml @@ -35,43 +35,30 @@ jobs: git fetch origin git rebase origin/main - - name: install `just` - run: sudo snap install --edge --classic just + - name: Install development tools + uses: taiki-e/install-action@v2 + with: + tool: just,sqlx-cli - name: restore build & cargo cache uses: Swatinem/rust-cache@v2 with: prefix-key: ${{ env.RUST_CACHE_KEY }} - - name: Launch postgres - run: | - cp .env.sample .env - mkdir -p ${DOCSRS_PREFIX}/public-html - docker compose up -d db s3 - # Give the database enough time to start up - sleep 5 - # Make sure the database is actually working - psql "${DOCSRS_DATABASE_URL}" - - - name: install SQLX CLI - run: cargo install sqlx-cli --no-default-features --features postgres - - - name: run database migrations - run: cargo sqlx migrate run --database-url $DOCSRS_DATABASE_URL - - name: Commit sqlx changes on main branch if any id: sqlx_check run: | - just sqlx-prepare + just sqlx-update # If there are differences in the SQLX files, then we push them on the main branch - if git status --porcelain .sqlx ; then + if [ -n "$(git status --porcelain .sqlx)" ]; then echo "need_pr=1" >> "$GITHUB_OUTPUT" else echo "need_pr=0" >> "$GITHUB_OUTPUT" fi - - name: Clean up the database - run: docker compose down --volumes + - name: shut down test environment + if: ${{ always() }} + run: just compose-down-and-wipe - name: Open pull request if: ${{ steps.sqlx_check.outputs.need_pr == '1' }} diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index 0486786979..7f33a0c780 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -15,6 +15,10 @@ jobs: steps: - uses: actions/checkout@v7 + - uses: taiki-e/install-action@v2 + with: + tool: just + - name: setup docker buildx uses: docker/setup-buildx-action@v4 @@ -31,17 +35,4 @@ jobs: *.cache-to=type=gha,mode=max,scope=docs-rs-images - name: smoke test packaged binaries - run: | - set -euo pipefail - - docker buildx bake --file docker-bake.hcl --print | - jq -r ' - . as $bake - | $bake.group.default.targets[] as $target - | $bake.target[$target].tags[0] - // error("Bake target \($target) has no image tag") - ' | - while IFS= read -r image; do - echo "testing $image..." - docker run --rm "$image" --help - done + run: just docker-smoke-test diff --git a/.gitignore b/.gitignore index e418ad2ee5..57df98ebc5 100644 --- a/.gitignore +++ b/.gitignore @@ -13,5 +13,6 @@ target .rustwide-docker archive_cache .workspace +node_modules/ docs/book/ docs/src/generated/ diff --git a/Justfile b/Justfile index ce62299089..6bce864ad9 100644 --- a/Justfile +++ b/Justfile @@ -18,9 +18,13 @@ _default: import 'justfiles/book.just' import 'justfiles/cli.just' +import 'justfiles/docker.just' +import 'justfiles/linting.just' import 'justfiles/services.just' +import 'justfiles/sqlx.just' import 'justfiles/testing.just' import 'justfiles/utils.just' -psql: +# Open a PostgreSQL shell for the local docs.rs database. +psql: compose-up-resources psql $DOCSRS_DATABASE_URL diff --git a/README.md b/README.md index 1adf5b1eb9..25405a093e 100644 --- a/README.md +++ b/README.md @@ -47,16 +47,21 @@ $ mkdir -p ignored/cratesfyi-prefix/crates.io-index $ SQLX_OFFLINE=1 cargo build ``` -Start PostgreSQL and the local S3 service, then initialize them: +Start PostgreSQL and the local S3 service, then initialize the database: ```console -$ docker compose up --wait db s3 -$ . ./.env -$ cargo run --bin docs_rs_admin -- database migrate +$ just compose-up-resources +$ just sqlx-migrate-run ``` -Commands run outside Docker Compose need the environment variables from `.env`. -Either source it as above or use a dotenv integration for your shell. +Most recipes start these resources automatically; use +`just compose-up-resources` when running application commands directly. The +`cli`, `builder`, `watcher`, and Compose application recipes also apply pending +migrations before starting. + +The `just` recipes load `.env` and start PostgreSQL and S3 when needed. Commands +run directly with Cargo need the same environment variables; source `.env` or +use a dotenv integration for your shell before running them. Large local files should go in `ignored/`, which is excluded from both Git and Docker build contexts. @@ -64,32 +69,41 @@ Docker build contexts. ### Run the web server ```console -$ . ./.env -$ cargo run --bin docs_rs_web +$ just web ``` The site is available at . To restart it automatically -when Rust source or templates change, install `cargo-watch` and run: +when web, template, asset, shared-library, or workspace configuration files +change, run: ```console -$ . ./.env -$ cargo watch -x "run --bin docs_rs_web" +$ just web-watch ``` +The watch command runs from the repository root and ignores changes confined to +other application binaries, such as the builder and registry watcher. + ### Build documentation for a crate Set up or update the docs.rs nightly toolchain, then build a release: ```console -$ . ./.env -$ cargo run --bin docs_rs_builder -- build update-toolchain -$ cargo run --bin docs_rs_builder -- build crate regex 1.3.1 +$ just builder build update-toolchain +$ just builder build crate regex 1.3.1 ``` +The `builder` recipe uses `DOCSRS_BUILDER_CLI_MODE`: it defaults to `local` on +amd64 Linux and `docker` on other platforms. Set the variable explicitly to +override that choice. + +The `cli` and `watcher` recipes similarly use `DOCSRS_CLI_MODE`, but default to +`local` on every platform. Set either mode variable to `docker` to keep using +the same high-level recipe through its corresponding Compose service. + To test a local package instead: ```console -$ cargo run --bin docs_rs_builder -- build crate --local /path/to/package +$ just builder build crate --local /path/to/package ``` Some workspace packages must first be packaged with Cargo. See @@ -99,14 +113,21 @@ If you only need an existing release in your local environment, import it instead of running the builder: ```console -$ . ./.env -$ cargo run -p docs_rs_import_release -- regex latest +$ just import-release regex latest ``` ### Run with Docker Compose only If running the Rust binaries on the host is impractical, the `just` recipes can -also run them in Docker Compose: +keep the same interface while running them through Docker Compose. Add these +settings to `.env`: + +```dotenv +DOCSRS_CLI_MODE=docker +DOCSRS_BUILDER_CLI_MODE=docker +``` + +Then use the normal recipes: ```console $ just cli-db-migrate @@ -123,13 +144,15 @@ $ just compose-up-watcher Common one-off commands include: ```console -$ just cli-build-update-toolchain -$ just cli-build-crate regex 1.3.1 -$ just cli-queue-add regex 1.3.1 +$ just builder build update-toolchain +$ just builder build crate regex 1.3.1 +$ just cli queue add regex 1.3.1 ``` -Use `just --list` to see all available recipes. Tests are not currently -supported in the Docker-Compose-only development environment. +Use `just --list` to see all available recipes. The Rust test suite still runs +on the host; the GUI suite has a container integration mode described below. The +lower-level `docker-run` recipe is available when a specific Compose service +must be selected explicitly, but is not needed for normal development. To stop the services while retaining their data, or to remove their local data: @@ -159,6 +182,19 @@ Run the ignored builder tests separately with: $ just run-builder-tests ``` +Test database migrations through both SQLx CLI and `docs_rs_admin` with: + +```console +$ just test-database-migrations +``` + +After changing queries or migrations, apply migrations and regenerate the +committed SQLx offline metadata with: + +```console +$ just sqlx-update +``` + Run the complete lint suite with: ```console @@ -166,8 +202,8 @@ $ just lint ``` Linting GitHub Actions workflows requires -[`actionlint`](https://github.com/rhysd/actionlint/blob/main/docs/install.md). If -it is not installed, that check is skipped with a warning. +[`actionlint`](https://github.com/rhysd/actionlint/blob/main/docs/install.md). +If it is not installed, that check is skipped with a warning. Run all formatters with: @@ -178,21 +214,46 @@ $ just format If files are not formatted correctly, this command rewrites them and exits with an error so that you can review the changes. -Run browser-based GUI tests with: +Prepare the GUI fixture crates once with: + +```console +$ just prepare-gui-tests +``` + +The builder follows `DOCSRS_BUILDER_CLI_MODE`, so it normally runs on the host +on amd64 Linux and through the packaged builder image elsewhere. The generated +fixture data remains in PostgreSQL and S3. + +Run the GUI tests against a temporary host web server with: ```console $ just run-gui-tests ``` +This reuses the existing fixtures, so changes limited to templates, CSS, +JavaScript, or web behavior do not require another preparation step. Fixture +data remains available after `just compose-down`, while +`just compose-down-and-wipe` removes it. + +To reproduce the container integration setup used in CI, run: + +```console +$ DOCSRS_CLI_MODE=docker DOCSRS_BUILDER_CLI_MODE=docker \ + just prepare-gui-tests run-gui-tests-e2e +``` + +This applies migrations through the packaged admin image, builds fixtures +through the packaged builder image, and serves them with the packaged web image. +The Node/Puppeteer browser runner remains on the host. + These tests use [browser-ui-test](https://github.com/GuillaumeGomez/browser-UI-test/); its [script documentation](https://github.com/GuillaumeGomez/browser-UI-test/blob/main/goml-script.md) -describes the test format. To run the browser test runner manually against an -already-running web server, install the package and invoke the script directly: +describes the test format. To run only the browser assertions against a web +server already listening on port 3000, use: ```console -$ npm install browser-ui-test -$ node gui-tests/tester.js +$ just run-gui-browser-tests ``` The test suite needs at least 4096 open file descriptors. If tests fail or time diff --git a/docker-compose.yml b/docker-compose.yml index 87f605d7fc..166e8d5cd3 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -275,22 +275,6 @@ services: - metrics - full - gui_tests: - platform: "linux/amd64" - build: - context: . - dockerfile: ./dockerfiles/Dockerfile-gui-tests - <<: *docker-cache - network_mode: "host" - extra_hosts: - - "host.docker.internal:host-gateway" - volumes: - - "${PWD}:/build/out" - profiles: - # gui_tests should not be run as background daemon. - # Run via `just run-gui-tests`. - - manual - volumes: postgres-data: {} minio-data: {} diff --git a/dockerfiles/Dockerfile-gui-tests b/dockerfiles/Dockerfile-gui-tests deleted file mode 100644 index 0ec0b551f0..0000000000 --- a/dockerfiles/Dockerfile-gui-tests +++ /dev/null @@ -1,82 +0,0 @@ -FROM node:24-trixie-slim - -ENV DEBIAN_FRONTEND=noninteractive - -# Install packaged dependencies -# hadolint ignore=DL3008 -RUN apt-get update && \ - apt-get install -y --no-install-recommends \ - build-essential \ - git \ - curl \ - cmake \ - gcc \ - g++ \ - pkg-config \ - libmagic-dev \ - libssl-dev \ - zlib1g-dev \ - ca-certificates \ - docker.io \ - unzip \ - xz-utils - -# Install dependencies for chromium browser -# hadolint ignore=DL3008 -RUN apt-get install -y --no-install-recommends \ - libasound2 \ - libatk1.0-0 \ - libatk-bridge2.0-0 \ - libc6 \ - libcairo2 \ - libcups2 \ - libdbus-1-3 \ - libexpat1 \ - libfontconfig1 \ - libgbm-dev \ - libgcc1 \ - libglib2.0-0 \ - libgtk-3-0 \ - libnspr4 \ - libpango-1.0-0 \ - libpangocairo-1.0-0 \ - libstdc++6 \ - libx11-6 \ - libx11-xcb1 \ - libxcb1 \ - libxcomposite1 \ - libxcursor1 \ - libxdamage1 \ - libxext6 \ - libxfixes3 \ - libxi6 \ - libxrandr2 \ - libxrender1 \ - libxss1 \ - libxtst6 \ - fonts-liberation \ - libnss3 \ - lsb-release \ - xdg-utils \ - wget - -RUN apt-get clean \ - && rm -rf /var/lib/apt/lists/* - -WORKDIR /build - -RUN mkdir out - -COPY ../package.json /build/package.json - -# For now, we need to use `--unsafe-perm=true` to go around an issue when npm tries -# to create a new folder. For reference: -# https://github.com/puppeteer/puppeteer/issues/375 -# -# We also specify the version in case we need to update it to go around cache limitations. -RUN npm install --unsafe-perm=true --loglevel verbose --force - -# Used in gui-tests/tester.js -ENV NODE_MODULE_PATH="/build/node_modules" - -CMD ["node", "/build/out/gui-tests/tester.js"] diff --git a/docs/src/binaries/index-watcher.md b/docs/src/binaries/index-watcher.md index 29cf779ecd..833909a41b 100644 --- a/docs/src/binaries/index-watcher.md +++ b/docs/src/binaries/index-watcher.md @@ -25,7 +25,7 @@ every release already present in the index. To start from a particular Git reference, set it before starting the watcher: ```console -$ just cli-queue-reset-last-seen-ref +$ just watcher queue set-last-seen-reference ``` Omit the reference, or pass `--head`, to reset it to the index's current HEAD. diff --git a/docs/src/development/docker-commands.md b/docs/src/development/docker-commands.md index 8b2352bc4e..68d7732535 100644 --- a/docs/src/development/docker-commands.md +++ b/docs/src/development/docker-commands.md @@ -16,13 +16,25 @@ Docker images are defined in `docker-bake.hcl`. Build one image with its Bake target: ```console -$ docker buildx bake build-server +$ just docker-build build-server ``` Build all application images with: ```console -$ docker buildx bake +$ just docker-build +``` + +After building, run the same packaged-binary smoke tests as CI with: + +```console +$ just docker-smoke-test +``` + +Or build and smoke-test the complete default group in one command: + +```console +$ just docker-test ``` The images are loaded into the local Docker daemon. For example, smoke-test the @@ -38,8 +50,40 @@ share a Cargo target cache local to the Buildx builder, which enables incremental rebuilds after source changes. A new Buildx builder starts without that local incremental cache. +## Run one-off CLI commands + +The `cli`, `watcher`, and `builder` recipes select host or Compose execution +through their configured CLI mode. See +[CLI execution modes](local-configuration.md#cli-execution-modes) for the +defaults, environment variables, and configuration-file behavior. + +Override a mode for one command when you want to keep using its high-level +recipe: + +```console +$ DOCSRS_CLI_MODE=docker just cli-db-migrate +$ DOCSRS_CLI_MODE=docker just watcher queue set-last-seen-reference --head +$ DOCSRS_BUILDER_CLI_MODE=docker just builder build crate regex 1.3.1 +``` + +Or bypass mode selection and run a specific Compose service directly: + +```console +$ just docker-run builder-cli build crate regex 1.3.1 +$ just docker-run registry-watcher-cli queue set-last-seen-reference --head +``` + ## Start services +Start the default PostgreSQL and S3 resources used by host-side development: + +```console +$ just compose-up-resources +``` + +Recipes that need these resources start them automatically. The explicit command +is useful before running application binaries directly with Cargo. + Start individual application profiles with: ```console @@ -87,3 +131,45 @@ $ just compose-down-and-wipe The second command deletes the local development database and object-storage contents. + +## GUI tests + +Build the crate fixtures required by the GUI suite: + +```console +$ just prepare-gui-tests +``` + +This uses the `builder` recipe and therefore follows `DOCSRS_BUILDER_CLI_MODE`. +The generated documentation is retained in the local PostgreSQL and S3 +resources. + +After preparing fixtures, start a temporary host web server and run the browser +assertions with: + +```console +$ just run-gui-tests +``` + +This does not rebuild fixtures, making it the fast path for changes to +templates, CSS, JavaScript, and web behavior. `just compose-down` preserves the +fixtures; `just compose-down-and-wipe` removes them. + +If a suitable web server is already listening on port 3000, run only the browser +assertions with: + +```console +$ just run-gui-browser-tests +``` + +To reproduce the container integration path used in CI, run: + +```console +$ DOCSRS_CLI_MODE=docker DOCSRS_BUILDER_CLI_MODE=docker \ + just prepare-gui-tests run-gui-tests-e2e +``` + +This applies migrations through the packaged admin image, builds fixtures +through the packaged build-server image, and serves the results from the +packaged web-server image. Node and Puppeteer remain on the host so the test +driver does not require a separate image. diff --git a/docs/src/development/local-configuration.md b/docs/src/development/local-configuration.md index 0651415e95..b52751f55f 100644 --- a/docs/src/development/local-configuration.md +++ b/docs/src/development/local-configuration.md @@ -16,6 +16,45 @@ $ . ./.env $ cargo run --bin docs_rs_web ``` +## CLI execution modes + +The high-level CLI recipes can run their Rust binary on the host or through a +one-off Docker Compose service: + +| Recipe | Configuration | Default | +| ---------------- | ------------------------- | ------------------------------------------ | +| `just cli …` | `DOCSRS_CLI_MODE` | `local` | +| `just watcher …` | `DOCSRS_CLI_MODE` | `local` | +| `just builder …` | `DOCSRS_BUILDER_CLI_MODE` | `local` on amd64 Linux; `docker` elsewhere | + +The `local` mode uses `cargo run`. The `docker` mode builds and runs the +corresponding `cli`, `registry-watcher-cli`, or `builder-cli` Compose service. +In either mode, the recipes start the default PostgreSQL and S3 resources and +apply pending database migrations when necessary. + +Set a mode in `.env` to make it the default for the repository, or override it +for one invocation: + +```console +$ DOCSRS_BUILDER_CLI_MODE=docker just builder build crate regex 1.3.1 +``` + +Both mode variables accept `local` or `docker`. Use `docker-run` to bypass mode +selection and name a Compose service explicitly: + +```console +$ just docker-run builder-cli build crate regex 1.3.1 +``` + +`.env` controls mode selection and configures commands that run on the host. +`.docker.env` configures the docs.rs process inside a Compose container; it does +not select where a recipe runs. + +The GUI end-to-end CI job sets both mode variables to `docker`. It prepares +fixtures through the packaged admin and builder images before testing the +packaged web image. The ordinary local defaults favor faster host builds where +the builder supports them. + ## Accessing PostgreSQL After starting the local database, open a `psql` session with: diff --git a/docs/src/development/troubleshooting.md b/docs/src/development/troubleshooting.md index 7090868cd5..1c42762d21 100644 --- a/docs/src/development/troubleshooting.md +++ b/docs/src/development/troubleshooting.md @@ -17,15 +17,26 @@ Then check out a fresh copy of the affected file. ## A builder command reports `Exec format error` Running builds directly on the host requires a compatible Linux environment. On -macOS, Windows, or an incompatible architecture, run the builder through Docker -Compose instead: +platforms other than amd64 Linux, the `builder` recipe defaults to Docker mode +automatically. If local mode was selected explicitly or the detected host is +still incompatible, override it for the command: ```console -$ just compose-up-builder -$ just cli-build-update-toolchain -$ just cli-build-crate regex 1.3.1 +$ DOCSRS_BUILDER_CLI_MODE=docker just builder build update-toolchain +$ DOCSRS_BUILDER_CLI_MODE=docker just builder build crate regex 1.3.1 ``` +To use Docker mode for all builder commands in this checkout, add the following +to `.env`: + +```dotenv +DOCSRS_BUILDER_CLI_MODE=docker +``` + +See [CLI execution modes](local-configuration.md#cli-execution-modes) for the +mode defaults and configuration behavior. To bypass mode selection entirely, run +the Compose service explicitly with `just docker-run builder-cli …`. + ## Tests fail or time out unexpectedly The test suite needs at least 4096 open file descriptors. Check the current diff --git a/docs/src/development/vendored-assets.md b/docs/src/development/vendored-assets.md index 45290af4f4..35ccc2ca8c 100644 --- a/docs/src/development/vendored-assets.md +++ b/docs/src/development/vendored-assets.md @@ -26,5 +26,8 @@ needed, and run: ```console $ cargo test --package docs_rs_web -$ just run-gui-tests +$ just prepare-gui-tests run-gui-tests ``` + +For the container integration path, set both CLI modes to `docker` and run +`just prepare-gui-tests run-gui-tests-e2e` instead. diff --git a/justfiles/book.just b/justfiles/book.just index 32eaa55607..4175a953b9 100644 --- a/justfiles/book.just +++ b/justfiles/book.just @@ -1,5 +1,6 @@ -_ensure_mdbook_installed: (_ensure_cargo_installed "mdbook" "mdbook-linkcheck2" "mdbook-mermaid") +_ensure_mdbook_installed: (_ensure_cargo_installed "mdbook") (_ensure_cargo_installed "mdbook-linkcheck2") (_ensure_cargo_installed "mdbook-mermaid") +# Generate CLI help pages and build the developer guide. [group('book')] book-build *args: _ensure_mdbook_installed #!/usr/bin/env bash @@ -15,14 +16,17 @@ book-build *args: _ensure_mdbook_installed mdbook build docs {{ args }} +# Build and test the developer guide. [group('book')] [working-directory('./docs/')] book-test: book-build mdbook test +# Build the developer guide and open it in a browser. [group('book')] book-open: (book-build "--open") +# Watch, rebuild, and serve the developer guide locally. [group('book')] book-watch: book-build mdbook watch ./docs --open diff --git a/justfiles/cli.just b/justfiles/cli.just index 774c76b8cd..d339af2d8b 100644 --- a/justfiles/cli.just +++ b/justfiles/cli.just @@ -1,97 +1,71 @@ -# a collection of just commands to wrap various docs.rs CLI commands, -# and run them in a one-off docker container. -# _Which_ container depends on the command itself and its dependencies. -# Most service containers have their corresponding CLI container: -# * web -> cli -# * builder-x -> builder-cli -# * registry-watcher -> registry-watcher-cli +# Builder commands default to the host on amd64 Linux and Docker elsewhere. +builder_cli_mode_default := if os() + "-" + arch() == "linux-x86_64" { "local" } else { "docker" } +export DOCSRS_BUILDER_CLI_MODE := env("DOCSRS_BUILDER_CLI_MODE", builder_cli_mode_default) -# low-level helper to run any CLI command in its own one-off docker container, -# ensuring that `db` and `s3` are running. -_cli service_name *args: _touch-docker-env _ensure_db_and_s3_are_running - # dependencies in the docker-compose file are ignored - # when running a one-off service with `docker compose run`. - # Instead we explicitly start any dependent services first via - # `_ensure_db_and_s3_are_running`. +# Admin and watcher commands default to the host on every platform. +export DOCSRS_CLI_MODE := env("DOCSRS_CLI_MODE", "local") - docker compose run --build --rm {{ service_name }} {{ args }} - -# run any CLI command in its own one-off `cli` docker container. Args are passed to the container. -# Only for commands that just need `db` and `s3` and minimal system dependencies. -[group('cli')] -cli +args: _touch-docker-env cli-db-migrate - just _cli cli {{ args }} - -# Initialize the `docs.rs` database -[group('cli')] -[group('database')] -cli-db-migrate: - # intentially not using `cli` recipe, because it has a dependency on `cli-db-migrate`. - # Otherwise we would have a stack overflow / infinite recursion. - # - # TODO: potential optimization: only run the container when we have to - # run migrations? - just _cli cli database migrate - -# add a release to the build queue -[group('cli')] -[group('queue')] -cli-queue-add crate_name crate_version: - # only does things with the database, so can use the lightweight `cli` container. - just cli queue add {{ crate_name }} {{ crate_version }} - -# run builder CLI command in its own one-off `build-server` docker container. -# Uses a separate builder-cli container & workspace that doesn't conflict -# with the continiously running build-servers. -[group('builder')] -[group('cli')] -cli-build +args: _touch-docker-env cli-db-migrate - just _cli builder-cli {{ args }} - -# set the nightly rust version to be used for builds. Format: `nightly-YYYY-MM-DD` -# or just `nightly` for always using the latest nightly. -[group('builder')] -[group('cli')] -cli-build-set-toolchain name only_first_time="false": +_run-cli mode package service_name *args: #!/usr/bin/env bash set -euo pipefail - FLAG="" - if [ "{{ only_first_time }}" = "true" ]; then FLAG="--only-first-time"; fi - just cli-build build set-toolchain {{ name }} $FLAG + case "{{ mode }}" in + local) + cargo run -p {{ package }} -- {{ args }} + ;; + docker) + just docker-run {{ service_name }} {{ args }} + ;; + *) + echo "Invalid CLI mode: {{ mode }}" >&2 + echo "Expected one of: local, docker" >&2 + exit 2 + ;; + esac -# update the toolchain in the builders -[group('builder')] +# Run a docs_rs_admin command using DOCSRS_CLI_MODE. [group('cli')] -cli-build-update-toolchain: - just cli-build build update-toolchain +cli *args: _ensure_db_migrated + SQLX_OFFLINE=1 just _run-cli "$DOCSRS_CLI_MODE" docs_rs_admin cli {{ args }} -# build & upload toolchain shared static resources -[group('builder')] -[group('cli')] -cli-build-add-essential-files: - just cli-build build add-essential-files +_builder *args: + # on non-linux (and arm/linux) we need to run the builder inside + # a docker container because many places expect the builder to + # run on a linux host. + just _run-cli "$DOCSRS_BUILDER_CLI_MODE" docs_rs_builder builder-cli {{ args }} -# build a release -[group('builder')] +# Run a docs_rs_builder command using DOCSRS_BUILDER_CLI_MODE. [group('cli')] -cli-build-crate name version: - just cli-build build crate {{ name }} {{ version }} +builder *args: _ensure_db_migrated + just _builder {{ args }} -# run registry-watcher CLI command in its own one-off `registry-watcher` docker container. +# Run a docs_rs_watcher command using DOCSRS_CLI_MODE. [group('cli')] -[group('watcher')] -cli-watcher +args: _touch-docker-env cli-db-migrate - just _cli registry-watcher-cli {{ args }} +watcher *args: _ensure_db_migrated + just _run-cli "$DOCSRS_CLI_MODE" docs_rs_watcher registry-watcher-cli {{ args }} -# Update last seen reference to the given hash, or the current `HEAD`. +# Migrate to an optional version using docs_rs_admin and DOCSRS_CLI_MODE. [group('cli')] -[group('queue')] -cli-queue-reset-last-seen-ref ref="--head": - just cli-watcher queue set-last-seen-reference {{ ref }} +cli-db-migrate version="": compose-up-resources + SQLX_OFFLINE=1 just _run-cli "$DOCSRS_CLI_MODE" docs_rs_admin cli database migrate {{ version }} -# find differences between crates.io and our own database, and fix them on our side. -[group('cli')] -[group('database')] -cli-db-synchronize *args: - just cli-watcher database synchronize {{ args }} +# Run the web server on the host. +[group('development')] +web *args: _ensure_db_migrated + cargo run -p docs_rs_web -- {{ args }} + +# Watch web and shared-library sources, restarting the host web server on changes. +[group('development')] +web-watch: _ensure_db_migrated (_ensure_cargo_installed "cargo-watch") + cargo watch \ + --watch .cargo \ + --watch Cargo.lock \ + --watch Cargo.toml \ + --watch crates/bin/docs_rs_web \ + --watch crates/lib \ + --exec 'run -p docs_rs_web' + +# Import a published crate release into the local environment. +[group('development')] +import-release +args: _ensure_db_migrated + cargo run -p docs_rs_import_release -- {{ args }} diff --git a/justfiles/docker.just b/justfiles/docker.just new file mode 100644 index 0000000000..cab95fc185 --- /dev/null +++ b/justfiles/docker.just @@ -0,0 +1,28 @@ +# Build all images or the selected Docker Bake targets for local use. +[group('docker')] +docker-build *targets: + docker buildx bake --file docker-bake.hcl {{ targets }} + +# Run --help in every image from the default Docker Bake group. +[group('docker')] +[group('testing')] +docker-smoke-test: + #!/usr/bin/env bash + set -euo pipefail + + docker buildx bake --file docker-bake.hcl --print | + jq -r ' + . as $bake + | $bake.group.default.targets[] as $target + | $bake.target[$target].tags[0] + // error("Bake target \($target) has no image tag") + ' | + while IFS= read -r image; do + echo "testing $image..." + docker run --rm "$image" --help + done + +# Build and smoke-test every image in the default Docker Bake group. +[group('docker')] +[group('testing')] +docker-test: docker-build docker-smoke-test diff --git a/justfiles/linting.just b/justfiles/linting.just new file mode 100644 index 0000000000..abd033af1f --- /dev/null +++ b/justfiles/linting.just @@ -0,0 +1,171 @@ +_format_justfile justfile: + #!/usr/bin/env bash + set -euo pipefail + + echo "formatting {{ justfile }}.." + # like this we get both the non-zero exit code, and the local code is + # formatted. + if ! just --fmt --justfile "{{ justfile }}" --check >/dev/null; then + just --fmt --justfile "{{ justfile }}" + exit 1 + fi + +_format_markdown mdfile: + #!/usr/bin/env bash + set -euo pipefail + + echo "formatting {{ mdfile }}.." + # like this we get both the non-zero exit code, and the local code is + # formatted. + if ! deno fmt --quiet --check "{{ mdfile }}" >/dev/null; then + deno fmt "{{ mdfile }}" + exit 1 + fi + +# Format all Rust source files. +[group('linting')] +format-rust: + #!/usr/bin/env bash + set -euo pipefail + + echo "running cargo fmt" + rustup component add rustfmt + if ! cargo fmt --all -- --check >/dev/null; then + echo "rust files weren't formatted..." >&2 + cargo fmt --all + exit 1 + fi + +# Run every formatter and report all formatting failures. +[group('linting')] +format: + #!/usr/bin/env bash + set -euo pipefail + + exit_code=0 + + just format-rust || exit_code=1 + just format-just || exit_code=1 + just format-markdown || exit_code=1 + just format-cargo-toml || exit_code=1 + + exit "$exit_code" + +# Format all Justfiles. +[group('linting')] +format-just: + fd \ + --type file \ + --threads 1 \ + '^(Justfile|.+\.just)$' . \ + --exec just _format_justfile {} || exit_code=1 + +# Format maintained Markdown files with Deno. +[group('linting')] +format-markdown: + fd \ + --type file \ + --threads 1 \ + --extension md \ + --exclude 'crates/lib/font-awesome-as-a-crate/' \ + --exclude 'crates/bin/docs_rs_web/assets/syntaxes/' \ + --exclude 'crates/bin/docs_rs_web/static/' \ + --exec just _format_markdown {} || exit_code=1 + +# Run Clippy for the complete workspace. +[group('linting')] +clippy *args: + rustup component add clippy + cargo clippy \ + --all-features \ + --all-targets \ + --workspace \ + --locked \ + {{ args }} \ + -- -D warnings + +# Apply Clippy suggestions to dirty or staged files. +[group('linting')] +clippy-fix: (clippy "--fix --allow-dirty --allow-staged") + +# Run Rust linting, applying fixes outside CI. +[group('linting')] +lint-rust: + #!/usr/bin/env bash + set -euo pipefail + + if [ "${GITHUB_ACTIONS:-}" = "true" ]; then + just clippy + else + just clippy-fix + fi + +# Run the standard local and CI lint suite. +[group('linting')] +lint: lint-rust lint-actions lint-js lint-dependencies-machete + +# Validate GitHub Actions workflows with actionlint when installed. +[group('linting')] +lint-actions: + @command -v actionlint >/dev/null || { echo "warning: actionlint not installed, skipping"; exit 0; } + actionlint -ignore SC2086 + +# Format workspace Cargo.toml files with cargo-sort. +[group('linting')] +format-cargo-toml *args: (_ensure_cargo_installed "cargo-sort") + #!/usr/bin/env bash + set -euo pipefail + + if [ {{ semver_matches(trim_start_match(shell("cargo-sort --version"), "cargo-sort "), ">=2.1.3") }} != 'true' ]; then + echo "cargo-sort to old, must be >=2.1.3" + exit 1; + fi + + # like this we get both the non-zero exit code, and the local code is + # formatted. + if ! cargo sort --workspace --check {{ args }} >/dev/null; then + cargo sort --workspace {{ args }} + exit 1 + fi + +# Check workspace manifests for unused dependencies with cargo-machete. +[group('linting')] +lint-dependencies-machete: (_ensure_cargo_installed "cargo-machete") + #!/usr/bin/env bash + set -euo pipefail + + # check unused deps with cargo machete is fast, + # but has many false positives. + # While it can also recurse into subdirs, it would + # also stumble onto our broken crates in `/tests/crates/*`, + # where I also don't want to add machete-metadata. + fd \ + --glob 'Cargo.toml' \ + --type file \ + --exclude tests \ + -X cargo machete {} + +# Run the slower nightly unused-dependency checks with cargo-udeps. +[group('linting')] +lint-dependencies-udeps: (_ensure_cargo_installed "cargo-udeps") + #!/usr/bin/env bash + set -euo pipefail + + # check unused deps with cargo udeps. + # Optional, since udeps is much slower because it + # needs to additionally compile the workspace with nightly + echo "check for unused normal dependencies" + cargo +nightly udeps --workspace + + echo "check for unused dev dependencies" + cargo +nightly udeps --workspace --all-targets + +# Lint frontend JavaScript and templates with ESLint. +[group('linting')] +lint-js *args: + deno run -A npm:eslint@9 \ + crates/bin/docs_rs_web/static \ + crates/bin/docs_rs_web/templates \ + eslint.config.js \ + gui-tests \ + {{ args }} diff --git a/justfiles/services.just b/justfiles/services.just index 00026abd11..9d75ca6c0a 100644 --- a/justfiles/services.just +++ b/justfiles/services.just @@ -1,41 +1,41 @@ -# run migrations, then launch one or more docker compose profiles in the background +# Start the PostgreSQL and S3 resources used by local development. [group('compose')] -compose-up *profiles: _touch-docker-env cli-db-migrate +compose-up-resources: _touch-docker-env + # this just start up the "default" resources from `docker-compose.yml` + docker compose up --detach --wait --remove-orphans + +# Apply migrations, then start the requested Compose profiles. +[group('compose')] +compose-up *profiles: _touch-docker-env _ensure_db_migrated docker compose {{ prepend("--profile ", profiles) }} up --build -d --wait --remove-orphans -# Launch web server in the background +# Start the web-server Compose profile. [group('compose')] -compose-up-web: - just compose-up web +compose-up-web: (compose-up "web") -# Launch two build servers in the background -[group('builder')] +# Start the Compose profile containing two build servers. [group('compose')] -compose-up-builder: - just compose-up builder +compose-up-builder: (compose-up "builder") -# Launch registry watcher in the background +# Start the registry-watcher Compose profile. [group('compose')] [group('watcher')] -compose-up-watcher: - just compose-up watcher +compose-up-watcher: (compose-up "watcher") -# Launch metrics collector in the background +# Start the OpenTelemetry metrics Compose profile. [group('compose')] -compose-up-metrics: - just compose-up metrics +compose-up-metrics: (compose-up "metrics") -# Launch everything, all at once, in the background +# Start every application Compose profile. [group('compose')] -compose-up-full: - just compose-up full +compose-up-full: (compose-up "full") -# Shutdown docker services, keep containers & volumes alive. +# Stop Compose services while retaining local images and volumes. [group('compose')] compose-down: docker compose --profile full --profile manual down --remove-orphans -# Shutdown docker services, then clean up docker images, volumes & other local artifacts from this docker-compose project +# Remove Compose services, images, volumes, and generated local artifacts. [group('compose')] compose-down-and-wipe: #!/usr/bin/env bash @@ -43,11 +43,11 @@ compose-down-and-wipe: docker compose --profile full --profile manual down --volumes --remove-orphans --rmi local - # When testing this in CI, I had permission issues when trying to remove this folder. - # Likely it's related to the docker container runnning as a different (root?) user, so - # these files in the `ignored/` folder belong to `root`. + # When testing this in CI, I had permission issues when trying to remove this folder. + # Likely it's related to the docker container runnning as a different (root?) user, so + # these files in the `ignored/` folder belong to `root`. - # so we just try if we can use passwordless `sudo`: + # so we just try if we can use passwordless `sudo`: if sudo -n true 2>/dev/null; then echo "deleting ignored/ folder with sudo" sudo -n rm -rf ignored/ @@ -58,7 +58,15 @@ compose-down-and-wipe: mkdir -p ignored -# stream logs from all services running in docker-compose. Optionally specify services to tail logs from. +# Follow logs from all Compose services or the specified services. [group('compose')] compose-logs *services: docker compose --profile full logs -f {{ services }} + +# Run a command in a one-off Compose service container. +[group('cli')] +[group('compose')] +docker-run service_name *args: compose-up-resources + # `docker compose run` ignores service dependencies, so the recipe starts + # the database and object storage explicitly before reaching this point. + docker compose run --build --rm {{ service_name }} {{ args }} diff --git a/justfiles/sqlx.just b/justfiles/sqlx.just new file mode 100644 index 0000000000..002aa5c48b --- /dev/null +++ b/justfiles/sqlx.just @@ -0,0 +1,38 @@ +_ensure_sqlx_cli_installed: (_ensure_cargo_installed "sqlx-cli" "sqlx") + +# Regenerate SQLx offline metadata for the workspace. +[group('sqlx')] +sqlx-prepare *args: _ensure_sqlx_cli_installed compose-up-resources + # sqlx prepare needs `--workspace` twice: + # https://github.com/transact-rs/sqlx/issues/3362 + # once for the sqlx-cli, once for the inner `cargo check` command. + + cargo sqlx prepare \ + --database-url $DOCSRS_DATABASE_URL \ + --workspace \ + {{ args }} \ + -- --workspace --all-targets --all-features + +# Check that committed SQLx offline metadata is current. +[group('sqlx')] +sqlx-check: (sqlx-prepare "--check") + +# Apply migrations and regenerate SQLx offline metadata. +[group('sqlx')] +sqlx-update: sqlx-migrate-run sqlx-prepare + +# Apply all pending SQLx migrations to the local database. +[group('sqlx')] +sqlx-migrate-run: _ensure_sqlx_cli_installed compose-up-resources + cargo sqlx migrate run \ + --database-url $DOCSRS_DATABASE_URL \ + --source ./crates/lib/docs_rs_database/migrations + +# Revert SQLx migrations down to a target version (defaults to zero). +[group('sqlx')] +sqlx-migrate-revert target="0": _ensure_sqlx_cli_installed compose-up-resources + # --target 0 means "revert everything" + cargo sqlx migrate revert \ + --database-url $DOCSRS_DATABASE_URL \ + --source ./crates/lib/docs_rs_database/migrations \ + --target-version {{ target }} diff --git a/justfiles/testing.just b/justfiles/testing.just index 3ac67a8c80..df69d0f0d5 100644 --- a/justfiles/testing.just +++ b/justfiles/testing.just @@ -1,5 +1,6 @@ # just commands for CI & local development +# Benchmark a rustdoc page with ApacheBench. [group('testing')] bench-rustdoc-page host="http://127.0.0.1:8888": rm -rf ignored/cratesfyi-prefix/archive_cache/* @@ -8,220 +9,61 @@ bench-rustdoc-page host="http://127.0.0.1:8888": -c 500 \ {{ host }}/rayon/1.11.0/rayon/ -# update sqlx metadata offline mode, for all -# crates that have it. -[group('sqlx')] +# Build the crate fixtures required by the GUI test suite. [group('testing')] -sqlx-prepare *args: _ensure_db_and_s3_are_running - # sqlx prepare needs `--workspace` twice: - # https://github.com/transact-rs/sqlx/issues/3362 - # once for the sqlx-cli, once for the inner `cargo check` command. +prepare-gui-tests: _ensure_db_migrated + just _builder build update-toolchain + just _builder build crate sysinfo 0.23.4 + just _builder build crate sysinfo 0.23.5 + just _builder build crate libtest 0.0.1 + just _builder build crate zbus 5.15.0 + just _builder build add-essential-files - cargo sqlx prepare \ - --database-url $DOCSRS_DATABASE_URL \ - --workspace \ - {{ args }} \ - -- --workspace --all-targets --all-features - -[group('sqlx')] -[group('testing')] -sqlx-check: - just sqlx-prepare --check - -[group('sqlx')] -[group('testing')] -sqlx-migrate-run: _ensure_db_and_s3_are_running - cargo sqlx migrate run \ - --database-url $DOCSRS_DATABASE_URL \ - --source ./crates/lib/docs_rs_database/migrations - -[group('sqlx')] -[group('testing')] -sqlx-migrate-revert target="0": _ensure_db_and_s3_are_running - # --target 0 means "revert everything" - cargo sqlx migrate revert \ - --database-url $DOCSRS_DATABASE_URL \ - --source ./crates/lib/docs_rs_database/migrations \ - --target-version {{ target }} - -_format_justfile justfile: - #!/usr/bin/env bash - set -euo pipefail - - echo "formatting {{ justfile }}.." - # like this we get both the non-zero exit code, and the local code is - # formatted. - if ! just --fmt --justfile "{{ justfile }}" --check >/dev/null; then - just --fmt --justfile "{{ justfile }}" - exit 1 - fi - -_format_markdown mdfile: - #!/usr/bin/env bash - set -euo pipefail - - echo "formatting {{ mdfile }}.." - # like this we get both the non-zero exit code, and the local code is - # formatted. - if ! deno fmt --quiet --check "{{ mdfile }}" >/dev/null; then - deno fmt "{{ mdfile }}" - exit 1 - fi - -# format rust code -[group('testing')] -format-rust: - #!/usr/bin/env bash - set -euo pipefail - - echo "running cargo fmt" - rustup component add rustfmt - if ! cargo fmt --all -- --check >/dev/null; then - echo "rust files weren't formatted..." >&2 - cargo fmt --all - exit 1 - fi - -# run all formatters, continue after error -[group('testing')] -format: - #!/usr/bin/env bash - set -euo pipefail - - exit_code=0 - - just format-rust || exit_code=1 - just format-just || exit_code=1 - just format-markdown || exit_code=1 - just format-cargo-toml || exit_code=1 - - exit "$exit_code" - -# format all justfiles +# Run browser assertions against an existing web server on localhost:3000. [group('testing')] -format-just: - fd \ - --type file \ - --threads 1 \ - '^(Justfile|.+\.just)$' . \ - --exec just _format_justfile {} || exit_code=1 +run-gui-browser-tests: + npm install --loglevel verbose + npx --no-install puppeteer browsers install chrome + node ./gui-tests/tester.js -# format all markdown files we maintain +# Run GUI tests with the web server on the host, reusing existing fixtures. [group('testing')] -format-markdown: - fd \ - --type file \ - --threads 1 \ - --extension md \ - --exclude 'crates/lib/font-awesome-as-a-crate/' \ - --exclude 'crates/bin/docs_rs_web/assets/syntaxes/' \ - --exclude 'crates/bin/docs_rs_web/static/' \ - --exec just _format_markdown {} || exit_code=1 - -# run clippy, in our config -[group('testing')] -clippy *args: - rustup component add clippy - cargo clippy \ - --all-features \ - --all-targets \ - --workspace \ - --locked \ - {{ args }} \ - -- -D warnings - -# run clippy --fix -[group('testing')] -clippy-fix: - just clippy --fix --allow-dirty --allow-staged - -[group('testing')] -lint-rust: +run-gui-tests: _ensure_db_migrated #!/usr/bin/env bash set -euo pipefail - if [ "${GITHUB_ACTIONS:-}" = "true" ]; then - just clippy - else - just clippy-fix - fi + cargo build -p docs_rs_web -# run all linters, for local development & CI -[group('testing')] -lint: lint-rust lint-actions lint-js lint-dependencies-machete + web_pid="" -# validate GitHub Actions workflows -[group('testing')] -lint-actions: - @command -v actionlint >/dev/null || { echo "warning: actionlint not installed, skipping"; exit 0; } - actionlint -ignore SC2086 + cleanup() { + if [ -n "$web_pid" ]; then + kill -KILL "$web_pid" 2>/dev/null || true + wait "$web_pid" 2>/dev/null || true + fi + } + trap cleanup EXIT INT TERM -[group('testing')] -format-cargo-toml *args: - #!/usr/bin/env bash - set -euo pipefail + cargo run -p docs_rs_web & + web_pid=$! - if [ {{ semver_matches(trim_start_match(shell("cargo-sort --version"), "cargo-sort "), ">=2.1.3") }} != 'true' ]; then - echo "cargo-sort to old, must be >=2.1.3" - exit 1; - fi + # Fail instead of waiting forever if the server fails to start. + for _ in {1..100}; do + if curl --silent --fail http://localhost:3000/ >/dev/null; then + break + fi + if ! kill -0 "$web_pid" 2>/dev/null; then + wait "$web_pid" + fi + sleep 0.2 + done - # like this we get both the non-zero exit code, and the local code is - # formatted. - if ! cargo sort --workspace --check {{ args }} >/dev/null; then - cargo sort --workspace {{ args }} - exit 1 - fi + curl --silent --fail http://localhost:3000/ >/dev/null + just run-gui-browser-tests +# Run GUI tests against the packaged web-server Compose service. [group('testing')] -lint-dependencies-machete: - #!/usr/bin/env bash - set -euo pipefail - - # check unused deps with cargo machete is fast, - # but has many false positives. - # While it can also recurse into subdirs, it would - # also stumble onto our broken crates in `/tests/crates/*`, - # where I also don't want to add machete-metadata. - fd \ - --glob 'Cargo.toml' \ - --type file \ - --exclude tests \ - -X cargo machete {} - -[group('testing')] -lint-dependencies-udeps: - #!/usr/bin/env bash - set -euo pipefail - - # check unused deps with cargo udeps. - # Optional, since udeps is much slower because it - # needs to additionally compile the workspace with nightly - echo "check for unused normal dependencies" - cargo +nightly udeps --workspace - - echo "check for unused dev dependencies" - cargo +nightly udeps --workspace --all-targets - -[group('testing')] -lint-js *args: - deno run -A npm:eslint@9 \ - crates/bin/docs_rs_web/static \ - crates/bin/docs_rs_web/templates \ - eslint.config.js \ - gui-tests \ - {{ args }} - -[group('testing')] -run-gui-tests: _ensure_db_and_s3_are_running cli-db-migrate compose-up-web - just cli-build-update-toolchain - just cli-build-crate sysinfo 0.23.4 - just cli-build-crate sysinfo 0.23.5 - just cli-build-crate libtest 0.0.1 - just cli-build-crate zbus 5.15.0 - just cli-build-add-essential-files - - just _cli gui_tests +run-gui-tests-e2e: compose-up-web run-gui-browser-tests _build-test-binaries: #!/usr/bin/env bash @@ -230,8 +72,9 @@ _build-test-binaries: export SQLX_OFFLINE=1 cargo test --no-run --workspace --locked +# Build and run the complete Rust workspace test suite. [group('testing')] -run-tests: _ensure_db_and_s3_are_running _build-test-binaries +run-tests: compose-up-resources _build-test-binaries #!/usr/bin/env bash set -euo pipefail @@ -246,9 +89,9 @@ run-tests: _ensure_db_and_s3_are_running _build-test-binaries cargo test --workspace --locked --no-fail-fast -[group('builder')] +# Run ignored builder integration tests serially. [group('testing')] -run-builder-tests: _ensure_db_and_s3_are_running +run-builder-tests: compose-up-resources #!/usr/bin/env bash set -euo pipefail @@ -259,3 +102,12 @@ run-builder-tests: _ensure_db_and_s3_are_running export DOCSRS_PREFIX=ignored/cratesfyi-prefix cargo test --locked -- --ignored --test-threads=1 + +# Test migrations with both SQLx CLI and docs_rs_admin. +[group('testing')] +test-database-migrations: + just sqlx-migrate-run + just sqlx-check + just sqlx-migrate-revert + just cli-db-migrate + just cli-db-migrate 0 diff --git a/justfiles/utils.just b/justfiles/utils.just index db9458e2cc..ec97342405 100644 --- a/justfiles/utils.just +++ b/justfiles/utils.just @@ -1,32 +1,44 @@ - -_ensure_db_and_s3_are_running: _touch-docker-env - # dependencies in the docker-cli file are ignored - # here. Instead we explicitly start any dependent services first. - docker compose up -d db s3 --wait - _touch-docker-env: touch .docker.env + touch .env -# helper recipe to ensure a CLI tool is installed. -# * Accepts multiple names +# Helper recipe to ensure a Cargo CLI tool is installed. +# The executable name defaults to the package name, but can be overridden for +# packages such as `sqlx-cli`, which installs an executable named `sqlx`. # * uses `cargo binstall` if it exists. # # example usage: # ``` -# _ensure_mdbook_installed: (_ensure_cargo_installed "mdbook" "mdbook-linkcheck2") +# _ensure_sqlx_cli_installed: (_ensure_cargo_installed "sqlx-cli" "sqlx") # ``` -_ensure_cargo_installed *packages: +_ensure_cargo_installed package binary=package: #!/usr/bin/env bash set -euo pipefail - for package in {{ packages }} ; do - if command -v "$package" >/dev/null 2>&1; then - continue - fi + if command -v "{{ binary }}" >/dev/null 2>&1; then + exit 0 + fi + + if command -v cargo-binstall >/dev/null 2>&1; then + cargo binstall -y "{{ package }}" + else + cargo install "{{ package }}" + fi + +_ensure_db_migrated: + #!/usr/bin/env bash + set -euo pipefail - if command -v cargo-binstall >/dev/null 2>&1; then - cargo binstall -y "$package" - else - cargo install "$package" - fi - done + case "$DOCSRS_CLI_MODE" in + local) + just sqlx-migrate-run + ;; + docker) + just cli-db-migrate + ;; + *) + echo "Invalid CLI mode: $DOCSRS_CLI_MODE" >&2 + echo "Expected one of: local, docker" >&2 + exit 2 + ;; + esac diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000000..18c3bf6bb8 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,400 @@ +{ + "name": "deps", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "deps", + "dependencies": { + "browser-ui-test": "^0.25.0" + } + }, + "node_modules/@puppeteer/browsers": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/@puppeteer/browsers/-/browsers-3.2.1.tgz", + "integrity": "sha512-KDz+3qDRdBAlRlMjmKyj6dEs33YHTk/xRHEENSXq6TNnhgoU15ruSHtEBeVF6OZ9tBDY55Se4P0nFMNsipzU9A==", + "license": "Apache-2.0", + "dependencies": { + "modern-tar": "^0.8.0", + "yargs": "^18.0.0" + }, + "bin": { + "browsers": "lib/main-cli.js" + }, + "engines": { + "node": ">=22.12.0" + }, + "peerDependencies": { + "proxy-agent": ">=8.0.1", + "yauzl": "^2.10.0 || ^3.4.0" + }, + "peerDependenciesMeta": { + "proxy-agent": { + "optional": true + }, + "yauzl": { + "optional": true + } + } + }, + "node_modules/ansi-regex": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.3.0.tgz", + "integrity": "sha512-WpDfL7NO6j7tH88IDBNVdUJxDh9nmCteAVW9dsep846XdwF4naCBK+/tGLX3KJgcpgMRXCFlTM2hKGoK9FsdrQ==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/ansi-styles": { + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", + "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/browser-ui-test": { + "version": "0.25.1", + "resolved": "https://registry.npmjs.org/browser-ui-test/-/browser-ui-test-0.25.1.tgz", + "integrity": "sha512-woRwKU1dPBIwYmCI6npox8qlPO0WQ8GZH2YbL39mNkiWymByebiB4EK0PlaGMbmEja0MEqfMQD+d33LCW4S2AA==", + "license": "MIT", + "dependencies": { + "css-unit-converter": "^1.1.2", + "pngjs": "^3.4.0", + "puppeteer": "^25.1.0", + "readline-sync": "^1.4.10" + }, + "bin": { + "browser-ui-test": "src/index.js" + } + }, + "node_modules/chromium-bidi": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/chromium-bidi/-/chromium-bidi-17.0.2.tgz", + "integrity": "sha512-5v9GQFhTktFvotn/OFNJBmKLKRAb6n9r0bVCwf7sHgWc3/JryK0bj1nn93L3pHFrfgcsu6Be6EWsDi+1XHTGDg==", + "license": "Apache-2.0", + "dependencies": { + "mitt": "^3.0.1", + "zod": "^3.24.1" + }, + "engines": { + "node": ">=20.19.0 <22.0.0 || >=22.12.0" + }, + "peerDependencies": { + "devtools-protocol": "*" + } + }, + "node_modules/cliui": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-9.0.1.tgz", + "integrity": "sha512-k7ndgKhwoQveBL+/1tqGJYNz097I7WOvwbmmU2AR5+magtbjPWQTS1C5vzGkBC8Ym8UWRzfKUzUUqFLypY4Q+w==", + "license": "ISC", + "dependencies": { + "string-width": "^7.2.0", + "strip-ansi": "^7.1.0", + "wrap-ansi": "^9.0.0" + }, + "engines": { + "node": ">=20" + } + }, + "node_modules/cliui/node_modules/string-width": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", + "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", + "license": "MIT", + "dependencies": { + "emoji-regex": "^10.3.0", + "get-east-asian-width": "^1.0.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/css-unit-converter": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/css-unit-converter/-/css-unit-converter-1.1.2.tgz", + "integrity": "sha512-IiJwMC8rdZE0+xiEZHeru6YoONC4rfPMqGm2W85jMIbkFvv5nFTwJVFHam2eFrN6txmoUYFAFXiv8ICVeTO0MA==", + "license": "MIT" + }, + "node_modules/devtools-protocol": { + "version": "0.0.1666840", + "resolved": "https://registry.npmjs.org/devtools-protocol/-/devtools-protocol-0.0.1666840.tgz", + "integrity": "sha512-gCcO42XCHKEs7Ag0S7aGYsnJ7hlgrO3qderYqeiY0Eqk+0GFfuvT13IA0hHreJTa2KCdDVyGMeOhdMNmrrTjVg==", + "license": "BSD-3-Clause" + }, + "node_modules/emoji-regex": { + "version": "10.6.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.6.0.tgz", + "integrity": "sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A==", + "license": "MIT" + }, + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "license": "ISC", + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/get-east-asian-width": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/get-east-asian-width/-/get-east-asian-width-1.6.0.tgz", + "integrity": "sha512-QRbvDIbx6YklUe6RxeTeleMR0yv3cYH6PsPZHcnVn7xv7zO1BHN8r0XETu8n6Ye3Q+ahtSarc3WgtNWmehIBfA==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lilconfig": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.3.tgz", + "integrity": "sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw==", + "license": "MIT", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/antonk52" + } + }, + "node_modules/mitt": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/mitt/-/mitt-3.0.1.tgz", + "integrity": "sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw==", + "license": "MIT" + }, + "node_modules/modern-tar": { + "version": "0.8.4", + "resolved": "https://registry.npmjs.org/modern-tar/-/modern-tar-0.8.4.tgz", + "integrity": "sha512-gN54ddmyzEg10orwZ2u4OOv+bjpMWdIl5jIkodK97bMq8QBSL5c0D7YX0lT1Ooz+99S7+PvFbnxzdjgHo1r41g==", + "license": "MIT", + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/pngjs": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/pngjs/-/pngjs-3.4.0.tgz", + "integrity": "sha512-NCrCHhWmnQklfH4MtJMRjZ2a8c80qXeMlQMv2uVp9ISJMTt562SbGd6n2oq0PaPgKm7Z6pL9E2UlLIhC+SHL3w==", + "license": "MIT", + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/puppeteer": { + "version": "25.8.0", + "resolved": "https://registry.npmjs.org/puppeteer/-/puppeteer-25.8.0.tgz", + "integrity": "sha512-3gcUJ+Jfodb5zNa/lWLZukBUwYiRIwAc8WRICoqfi+ZYmNWqpsPFyanTU3Gw/lhgII9aotVbAmhT6/NKHWgyUA==", + "hasInstallScript": true, + "license": "Apache-2.0", + "dependencies": { + "@puppeteer/browsers": "3.2.1", + "chromium-bidi": "17.0.2", + "devtools-protocol": "0.0.1666840", + "lilconfig": "^3.1.3", + "puppeteer-core": "25.8.0", + "typed-query-selector": "^2.12.2" + }, + "bin": { + "puppeteer": "lib/puppeteer/node/cli.js" + }, + "engines": { + "node": ">=22.12.0" + } + }, + "node_modules/puppeteer-core": { + "version": "25.8.0", + "resolved": "https://registry.npmjs.org/puppeteer-core/-/puppeteer-core-25.8.0.tgz", + "integrity": "sha512-LDOrawV8vfCVk+yLj2ozvajNP4Sv3OV9y3Tpiyy2g2Z+aQlbcozP6KJfI4iSBq7YQER+86ihEtPa5ioiZyWxMQ==", + "license": "Apache-2.0", + "dependencies": { + "@puppeteer/browsers": "3.2.1", + "chromium-bidi": "17.0.2", + "devtools-protocol": "0.0.1666840", + "typed-query-selector": "^2.12.2", + "webdriver-bidi-protocol": "0.4.2", + "ws": "^8.21.1" + }, + "engines": { + "node": ">=22.12.0" + } + }, + "node_modules/readline-sync": { + "version": "1.4.10", + "resolved": "https://registry.npmjs.org/readline-sync/-/readline-sync-1.4.10.tgz", + "integrity": "sha512-gNva8/6UAe8QYepIQH/jQ2qn91Qj0B9sYjMBBs3QOB8F2CXcKgLxQaJRP76sWVRQt+QU+8fAkCbCvjjMFu7Ycw==", + "license": "MIT", + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/string-width": { + "version": "8.2.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-8.2.2.tgz", + "integrity": "sha512-GaPUh5gfdrYzqeVNZvUfT23vYYxXzKYidUcnMtJg/3rxRV63EFZy3k6xfKlmfeJD0176lnUV/Usr3XcwSvFzpg==", + "license": "MIT", + "dependencies": { + "get-east-asian-width": "^1.5.0", + "strip-ansi": "^7.1.2" + }, + "engines": { + "node": ">=20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/strip-ansi": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.2.0.tgz", + "integrity": "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.2.2" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/typed-query-selector": { + "version": "2.12.2", + "resolved": "https://registry.npmjs.org/typed-query-selector/-/typed-query-selector-2.12.2.tgz", + "integrity": "sha512-EOPFbyIub4ngnEdqi2yOcNeDLaX/0jcE1JoAXQDDMIthap7FoN795lc/SHfIq2d416VufXpM8z/lD+WRm2gfOQ==", + "license": "MIT" + }, + "node_modules/webdriver-bidi-protocol": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/webdriver-bidi-protocol/-/webdriver-bidi-protocol-0.4.2.tgz", + "integrity": "sha512-VSV+fzfChirL3e7jay2yUC7B4HQCGtEWEg/MSSQbK+qWbqeGlRLlXTzPpYr3XGUvbpDHumWZBJxgesg4N7dbtA==", + "license": "Apache-2.0" + }, + "node_modules/wrap-ansi": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.2.tgz", + "integrity": "sha512-42AtmgqjV+X1VpdOfyTGOYRi0/zsoLqtXQckTmqTeybT+BDIbM/Guxo7x3pE2vtpr1ok6xRqM9OpBe+Jyoqyww==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^6.2.1", + "string-width": "^7.0.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi/node_modules/string-width": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", + "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", + "license": "MIT", + "dependencies": { + "emoji-regex": "^10.3.0", + "get-east-asian-width": "^1.0.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ws": { + "version": "8.21.3", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.21.3.tgz", + "integrity": "sha512-201TZ/kPWxoPr/OKWjquZR1SWKXcvxdH+e1xrx89b3YbmzLMFCLfnaG1HFIgWzJOEWZ7MvpK++odZufgYR50Rw==", + "license": "MIT", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "license": "ISC", + "engines": { + "node": ">=10" + } + }, + "node_modules/yargs": { + "version": "18.1.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-18.1.0.tgz", + "integrity": "sha512-2rAgRKu54VsHkqI0/tYkmluGXHD4KW7yZoycuqDQ15QOTnc2VVfy0nN/1eMhnQLO00A+dwtK20xuCnc1YGeUyg==", + "license": "MIT", + "dependencies": { + "cliui": "^9.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "string-width": "^8.2.1", + "y18n": "^5.0.5", + "yargs-parser": "^22.0.0" + }, + "engines": { + "node": "^20.19.0 || ^22.12.0 || >=23" + } + }, + "node_modules/yargs-parser": { + "version": "22.0.0", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-22.0.0.tgz", + "integrity": "sha512-rwu/ClNdSMpkSrUb+d6BRsSkLUq1fmfsY6TOpYzTwvwkg1/NRG85KBy3kq++A8LKQwX6lsu+aWad+2khvuXrqw==", + "license": "ISC", + "engines": { + "node": "^20.19.0 || ^22.12.0 || >=23" + } + }, + "node_modules/zod": { + "version": "3.25.76", + "resolved": "https://registry.npmjs.org/zod/-/zod-3.25.76.tgz", + "integrity": "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } + } + } +} From 8b8282483401ab5d89938da13984d2886f5d464c Mon Sep 17 00:00:00 2001 From: Denis Cornehl Date: Mon, 31 Aug 2026 11:43:48 +0200 Subject: [PATCH 2/3] remove package-lock.json --- package-lock.json | 400 ---------------------------------------------- 1 file changed, 400 deletions(-) delete mode 100644 package-lock.json diff --git a/package-lock.json b/package-lock.json deleted file mode 100644 index 18c3bf6bb8..0000000000 --- a/package-lock.json +++ /dev/null @@ -1,400 +0,0 @@ -{ - "name": "deps", - "lockfileVersion": 3, - "requires": true, - "packages": { - "": { - "name": "deps", - "dependencies": { - "browser-ui-test": "^0.25.0" - } - }, - "node_modules/@puppeteer/browsers": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/@puppeteer/browsers/-/browsers-3.2.1.tgz", - "integrity": "sha512-KDz+3qDRdBAlRlMjmKyj6dEs33YHTk/xRHEENSXq6TNnhgoU15ruSHtEBeVF6OZ9tBDY55Se4P0nFMNsipzU9A==", - "license": "Apache-2.0", - "dependencies": { - "modern-tar": "^0.8.0", - "yargs": "^18.0.0" - }, - "bin": { - "browsers": "lib/main-cli.js" - }, - "engines": { - "node": ">=22.12.0" - }, - "peerDependencies": { - "proxy-agent": ">=8.0.1", - "yauzl": "^2.10.0 || ^3.4.0" - }, - "peerDependenciesMeta": { - "proxy-agent": { - "optional": true - }, - "yauzl": { - "optional": true - } - } - }, - "node_modules/ansi-regex": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.3.0.tgz", - "integrity": "sha512-WpDfL7NO6j7tH88IDBNVdUJxDh9nmCteAVW9dsep846XdwF4naCBK+/tGLX3KJgcpgMRXCFlTM2hKGoK9FsdrQ==", - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" - } - }, - "node_modules/ansi-styles": { - "version": "6.2.3", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", - "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/browser-ui-test": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/browser-ui-test/-/browser-ui-test-0.25.1.tgz", - "integrity": "sha512-woRwKU1dPBIwYmCI6npox8qlPO0WQ8GZH2YbL39mNkiWymByebiB4EK0PlaGMbmEja0MEqfMQD+d33LCW4S2AA==", - "license": "MIT", - "dependencies": { - "css-unit-converter": "^1.1.2", - "pngjs": "^3.4.0", - "puppeteer": "^25.1.0", - "readline-sync": "^1.4.10" - }, - "bin": { - "browser-ui-test": "src/index.js" - } - }, - "node_modules/chromium-bidi": { - "version": "17.0.2", - "resolved": "https://registry.npmjs.org/chromium-bidi/-/chromium-bidi-17.0.2.tgz", - "integrity": "sha512-5v9GQFhTktFvotn/OFNJBmKLKRAb6n9r0bVCwf7sHgWc3/JryK0bj1nn93L3pHFrfgcsu6Be6EWsDi+1XHTGDg==", - "license": "Apache-2.0", - "dependencies": { - "mitt": "^3.0.1", - "zod": "^3.24.1" - }, - "engines": { - "node": ">=20.19.0 <22.0.0 || >=22.12.0" - }, - "peerDependencies": { - "devtools-protocol": "*" - } - }, - "node_modules/cliui": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-9.0.1.tgz", - "integrity": "sha512-k7ndgKhwoQveBL+/1tqGJYNz097I7WOvwbmmU2AR5+magtbjPWQTS1C5vzGkBC8Ym8UWRzfKUzUUqFLypY4Q+w==", - "license": "ISC", - "dependencies": { - "string-width": "^7.2.0", - "strip-ansi": "^7.1.0", - "wrap-ansi": "^9.0.0" - }, - "engines": { - "node": ">=20" - } - }, - "node_modules/cliui/node_modules/string-width": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", - "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", - "license": "MIT", - "dependencies": { - "emoji-regex": "^10.3.0", - "get-east-asian-width": "^1.0.0", - "strip-ansi": "^7.1.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/css-unit-converter": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/css-unit-converter/-/css-unit-converter-1.1.2.tgz", - "integrity": "sha512-IiJwMC8rdZE0+xiEZHeru6YoONC4rfPMqGm2W85jMIbkFvv5nFTwJVFHam2eFrN6txmoUYFAFXiv8ICVeTO0MA==", - "license": "MIT" - }, - "node_modules/devtools-protocol": { - "version": "0.0.1666840", - "resolved": "https://registry.npmjs.org/devtools-protocol/-/devtools-protocol-0.0.1666840.tgz", - "integrity": "sha512-gCcO42XCHKEs7Ag0S7aGYsnJ7hlgrO3qderYqeiY0Eqk+0GFfuvT13IA0hHreJTa2KCdDVyGMeOhdMNmrrTjVg==", - "license": "BSD-3-Clause" - }, - "node_modules/emoji-regex": { - "version": "10.6.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.6.0.tgz", - "integrity": "sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A==", - "license": "MIT" - }, - "node_modules/escalade": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", - "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/get-caller-file": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "license": "ISC", - "engines": { - "node": "6.* || 8.* || >= 10.*" - } - }, - "node_modules/get-east-asian-width": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/get-east-asian-width/-/get-east-asian-width-1.6.0.tgz", - "integrity": "sha512-QRbvDIbx6YklUe6RxeTeleMR0yv3cYH6PsPZHcnVn7xv7zO1BHN8r0XETu8n6Ye3Q+ahtSarc3WgtNWmehIBfA==", - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/lilconfig": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.3.tgz", - "integrity": "sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw==", - "license": "MIT", - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/antonk52" - } - }, - "node_modules/mitt": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/mitt/-/mitt-3.0.1.tgz", - "integrity": "sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw==", - "license": "MIT" - }, - "node_modules/modern-tar": { - "version": "0.8.4", - "resolved": "https://registry.npmjs.org/modern-tar/-/modern-tar-0.8.4.tgz", - "integrity": "sha512-gN54ddmyzEg10orwZ2u4OOv+bjpMWdIl5jIkodK97bMq8QBSL5c0D7YX0lT1Ooz+99S7+PvFbnxzdjgHo1r41g==", - "license": "MIT", - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/pngjs": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/pngjs/-/pngjs-3.4.0.tgz", - "integrity": "sha512-NCrCHhWmnQklfH4MtJMRjZ2a8c80qXeMlQMv2uVp9ISJMTt562SbGd6n2oq0PaPgKm7Z6pL9E2UlLIhC+SHL3w==", - "license": "MIT", - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/puppeteer": { - "version": "25.8.0", - "resolved": "https://registry.npmjs.org/puppeteer/-/puppeteer-25.8.0.tgz", - "integrity": "sha512-3gcUJ+Jfodb5zNa/lWLZukBUwYiRIwAc8WRICoqfi+ZYmNWqpsPFyanTU3Gw/lhgII9aotVbAmhT6/NKHWgyUA==", - "hasInstallScript": true, - "license": "Apache-2.0", - "dependencies": { - "@puppeteer/browsers": "3.2.1", - "chromium-bidi": "17.0.2", - "devtools-protocol": "0.0.1666840", - "lilconfig": "^3.1.3", - "puppeteer-core": "25.8.0", - "typed-query-selector": "^2.12.2" - }, - "bin": { - "puppeteer": "lib/puppeteer/node/cli.js" - }, - "engines": { - "node": ">=22.12.0" - } - }, - "node_modules/puppeteer-core": { - "version": "25.8.0", - "resolved": "https://registry.npmjs.org/puppeteer-core/-/puppeteer-core-25.8.0.tgz", - "integrity": "sha512-LDOrawV8vfCVk+yLj2ozvajNP4Sv3OV9y3Tpiyy2g2Z+aQlbcozP6KJfI4iSBq7YQER+86ihEtPa5ioiZyWxMQ==", - "license": "Apache-2.0", - "dependencies": { - "@puppeteer/browsers": "3.2.1", - "chromium-bidi": "17.0.2", - "devtools-protocol": "0.0.1666840", - "typed-query-selector": "^2.12.2", - "webdriver-bidi-protocol": "0.4.2", - "ws": "^8.21.1" - }, - "engines": { - "node": ">=22.12.0" - } - }, - "node_modules/readline-sync": { - "version": "1.4.10", - "resolved": "https://registry.npmjs.org/readline-sync/-/readline-sync-1.4.10.tgz", - "integrity": "sha512-gNva8/6UAe8QYepIQH/jQ2qn91Qj0B9sYjMBBs3QOB8F2CXcKgLxQaJRP76sWVRQt+QU+8fAkCbCvjjMFu7Ycw==", - "license": "MIT", - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/string-width": { - "version": "8.2.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-8.2.2.tgz", - "integrity": "sha512-GaPUh5gfdrYzqeVNZvUfT23vYYxXzKYidUcnMtJg/3rxRV63EFZy3k6xfKlmfeJD0176lnUV/Usr3XcwSvFzpg==", - "license": "MIT", - "dependencies": { - "get-east-asian-width": "^1.5.0", - "strip-ansi": "^7.1.2" - }, - "engines": { - "node": ">=20" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/strip-ansi": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.2.0.tgz", - "integrity": "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==", - "license": "MIT", - "dependencies": { - "ansi-regex": "^6.2.2" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" - } - }, - "node_modules/typed-query-selector": { - "version": "2.12.2", - "resolved": "https://registry.npmjs.org/typed-query-selector/-/typed-query-selector-2.12.2.tgz", - "integrity": "sha512-EOPFbyIub4ngnEdqi2yOcNeDLaX/0jcE1JoAXQDDMIthap7FoN795lc/SHfIq2d416VufXpM8z/lD+WRm2gfOQ==", - "license": "MIT" - }, - "node_modules/webdriver-bidi-protocol": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/webdriver-bidi-protocol/-/webdriver-bidi-protocol-0.4.2.tgz", - "integrity": "sha512-VSV+fzfChirL3e7jay2yUC7B4HQCGtEWEg/MSSQbK+qWbqeGlRLlXTzPpYr3XGUvbpDHumWZBJxgesg4N7dbtA==", - "license": "Apache-2.0" - }, - "node_modules/wrap-ansi": { - "version": "9.0.2", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.2.tgz", - "integrity": "sha512-42AtmgqjV+X1VpdOfyTGOYRi0/zsoLqtXQckTmqTeybT+BDIbM/Guxo7x3pE2vtpr1ok6xRqM9OpBe+Jyoqyww==", - "license": "MIT", - "dependencies": { - "ansi-styles": "^6.2.1", - "string-width": "^7.0.0", - "strip-ansi": "^7.1.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/wrap-ansi/node_modules/string-width": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", - "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", - "license": "MIT", - "dependencies": { - "emoji-regex": "^10.3.0", - "get-east-asian-width": "^1.0.0", - "strip-ansi": "^7.1.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/ws": { - "version": "8.21.3", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.21.3.tgz", - "integrity": "sha512-201TZ/kPWxoPr/OKWjquZR1SWKXcvxdH+e1xrx89b3YbmzLMFCLfnaG1HFIgWzJOEWZ7MvpK++odZufgYR50Rw==", - "license": "MIT", - "engines": { - "node": ">=10.0.0" - }, - "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": ">=5.0.2" - }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { - "optional": true - } - } - }, - "node_modules/y18n": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", - "license": "ISC", - "engines": { - "node": ">=10" - } - }, - "node_modules/yargs": { - "version": "18.1.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-18.1.0.tgz", - "integrity": "sha512-2rAgRKu54VsHkqI0/tYkmluGXHD4KW7yZoycuqDQ15QOTnc2VVfy0nN/1eMhnQLO00A+dwtK20xuCnc1YGeUyg==", - "license": "MIT", - "dependencies": { - "cliui": "^9.0.1", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "string-width": "^8.2.1", - "y18n": "^5.0.5", - "yargs-parser": "^22.0.0" - }, - "engines": { - "node": "^20.19.0 || ^22.12.0 || >=23" - } - }, - "node_modules/yargs-parser": { - "version": "22.0.0", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-22.0.0.tgz", - "integrity": "sha512-rwu/ClNdSMpkSrUb+d6BRsSkLUq1fmfsY6TOpYzTwvwkg1/NRG85KBy3kq++A8LKQwX6lsu+aWad+2khvuXrqw==", - "license": "ISC", - "engines": { - "node": "^20.19.0 || ^22.12.0 || >=23" - } - }, - "node_modules/zod": { - "version": "3.25.76", - "resolved": "https://registry.npmjs.org/zod/-/zod-3.25.76.tgz", - "integrity": "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==", - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/colinhacks" - } - } - } -} From f42c084ea88f537385db0ea51ddb97d73eff0649 Mon Sep 17 00:00:00 2001 From: Denis Cornehl Date: Mon, 31 Aug 2026 12:11:40 +0200 Subject: [PATCH 3/3] ci: remove setup-node npm cache --- .github/workflows/ci.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 79223bec4f..46d78d0cf9 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -97,7 +97,6 @@ jobs: - uses: actions/setup-node@v6 with: node-version: 24 - cache: npm - name: Run end-to-end GUI tests env: