Skip to content

chore: evaluate Remote Build Execution (RBE) @ Namespace - #10579

Open
basvandijk wants to merge 245 commits into
masterfrom
basvandijk/namespace-bazel-remote-execution
Open

chore: evaluate Remote Build Execution (RBE) @ Namespace#10579
basvandijk wants to merge 245 commits into
masterfrom
basvandijk/namespace-bazel-remote-execution

Conversation

@basvandijk

@basvandijk basvandijk commented Jun 26, 2026

Copy link
Copy Markdown
Collaborator

Why

To reduce reliance on DFINITY's own Data Centers and to make developing, building and testing the IC more portable we're planning to switch the majority of CI to run on Namespace, a CI provider who DFINITY already uses for ARM64 builds on Linux and MacOS.

In particular we're planning to move the bazel-test-all job (AMD64 bazel build and test) to Namespace. This includes system-tests. Since Namespace does not have access to Farm the system-tests on Namespace will use the Local system-test backend, i.e. each test will spawn its QEMU VMs locally on the worker running the bazel action.

Considering that local system-tests are resource heavy, i.e. they can easily consume 10s of CPUs, they shouldn't be executed on a single worker because that would effectively sequentialise all system-tests which would consume almost 4 hours.

We therefor configure bazel to run its actions on a Remote Build Execution (RBE) cluster @ Namespace. This way builds and tests distribute over many workers and run in parallel. 15 workers for now of shape 32x64 that each can accept 16 action slots.

Before switching to RBE we first need to evaluate its performance and stability. That's this PR.

What

To compare our existing bazel-test-all with RBE we need to have a copy of that job that is as similar as possible with the only difference that it runs bazel on RBE @ Namespace. To this end:

  • ci-kickoff.yml is extended with a ci-rbe-evaluation job (like ci-main) which calls the new ci-rbe-evaluation.yml workflow.

  • ci-rbe-evaluation.yml is a slimmed down copy of ci-main.yml with similar jobs like config, infer-bazel-targets and bazel-test-all-rbe. The infer-bazel-targets job will behave the same as in ci-main except that it excludes Farm-based system-tests; the reverse is true for infer-bazel-targets in ci-main which excludes local system-tests.

  • bazel-test-all-rbe is similar to bazel-test-all except that it runs on a namespace-profile-rbe-driver-amd64-linux-16x32 runner and configures bazel to use Namespace's RBE cluster.
    Note that this job doesn't use the same container image as bazel-test-all but instead uses a special optimised variant stored at Namespace's Container Registry (nscr.io).

  • container-autobuild.yml‎ has been extended with a rbe-worker-image job which generates this special variant. It takes the ic-build container image, mirrors it to nscr.io and optimises it for RBE. The existing update-image-references job will then make sure references to this image are updated in the code .

Evaluation

Since now both bazel-test-all and bazel-test-all-rbe will run on each update to each PR, for each push to master and for each Release Testing run we can compare the difference in performance, stability and debugability.

Note that bazel-test-all-rbe is configured with continue-on-error: true to ensure it doesn't block PRs or releases in case it fails.

Regarding debugability, bazel-test-all-rbe doesn't upload its BEP data to our internal BuildBuddy. Instead it uploads logs of failed runs to Namespace's Artifact Storage from which users can download them.

We'll run with this for a short while until we're confident we can switch to RBE @ Namespace completely.

Unresolved Questions

There are a currently 94 system-tests that are currently configured as Farm-only (backend = "farm") we need to decide how to handle these when we switch to Namespace completely.

@basvandijk
basvandijk requested a review from Copilot June 26, 2026 12:28
@basvandijk basvandijk changed the title Experiment with Bazel Remote Execution (BRE) on Namespace chore: experiment with Bazel Remote Execution (BRE) on Namespace Jun 26, 2026
@github-actions github-actions Bot added the chore label Jun 26, 2026

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

This PR introduces an experimental GitHub Actions path to run bazel test using Namespace Bazel Remote Execution (BRE), including automation to build/mirror/optimize a worker image and keep the workflow pinned to an immutable digest.

Changes:

  • Adds a new experimental workflow to run bazel test on Namespace runners with remote execution enabled.
  • Extends the container autobuild workflow with jobs to mirror ic-build into nscr.io, optimize it for BRE, and automatically update the pinned worker-image digest used by the new workflow.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.

File Description
.github/workflows/container-autobuild.yml Adds jobs to create an optimized Namespace BRE worker image and auto-update the pinned digest reference in workflows.
.github/workflows/bre-namespace-test.yml New opt-in workflow to run bazel test using Namespace remote execution with a pinned worker image.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread .github/workflows/bre-namespace-test.yml Outdated

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 2 out of 2 changed files in this pull request and generated 4 comments.

Comment thread .github/workflows/container-autobuild.yml Outdated
Comment thread .github/workflows/container-autobuild.yml Outdated
Comment thread .github/workflows/container-autobuild.yml Outdated
Comment thread .github/workflows/bre-namespace-test.yml Outdated

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 2 out of 2 changed files in this pull request and generated no new comments.

Add a new 'bre-namespace-test.yml' workflow that runs 'bazel test' on Namespace runners using Bazel Remote Execution (BRE). Actions execute on Namespace workers booted from a custom worker image (a mirror of ic-build).

Extend 'container-autobuild.yml' to mirror the freshly built ic-build image into nscr.io, optimize it for BRE, and pin the resulting digest. These jobs are decoupled from the production image-reference update so an early-access BRE failure can never block it.
Addresses Copilot review: 'nsc bazel execution setup' writes short-lived credentials into the bazelrc, so 'cat'-ing it could leak auth material into the Actions logs.
…update job

- Use the same fully-qualified nscr.io ref for the upload destination and the digest lookup, so the inspected tag is guaranteed to exist.

- Guard bre-worker-image and bre-namespace-test against fork PRs via head.repo.full_name == github.repository (matching ci-kickoff.yml), since both run on privileged Namespace runners with pre-authenticated nsc.

- Drop update-image-references from update-worker-reference's needs for true decoupling; the existing 'git pull --rebase' absorbs any concurrent push.
@basvandijk
basvandijk force-pushed the basvandijk/namespace-bazel-remote-execution branch from 27f3f10 to 95ee442 Compare June 28, 2026 12:15
…ac895bdd550cac7bacb9dad553bae

ic-build: sha256:f4c6c7e0e16da470cba7ebceb0145f588d5fd4859c04acfa607bee475ecfa914

ic-dev:   sha256:2f98d344d708a1ae70938d5e777a1f141f7f2a9545687653f407a405eb1a27ea
@github-actions

github-actions Bot commented Jun 28, 2026

Copy link
Copy Markdown
Contributor

Run URL: https://github.com/dfinity/ic/actions/runs/30281453965

New container images with tag: d82f82fd3da23633ea37dee630d0eff9814d04bfc8e46f6e9a1ebd61765d3472
ic-build: sha256:3e3ee32a5de1fde724d4ab931cd5868dad52fef823c41331494a5b36742a6907
ic-dev: sha256:ad31e83146e452c3b6c31ecbb25c1ccfda79ecd10ec16e8dedb1f6952f1dfd6c
ic-build-worker: nscr.io/c9ptjuknd7oc6/ic-build-worker@sha256:145163a97a493d19798422b6b87cabb5b64d8eac50318a14395d6a25d3796439

update-image-references now depends on bre-worker-image (default needs semantics) and pins the worker digest unconditionally in the same commit, dropping the cancelled()-guard and the separate update-worker-reference job. Waiting on bre-worker-image before committing/pushing avoids the concurrency cancellation seen earlier.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 19 out of 19 changed files in this pull request and generated 3 comments.

Comment thread .github/workflows/bre-namespace-test.yml Outdated
Comment thread .github/workflows/bre-namespace-test.yml Outdated
Comment thread .github/workflows/container-autobuild.yml Outdated
nsc base-image upload prepends $NSC_CONTAINER_REGISTRY (nscr.io/<tenant>) to a relative name. Passing the fully-qualified nscr.io/dfinity ref caused a double-prefixed push (nscr.io/<tenant>/nscr.io/dfinity/...) and a 401 on the digest lookup. Derive the registry from $NSC_CONTAINER_REGISTRY, upload a relative name, pin the resulting full ref, and match any tenant in the pin sed. Also fixes a stale comment referencing the removed update-worker-reference job.

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This pull request changes code owned by the Governance team. Therefore, make sure that
you have considered the following (for Governance-owned code):

  1. Update unreleased_changelog.md (if there are behavior changes, even if they are
    non-breaking).

  2. Are there BREAKING changes?

  3. Is a data migration needed?

  4. Security review?

How to Satisfy This Automatic Review

  1. Go to the bottom of the pull request page.

  2. Look for where it says this bot is requesting changes.

  3. Click the three dots to the right.

  4. Select "Dismiss review".

  5. In the text entry box, respond to each of the numbered items in the previous
    section, declare one of the following:

  • Done.

  • $REASON_WHY_NO_NEED. E.g. for unreleased_changelog.md, "No
    canister behavior changes.", or for item 2, "Existing APIs
    behave as before.".

Brief Guide to "Externally Visible" Changes

"Externally visible behavior change" is very often due to some NEW canister API.

Changes to EXISTING APIs are more likely to be "breaking".

If these changes are breaking, make sure that clients know how to migrate, how to
maintain their continuity of operations.

If your changes are behind a feature flag, then, do NOT add entrie(s) to
unreleased_changelog.md in this PR! But rather, add entrie(s) later, in the PR
that enables these changes in production.

Reference(s)

For a more comprehensive checklist, see here.

GOVERNANCE_CHECKLIST_REMINDER_DEDUP

@zeropath-ai

zeropath-ai Bot commented Jul 24, 2026

Copy link
Copy Markdown

No security or compliance issues detected. Reviewed everything up to cbabdf1.

Security Overview
Detected Code Changes
Change Type Relevant files
Enhancement ► .github/workflows/ci-rbe-evaluation.yml
    Add new CI RBE Evaluation workflow (new file)
Enhancement ► .github/workflows/ci-main.yml
    Switch ic-build-image to new sha256:3e3ee...6907 and adjust related references
► .github/workflows/ci-pr-only.yml
    Switch ic-build-image to new sha256:3e3ee...6907
Enhancement ► .github/workflows/container-autobuild.yml
    Add rbe-worker-image job to build and publish Remote Build Execution worker image
► .github/workflows/update-mainnet-canister-revisions.yaml
    Switch ic-build image to new sha256:3e3ee...6907
Enhancement ► .github/workflows/container-api-bn-recovery.yml
    Switch ic-build image to new sha256:3e3ee...6907
Enhancement ► .github/workflows/container-scan-nightly.yml
    Switch ic-build image to new sha256:3e3ee...6907
Enhancement ► .github/workflows/container-autobuild.yml\n    Add rbe-worker-image integration and references to updated worker image in update logic
Enhancement ► ci/scripts/targets.py
    Update target generation logic (commented sections removed; adjustments to excluded tags)
Enhancement ► ic-os/bootloader/BUILD.bazel
    Add exec_properties with namespace_requires_network = true
Enhancement ► rs/ic_os/sev/host/BUILD.bazel
    Add exec_properties with namespace_requires_network = true
Enhancement ► rs/ledger_suite/icp/BUILD.bazel
    Add exec_properties with namespace_requires_network = true
Enhancement ► rs/ledger_suite/icrc1/BUILD.bazel
    Add exec_properties with namespace_requires_network = true
Enhancement ► rs/nns/integration_tests/BUILD.bazel
    Add exec_properties with namespace_requires_network = true
Enhancement ► rs/sns/integration_tests/BUILD.bazel
    Add exec_properties with namespace_requires_network = true
Enhancement ► bazel/hermetic_cc_toolchain_cache_dir.patch
    Patch to shard toolchain cache per action to avoid race conditions on remote execution
Enhancement ► toolchain/zig-wrapper.zig
    Modify to shard cache per action in remote execution environments
Enhancement ► a/.devcontainer/devcontainer.json (and related .github/workflows references switch to new ic-build image sha)
Bug Fix (Not explicitly stated; changes primarily relate to image references and RBE-related enhancements)

@zeropath-ai

zeropath-ai Bot commented Jul 24, 2026

Copy link
Copy Markdown

No security or compliance issues detected. Reviewed everything up to cbabdf1.

Security Overview
Detected Code Changes
Change Type Relevant files
Enhancement ► .github/workflows/ci-rbe-evaluation.yml
    Add new CI RBE Evaluation workflow (new file)
Enhancement ► .github/workflows/ci-main.yml
    Switch ic-build-image to new sha256:3e3ee...6907 and adjust related references
► .github/workflows/ci-pr-only.yml
    Switch ic-build-image to new sha256:3e3ee...6907
Enhancement ► .github/workflows/container-autobuild.yml
    Add rbe-worker-image job to build and publish Remote Build Execution worker image
► .github/workflows/update-mainnet-canister-revisions.yaml
    Switch ic-build image to new sha256:3e3ee...6907
Enhancement ► .github/workflows/container-api-bn-recovery.yml
    Switch ic-build image to new sha256:3e3ee...6907
Enhancement ► .github/workflows/container-scan-nightly.yml
    Switch ic-build image to new sha256:3e3ee...6907
Enhancement ► .github/workflows/container-autobuild.yml\n    Add rbe-worker-image integration and references to updated worker image in update logic
Enhancement ► ci/scripts/targets.py
    Update target generation logic (commented sections removed; adjustments to excluded tags)
Enhancement ► ic-os/bootloader/BUILD.bazel
    Add exec_properties with namespace_requires_network = true
Enhancement ► rs/ic_os/sev/host/BUILD.bazel
    Add exec_properties with namespace_requires_network = true
Enhancement ► rs/ledger_suite/icp/BUILD.bazel
    Add exec_properties with namespace_requires_network = true
Enhancement ► rs/ledger_suite/icrc1/BUILD.bazel
    Add exec_properties with namespace_requires_network = true
Enhancement ► rs/nns/integration_tests/BUILD.bazel
    Add exec_properties with namespace_requires_network = true
Enhancement ► rs/sns/integration_tests/BUILD.bazel
    Add exec_properties with namespace_requires_network = true
Enhancement ► bazel/hermetic_cc_toolchain_cache_dir.patch
    Patch to shard toolchain cache per action to avoid race conditions on remote execution
Enhancement ► toolchain/zig-wrapper.zig
    Modify to shard cache per action in remote execution environments
Enhancement ► a/.devcontainer/devcontainer.json (and related .github/workflows references switch to new ic-build image sha)
Bug Fix (Not explicitly stated; changes primarily relate to image references and RBE-related enhancements)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

approving for Governance-owned files.

basvandijk and others added 10 commits July 25, 2026 12:06
Bazel declares test.xml as an output of every test action. When a test
doesn't write $XML_OUTPUT_FILE itself, StandaloneTestStrategy runs a
*second* spawn (@bazel_tools//tools/test:test_xml_generator) to derive it
from test.log. Under RBE that spawn has to queue for a free worker to do
well under a second of work: in run 30158073133 every one of the 152
executed system tests paid a median 435s of queueing for it (p90 1726s).

Convert the SystemGroupSummary into a JUnit XML document and write it to
$XML_OUTPUT_FILE at the end of the parent process. Bazel only runs the
generator when the test didn't produce test.xml itself, so writing it
ourselves skips that spawn entirely.

Also stop the test-driver e2e scenarios from inheriting XML_OUTPUT_FILE:
they spawn the driver as a child process, and those children would each
overwrite the test.xml that Bazel expects //rs/tests/idx:test_e2e_scenarios
itself to produce.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…it XML

Every <testcase> was emitted with status="run", including the skipped
ones, which contradicts the <skipped/> child element they carry and can
confuse consumers that aggregate on the attribute. Derive it from the
outcome instead, following GoogleTest's convention that Bazel's own
test_xml_generator also emits: "run" for a case that executed, "notrun"
for one that didn't.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Addresses review comments on #10908:

- Validate that `cpus_oversubscription_factor` and `cpus` are ints >= 1 and
  `fail()` with a clear message otherwise. Previously a 0 factor produced an
  obscure division-by-zero at analysis time, a negative one silently produced
  a nonsense reservation, and a float produced a non-integral `cpu`
  exec_property like "16.0".
- Compute the ceiling with `(cpus + factor - 1) // factor` instead of
  `-(-cpus // factor)`; now that both are known-positive ints, this is the
  clearer idiom. Verified the two formulas agree, and that all 369 `_local`
  targets keep byte-identical `cpu` exec_properties.
- Reword the `cpus_oversubscription_factor` docstring, which was
  grammatically unclear ("factor to divide the requested cpus with which").

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

@nmattia nmattia left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Really exciting! couple questions related to the GHA side of things to start with

# This job runs a bazel build & test on the Remote Build Execution cluster @ Namespace.
# It's currently in the evaluation phase where we compare its speed and stability with the `bazel-test-all` job.
# We expect it to fail and that's OK and it shouldn't block PRs & releases.
ci-rbe-evaluation:

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

for the time being (while it's being evaluated) how about we keep this as a separate workflow (./.github/workflows/ci-rbe-evaluation.yml) with regular (eg pull_request) trigger and only wire it in here when we decide to make it blocking?

this way we keep things simple and agile for the RBE side of things and avoid modifying the infra we currently rely on for gatekeeping

@basvandijk basvandijk Jul 27, 2026

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

As discussed privately: we need to make sure this workflow doesn't run on PRs from forks. ci-kickoff.yml has the protection in place for that. If we would introduce a new workflow with its own pull_request trigger we would have to distribute the right if condition to every job in the workflow.

The current approach is simpler and more secure.

id: worker
shell: bash
run: |
set -xeuo pipefail

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Suggested change
set -xeuo pipefail
set -euo pipefail


ic_build_repo="ghcr.io/dfinity/ic-build"
src="${ic_build_repo}@${{ needs.ic-build-image.outputs.ic-build-imageid }}"
upload_log="$(nsc base-image upload "$src" "ic-build-worker:${{ needs.build-image-prep.outputs.image_tag }}" 2>&1)"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

nit: use tee

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Done.

src="${ic_build_repo}@${{ needs.ic-build-image.outputs.ic-build-imageid }}"
upload_log="$(nsc base-image upload "$src" "ic-build-worker:${{ needs.build-image-prep.outputs.image_tag }}" 2>&1)"
echo "$upload_log"
worker_digest="$(printf '%s\n' "$upload_log" | grep -i 'Uploaded base image' | grep -oE 'sha256:[0-9a-f]{64}' | tail -n1 || true)"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

probably simpler to read the digest from the build-push-action: https://github.com/docker/build-push-action#outputs

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

I suggest we do a revamp of the container image builds and how we refer to them in a separate PR because I don't want to make any imageid and digest changes which don't strictly have to do with RBE.

uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
ref: ${{ github.head_ref }}
ref: ${{ github.head_ref || github.ref_name }}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

is this relevant?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

IDK anymore why I had that there. Removed.

-m 'ic-build: ${{ needs.ic-build-image.outputs.ic-build-imageid }}' \
-m 'ic-dev: ${{ needs.ic-build-image.outputs.ic-dev-imageid }}'
-m 'ic-dev: ${{ needs.ic-build-image.outputs.ic-dev-imageid }}' \
-m 'ic-build-worker: ${{ needs.rbe-worker-image.outputs.worker-image }}'

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I'm a bit surprised, why is the worker image different? isn't it just ic-build?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

It's the RBE optimised variant of ic-build

basvandijk and others added 9 commits July 27, 2026 14:47
…d04bfc8e46f6e9a1ebd61765d3472

ic-build: sha256:7d8e6aa9eae77e13e91ed30835c0fa72e05e86d5067c6d0dd14905e8c53efc36

ic-dev:   sha256:06d7680338792de19f456577f37614d344e3feb119b843f535311ec5bdd66eb6

ic-build-worker: nscr.io/c9ptjuknd7oc6/ic-build-worker@sha256:28668b9bb053f840fb12354545ef4a2434cb41b7a7dfcb594afc6cb6686e4c17
…d04bfc8e46f6e9a1ebd61765d3472

ic-build: sha256:3e3ee32a5de1fde724d4ab931cd5868dad52fef823c41331494a5b36742a6907

ic-dev:   sha256:ad31e83146e452c3b6c31ecbb25c1ccfda79ecd10ec16e8dedb1f6952f1dfd6c

ic-build-worker: nscr.io/c9ptjuknd7oc6/ic-build-worker@sha256:145163a97a493d19798422b6b87cabb5b64d8eac50318a14395d6a25d3796439
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

9 participants