feat: Pass Dockerfiles to unikraft build - #503
danielvallance wants to merge 2 commits into
Conversation
There was a problem hiding this comment.
馃煛 Changes recommended
Add end-to-end coverage for direct Kraftfile inputs, precedence, relative sources, and resource cleanup.
Get a fresh assessment by requesting another Copilot review.
Pull request overview
Adds Dockerfile-based, kernel-less image builds with architecture validation and Kraftfile precedence.
Changes:
- Supports directory and direct-file build inputs.
- Adds input-resolution tests, integration coverage, help snapshots, and documentation.
File summaries
| File | Summary |
|---|---|
skills/unikraft-cli/SKILL.md |
Documents Dockerfile builds. |
README.md |
Adds Dockerfile build guidance. |
internal/cmd/build.go |
Loads inputs and validates architecture. |
internal/builder/rootfs.go |
Reuses Dockerfile detection. |
internal/builder/input.go |
Resolves Kraftfile and Dockerfile inputs; needs additional end-to-end coverage. |
internal/builder/input_test.go |
Tests input resolution. |
cmd/unikraft/testdata/TestHelp/images |
Updates image help output. |
cmd/unikraft/testdata/TestHelp/build |
Updates build help output. |
cmd/unikraft/integration/build_test.go |
Tests Dockerfile-only builds. |
Review details
- Files reviewed: 9/9 changed files
- Comments generated: 1
- Review effort level: Lite
馃挕 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
| if isDockerfileName(filepath.Base(path)) { | ||
| return DockerfileToBuildOpts(path), nil | ||
| } | ||
| return loadKraftfile(ctx, path, filepath.Dir(path)) |
4acb2ae to
c1c1158
Compare
There was a problem hiding this comment.
馃煛 Changes recommended
Dockerfile-only builds currently discard Dockerfile labels, and architecture documentation contradicts supported runtime-derived platforms.
Get a fresh assessment by requesting another Copilot review.
Review details
- Files reviewed: 9/9 changed files
- Comments generated: 3
- Review effort level: Balanced
| func DockerfileToBuildOpts(path string) BuildOpts { | ||
| return BuildOpts{ | ||
| Rootfs: FSOpts{ | ||
| Path: path, | ||
| Type: kraftfile.SourceTypeDockerfile, | ||
| }, | ||
| } |
c1c1158 to
f6f6e9b
Compare
| ctx := integrationContext(t) | ||
| dockerfile := ` | ||
| FROM scratch | ||
| LABEL org.unikraft.source=dockerfile org.unikraft.only=dockerfile |
There was a problem hiding this comment.
where is org.unikraft.source coming from?
IMHO we should use com. || cloud. for anything specifically cloud-based - so as not to mess with stuff in the OSS/KraftKit.
There was a problem hiding this comment.
a similar label was in TestBuildCmdEnvLabelsIntegration - however that test and the tests I added do not rely on the meaning of the label at all, so am just going to change them to use com.example.* type labels
|
do let me know when I should check it out 馃槈 |
f6f6e9b to
55d7e45
Compare
|
@craciunoiuc stable integration test is failing because of a platform issue fixed in latest version |
|
@craciunoiuc they pass now! |
| // kraftfileNames are the Kraftfile names that a project directory can contain, | ||
| // in order of precedence. The order is the name order of the directory listing. | ||
| var kraftfileNames = []string{ | ||
| "Kraftfile", | ||
| "Kraftfile.yaml", | ||
| "Kraftfile.yml", | ||
| "kraft.yaml", | ||
| "kraft.yml", | ||
| } |
There was a problem hiding this comment.
If this isn't already in x/kraftfile then it should be probably 馃
There was a problem hiding this comment.
sure - I can add that afterwards
| func loadKraftfile(ctx context.Context, path, dir string) (BuildOpts, error) { | ||
| kf, err := kraftfile.ParseFile(path, kraftfile.WithSkippedVersionCheck()) | ||
| if err != nil { | ||
| return BuildOpts{}, err | ||
| } | ||
| if semver.Compare(kf.Spec, kraftfile.SpecVersionMin) < 0 { | ||
| log.G(ctx).Warn(). | ||
| Str("spec", kf.Spec). | ||
| Str("min", kraftfile.SpecVersionMin). | ||
| Msg("Kraftfile spec version is older than minimum; parsing is best-effort") | ||
| } else if semver.Compare(kf.Spec, kraftfile.SpecVersionMax) > 0 { | ||
| log.G(ctx).Warn(). | ||
| Str("spec", kf.Spec). | ||
| Str("max", kraftfile.SpecVersionMax). | ||
| Msg("Kraftfile spec version is newer than maximum; parsing is best-effort") | ||
| } | ||
| return KraftfileToBuildOpts(dir, kf) | ||
| } |
There was a problem hiding this comment.
just one use place, so inline
There was a problem hiding this comment.
do you mind if i keep this as its own function? it is used twice so i think having it as its own function keeps it simpler
There was a problem hiding this comment.
well if you ask me so nicely how can I say no
55d7e45 to
0abe268
Compare
Now that the platform supports kernel-less images, it is not strictly necessary to pass a Kraftfile to unikraft build - instead it can accept a Dockerfile. Passing a Dockerfile will build a image which contains a rootfs based off the Dockerfile, and no kernel. The filename is used to determine which type of file has been passed. If a directory is passed, the Kraftfile takes precedence over the Dockerfile. When a Dockerfile is passed, the --arch argument must be set so the CLI knows which architecure to build for. Kernel-less images can only be run on metros with a default kernel installed. Closes: TOOL-1439 Signed-off-by: Daniel Vallance <daniel@unikraft.com>
unikraft.org is the OSS project and we don't want to confuse that with our cloud offering Signed-off-by: Daniel Vallance <daniel@unikraft.com>
0abe268 to
7f27c21
Compare
craciunoiuc
left a comment
There was a problem hiding this comment.
I think you have like a crazy commit message rule.
You can ask it for under 50 lines for titles and under 70 lines for commit bodies.
Other than that it looks good to me I think? @jedevc you're free to do a pass
There was a problem hiding this comment.
All of this logic is very similar to ParseDirectory.
Instead of doing all that, can we just try that first, then if we detect an error (probably need to make an exported "no kraftfile found in directory" error type), try and load from a dockerfile?
Then we don't need to import all this logic again.
Now that the platform supports kernel-less images, it is not strictly necessary to pass a Kraftfile
to unikraft build - instead it can accept a
Dockerfile.
Passing a Dockerfile will build a image which
contains a rootfs based off the Dockerfile,
and no kernel.
The filename is used to determine which
type of file has been passed. If a directory
is passed, the Kraftfile takes precedence
over the Dockerfile.
When a Dockerfile is passed, the --arch argument
must be set so the CLI knows which architecure
to build for.
Kernel-less images can only be run on metros
with a default kernel installed.
Closes: TOOL-1439