Use native buildkit symlink file action for post-install symlinks#1098
Use native buildkit symlink file action for post-install symlinks#1098cpuguy83 wants to merge 2 commits into
Conversation
There was a problem hiding this comment.
Pull request overview
This PR switches the post-install symlink creation (image.post.symlinks) from executing a shell script (ln -s, chown -h, chgrp -h) in a worker container to using BuildKit's native llb.Symlink file action when the connected BuildKit instance supports it (via pb.CapFileSymlinkCreate). When the capability is unavailable or DALEC_DISABLE_SYMLINK=1 is set, the original exec-based implementation is used as a fallback.
Changes:
- Added capability detection (
SupportsSymlink) infrontend/gateway.goand wired it infrontend/router.go, following the establishedDisableDiffMerge/SupportsDiffMergepattern. TheDALEC_DISABLE_SYMLINKbuild arg is registered inload.go. - Refactored
InstallPostSymlinksinhelpers.gointo two internal functions—installPostSymlinksNative(BuildKit file action chain withllb.Mkdir+llb.Symlink) andinstallPostSymlinksExec(preserved shell-exec fallback)—with ownership semantics that explicitly set unspecified user/group to root (id 0). - Extracted post-install symlink integration tests from the combined container test into a dedicated
testLinuxPostInstallSymlinksfunction that runs both native and exec fallback paths, and added comprehensive unit tests inhelpers_symlink_test.goasserting the marshaled LLB output.
Reviewed changes
Copilot reviewed 6 out of 6 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
frontend/gateway.go |
Added SupportsSymlink/checkSymlink for CapFileSymlinkCreate detection, mirroring SupportsDiffMerge |
frontend/router.go |
Wired DisableSymlink(true) when symlink capability is not supported |
helpers.go |
Split InstallPostSymlinks into native (llb.Symlink file action) and exec (ln -s shell script) paths; added symlinkChown helper |
load.go |
Registered DALEC_DISABLE_SYMLINK as a known build arg |
helpers_symlink_test.go |
New unit tests verifying marshaled LLB ops for both native and exec paths |
test/linux_target_test.go |
Moved symlink tests to dedicated testLinuxPostInstallSymlinks with subtests for native and exec-fallback paths |
6be4538 to
917550f
Compare
4de62d9 to
3b65fd1
Compare
|
@cpuguy83 can you resolve conflicts? |
invidian
left a comment
There was a problem hiding this comment.
Should we also add some documentation around this feature environment variable?
3b65fd1 to
e301359
Compare
✅ Deploy Preview for dalec ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
LLBOpsFromState is only ever called from tests that already hold a *testing.T, so take one and assert internally via t.Fatalf instead of returning an error. Callers drop the repeated error-check boilerplate. Signed-off-by: Brian Goff <cpuguy83@gmail.com>
The args are not so much a feature as they are a way for us to test both modes. I'd rather not document them for public use. |
e302b20 to
80d85db
Compare
invidian
left a comment
There was a problem hiding this comment.
Just some nitpicks, overall LGTM
Post-install symlinks (image.post.symlinks) were created by executing a shell script (ln -s, chown -h, chgrp -h) in the worker, mounting /etc/passwd and /etc/group to resolve ownership. Buildkit now provides a native symlink file action, so use it when available. Support is detected via the pb.CapFileSymlinkCreate LLB capability, mirroring the existing diff/merge detection. When the connected buildkit does not advertise the capability (or DALEC_DISABLE_SYMLINK=1 is set), Dalec falls back to the original shell-exec implementation, preserving backward compatibility with older buildkit versions. The native path chains llb.Mkdir (for parent directories, which the symlink action does not create itself) and llb.Symlink into a single file op resolved against the installed rootfs, avoiding the extra exec plus the /etc/passwd and /etc/group mounts. Ownership semantics are preserved exactly: chowning by user name alone would also set the group to that user's primary group, so both user and group are always set explicitly and an unspecified side stays root (id 0), matching chown -h user / chgrp -h group. Integration tests run the post-install symlink scenario under both paths (native by default and the exec fallback via DALEC_DISABLE_SYMLINK=1) and the block is removed from the large combined container test to avoid duplication. Signed-off-by: Brian Goff <cpuguy83@gmail.com>
80d85db to
15f89c6
Compare
What this PR does / why we need it:
Post-install symlinks (
image.post.symlinks) were created by executing a shellscript (
ln -s,chown -h,chgrp -h) in the worker, mounting/etc/passwdand
/etc/groupto resolve ownership by name. Buildkit now provides a nativesymlink file action, so this switches to it when it is available.
Support is detected via the
pb.CapFileSymlinkCreateLLB capability, mirroringthe existing diff/merge capability detection. When the connected buildkit does
not advertise the capability — or
DALEC_DISABLE_SYMLINK=1is set — Dalec fallsback to the original shell-exec implementation, so older buildkit versions keep
working.
The native path chains
llb.Mkdir(for parent directories, which the symlinkaction does not create itself) and
llb.Symlinkinto a single file op resolvedagainst the installed rootfs. This avoids the extra
execand the/etc/passwd/
/etc/groupmounts.Ownership semantics are preserved exactly. Chowning by user name alone would
also set the group to that user's primary group, whereas the exec fallback
leaves the unspecified side as root. To match, both user and group are always
set explicitly and an unspecified side stays
0, mirroringchown -h user/chgrp -h group.Which issue(s) this PR fixes (optional, using
fixes #<issue number>(, fixes #<issue_number>, ...)format, will close the issue(s) when the PR gets merged):Fixes #
Special notes for your reviewer:
frontend/gateway.go(SupportsSymlink) and iswired in
frontend/router.go, just likeDisableDiffMerge.DALEC_DISABLE_SYMLINKis registered as a known build-arg inload.goand canbe used to force the legacy behavior.
helpers_symlink_test.goassert the marshaled LLB for both thenative and exec paths (symlink actions, parent mkdirs, and ownership).
testLinuxPostInstallSymlinksruns the post-installsymlink scenario under both paths via subtests — native by default and the
exec fallback with
DALEC_DISABLE_SYMLINK=1. The equivalent block was removedfrom the large combined container test to avoid duplicating the coverage.