Skip to content

Commit 0d9ee14

Browse files
authored
add support for default global args (#44)
* add support for default global args * add `BuildPlatform` property to `BOpts` * apply feedbacks from the review * add unit tests for frontend `globalArgs` and `resolveStates` * support a list of build platforms
1 parent 586ff53 commit 0d9ee14

File tree

3 files changed

+785
-7
lines changed

3 files changed

+785
-7
lines changed

pkg/build/buildopts.go

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,12 +23,13 @@ import (
2323
"path/filepath"
2424
"strings"
2525

26-
"github.com/containerd/containerd/platforms"
26+
"github.com/containerd/platforms"
2727
"github.com/moby/buildkit/frontend/dockerfile/instructions"
2828
"github.com/moby/buildkit/frontend/dockerfile/parser"
2929
"github.com/moby/buildkit/util/progress/progresswriter"
3030
ocispecs "github.com/opencontainers/image-spec/specs-go/v1"
3131

32+
"github.com/apple/container-builder-shim/pkg/build/utils"
3233
"github.com/apple/container-builder-shim/pkg/content"
3334
"github.com/apple/container-builder-shim/pkg/fssync"
3435
"github.com/apple/container-builder-shim/pkg/resolver"
@@ -63,6 +64,7 @@ type BOpts struct {
6364
Dockerfile []byte
6465
Tag string
6566
ContextDir string
67+
BuildPlatforms []ocispecs.Platform
6668
Platforms []ocispecs.Platform
6769
NoCache bool
6870
Target string
@@ -131,6 +133,11 @@ func NewBuildOpts(ctx context.Context, basePath string, contextMap map[string][]
131133
ctxDir = c
132134
}
133135

136+
bps := utils.BuildPlatforms()
137+
if len(bps) == 0 {
138+
bps = append(bps, platforms.DefaultSpec())
139+
}
140+
134141
pls, err := func() ([]ocispecs.Platform, error) {
135142
pls := []ocispecs.Platform{}
136143
values, ok := contextMap[KeyPlatforms]
@@ -231,6 +238,7 @@ func NewBuildOpts(ctx context.Context, basePath string, contextMap map[string][]
231238
BuildID: buildID,
232239
Dockerfile: dockerfileBytes,
233240
Tag: tag,
241+
BuildPlatforms: bps,
234242
Platforms: pls,
235243
ContextDir: ctxDir,
236244
ContentStore: contentProxy,

pkg/build/frontend.go

Lines changed: 46 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,8 @@ func resolveStates(ctx context.Context, bopts *BOpts, platform ocispecs.Platform
135135
defer wg.Done()
136136

137137
shlex := shell.NewLex(dockerfile.EscapeToken)
138-
resolvedBaseStageName, err := shlex.ProcessWordWithMatches(stage.BaseName, utils.NewMapGetter(bopts.BuildArgs))
138+
resolvedGlobalArgs := globalArgs(bopts.BuildPlatforms[0], platform, bopts.BuildArgs, bopts.Target)
139+
resolvedBaseStageName, err := shlex.ProcessWordWithMatches(stage.BaseName, resolvedGlobalArgs)
139140
if err != nil {
140141
errCh <- fmt.Errorf("invalid arg for stage[%s]: %v", stage.BaseName, err)
141142
return
@@ -145,6 +146,22 @@ func resolveStates(ctx context.Context, bopts *BOpts, platform ocispecs.Platform
145146
return
146147
}
147148

149+
// if platform is specified for the stage, parse and use as the target platform
150+
stagePlatform := platform
151+
if stage.Platform != "" {
152+
resolvedStagePlatformStr, err := shlex.ProcessWordWithMatches(stage.Platform, resolvedGlobalArgs)
153+
if err != nil {
154+
errCh <- fmt.Errorf("invalid platform for stage[%s]: %v", stage.BaseName, err)
155+
return
156+
}
157+
resolvedStagePlatform, err := platforms.Parse(resolvedStagePlatformStr.Result)
158+
if err != nil {
159+
errCh <- fmt.Errorf("invalid platform for stage[%s]: %v", stage.BaseName, err)
160+
return
161+
}
162+
stagePlatform = resolvedStagePlatform
163+
}
164+
148165
// if there's another stage with this name before the current stage, that will be used as the source
149166
namedIndex, hasNamedStage := instructions.HasStage(stages, resolvedBaseStageName.Result)
150167
if hasNamedStage && namedIndex < i {
@@ -164,7 +181,7 @@ func resolveStates(ctx context.Context, bopts *BOpts, platform ocispecs.Platform
164181
clog("[resolver] fetching image...%s", ref.String())
165182

166183
resolverOpts := sourceresolver.Opt{
167-
Platform: &platform,
184+
Platform: &stagePlatform,
168185
}
169186
resolverOpts.OCILayoutOpt = &sourceresolver.ResolveOCILayoutOpt{
170187
Store: sourceresolver.ResolveImageConfigOptStore{
@@ -196,7 +213,7 @@ func resolveStates(ctx context.Context, bopts *BOpts, platform ocispecs.Platform
196213
fqdn = fqdn + "@" + digest.String()
197214
}
198215
logrus.WithField("ref", fqdn).Infof("creating llb")
199-
st := llb.OCILayout(fqdn, llb.OCIStore("", "container"), llb.Platform(platform))
216+
st := llb.OCILayout(fqdn, llb.OCIStore("", "container"), llb.Platform(stagePlatform))
200217

201218
named, err := dref.ParseNormalizedNamed(ref.String())
202219
if err != nil {
@@ -206,7 +223,7 @@ func resolveStates(ctx context.Context, bopts *BOpts, platform ocispecs.Platform
206223
name := strings.TrimSuffix(dref.FamiliarString(named), ":latest")
207224

208225
// pname constructs a platform-qualified image reference in the format buildkit requires for digest resolution
209-
pname := name + "::" + platforms.FormatAll(platforms.Normalize(platform))
226+
pname := name + "::" + platforms.FormatAll(platforms.Normalize(stagePlatform))
210227
imgMetaMap := map[string][]byte{
211228
exptypes.ExporterImageConfigKey: img,
212229
}
@@ -221,7 +238,7 @@ func resolveStates(ctx context.Context, bopts *BOpts, platform ocispecs.Platform
221238
defer stateLock.Unlock()
222239

223240
states[pname] = stateMeta{
224-
state: st.Platform(platform),
241+
state: st.Platform(stagePlatform),
225242
imgMeta: imgMeta,
226243
}
227244
}(stage)
@@ -317,7 +334,7 @@ func solvePlatform(ctx context.Context, bopts *BOpts, pl ocispecs.Platform, c ga
317334
Client: cl,
318335
}
319336

320-
convertOpt.BuildPlatforms = utils.BuildPlatforms()
337+
convertOpt.BuildPlatforms = bopts.BuildPlatforms
321338
convertOpt.TargetPlatforms = bopts.Platforms
322339
convertOpt.BuildArgs = bopts.BuildArgs
323340
convertOpt.Labels = bopts.Labels
@@ -377,3 +394,26 @@ func solvePlatform(ctx context.Context, bopts *BOpts, pl ocispecs.Platform, c ga
377394
}
378395
return ref, cfgJSON, nil
379396
}
397+
398+
func globalArgs(buildPlatform, targetPlatform ocispecs.Platform, buildArgs map[string]string, target string) utils.MapGetter {
399+
if target == "" {
400+
target = "default"
401+
}
402+
args := map[string]string{
403+
"BUILDPLATFORM": platforms.Format(buildPlatform),
404+
"BUILDOS": buildPlatform.OS,
405+
"BUILDOSVERSION": buildPlatform.OSVersion,
406+
"BUILDARCH": buildPlatform.Architecture,
407+
"BUILDVARIANT": buildPlatform.Variant,
408+
"TARGETPLATFORM": platforms.FormatAll(targetPlatform),
409+
"TARGETOS": targetPlatform.OS,
410+
"TARGETOSVERSION": targetPlatform.OSVersion,
411+
"TARGETARCH": targetPlatform.Architecture,
412+
"TARGETVARIANT": targetPlatform.Variant,
413+
"TARGETSTAGE": target,
414+
}
415+
for k, v := range buildArgs {
416+
args[k] = v
417+
}
418+
return utils.NewMapGetter(args)
419+
}

0 commit comments

Comments
 (0)