chore: migrate to Aspect CLI AXL tasks on ephemeral GHA runners (#2858)
Migrate CI from Aspect Workflows (`.aspect/workflows/config.yaml`) to
the Aspect CLI on ephemeral GitHub Actions runners.
### Adds
- `.aspect/version.axl` — pins the Aspect CLI to `2026.21.44`.
- `.aspect/config.axl` — opts in to artifact uploads
(testlogs/profile/BEP), sets `--config=ci` in CI, registers an `aspect
buildifier` alias of `aspect format`.
- `.github/workflows/ci-workflows.yaml` — matrix `test` job on
(workspace × {Bazel 7, 8, 9, 9-no-execroot-entry-point}) plus single
`format` and `buildifier` jobs. Per-workspace exclusions match the
legacy config.
- `tools/format/BUILD.bazel` — `format` (multi-language) + `buildifier`
(Starlark-only) `format_multirun` targets.
- Root `//:format` and `//:buildifier` aliases into `//tools/format`.
- README note linking to the Aspect CLI docs / install.
- `rules_nodejs` bumped to 6.7.4 and `rules_go` pinned at 0.60.0 — older
versions reference the legacy global `CcInfo` removed in Bazel 9.
- `common:ci --lockfile_mode=off` (+ build-without-bytes flags) in each
e2e / examples sub-workspace `.bazelrc` so they don't trip the preset's
strict lockfile mode under `:ci` when run from their own workspace root.
### Removes / renames
- `.aspect/workflows/config.yaml` and `.aspect/workflows/bazelrc` —
bazelrc settings hoisted into root `.bazelrc` under `:ci` with
`--lockfile_mode=off` (lock is gitignored).
- `.github/workflows/ci.yaml` → `ci-vanilla-bazel.yaml` (kept as the
vanilla-bazel matrix).
- `.github/workflows/buildifier.yaml` (replaced by the `buildifier` job
in `ci-workflows.yaml`).
- Root `//:buildifier` / `//:buildifier.check` rules (moved into
`tools/format`).
### Notes
- Bazel 9 variants pin `9.0.2` rather than `9.x` until
[bazelbuild/bazel#29393](https://github.com/bazelbuild/bazel/issues/29393)
is fixed (carried over from the legacy config).
---
### Changes are visible to end-users: no
### Test plan
- CI on this PRdiff --git a/.aspect/config.axl b/.aspect/config.axl
new file mode 100644
index 0000000..2eeeab7
--- /dev/null
+++ b/.aspect/config.axl
@@ -0,0 +1,32 @@
+"""Aspect CLI configuration."""
+
+load("@aspect//feature/artifacts.axl", "ArtifactUpload")
+load("@aspect//format.axl", "format")
+load("@aspect//traits.axl", "BazelTrait")
+
+# `aspect buildifier` — alias of `aspect format` preset to the Starlark-only
+# formatter target. CI and local users can run `aspect buildifier` instead
+# of `aspect format --formatter-target=//tools/format:buildifier`.
+buildifier = format.alias(
+ defaults = {
+ "formatter_target": "//tools/format:buildifier",
+ },
+ summary = "Format Starlark files using buildifier.",
+)
+
+def config(ctx: ConfigContext):
+ is_ci = bool(ctx.std.env.var("CI"))
+
+ if is_ci:
+ ctx.traits[BazelTrait].extra_flags.extend([
+ "--config=ci",
+ ])
+
+ # Register the buildifier alias as a real CLI command.
+ ctx.tasks.add(buildifier)
+
+ # Enable artifact uploads for testlogs, profile, and BEP.
+ # upload_test_logs="failed" — only the logs from failing tests are useful.
+ ctx.features[ArtifactUpload].args.upload_test_logs = "failed"
+ ctx.features[ArtifactUpload].args.upload_profile = True
+ ctx.features[ArtifactUpload].args.upload_bep = True
diff --git a/.aspect/version.axl b/.aspect/version.axl
new file mode 100644
index 0000000..3710678
--- /dev/null
+++ b/.aspect/version.axl
@@ -0,0 +1 @@
+version("2026.21.44")
diff --git a/.aspect/workflows/bazelrc b/.aspect/workflows/bazelrc
deleted file mode 100644
index 51dae69..0000000
--- a/.aspect/workflows/bazelrc
+++ /dev/null
@@ -1,3 +0,0 @@
-# build without the bytes
-common --remote_download_outputs=minimal
-common --nobuild_runfile_links
diff --git a/.aspect/workflows/config.yaml b/.aspect/workflows/config.yaml
deleted file mode 100644
index c9f6d81..0000000
--- a/.aspect/workflows/config.yaml
+++ /dev/null
@@ -1,196 +0,0 @@
-# See https://docs.aspect.build/workflows/configuration
-workspaces:
- .:
- icon: js
- label: rules_js
- e2e/bzlmod:
- icon: bazel
- tasks: &e2e_tasks
- - test:
- queue: aspect-medium
- - format:
- without: true
- - buildifier:
- without: true
- e2e/git_dep_metadata:
- icon: npm
- tasks: *e2e_tasks
- e2e/gyp_no_install_script:
- icon: npm
- tasks: *e2e_tasks
- e2e/js_binary_workspace:
- icon: js
- tasks: *e2e_tasks
- e2e/js_image_oci:
- icon: linux
- tasks:
- - test:
- queue: aspect-medium
- - format:
- without: true
- - buildifier:
- without: true
- # The `llvm` module's hermetic toolchain requires Bazel 8+.
- - bazel-7:
- without: true
- e2e/nextjs:
- icon: nextjs
- tasks: *e2e_tasks
- # No test targets. Requires running test.sh.
- # e2e/js_run_devserver:
- e2e/npm_link_package:
- icon: npm
- tasks: *e2e_tasks
- e2e/npm_link_package-rerooted:
- icon: npm
- tasks: *e2e_tasks
- e2e/npm_translate_lock:
- icon: npm
- tasks: *e2e_tasks
- e2e/npm_translate_lock_replace_packages:
- icon: npm
- tasks: *e2e_tasks
- e2e/npm_translate_lock_empty:
- icon: npm
- tasks: *e2e_tasks
- e2e/npm_translate_lock_exclude_package_contents:
- icon: npm
- tasks: *e2e_tasks
- e2e/npm_translate_lock_multi:
- icon: npm
- tasks: *e2e_tasks
- e2e/npm_translate_lock_partial_clone:
- icon: npm
- tasks: *e2e_tasks
- # No test targets. Requires running test.sh.
- # e2e/npm_translate_lock_package_visibility:
- e2e/npm_translate_lock_subdir_patch:
- icon: npm
- tasks: *e2e_tasks
- # Requires an auth token
- # e2e/npm_translate_lock_auth:
- e2e/npm_translate_lock_disable_hooks:
- icon: npm
- tasks: *e2e_tasks
- # Requires an SSH token
- # e2e/npm_translate_lock_git+ssh:
- e2e/npm_translate_package_lock:
- icon: npm
- tasks: *e2e_tasks
- e2e/npm_translate_yarn_lock:
- icon: yarn
- tasks: *e2e_tasks
- e2e/patch_from_repo:
- icon: npm
- tasks:
- - test:
- queue: aspect-medium
- - format:
- without: true
- - buildifier:
- without: true
- # Has bazel7 specific absolute label in MODULE
- - bazel-8:
- without: true
- - bazel-9:
- without: true
- - bazel-9-no-execroot-entry-point:
- without: true
- e2e/pnpm_lockfiles:
- icon: pnpm
- tasks: *e2e_tasks
- e2e/pnpm_repo_install:
- icon: pnpm
- tasks: *e2e_tasks
- e2e/pnpm_workspace:
- icon: pnpm
- tasks: *e2e_tasks
- e2e/pnpm_workspace_deps:
- icon: pnpm
- tasks: *e2e_tasks
- e2e/pnpm_workspace_rerooted:
- icon: pnpm
- tasks: *e2e_tasks
- e2e/protobuf-es:
- icon: proto
- tasks: *e2e_tasks
- e2e/protobuf-google:
- icon: proto
- tasks: *e2e_tasks
- e2e/repo_mapping:
- icon: js
- tasks:
- - test:
- queue: aspect-medium
- - format:
- without: true
- - buildifier:
- without: true
- # aspect_rules_js is given a different name in this repo, so we
- # cannot use a flag beginning with --@aspect_rules_js//.
- - bazel-9-no-execroot-entry-point:
- without: true
- e2e/output_paths:
- icon: js
- tasks: *e2e_tasks
- e2e/vendored_node:
- icon: js
- tasks: *e2e_tasks
- e2e/vendored_tarfile:
- icon: js
- tasks: *e2e_tasks
- e2e/verify_patches:
- icon: js
- tasks: *e2e_tasks
- # No test targets. Requires running test.sh.
- # e2e/update_pnpm_lock:
- # e2e/update_pnpm_lock_with_import:
- # e2e/webpack_devserver:
- # e2e/webpack_devserver_esm:
- examples:
- icon: js
- tasks: *e2e_tasks
-bazel:
- flags:
- - --config=ci
-tasks:
- - checkout:
- update_strategy: rebase
- - test:
- name: Bazel 7
- id: bazel-7
- bazel:
- flags: ['--test_tag_filters=-skip-on-bazel7']
- env:
- USE_BAZEL_VERSION: '7.x'
- - test:
- name: Bazel 8
- id: bazel-8
- bazel:
- flags: ['--test_tag_filters=-skip-on-bazel8']
- env:
- USE_BAZEL_VERSION: '8.x'
- - test:
- name: Bazel 9
- id: bazel-9
- bazel:
- flags: ['--test_tag_filters=-skip-on-bazel9']
- env:
- # TODO: change this back to 9.x once this bug is fixed:
- # https://github.com/bazelbuild/bazel/issues/29393
- USE_BAZEL_VERSION: '9.0.2'
- - test:
- name: Bazel 9 (no execroot entry point)
- id: bazel-9-no-execroot-entry-point
- bazel:
- flags: ['--test_tag_filters=-skip-on-bazel9', '--@aspect_rules_js//js:use_execroot_entry_point=False']
- env:
- USE_BAZEL_VERSION: '9.0.2'
- - format:
- queue: aspect-medium
- - buildifier:
- queue: aspect-medium
- - finalization:
- queue: aspect-small
-notifications:
- github: {}
diff --git a/.bazelrc b/.bazelrc
index cfbb924..3d3ccf3 100644
--- a/.bazelrc
+++ b/.bazelrc
@@ -1,7 +1,5 @@
import %workspace%/tools/preset.bazelrc
-### YOUR PROJECT SPECIFIC OPTIONS GO HERE ###
-
common --noenable_workspace
# We have some empty globs in rules_js
@@ -22,14 +20,15 @@
# https://bazelbuild.slack.com/archives/C014RARENH0/p1691158021917459?thread_ts=1691156601.420349&cid=C014RARENH0
common --check_direct_dependencies=off
-
# Ignore this test as it breaks the runfiles tree generation in coverage mode.
# Also see: .aspect/bazelrc/performance.bazelrc where runfiles trees are eagerly
# generated due to `coverage --build_runfile_links`
coverage --deleted_packages=js/private/test/image/non_ascii
-# Load any settings & overrides specific to the current user from `.aspect/bazelrc/user.bazelrc`.
-# This file should appear in `.gitignore` so that settings are not shared with team members. This
-# should be last statement in this config so the user configuration is able to overwrite flags from
-# this file. See https://bazel.build/configure/best-practices#bazelrc-file.
-try-import %workspace%/.aspect/bazelrc/user.bazelrc
+# Build without the bytes
+common:ci --remote_download_outputs=minimal
+common:ci --nobuild_runfile_links
+
+# Override the preset's `--lockfile_mode=error` on CI since we don't
+# yet commit MODULE.bazel.lock — see .gitignore.
+common:ci --lockfile_mode=off
diff --git a/.github/workflows/buildifier.yaml b/.github/workflows/buildifier.yaml
deleted file mode 100644
index f08c181..0000000
--- a/.github/workflows/buildifier.yaml
+++ /dev/null
@@ -1,20 +0,0 @@
-name: Buildifier
-
-# Controls when the action will run.
-on:
- # Triggers the workflow on push or pull request events but only for the main branch
- push:
- branches: [main]
- pull_request:
- branches: [main]
-
- # Allows you to run this workflow manually from the Actions tab
- workflow_dispatch:
-
-jobs:
- check:
- runs-on: ubuntu-latest
- steps:
- - uses: actions/checkout@v6
- - name: buildifier
- run: bazel run //:buildifier.check
diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci-vanilla-bazel.yaml
similarity index 91%
rename from .github/workflows/ci.yaml
rename to .github/workflows/ci-vanilla-bazel.yaml
index 09c4908..18782a0 100644
--- a/.github/workflows/ci.yaml
+++ b/.github/workflows/ci-vanilla-bazel.yaml
@@ -1,4 +1,4 @@
-name: CI
+name: CI - Vanilla Bazel
# Controls when the action will run
on:
@@ -12,10 +12,8 @@
workflow_dispatch:
concurrency:
- # Cancel previous actions from the same PR or branch except 'main' branch.
- # See https://docs.github.com/en/actions/using-jobs/using-concurrency and https://docs.github.com/en/actions/learn-github-actions/contexts for more info.
- group: concurrency-group::${{ github.workflow }}::${{ github.event.pull_request.number > 0 && format('pr-{0}', github.event.pull_request.number) || github.ref_name }}${{ github.ref_name == 'main' && format('::{0}', github.run_id) || ''}}
- cancel-in-progress: ${{ github.ref_name != 'main' }}
+ group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}
+ cancel-in-progress: true
jobs:
semantic-pull-request:
diff --git a/.github/workflows/ci-workflows.yaml b/.github/workflows/ci-workflows.yaml
new file mode 100644
index 0000000..1701435
--- /dev/null
+++ b/.github/workflows/ci-workflows.yaml
@@ -0,0 +1,176 @@
+name: CI - Aspect Workflows
+
+on:
+ push:
+ branches: [main]
+ pull_request:
+ branches: [main]
+ workflow_dispatch:
+
+permissions:
+ id-token: write
+
+env:
+ ASPECT_API_TOKEN: ${{ secrets.ASPECT_API_TOKEN }}
+ INSTALL_ASPECT_LAUNCHER_VERSION: 2026.21.44
+
+concurrency:
+ group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}
+ cancel-in-progress: true
+
+jobs:
+ format:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v6
+ - uses: bazel-contrib/setup-bazel@c5acdfb288317d0b5c0bbd7a396a3dc868bb0f86 # 0.19.0
+ with:
+ bazelisk-cache: true
+ disk-cache: ${{ github.workflow }}-format
+ repository-cache: true
+ external-cache: true
+ - name: Format
+ run: |
+ curl -fsSL https://install.aspect.build | bash -s -- "$INSTALL_ASPECT_LAUNCHER_VERSION"
+ aspect format --task-key=format
+ buildifier:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v6
+ - uses: bazel-contrib/setup-bazel@c5acdfb288317d0b5c0bbd7a396a3dc868bb0f86 # 0.19.0
+ with:
+ bazelisk-cache: true
+ disk-cache: ${{ github.workflow }}-buildifier
+ repository-cache: true
+ external-cache: true
+ - name: Buildifier
+ run: |
+ curl -fsSL https://install.aspect.build | bash -s -- "$INSTALL_ASPECT_LAUNCHER_VERSION"
+ aspect buildifier --task-key=buildifier
+ # Builds the workspace matrix axis. e2e tests gated on secrets that forks don't have
+ # (ASPECT_GHTESTER_SSH_KEY, ASPECT_NPM_AUTH_TOKEN) are only appended when the secret is
+ # available, so PRs from forks skip them instead of failing.
+ e2e-tests-list:
+ runs-on: ubuntu-latest
+ steps:
+ - id: workspace
+ name: Prepare 'workspace' matrix axis
+ run: |
+ paths=(
+ .
+ e2e/bzlmod
+ e2e/gyp_no_install_script
+ e2e/js_binary_workspace
+ e2e/js_image_oci
+ e2e/nextjs
+ e2e/npm_link_package
+ e2e/npm_link_package-rerooted
+ e2e/npm_translate_lock
+ e2e/npm_translate_lock_replace_packages
+ e2e/npm_translate_lock_empty
+ e2e/npm_translate_lock_exclude_package_contents
+ e2e/npm_translate_lock_multi
+ e2e/npm_translate_lock_partial_clone
+ e2e/npm_translate_lock_subdir_patch
+ e2e/npm_translate_lock_disable_hooks
+ e2e/npm_translate_package_lock
+ e2e/npm_translate_yarn_lock
+ e2e/patch_from_repo
+ e2e/pnpm_repo_install
+ e2e/pnpm_workspace
+ e2e/pnpm_workspace_deps
+ e2e/pnpm_workspace_rerooted
+ e2e/protobuf-es
+ e2e/protobuf-google
+ e2e/repo_mapping
+ e2e/output_paths
+ e2e/vendored_node
+ e2e/vendored_tarfile
+ e2e/verify_patches
+ examples
+ )
+ # e2e/git_dep_metadata and e2e/npm_translate_lock_git+ssh clone over ssh and
+ # require an SSH key not available on forks. e2e/pnpm_lockfiles is in this
+ # bucket too: one of its v110 lockfile entries (jquery-git-https-763ade6)
+ # resolves to a `type: git` repo at git@github.com:jquery/jquery.git, so
+ # rules_js does a real SSH clone.
+ if [[ "${{ env.ASPECT_GHTESTER_SSH_KEY }}" ]]; then
+ paths+=(
+ e2e/git_dep_metadata
+ e2e/npm_translate_lock_git+ssh
+ e2e/pnpm_lockfiles
+ )
+ fi
+ # e2e/npm_translate_lock_auth requires an npm auth token not available on forks.
+ if [[ "${{ env.ASPECT_NPM_AUTH_TOKEN }}" ]]; then
+ paths+=( e2e/npm_translate_lock_auth )
+ fi
+
+ # Slug feeds aspect --task-key, the disk-cache key, and the job name, all
+ # of which require [A-Za-z0-9_-]. Map "." → "root"; replace "/" with "-"
+ # and "+" with "_" so e.g. e2e/npm_translate_lock_git+ssh becomes a valid
+ # e2e-npm_translate_lock_git_ssh slug.
+ entries=()
+ for p in "${paths[@]}"; do
+ if [[ "$p" == "." ]]; then
+ slug=root
+ else
+ slug=${p//\//-}
+ slug=${slug//+/_}
+ fi
+ entries+=( "{\"path\":\"$p\",\"slug\":\"$slug\"}" )
+ done
+ printf -v j '%s,' "${entries[@]}"
+ echo "res=[${j%,}]" | tee -a $GITHUB_OUTPUT
+ env:
+ ASPECT_GHTESTER_SSH_KEY: ${{ secrets.ASPECT_GHTESTER_SSH_KEY }}
+ ASPECT_NPM_AUTH_TOKEN: ${{ secrets.ASPECT_NPM_AUTH_TOKEN }}
+ outputs:
+ workspace: ${{ steps.workspace.outputs.res }}
+
+ test:
+ name: test (${{ matrix.workspace.path }}, ${{ matrix.bazel.id }})
+ runs-on: ubuntu-latest
+ needs: e2e-tests-list
+ strategy:
+ fail-fast: false
+ matrix:
+ workspace: ${{ fromJSON(needs.e2e-tests-list.outputs.workspace) }}
+ bazel:
+ - { id: "bazel-7", version: "7.x", flags: "--bazel-flag=--test_tag_filters=-skip-on-bazel7" }
+ - { id: "bazel-8", version: "8.x", flags: "--bazel-flag=--test_tag_filters=-skip-on-bazel8" }
+ # TODO: change this back to 9.x once this bug is fixed: https://github.com/bazelbuild/bazel/issues/29393
+ - { id: "bazel-9", version: "9.0.2", flags: "--bazel-flag=--test_tag_filters=-skip-on-bazel9" }
+ - { id: "bazel-9-no-execroot-entry-point", version: "9.0.2", flags: "--bazel-flag=--test_tag_filters=-skip-on-bazel9 --bazel-flag=--@aspect_rules_js//js:use_execroot_entry_point=False" }
+ exclude:
+ # e2e/js_image_oci pulls in the `llvm` module, whose hermetic toolchain requires Bazel 8+.
+ - { workspace: { slug: "e2e-js_image_oci" }, bazel: { id: "bazel-7" } }
+ # e2e/patch_from_repo has a bazel7-specific absolute label in its MODULE.bazel.
+ - { workspace: { slug: "e2e-patch_from_repo" }, bazel: { id: "bazel-8" } }
+ - { workspace: { slug: "e2e-patch_from_repo" }, bazel: { id: "bazel-9" } }
+ - { workspace: { slug: "e2e-patch_from_repo" }, bazel: { id: "bazel-9-no-execroot-entry-point" } }
+ # e2e/repo_mapping renames aspect_rules_js, so a flag beginning with
+ # --@aspect_rules_js// (as used by the no-execroot-entry-point variant) doesn't resolve.
+ - { workspace: { slug: "e2e-repo_mapping" }, bazel: { id: "bazel-9-no-execroot-entry-point" } }
+ env:
+ USE_BAZEL_VERSION: ${{ matrix.bazel.version }}
+ ASPECT_GH_PACKAGES_AUTH_TOKEN: ${{ secrets.ASPECT_GH_PACKAGES_AUTH_TOKEN }}
+ ASPECT_NPM_AUTH_TOKEN: ${{ secrets.ASPECT_NPM_AUTH_TOKEN }}
+ steps:
+ - uses: actions/checkout@v6
+ # Setup an ssh keypair for e2e tests that clone a git repository via ssh.
+ - uses: webfactory/ssh-agent@a6f90b1f127823b31d4d4a8d96047790581349bd # v0.9.1
+ if: matrix.workspace.slug == 'e2e-git_dep_metadata' || matrix.workspace.slug == 'e2e-npm_translate_lock_git_ssh' || matrix.workspace.slug == 'e2e-pnpm_lockfiles'
+ with:
+ ssh-private-key: ${{ secrets.ASPECT_GHTESTER_SSH_KEY }}
+ - uses: bazel-contrib/setup-bazel@c5acdfb288317d0b5c0bbd7a396a3dc868bb0f86 # 0.19.0
+ with:
+ bazelisk-cache: true
+ disk-cache: ${{ github.workflow }}-test-${{ matrix.workspace.slug }}-${{ matrix.bazel.id }}
+ repository-cache: true
+ external-cache: true
+ - name: Test
+ working-directory: ${{ matrix.workspace.path }}
+ run: |
+ curl -fsSL https://install.aspect.build | bash -s -- "$INSTALL_ASPECT_LAUNCHER_VERSION"
+ aspect test --task-key=test-${{ matrix.workspace.slug }}-${{ matrix.bazel.id }} ${{ matrix.bazel.flags }} -- //...
diff --git a/.gitignore b/.gitignore
index 8563c7b..7112b71 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,5 +1,4 @@
bazel-*
-user.bazelrc
node_modules/
.pnpm-*
diff --git a/BUILD.bazel b/BUILD.bazel
index 39d8a7a..3a69373 100644
--- a/BUILD.bazel
+++ b/BUILD.bazel
@@ -1,6 +1,5 @@
load("@bazel_lib//lib:diff_test.bzl", "diff_test")
load("@bazel_skylib//rules:build_test.bzl", "build_test")
-load("@buildifier_prebuilt//:rules.bzl", "buildifier")
load("@npm//:defs.bzl", "npm_link_all_packages", "npm_link_targets")
load("@pnpm__links//:defs.bzl", npm_link_pnpm = "npm_link_imported_package")
load("//js:defs.bzl", "js_library")
@@ -57,29 +56,12 @@
file2 = "query_npm_link_targets_node_modules",
)
-buildifier(
- name = "buildifier",
- exclude_patterns = [
- "./.git/*",
- "**/snapshots/*",
- ],
- lint_mode = "fix",
- mode = "fix",
- tags = ["manual"], # tag as manual so windows ci does not build it by default
-)
-
-buildifier(
- name = "buildifier.check",
- exclude_patterns = [
- "./.git/*",
- "**/snapshots/*",
- ],
- lint_mode = "warn",
- mode = "diff",
- tags = ["manual"], # tag as manual so windows ci does not build it by default
+alias(
+ name = "format",
+ actual = "//tools/format",
)
alias(
- name = "format",
- actual = "//tools:format",
+ name = "buildifier",
+ actual = "//tools/format:buildifier",
)
diff --git a/MODULE.bazel b/MODULE.bazel
index 18f5466..2bdbf6e 100644
--- a/MODULE.bazel
+++ b/MODULE.bazel
@@ -108,7 +108,7 @@
)
use_repo(pnpm10, "pnpm10")
-bazel_dep(name = "bazelrc-preset.bzl", version = "1.3.0", dev_dependency = True)
+bazel_dep(name = "bazelrc-preset.bzl", version = "1.9.2", dev_dependency = True)
bazel_dep(name = "aspect_rules_lint", version = "2.3.0", dev_dependency = True)
bazel_dep(name = "buildifier_prebuilt", version = "8.2.1.1", dev_dependency = True)
bazel_dep(name = "rules_shell", version = "0.6.1", dev_dependency = True)
diff --git a/README.md b/README.md
index 42a9242..a4127a5 100644
--- a/README.md
+++ b/README.md
@@ -1,5 +1,9 @@
# Bazel rules for JavaScript
+> [!NOTE]
+> This repository uses the [Aspect CLI](https://github.com/aspect-build/aspect-cli) for CI and local development.
+> See the [docs](https://docs.aspect.build/cli/overview) and [install instructions](https://docs.aspect.build/cli/install) to get started.
+
This ruleset is a high-performance Bazel integration for JavaScript, based on the [pnpm package manager](https://pnpm.io).
- Lazy: only fetches/installs npm packages needed for the requested build/test targets.
diff --git a/e2e/e2e.bazelrc b/e2e/e2e.bazelrc
index c1abb89..5574d1d 100644
--- a/e2e/e2e.bazelrc
+++ b/e2e/e2e.bazelrc
@@ -1 +1,9 @@
common --noenable_workspace
+
+# Build without the bytes
+common:ci --remote_download_outputs=minimal
+common:ci --nobuild_runfile_links
+
+# Override the preset's `--lockfile_mode=error` on CI since we don't
+# yet commit MODULE.bazel.lock — see .gitignore.
+common:ci --lockfile_mode=off
diff --git a/e2e/js_binary_workspace/.bazelrc b/e2e/js_binary_workspace/.bazelrc
index b09f80b..58d7130 100644
--- a/e2e/js_binary_workspace/.bazelrc
+++ b/e2e/js_binary_workspace/.bazelrc
@@ -1 +1,2 @@
import %workspace%/../../tools/preset.bazelrc
+import %workspace%/../e2e.bazelrc
diff --git a/e2e/js_image_oci/.bazelrc b/e2e/js_image_oci/.bazelrc
index 60d7d89..58d7130 100644
--- a/e2e/js_image_oci/.bazelrc
+++ b/e2e/js_image_oci/.bazelrc
@@ -1,10 +1,2 @@
import %workspace%/../../tools/preset.bazelrc
import %workspace%/../e2e.bazelrc
-
-### YOUR PROJECT SPECIFIC OPTIONS GO HERE ###
-
-# Load any settings & overrides specific to the current user from `.aspect/bazelrc/user.bazelrc`.
-# This file should appear in `.gitignore` so that settings are not shared with team members. This
-# should be last statement in this config so the user configuration is able to overwrite flags from
-# this file. See https://bazel.build/configure/best-practices#bazelrc-file.
-try-import %workspace%/../../.aspect/bazelrc/user.bazelrc
diff --git a/e2e/pnpm_repo_install/.bazelrc b/e2e/pnpm_repo_install/.bazelrc
index f14f7ee..3d60bcf 100644
--- a/e2e/pnpm_repo_install/.bazelrc
+++ b/e2e/pnpm_repo_install/.bazelrc
@@ -1,12 +1,4 @@
import %workspace%/../../tools/preset.bazelrc
import %workspace%/../e2e.bazelrc
-### YOUR PROJECT SPECIFIC OPTIONS GO HERE ###
-
build --sandbox_default_allow_network=true
-
-# Load any settings & overrides specific to the current user from `.aspect/bazelrc/user.bazelrc`.
-# This file should appear in `.gitignore` so that settings are not shared with team members. This
-# should be last statement in this config so the user configuration is able to overwrite flags from
-# this file. See https://bazel.build/configure/best-practices#bazelrc-file.
-try-import %workspace%/../../.aspect/bazelrc/user.bazelrc
diff --git a/e2e/protobuf-es/.bazelrc b/e2e/protobuf-es/.bazelrc
index 48a1fb5..34a6be1 100644
--- a/e2e/protobuf-es/.bazelrc
+++ b/e2e/protobuf-es/.bazelrc
@@ -1,3 +1,6 @@
+import %workspace%/../../tools/preset.bazelrc
+import %workspace%/../e2e.bazelrc
+
# Avoid building protoc from source
build --incompatible_enable_proto_toolchain_resolution
build --@protobuf//bazel/toolchains:prefer_prebuilt_protoc
diff --git a/e2e/protobuf-google/.bazelrc b/e2e/protobuf-google/.bazelrc
index 48a1fb5..34a6be1 100644
--- a/e2e/protobuf-google/.bazelrc
+++ b/e2e/protobuf-google/.bazelrc
@@ -1,3 +1,6 @@
+import %workspace%/../../tools/preset.bazelrc
+import %workspace%/../e2e.bazelrc
+
# Avoid building protoc from source
build --incompatible_enable_proto_toolchain_resolution
build --@protobuf//bazel/toolchains:prefer_prebuilt_protoc
diff --git a/tools/BUILD.bazel b/tools/BUILD.bazel
index ffc77ab..153bcc9 100644
--- a/tools/BUILD.bazel
+++ b/tools/BUILD.bazel
@@ -1,20 +1,7 @@
-"""Tools for local development and formatting in this repository.
-
-This is in its own package because it has so many loading-time symbols,
-we don't want to trigger eager fetches of these for builds that don't want to run format.
-"""
-
-load("@aspect_rules_lint//format:defs.bzl", "format_multirun")
load("@bazelrc-preset.bzl", "bazelrc_preset")
package(default_visibility = ["//:__subpackages__"])
-format_multirun(
- name = "format",
- shell = "@aspect_rules_lint//format:shfmt",
- starlark = "@buildifier_prebuilt//:buildifier",
-)
-
bazelrc_preset(
name = "preset",
doc_link_template = "https://registry.build/flag/bazel?filter={flag}",
diff --git a/tools/format/BUILD.bazel b/tools/format/BUILD.bazel
new file mode 100644
index 0000000..7357f5f
--- /dev/null
+++ b/tools/format/BUILD.bazel
@@ -0,0 +1,15 @@
+load("@aspect_rules_lint//format:defs.bzl", "format_multirun")
+
+package(default_visibility = ["//:__subpackages__"])
+
+format_multirun(
+ name = "format",
+ shell = "@aspect_rules_lint//format:shfmt",
+)
+
+# Starlark-only formatter for the dedicated buildifier CI step.
+# See https://docs.aspect.build/cli/migration/buildifier.
+format_multirun(
+ name = "buildifier",
+ starlark = "@buildifier_prebuilt//:buildifier",
+)
diff --git a/tools/preset.bazelrc b/tools/preset.bazelrc
index 55b66a7..5bb3396 100644
--- a/tools/preset.bazelrc
+++ b/tools/preset.bazelrc
@@ -67,6 +67,11 @@
common --experimental_remote_cache_eviction_retries=5
# Docs: https://registry.build/flag/bazel?filter=experimental_remote_cache_eviction_retries
+# Discard Merkle trees for remote actions reducing memory usage significantly.
+# Requires Bazel to recompute them upon remote cache misses and retries.
+common --experimental_remote_discard_merkle_trees
+# Docs: https://registry.build/flag/bazel?filter=experimental_remote_discard_merkle_trees
+
# This flag was added in Bazel 5.0.0 with a default of zero:
# https://github.com/bazelbuild/bazel/commit/a1137ec1338d9549fd34a9a74502ffa58c286a8e
# For Bazel 8.0.0 the default was changed to 5:
@@ -122,6 +127,10 @@
common --incompatible_disallow_empty_glob
# Docs: https://registry.build/flag/bazel?filter=incompatible_disallow_empty_glob
+# Accept multiple --modify_execution_info flags, rather than the last flag overwriting earlier ones.
+common --incompatible_modify_execution_info_additive
+# Docs: https://registry.build/flag/bazel?filter=incompatible_modify_execution_info_additive
+
# Make builds more reproducible by using a static value for PATH and not inheriting LD_LIBRARY_PATH.
# Use `--action_env=ENV_VARIABLE` if you want to inherit specific variables from the environment where Bazel runs.
# Note that doing so can prevent cross-user caching if a shared cache is used.
@@ -135,6 +144,11 @@
common --nolegacy_external_runfiles
# Docs: https://registry.build/flag/bazel?filter=legacy_external_runfiles
+# Fail the build if the MODULE.bazel.lock file is out of date.
+# Using this mode in ci prevents the lockfile from being out of date.
+common:ci --lockfile_mode="error"
+# Docs: https://registry.build/flag/bazel?filter=lockfile_mode
+
# On CI, don't download remote outputs to the local machine.
# Most CI pipelines don't need to access the files and they can remain at rest on the remote cache.
# Significant time can be spent on needless downloads, which is especially noticeable on fully-cached builds.