Skip to content

Proposal: add support for artifact aliasing - #419

Merged
lberki merged 7 commits into
bazelbuild:mainfrom
thesayyn:patch-1
Jul 23, 2026
Merged

Proposal: add support for artifact aliasing#419
lberki merged 7 commits into
bazelbuild:mainfrom
thesayyn:patch-1

Conversation

@thesayyn

Copy link
Copy Markdown
Contributor

This document proposes artifact aliasing in Bazel, allowing content to be addressable under multiple exec paths without copying. It details the API, semantics, and implications for backward compatibility and laydown strategies.

This document proposes artifact aliasing in Bazel, allowing content to be addressable under multiple exec paths without copying. It details the API, semantics, and implications for backward compatibility and laydown strategies.
@thesayyn
thesayyn requested review from jin and lberki as code owners July 21, 2026 01:54
thesayyn added a commit to thesayyn/bazel that referenced this pull request Jul 21, 2026
Adds ctx.actions.copy(output, target_file): makes target_file's content
available at output (a second exec path), sharing its digest, with no byte
copy and no spawn.

Unlike ctx.actions.symlink, which plants a followable symbolic link that
resolves back to the target's location, ctx.actions.copy only declares the
relationship and defers materialization to sandbox/spawn creation -- the
execution strategy places the target's content at the output's own path (hard
link, copy, or the shared digest on remote execution), so its realpath stays
inside the consuming tree (which tools such as Node.js require). Strategies
that cannot materialize content (a purely symlinking sandbox or non-sandboxed
local execution) fall back to a symlink. The original is never a declared
input of the consumer -- it sees only the copy.

Reuses the existing resolved-path metadata rather than adding new machinery:
FileArtifactValue.isContentCopy() marks the value (ordinary symlinks are
unchanged), a declaration-only CopyAction injects it, and the remote
prefetcher and the local sandbox stage the content from the recorded source.

Design: bazelbuild/proposals#419
thesayyn added a commit to thesayyn/bazel that referenced this pull request Jul 21, 2026
Adds ctx.actions.copy(output, target_file): makes target_file's content
available at output (a second exec path), sharing its digest, with no byte
copy and no spawn.

Unlike ctx.actions.symlink, which plants a followable symbolic link that
resolves back to the target's location, ctx.actions.copy only declares the
relationship and defers materialization to sandbox/spawn creation -- the
execution strategy places the target's content at the output's own path (hard
link, copy, or the shared digest on remote execution), so its realpath stays
inside the consuming tree (which tools such as Node.js require). Strategies
that cannot materialize content (a purely symlinking sandbox or non-sandboxed
local execution) fall back to a symlink. The original is never a declared
input of the consumer -- it sees only the copy.

Reuses the existing resolved-path metadata rather than adding new machinery:
FileArtifactValue.isContentCopy() marks the value (ordinary symlinks are
unchanged), a declaration-only CopyAction injects it, and the remote
prefetcher and the local sandbox stage the content from the recorded source.

Design: bazelbuild/proposals#419
thesayyn added a commit to thesayyn/bazel that referenced this pull request Jul 21, 2026
Adds ctx.actions.copy(output, target_file): makes target_file's content
available at output (a second exec path), sharing its digest, with no byte
copy and no spawn.

Unlike ctx.actions.symlink, which plants a followable symbolic link that
resolves back to the target's location, ctx.actions.copy only declares the
relationship and defers materialization to sandbox/spawn creation -- the
execution strategy places the target's content at the output's own path (hard
link, copy, or the shared digest on remote execution), so its realpath stays
inside the consuming tree (which tools such as Node.js require). Strategies
that cannot materialize content (a purely symlinking sandbox or non-sandboxed
local execution) fall back to a symlink. The original is never a declared
input of the consumer -- it sees only the copy.

Reuses the existing resolved-path metadata rather than adding new machinery:
FileArtifactValue.isContentCopy() marks the value (ordinary symlinks are
unchanged), a declaration-only CopyAction injects it, and the remote
prefetcher and the local sandbox stage the content from the recorded source.

Design: bazelbuild/proposals#419
thesayyn added a commit to thesayyn/bazel that referenced this pull request Jul 21, 2026
Adds ctx.actions.copy(output, target_file): makes target_file's content
available at output (a second exec path), sharing its digest, with no byte
copy and no spawn.

Unlike ctx.actions.symlink, which plants a followable symbolic link that
resolves back to the target's location, ctx.actions.copy only declares the
relationship and defers materialization to sandbox/spawn creation -- the
execution strategy places the target's content at the output's own path (hard
link, copy, or the shared digest on remote execution), so its realpath stays
inside the consuming tree (which tools such as Node.js require). Strategies
that cannot materialize content (a purely symlinking sandbox or non-sandboxed
local execution) fall back to a symlink. The original is never a declared
input of the consumer -- it sees only the copy.

Reuses the existing resolved-path metadata rather than adding new machinery:
FileArtifactValue.isContentCopy() marks the value (ordinary symlinks are
unchanged), a declaration-only CopyAction injects it, and the remote
prefetcher and the local sandbox stage the content from the recorded source.

Design: bazelbuild/proposals#419
thesayyn added a commit to thesayyn/bazel that referenced this pull request Jul 21, 2026
Adds ctx.actions.copy(output, target_file): makes target_file's content
available at output (a second exec path), sharing its digest, with no byte
copy and no spawn.

Unlike ctx.actions.symlink, which plants a followable symbolic link that
resolves back to the target's location, ctx.actions.copy only declares the
relationship and defers materialization to sandbox/spawn creation -- the
execution strategy places the target's content at the output's own path (hard
link, copy, or the shared digest on remote execution), so its realpath stays
inside the consuming tree (which tools such as Node.js require). Strategies
that cannot materialize content (a purely symlinking sandbox or non-sandboxed
local execution) fall back to a symlink. The original is never a declared
input of the consumer -- it sees only the copy.

Reuses the existing resolved-path metadata rather than adding new machinery:
FileArtifactValue.isContentCopy() marks the value (ordinary symlinks are
unchanged), a declaration-only CopyAction injects it, and the remote
prefetcher and the local sandbox stage the content from the recorded source.

Design: bazelbuild/proposals#419
thesayyn added a commit to thesayyn/bazel that referenced this pull request Jul 21, 2026
Adds ctx.actions.copy(output, target_file): makes target_file's content
available at output (a second exec path), sharing its digest, with no byte
copy and no spawn.

Unlike ctx.actions.symlink, which plants a followable symbolic link that
resolves back to the target's location, ctx.actions.copy only declares the
relationship and defers materialization to sandbox/spawn creation -- the
execution strategy places the target's content at the output's own path (hard
link, copy, or the shared digest on remote execution), so its realpath stays
inside the consuming tree (which tools such as Node.js require). Strategies
that cannot materialize content (a purely symlinking sandbox or non-sandboxed
local execution) fall back to a symlink. The original is never a declared
input of the consumer -- it sees only the copy.

Reuses the existing resolved-path metadata rather than adding new machinery:
FileArtifactValue.isContentCopy() marks the value (ordinary symlinks are
unchanged), a declaration-only CopyAction injects it, and the remote
prefetcher and the local sandbox stage the content from the recorded source.

Design: bazelbuild/proposals#419
Comment thread designs/2026-07-20-artifact-alias.md Outdated
Comment thread designs/2026-07-20-artifact-alias.md Outdated
Comment thread designs/2026-07-20-artifact-alias.md Outdated
Add artifact aliasing proposal with API and semantics.
@thesayyn
thesayyn requested a review from fmeum July 21, 2026 18:39
@thesayyn thesayyn changed the title Add proposal for artifact aliasing in Bazel Proposal: add support for artifact aliasing Jul 21, 2026
thesayyn added 2 commits July 21, 2026 11:48
Explain how tree aliases handle symlinks and content staging.
@lberki

lberki commented Jul 22, 2026

Copy link
Copy Markdown
Contributor

Why not link this from the main list in README.md? (put it in "Draft" state)

@sluongng

Copy link
Copy Markdown

potentially duplicated of #396 ?

@sluongng sluongng mentioned this pull request Jul 22, 2026
@thesayyn

Copy link
Copy Markdown
Contributor Author

potentially duplicated of #396

I described how this is different than what's on #396 and how it subsumes the proposal there.

@thesayyn

Copy link
Copy Markdown
Contributor Author

Why not link this from the main list in README.md

Will do, i missed that.

@lberki

lberki commented Jul 22, 2026

Copy link
Copy Markdown
Contributor

Why not link this from the main list in README.md

Will do, i missed that.

Far be it from me to be overly critical, but you haven't yet?

@thesayyn

Copy link
Copy Markdown
Contributor Author

Fixed, and fixed an earlier issue with sandbox proposal. thanks @lberki

Don't mind me asking, what's the next step to get this to be accepted?

@lberki
lberki merged commit 74a5b46 into bazelbuild:main Jul 23, 2026
1 check passed
@lberki

lberki commented Jul 23, 2026

Copy link
Copy Markdown
Contributor

We'll have to find a reviewer (and some capacity to review the change). Let me see what I can do.

@fmeum

fmeum commented Jul 23, 2026

Copy link
Copy Markdown
Contributor

Since this was sent as Markdown and not as a Google doc, should we comment on this PR or create a separate GitHub discussion? There is precedent for both :-)

Edit: Left some early general comments here: #396 (comment)

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.

4 participants