Skip to content

feat(bazelrc): config groups, deployment sections, and a flag catalog with opt-outs - #1442

Merged
gregmagolan merged 1 commit into
mainfrom
bazelrc-deployment-configs
Sep 16, 2026
Merged

gregmagolan merged 1 commit into
mainfrom
bazelrc-deployment-configs

Conversation

@gregmagolan

@gregmagolan gregmagolan commented Sep 14, 2026

Copy link
Copy Markdown
Member

aspect setup bazelrc writes a Bazel rc that points vanilla bazel calls at Aspect's services: on an Aspect Workflows runner the runner's own, elsewhere the deployments aspect auth status knows, as opt-in --config=aspect-* sections. Every Bazel flag Aspect sets on the user's behalf — into tasks and into that rc — is declared once, tied to the endpoint that justifies it, and individually opt-out-able.

The flag catalog. private/lib/aspect_flags.axl lists every tuning flag Aspect injects, with what it does, why, and what it presumes: a cache, a BES backend, any gRPC channel, or nothing. The Workflows feature (tasks on a runner), the Deployment feature (aspect <task> --remote), and aspect setup bazelrc all select from it, so a flag appears the same way for the same reason wherever it is set, and a runner or deployment with no cache, no BES, or no executor gets none of the flags that presume the missing one. aspect build --remote and bazel build --config=aspect-<name> therefore run with the same tuning, diagnostics upload, and --build_metadata.

Opt-outs, per surface. Tasks: --bazel-flags:omit=<flag> (repeatable), or once per repo via ctx.features[BazelFlags].args.omit in config.axl; the BazelFlags feature registers it on BazelTrait.injected_flag_filters, which the spawn path applies to everything features inject and never to the user's own flags. The rc: aspect setup bazelrc --omit-bazel-flag=<flag>, or ctx.tasks["bazelrc"].args.omit_bazel_flags. Both refuse the protected set — endpoints, credentials, --config chains, runner paths — with the reason. The BES pair is deliberately unprotected: a repository whose own rc routes vanilla builds to another backend keeps it with --omit-bazel-flag=--bes_backend, since Bazel reads the home rc after the workspace rc.

The rc's --config groups (private/lib/rc_groups.axl). Bazel collects rc sections before expanding any --config, so the rc defines every group and enables the ones that apply with common --config=<group> lines at the top; bazel build --announce_rc names the group each flag came from, and a host can borrow a group by name. Startup options have no --config and stay plain lines.

Group Holds
aspect-common tuning that presumes no endpoint: --heap_dump_on_oom, --experimental_repository_cache_hardlinks
aspect-cache the cache endpoint where ASPECT_WORKFLOWS_REMOTE_CACHE names one (with the Workflows cache's specifics on a runner), then the tuning any cache justifies
aspect-bes the BES backend and viewer where ASPECT_WORKFLOWS_BES_BACKEND names one (with --profile under the job tmpdir on a runner), then the enrichment and the diagnostics upload switch
aspect-exec-log the compact execution log for that upload, at the job tmpdir on a runner or %workspace%/.aspect/generated/exec.log.zstd in a checkout's rc; its own group, beside aspect-bes, so a repository on a thin link can drop this one large upload by removing the lines naming it
aspect-github-actions / aspect-circleci / aspect-gitlab what that host needs: --color=yes where Bazel's --color=auto misdetects (Buildkite gives jobs a PTY and gets no group); only in a machine's own rc, never the checkout's shared one
aspect-runner the runner's storage: --repository_cache
aspect-exec the runner's remote executor from ASPECT_WORKFLOWS_REMOTE_EXECUTOR, chaining aspect-cache when there is no cache; never enabled, --config=aspect-exec per call

Two shapes, one answer to "which deployment". Where the environment names the deployment — the runner marker, or any ASPECT_WORKFLOWS_* endpoint — the groups that apply are enabled and no deployment sections are written: a --config=aspect-cloud in a runner's rc would route a vanilla build off the runner's own services. On a runner ~/.bazelrc is written whole, and it carries the runner's BES backend so vanilla bazel reaches the Web UI like a task does (tasks run with --nohome_rc and stream BES from the CLI, so nothing in the file reaches them). Where the environment is silent, the rc is the checkout's, meant to be committed: <workspace>/.aspect/bazelrc, imported by the workspace .bazelrc through try-import %workspace%/.aspect/bazelrc, which the command adds once at the top of the file under a comment, so the repository's own lines come after and override the recommendations. The file is a starting point the repository then owns — its header says so — and rerunning the command restores the generated version. Nothing in it is one machine's: the credential helper is named aspect, the CI host's group is left out, and the compact execution log is placed at %workspace%/.aspect/generated/exec.log.zstd — Bazel expands %workspace% in rc values — with .aspect/generated/ created by the command as a self-ignoring directory (* and !.gitignore) to commit, so it exists in every checkout (Bazel does not create the log's parent). Nothing is enabled; each deployment section chains aspect-common and the tuning groups its endpoints justify. The file is inert until a section is named, so importing it into a developer's rc changes nothing.

Config Wires
--config=aspect-cloud Aspect Cloud's remote cache + BES
--config=aspect-<name> a configured deployment's remote cache and/or BES
--config=aspect-<name>-exec the same plus its remote execution (standalone for an executor-only deployment)

Each section sets --remote_cache / --bes_backend / --bes_results_url, authenticates through the aspect get credential helper scoped per distinct host (named aspect, since a checkout's rc is shared; the command warns when aspect is not on PATH), and chains its groups. Which actions are published as BEP events and --bes_upload_mode are left to the user. Two deployments landing on one config name is refused with the rename to make. No section names the default deployment: the file is committed and shared, and aspect auth use is one machine's setting. A flag omitted with --omit-bazel-flag is dropped inside its group; a group emptied that way disappears along with the lines that enabled or chained to it.

Runner contract additions. ASPECT_WORKFLOWS_REMOTE_EXECUTOR names an executor; nothing wires it until asked, since remote execution relocates every action: --workflows:remote-exec (or ctx.features[Workflows].args.remote_exec) for tasks, --config=aspect-exec for vanilla bazel. ASPECT_WORKFLOWS_REMOTE_CACHE_COMPRESSION says the cache accepts compressed blobs; unset, the runner forces --noremote_cache_compression (Bazel errors when a repository asks a cache that lacks compression for it), set, compression is left to the repository. A runner image flips it when its cache is upgraded, with no CLI release; the variable and the two flags go away once no Workflows deployment without compression is left.

aspect setup bazelrc. The command is useful off CI too, so it lives in a new setup group; aspect ci bazelrc, which the setup-aspect action, Buildkite plugin, CircleCI orb, and GitLab component call, stays as an alias: the same task registered under its old group, with config overrides under ctx.tasks["ci/bazelrc"].

Layout. bazelrc.axl is the task flow only. The rc document (rendering, the try-import placement) is private/lib/bazelrc_file.axl, the groups private/lib/rc_groups.axl, the deployment sections (naming, credential helpers, per-endpoint flags, aliases, collisions) private/lib/deployment_rc.axl, each with its own test suite.

The same rule holds for tasks. Where the environment names the deployment — a runner, or ASPECT_WORKFLOWS_REMOTE_CACHE / BES_BACKEND set by hand — tasks get the runner's flag set (minus its mounts off a runner) and --remote is refused, since a configured deployment would route the build off the one the machine is on. A customer who wants that combination sees the refusal and can ask.

Supporting changes: ctx.std.process.which(name) resolves an executable along PATH the way a shell does (the rc warns when it does not find aspect). A task-injected flag may name its rc section, (flag, version, "build"), and the bazelrc runtime then withholds it from query and its kin the way an rc file's build line is; the execution log uses this, being an execution option (aspect cache diff queries with the task's rc). ctx.aspect.auth.deployments() lists deployments from config alone, never the credential store, with builtin / default / api_token_env on DeploymentEndpoints. --build_metadata is set only where a BES backend reads it. The runner identity (ASPECT_WORKFLOWS_RUNNER_IDENTITY, the x-identity headers) is removed; runners do not set it. --bes_results_url is paired with Bazel's own backend only, so a task whose Bazel uploads to a third-party BES while the CLI streams to Aspect no longer gets Aspect's viewer injected into Bazel. Tasks no longer pass --build_event_publish_all_actions: the BEP consumers read only failed actions, which Bazel publishes by default, and per-action data comes from the compact execution log. The diagnostics upload (--remote_build_event_upload=all, the compact execution log) is on wherever a BES backend is wired; the ASPECT_WORKFLOWS_RUNNER_UPLOAD_BUILD_DIAGNOSTICS / --workflows:upload-build-diagnostics opt-in is removed, since no runner set the variable.


Changes are visible to end-users: yes

  • Searched for relevant documentation and updated as needed: no

  • Breaking change (forces users to change their own code or config): no

  • Suggested release notes appear below: yes

  • aspect ci bazelrc is now aspect setup bazelrc; the old name remains as an alias for the CI integrations. Config overrides target ctx.tasks["setup/bazelrc"].

  • aspect setup bazelrc writes --config=aspect-cloud, --config=aspect-<deployment>, and --config=aspect-<deployment>-exec sections for every deployment aspect auth status knows, so vanilla bazel calls on any CI can use Aspect's remote cache and BES.

  • Off an Aspect Workflows runner, aspect setup bazelrc writes the checkout's .aspect/bazelrc as a starting point to edit and commit (a rerun restores it), adds try-import %workspace%/.aspect/bazelrc at the top of the workspace .bazelrc so the repository's own lines override it, and creates a self-ignoring .aspect/generated/ for build-time outputs; commit all three. The imported rc changes nothing until a --config=aspect-* is named.

  • Every flag in the generated rc sits in a named --config group (aspect-common, aspect-cache, aspect-bes, aspect-<ci host>, aspect-runner, aspect-exec), so bazel build --announce_rc names the group each flag came from and a group can be borrowed by name.

  • On a Workflows runner, aspect setup bazelrc writes the runner's BES backend into ~/.bazelrc so vanilla bazel calls appear in the Web UI; a repository that routes vanilla builds elsewhere opts out with --omit-bazel-flag=--bes_backend.

  • --bazel-flags:omit=<flag> (or ctx.features[BazelFlags].args.omit in config.axl) drops a Bazel flag Aspect would otherwise set on a task's Bazel call; aspect setup bazelrc --omit-bazel-flag=<flag> (or ctx.tasks["bazelrc"].args.omit_bazel_flags) does the same for the written rc. Endpoints, credentials, and runner paths cannot be dropped.

  • aspect <task> --remote sets the same cache/BES tuning, diagnostics upload, and --build_metadata as the rc's --config=aspect-* sections. It is refused on an Aspect Workflows runner, or wherever the ASPECT_WORKFLOWS_* endpoint variables are set, since the environment already names the deployment those builds use.

  • Aspect's tuning flags are set only where the endpoint they tune is wired; the profile flags (--noslim_profile, --experimental_profile_include_*, --legacy_important_outputs) join them wherever a BES backend is.

  • A runner that sets ASPECT_WORKFLOWS_REMOTE_EXECUTOR offers remote execution on request: --workflows:remote-exec for tasks, --config=aspect-exec for vanilla bazel.

  • A runner that sets ASPECT_WORKFLOWS_REMOTE_CACHE_COMPRESSION no longer has --noremote_cache_compression forced on its builds; compression is left to the repository.

  • The JSON profile and compact execution log are uploaded to the BES backend wherever one is wired; the --workflows:upload-build-diagnostics opt-in is removed.

  • Tasks no longer pass --build_event_publish_all_actions to Bazel, shrinking the BES stream; failed actions are still published by Bazel's default.

Test plan

  • New test suites: aspect dev test-aspect-flags, test-bazelrc-file, test-rc-groups, test-deployment-rc; new cases in test-deployment-flags and the BES sinks suite; deployment_endpoints_come_from_config_alone in auth.rs.
  • Manual, with HOME pointed at a scratch dir holding a copy of ~/.aspect/config.json: ASPECT_WORKFLOWS_RUNNER=1 plus the runner variables writes ~/.bazelrc whole with the groups enabled and no sections; GITHUB_ACTIONS=true aspect setup bazelrc in a checkout writes .aspect/bazelrc with nothing enabled and the sections, adds try-import %workspace%/.aspect/bazelrc to the workspace .bazelrc, and reports it unchanged on a second run; bazel build --nobuild --config=aspect-bes from a subdirectory writes the execution log into .aspect/generated/; --omit-bazel-flag=--heap_dump_on_oom --omit-bazel-flag=--experimental_repository_cache_hardlinks drops the aspect-common group and its chains, --omit-bazel-flag=--remote_cache is refused. bazel --nohome_rc --nosystem_rc version --announce_rc reads the import through %workspace% and applies nothing from the deployment-shaped rc alone; with --config=aspect-cloud it expands each chained group with no warnings; the runner-shaped rc shows every enabled group, and --config=aspect-exec expands cleanly.

🤖 Generated with Claude Code

@coderabbitai

coderabbitai Bot commented Sep 14, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Advanced

Run ID: 9c43f2a5-2cdd-431f-8aec-02c5400443cb

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@aspect-workflows

aspect-workflows Bot commented Sep 14, 2026

Copy link
Copy Markdown

Aspect Workflows Tasks

📅 Wed Sep 16 04:25:29 UTC 2026

Task Results

Reproduce

❌ delivery (delivery-uncacheable · delivery-gha-debug · delivery-gha)

# --mode=always --track-state=false for off-runner with no state backend.
aspect delivery \
  --commit-sha=1c08f4f01d6a8f12bb36419f55844b669d48750c \
  --mode=always \
  --track-state=false \
  --dry-run=true

Install aspect: aspect.build/docs/cli/install


⏱ Last updated Wed Sep 16 04:31:47 UTC 2026 · 📊 GitHub API quota 419/7,700 (5% used, resets in 53m)
🚀 Powered by Aspect CLI (v0.0.0-dev)  |  Aspect Build · X · LinkedIn · YouTube

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 99b291a2d5

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread crates/aspect-cli/src/builtins/aspect/bazelrc.axl Outdated
Comment thread crates/aspect-cli/src/builtins/aspect/bazelrc.axl Outdated
@gregmagolan gregmagolan changed the title feat(bazelrc): write --config=aspect-* sections and the recommended profile flags feat(bazelrc): --config=aspect-* sections, a try-import into ~/.bazelrc, and the recommended profile flags Sep 14, 2026
@gregmagolan
gregmagolan force-pushed the bazelrc-deployment-configs branch from 5db53e2 to ab240e4 Compare September 14, 2026 03:25
@gregmagolan gregmagolan changed the title feat(bazelrc): --config=aspect-* sections, a try-import into ~/.bazelrc, and the recommended profile flags feat(bazelrc): --config=aspect-* sections, a flag catalog with opt-outs, and a try-import into ~/.bazelrc Sep 14, 2026
@gregmagolan
gregmagolan force-pushed the bazelrc-deployment-configs branch from 3bd2c28 to c32e00e Compare September 14, 2026 22:09
@gregmagolan gregmagolan changed the title feat(bazelrc): --config=aspect-* sections, a flag catalog with opt-outs, and a try-import into ~/.bazelrc feat(bazelrc): config groups, deployment sections, and a flag catalog with opt-outs Sep 15, 2026
@gregmagolan
gregmagolan force-pushed the bazelrc-deployment-configs branch from 79b13fc to b4b7a45 Compare September 15, 2026 05:46
@joshcbarnes

Copy link
Copy Markdown
Contributor

From Claude:

bes_group always appends diagnostics_upload_flags(exec_log_path), and off a runner that path is $TMPDIR/aspect-bazel-/exec.log.zstd — created once during aspect setup bazelrc, written literally into ~/.aspect/bazelrc, which persists:

common:aspect-bes --execution_log_compact_file=/var/folders/cx/…/T/aspect-bazel-65a987ac-…/exec.log.zstd

Bazel does not create the parent directory. Verified against Bazel 9.2.0:

ERROR: Error initializing execution log: /tmp/…/exec.log.zstd (No such file or directory)
ERROR: Build did NOT complete successfully

macOS clears /var/folders/**/T on reboot; systemd-tmpfiles clears /tmp after ~10 days. So bazel build --config=aspect-cloud starts failing some time after setup, with an error that points nowhere near the rc. Separately, the run_id namespacing in temp_exec_log_path's docstring ("concurrent jobs on one machine share that dir") doesn't hold in the rc: the id is the setup run's, so every later build on that machine writes the same file and concurrent builds clobber each other.

@gregmagolan

Copy link
Copy Markdown
Member Author

Nice catch. Resolved in 4ee534c by making the rc the checkout's rather than the machine's: off a runner aspect setup bazelrc now writes <workspace>/.aspect/bazelrc (committed, imported from the workspace .bazelrc via try-import %workspace%/.aspect/bazelrc) and the execution log is placed at %workspace%/.aspect/generated/exec.log.zstd. Bazel expands %workspace% in rc values (checked on 9.0.1 from the command line, an rc file, and a --default_override), so the committed line is right in every checkout, and builds within one checkout are serialized by the output-base lock so nothing clobbers the file. Bazel still won't create the parent, so the command creates .aspect/generated/ with a self-ignoring .gitignore (* plus !.gitignore) that is committed with the rest, and the directory exists wherever the repo is checked out. temp_exec_log_path is now used only by tasks, which create their per-run directory at build time; the runner's ~/.bazelrc keeps the job tmpdir path it regenerates every job.

@gregmagolan
gregmagolan force-pushed the bazelrc-deployment-configs branch from 4ee534c to 51efa25 Compare September 15, 2026 19:47
joshcbarnes added a commit that referenced this pull request Sep 15, 2026
…1453)

The GitHub-hosted jobs in `ci-workflows.yaml` have no remote cache — the
comment on `install-prebuilt-aspect-cli` says as much ("These small
runners have no remote-cache access"). They already authenticate to
Aspect Cloud, since every job hands `ASPECT_API_TOKEN` to setup-aspect,
which pipes it into `aspect auth login --with-api-token`. Only the
wiring was missing.

`.aspect/config.axl` now defaults `--remote=cache,bes` there, so no job
has to pass it. The 11 self-hosted jobs are untouched and keep using the
runner's own cache.

**The gate.** Three conditions, each guarding a real failure:

| Condition | Guards |
|---|---|
| `GITHUB_ACTIONS` | other CI hosts and dev machines stay untouched |
| not `ASPECT_WORKFLOWS_RUNNER` | a Workflows runner injects its own
cache/BES; Aspect Cloud would route builds off its own services |
| `ASPECT_HAS_API_TOKEN` | a fork PR gets no secrets, and the credential
helper exits non-zero for a host it cannot authenticate — every hosted
job on every fork PR would go red |

That last one reads a `"true"`/`"false"` the workflow computes with
`secrets.ASPECT_API_TOKEN != ''`. The token itself stays out of the job
env on purpose: setup-aspect keeps it out of `GITHUB_ENV` so only the
short-lived JWT is visible downstream, and an `ASPECT_API_TOKEN` in the
environment outranks that stored credential on every invocation.

**Auth goes through the credential helper.**
`--credential_helper=cache.aspect.build=aspect` resolves the CLI by name
on `PATH`, where `install-prebuilt-aspect-cli` puts it. The deployment
feature suppresses the `--remote_header` it would otherwise inject once
a helper covers the host, so the stream never carries two
`authorization` values. BES is streamed by the CLI rather than by Bazel,
so it keeps resolving its own bearer — the helper covers the cache
alone.

**Why `.aspect/config.json` is committed.** The helper refuses to send a
token to a host no configured deployment owns — a safety property that
stops a global helper leaking credentials to a third party. The built-in
Aspect Cloud entry ships with no hosts (`aspect_cloud_deployment()`
seeds `hosts: Vec::new()`), and only a discovery probe records them. The
browser login runs one; `auth login --with-api-token` — the CI path —
deliberately skips it (`auth.axl:257`), on the grounds that CI declares
its deployment in the repo's own `.aspect/config.json`. So this commits
exactly that file, as `aspect auth configure api.aspect.build` generates
it. `ASPECT_WORKSPACE` is how the CLI locates it.

Without this, `aspect get` returns `{"headers":{}}` and Bazel talks to
the cache unauthenticated.

**Web UI metadata is set explicitly.** The Workflows feature sets the
same flags but keys them on `ASPECT_WORKFLOWS_BES_BACKEND`, a
runner-injected variable. A `--remote` build reaches a BES backend by a
route that variable knows nothing about, so it arrives with no commit,
branch, PR, or link back to the Actions run. `get_build_metadata_flags`
is the same call the runner path makes.
`--remote_build_event_upload=all` makes BEP-referenced outputs — test
logs above all — resolvable as bytestream refs instead of `file://`
paths on a runner that no longer exists.

Deliberately excluded: `--execution_log_compact_file`, which stays off
repo-wide until on-disk redaction lands.

## Relationship to #1442

#1442 does this properly: a generated, committed `.aspect/bazelrc` with
`--config=aspect-cloud` sections, the same credential helper spelling,
and — the root fix — flags keyed on *"is a BES backend wired"* rather
than *"am I on a runner."* **When it lands, the `config.axl` block here
should be deleted in favour of `--config=aspect-cloud`.** Its
`config.axl` edits are confined to test registration, so this should
merge cleanly.

Two things #1442 does not address, both worth a look:

- **The discovery gap is inherited.** Its committed rc tells Bazel which
cache to use, but nothing tells the credential helper the cache is ours,
and `profile_for_uri` / `aspect_cloud_deployment()` are unchanged on
that branch. The clean fix is in the CLI: `ASPECT_CLOUD_HOSTS` already
lists these hostnames as constants; they are just never consulted for
host ownership. Seeding the built-in entry from it would need no probe,
no committed JSON, and no `ASPECT_WORKSPACE` — here or anywhere else.
- **`ASPECT_WORKSPACE` looks unwired.** It is read in exactly one place
and set nowhere in the repo, so the repo-level config the CI path relies
on is unreachable unless something exports it. This PR exports it from
the workflow.

## Known consequences

- **Build results split.** Hosted jobs report to `app.aspect.build`;
self-hosted keep reporting to `app.silo-aws`. Accepted for now.
- **`build-task-ephemeral` / `test-task-ephemeral`** keep their
deliberate `--remote_cache=` (an explicit flag outranks the injected
one), so their no-remote-cache path is preserved — but they will now
stream BES, which they did not before.
- Vanilla-`bazel` jobs such as `build_release_artifacts.yaml` are still
uncovered; #1442 is the path to those.

## Test plan

Verified against a CLI built from this branch, with `HOME` pointed at
scratch dirs to simulate a fresh runner:

- Gate matrix — local dev, fork PR (`ASPECT_HAS_API_TOKEN=false`), and
Workflows runner all get no cache and no helper; GitHub-hosted + token
gets `--remote_cache=grpcs://cache.aspect.build`, the helper, and no
`--remote_header`.
- Credential helper on a fresh `HOME` with the committed config and
`ASPECT_WORKSPACE`: returns a bearer for `cache.aspect.build`, and
`{"headers":{}}` for a third-party host. Without `ASPECT_WORKSPACE`, no
headers — which is the failure this PR fixes.
- Metadata: `COMMIT_SHA`, `BRANCH_NAME`, `BUILD_URL`,
`REPO_OWNER/NAME/URL`, `CI_HOST`, `VCS`, `RUN_TYPE`, `USER` all present,
up from `ASPECT_TASK_NAME`/`ASPECT_TASK_ID` alone.
- Bazel accepts every new flag; `aspect format` clean.

Not verifiable locally, and the first CI run will settle both: whether
the org token's tenant is right (a 401 at token exchange) and whether
the org has remote-cache entitlement (a 403 at the cache). Both fail
loudly rather than degrading silently.

### Changes are visible to end-users: no

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
@gregmagolan
gregmagolan force-pushed the bazelrc-deployment-configs branch from 17a4453 to e5ee959 Compare September 16, 2026 01:50
@gregmagolan
gregmagolan force-pushed the bazelrc-deployment-configs branch from cffc489 to 1c08f4f Compare September 16, 2026 04:22
@gregmagolan
gregmagolan enabled auto-merge (squash) September 16, 2026 04:37
@gregmagolan
gregmagolan merged commit 2296b05 into main Sep 16, 2026
77 checks passed
@gregmagolan
gregmagolan deleted the bazelrc-deployment-configs branch September 16, 2026 04:37
joshcbarnes added a commit to aspect-build/rules_lint that referenced this pull request Sep 16, 2026
Follows the pattern from aspect-build/aspect-cli#1442: the endpoints and
the tuning they justify are declared once in .aspect/bazelrc, inert until
a `--config=aspect-*` names them, and Bazel authenticates by running
`aspect get` through a credential helper.

Two routes reach it, because this repo builds two ways:

  - `aspect <task>` in the root workspace, via .aspect/config.axl, which
    also calls get_build_metadata_flags so the stream arrives with a repo,
    branch, PR and author instead of the runner's login.

  - plain `bazel`, via .github/actions/aspect-cloud. Each examples/* tree
    is its own workspace, so the repo's .bazelrc never reaches it and
    integration-test's bats fixtures have no command line to extend. The
    action writes the *user* bazelrc instead, which every bazel process on
    the runner reads, and emits the same metadata from git and the Actions
    environment.

Both are gated on a token being present, so fork PRs — which get no
secrets — build exactly as they did before.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
joshcbarnes added a commit to aspect-build/rules_lint that referenced this pull request Sep 16, 2026
Follows the pattern from aspect-build/aspect-cli#1442: the endpoints and
the tuning they justify are declared once in .aspect/bazelrc, inert until
a `--config=aspect-*` names them, and Bazel authenticates by running
`aspect get` through a credential helper.

Two routes reach it, because this repo builds two ways:

  - `aspect <task>` in the root workspace, via .aspect/config.axl, which
    also calls get_build_metadata_flags so the stream arrives with a repo,
    branch, PR and author instead of the runner's login.

  - plain `bazel`, via .github/actions/aspect-cloud. Each examples/* tree
    is its own workspace, so the repo's .bazelrc never reaches it and
    integration-test's bats fixtures have no command line to extend. The
    action writes the *user* bazelrc instead, which every bazel process on
    the runner reads, and emits the same metadata from git and the Actions
    environment.

Both are gated on a token being present, so fork PRs — which get no
secrets — build exactly as they did before.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
joshcbarnes added a commit to aspect-build/rules_lint that referenced this pull request Sep 16, 2026
Follows the pattern from aspect-build/aspect-cli#1442: the endpoints and
the tuning they justify are declared once in .aspect/bazelrc, inert until
a `--config=aspect-*` names them, and Bazel authenticates by running
`aspect get` through a credential helper.

Two routes reach it, because this repo builds two ways:

  - `aspect <task>` in the root workspace, via .aspect/config.axl, which
    also calls get_build_metadata_flags so the stream arrives with a repo,
    branch, PR and author instead of the runner's login.

  - plain `bazel`, via .github/actions/aspect-cloud. Each examples/* tree
    is its own workspace, so the repo's .bazelrc never reaches it and
    integration-test's bats fixtures have no command line to extend. The
    action writes the *user* bazelrc instead, which every bazel process on
    the runner reads, and emits the same metadata from git and the Actions
    environment.

Both are gated on a token being present, so fork PRs — which get no
secrets — build exactly as they did before.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
joshcbarnes added a commit to aspect-build/rules_lint that referenced this pull request Sep 16, 2026
Follows the pattern from aspect-build/aspect-cli#1442: the endpoints and
the tuning they justify are declared once in .aspect/bazelrc, inert until
a `--config=aspect-*` names them, and Bazel authenticates by running
`aspect get` through a credential helper.

Two routes reach it, because this repo builds two ways:

  - `aspect <task>` in the root workspace, via .aspect/config.axl, which
    also calls get_build_metadata_flags so the stream arrives with a repo,
    branch, PR and author instead of the runner's login.

  - plain `bazel`, via .github/actions/aspect-cloud. Each examples/* tree
    is its own workspace, so the repo's .bazelrc never reaches it and
    integration-test's bats fixtures have no command line to extend. The
    action writes the *user* bazelrc instead, which every bazel process on
    the runner reads, and emits the same metadata from git and the Actions
    environment.

Both are gated on a token being present, so fork PRs — which get no
secrets — build exactly as they did before.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
joshcbarnes added a commit to aspect-build/rules_lint that referenced this pull request Sep 16, 2026
Only the aspect-cli jobs report builds now; every job still reads the
cache. The composite action that computed build metadata in bash for
vanilla Bazel is gone, and with it ASPECT_HAS_API_TOKEN.

Follows aspect-build/aspect-cli#1442 properly this time. `aspect setup
bazelrc` generates .aspect/bazelrc, so it is no longer a hand-written
imitation of that command's output, and `aspect <task> --remote` wires
the cache, BES, credentials and the --build_metadata the Web UI reads
from the deployment `aspect auth login` recorded. That is what the
previous commit claimed config.axl was doing via get_build_metadata_flags;
it was not, and on 2026.25.20 it could not — the public path for it landed
in #1442. Hence the CLI bump, applied to every examples/* workspace too,
since each pins its own version and the format/lint aspect-cli jobs run
there.

Two things the upgrade forced:

  - `--task-key` is now `--task:name`. The old spelling is not rejected,
    it is forwarded to Bazel, which fails on it.

  - --remote's BES half only reaches the sinks in `aspect build`/`test`
    (bazel/invocation.axl passes the trait's bes_backends to
    collect_bes_sinks; lint.axl and format.axl do not), so lint and
    format stream nothing. $ASPECT_BES names the backend explicitly,
    which goes through the path that does attach the login JWT, and is
    deduped against --remote. Drop it once the CLI wires those tasks.

Vanilla Bazel has no --remote, and each examples/* tree is its own
workspace the repo's .bazelrc never reaches, so those jobs still go
through a ~/.bazelrc — now two try-imports and one gated line that
setup-aspect writes, rather than a 94-line action. It names
aspect-cloud-cache from .aspect/ci.bazelrc: Aspect Cloud's cache without
its BES, borrowing the generated file's groups by name so the tuning
stays in step. Kept out of .aspect/bazelrc so regenerating cannot
clobber it, and preferred over --omit-bazel-flag because omitting the
BES endpoints leaves the aspect-bes tuning group chained and the
generated "remote cache + BES" comment contradicting the file.

Fork PRs get no secret, so the activation line is withheld (an
unauthenticated credential helper is fatal) and --remote resolves to
none.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants