Skip to content

Commit 4969c22

Browse files
authored
feat: Support Bazel platform mappings (#9300)
* feat: Support Bazel platform mappings This change introduces an artifact-level setting for configuring Bazel and defines a platform mapping from Skaffold platforms to Bazel platforms. The Bazel artifact builder then passes the --platforms flag to Bazel if applicable. Fixes #9360. * Update examples/bazel * Copy examples/bazel to integration/examples/bazel * Add unit test * Remove bazel platforms from examples/bazel Summary: According to ./hack/check-samples.sh, ''' # /examples should use the latest released version LATEST_RELEASED="skaffold/$(go run ./hack/versions/cmd/latest_released/version.go)" ''' The new 'platforms' field is in v4beta10 and not available in a released version yet, so CI fails. It can be added to /examples/bazel later, after a release. Test Plan: `./hack/check-samples.sh` * Remove yaml block that breaks docs
1 parent a061e2a commit 4969c22

File tree

11 files changed

+106
-33
lines changed

11 files changed

+106
-33
lines changed

docs-v2/content/en/schemas/v4beta10.json

+36-1
Original file line numberDiff line numberDiff line change
@@ -694,6 +694,14 @@
694694
"[\"-flag\", \"--otherflag\"]"
695695
]
696696
},
697+
"platforms": {
698+
"items": {
699+
"$ref": "#/definitions/BazelPlatformMapping"
700+
},
701+
"type": "array",
702+
"description": "configure the --platforms flag for `bazel build` based on the configured skaffold target platform.",
703+
"x-intellij-html-description": "configure the --platforms flag for <code>bazel build</code> based on the configured skaffold target platform."
704+
},
697705
"target": {
698706
"type": "string",
699707
"description": "`bazel build` target to run.",
@@ -705,13 +713,40 @@
705713
},
706714
"preferredOrder": [
707715
"target",
708-
"args"
716+
"args",
717+
"platforms"
709718
],
710719
"additionalProperties": false,
711720
"type": "object",
712721
"description": "describes an artifact built with [Bazel](https://bazel.build/).",
713722
"x-intellij-html-description": "describes an artifact built with <a href=\"https://bazel.build/\">Bazel</a>."
714723
},
724+
"BazelPlatformMapping": {
725+
"required": [
726+
"platform",
727+
"target"
728+
],
729+
"properties": {
730+
"platform": {
731+
"type": "string",
732+
"description": "skaffold platform.",
733+
"x-intellij-html-description": "skaffold platform."
734+
},
735+
"target": {
736+
"type": "string",
737+
"description": "bazel platform target to be passed to bazel's `--platforms` flag.",
738+
"x-intellij-html-description": "bazel platform target to be passed to bazel's <code>--platforms</code> flag."
739+
}
740+
},
741+
"preferredOrder": [
742+
"platform",
743+
"target"
744+
],
745+
"additionalProperties": false,
746+
"type": "object",
747+
"description": "relates a skaffold platform (like 'linux/amd64') to a workspace-specific bazel platform target (e.g. '//platforms:linux_amd64').",
748+
"x-intellij-html-description": "relates a skaffold platform (like 'linux/amd64') to a workspace-specific bazel platform target (e.g. '//platforms:linux_amd64')."
749+
},
715750
"BuildConfig": {
716751
"type": "object",
717752
"anyOf": [

examples/bazel/BUILD.bazel

+2-13
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
load("@aspect_bazel_lib//lib:transitions.bzl", "platform_transition_filegroup")
21
load("@rules_go//go:def.bzl", "go_binary", "go_library")
32
load("@rules_oci//oci:defs.bzl", "oci_image", "oci_tarball")
43
load("@rules_pkg//:pkg.bzl", "pkg_tar")
@@ -31,18 +30,8 @@ oci_image(
3130
tars = [":app_layer"],
3231
)
3332

34-
# This is the target that should be released to the target platform
35-
platform_transition_filegroup(
36-
name = "transitioned_image",
37-
srcs = [":image"],
38-
target_platform = select({
39-
"@platforms//cpu:arm64": "@rules_go//go/toolchain:linux_arm64",
40-
"@platforms//cpu:x86_64": "@rules_go//go/toolchain:linux_amd64",
41-
}),
42-
)
43-
44-
# $ bazel build :tarball
45-
# $ docker load --input $(bazel cquery --output=files :tarball)
33+
# $ bazel build :skaffold-example.tar
34+
# $ docker load --input $(bazel cquery --output=files :skaffold-example.tar)
4635
# $ docker run --rm gcr.io/example:latest
4736

4837
oci_tarball(

examples/bazel/MODULE.bazel

-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
bazel_dep(name = "aspect_bazel_lib", version = "1.31.1")
21
bazel_dep(name = "gazelle", version = "0.31.0")
32
bazel_dep(name = "platforms", version = "0.0.5")
43
bazel_dep(name = "rules_oci", version = "1.2.0")

examples/bazel/README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ build:
1212
- image: skaffold-bazel
1313
context: .
1414
bazel:
15-
target: //:skaffold_example.tar
15+
target: //:skaffold-example.tar
1616
```
1717
1818
1. make sure the `context` contains the bazel files (`WORKSPACE`, `BUILD`)

integration/examples/bazel/BUILD.bazel

+2-13
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
load("@aspect_bazel_lib//lib:transitions.bzl", "platform_transition_filegroup")
21
load("@rules_go//go:def.bzl", "go_binary", "go_library")
32
load("@rules_oci//oci:defs.bzl", "oci_image", "oci_tarball")
43
load("@rules_pkg//:pkg.bzl", "pkg_tar")
@@ -31,18 +30,8 @@ oci_image(
3130
tars = [":app_layer"],
3231
)
3332

34-
# This is the target that should be released to the target platform
35-
platform_transition_filegroup(
36-
name = "transitioned_image",
37-
srcs = [":image"],
38-
target_platform = select({
39-
"@platforms//cpu:arm64": "@rules_go//go/toolchain:linux_arm64",
40-
"@platforms//cpu:x86_64": "@rules_go//go/toolchain:linux_amd64",
41-
}),
42-
)
43-
44-
# $ bazel build :tarball
45-
# $ docker load --input $(bazel cquery --output=files :tarball)
33+
# $ bazel build :skaffold-example.tar
34+
# $ docker load --input $(bazel cquery --output=files :skaffold-example.tar)
4635
# $ docker run --rm gcr.io/example:latest
4736

4837
oci_tarball(

integration/examples/bazel/MODULE.bazel

-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
bazel_dep(name = "aspect_bazel_lib", version = "1.31.1")
21
bazel_dep(name = "gazelle", version = "0.31.0")
32
bazel_dep(name = "platforms", version = "0.0.5")
43
bazel_dep(name = "rules_oci", version = "1.2.0")

integration/examples/bazel/README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ build:
1212
- image: skaffold-bazel
1313
context: .
1414
bazel:
15-
target: //:skaffold_example.tar
15+
target: //:skaffold-example.tar
1616
```
1717
1818
1. make sure the `context` contains the bazel files (`WORKSPACE`, `BUILD`)

integration/examples/bazel/skaffold.yaml

+5
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,11 @@ build:
99
- image: skaffold-bazel
1010
bazel:
1111
target: //:skaffold-example.tar
12+
platforms:
13+
- platform: linux/amd64
14+
target: "@rules_go//go/toolchain:linux_amd64"
15+
- platform: linux/arm64
16+
target: "@rules_go//go/toolchain:linux_arm64"
1217
deploy:
1318
kubectl: {}
1419
manifests:

pkg/skaffold/build/bazel/build.go

+12-2
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ func (b *Builder) Build(ctx context.Context, out io.Writer, artifact *latest.Art
4545

4646
a := artifact.ArtifactType.BazelArtifact
4747

48-
tarPath, err := b.buildTar(ctx, out, artifact.Workspace, a)
48+
tarPath, err := b.buildTar(ctx, out, artifact.Workspace, a, matcher)
4949
if err != nil {
5050
return "", err
5151
}
@@ -58,7 +58,7 @@ func (b *Builder) Build(ctx context.Context, out io.Writer, artifact *latest.Art
5858

5959
func (b *Builder) SupportedPlatforms() platform.Matcher { return platform.All }
6060

61-
func (b *Builder) buildTar(ctx context.Context, out io.Writer, workspace string, a *latest.BazelArtifact) (string, error) {
61+
func (b *Builder) buildTar(ctx context.Context, out io.Writer, workspace string, a *latest.BazelArtifact, matcher platform.Matcher) (string, error) {
6262
if !strings.HasSuffix(a.BuildTarget, ".tar") {
6363
return "", errors.New("the bazel build target should end with .tar, see https://github.com/bazelbuild/rules_docker#using-with-docker-locally")
6464
}
@@ -67,6 +67,16 @@ func (b *Builder) buildTar(ctx context.Context, out io.Writer, workspace string,
6767
args = append(args, a.BuildArgs...)
6868
args = append(args, a.BuildTarget)
6969

70+
platformMappings := a.PlatformMappings
71+
for _, mapping := range platformMappings {
72+
m, err := platform.Parse([]string{mapping.Platform})
73+
if err == nil {
74+
if matcher.Intersect(m).IsNotEmpty() {
75+
args = append(args, fmt.Sprintf("--platforms=%s", mapping.BazelPlatformTarget))
76+
}
77+
}
78+
}
79+
7080
if output.IsColorable(out) {
7181
args = append(args, "--color=yes")
7282
} else {

pkg/skaffold/build/bazel/build_test.go

+33
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@ import (
2323
"path/filepath"
2424
"testing"
2525

26+
specs "github.com/opencontainers/image-spec/specs-go/v1"
27+
2628
"github.com/GoogleContainerTools/skaffold/v2/pkg/skaffold/docker"
2729
"github.com/GoogleContainerTools/skaffold/v2/pkg/skaffold/platform"
2830
"github.com/GoogleContainerTools/skaffold/v2/pkg/skaffold/schema/latest"
@@ -77,6 +79,37 @@ func TestBazelTarPathPrependExecutionRoot(t *testing.T) {
7779
})
7880
}
7981

82+
func TestBazelAddPlatforms(t *testing.T) {
83+
testutil.Run(t, "", func(t *testutil.T) {
84+
t.Override(&util.DefaultExecCommand, testutil.CmdRun("bazel build //:app.tar --platforms=//platforms:linux-x86_64 --color=no").AndRunOut(
85+
"bazel cquery //:app.tar --output starlark --starlark:expr target.files.to_list()[0].path",
86+
"app.tar").AndRunOut("bazel info execution_root", ".."))
87+
testutil.CreateFakeImageTar("bazel:app", "../app.tar")
88+
89+
artifact := &latest.Artifact{
90+
Workspace: "..",
91+
ArtifactType: latest.ArtifactType{
92+
BazelArtifact: &latest.BazelArtifact{
93+
BuildTarget: "//:app.tar",
94+
PlatformMappings: []latest.BazelPlatformMapping{
95+
{
96+
Platform: "linux/amd64",
97+
BazelPlatformTarget: "//platforms:linux-x86_64",
98+
},
99+
},
100+
},
101+
},
102+
}
103+
104+
testPlatform := platform.Matcher{Platforms: []specs.Platform{{Architecture: "amd64", OS: "linux"}}}
105+
106+
builder := NewArtifactBuilder(fakeLocalDaemon(), &mockConfig{}, false)
107+
_, err := builder.Build(context.Background(), io.Discard, artifact, "img:tag", testPlatform)
108+
109+
t.CheckNoError(err)
110+
})
111+
}
112+
80113
func TestBuildBazelFailInvalidTarget(t *testing.T) {
81114
testutil.Run(t, "", func(t *testutil.T) {
82115
artifact := &latest.Artifact{

pkg/skaffold/schema/latest/config.go

+14
Original file line numberDiff line numberDiff line change
@@ -331,6 +331,16 @@ type TaggerComponent struct {
331331
Component TagPolicy `yaml:",inline" yamltags:"skipTrim"`
332332
}
333333

334+
// BazelPlatformMapping relates a skaffold platform (like 'linux/amd64')
335+
// to a workspace-specific bazel platform target (e.g. '//platforms:linux_amd64').
336+
type BazelPlatformMapping struct {
337+
// Platform is the skaffold platform.
338+
Platform string `yaml:"platform" yamltags:"required"`
339+
340+
// BazelPlatformTarget is the bazel platform target to be passed to bazel's `--platforms` flag.
341+
BazelPlatformTarget string `yaml:"target" yamltags:"required"`
342+
}
343+
334344
// BuildType contains the specific implementation and parameters needed
335345
// for the build step. Only one field should be populated.
336346
type BuildType struct {
@@ -1597,6 +1607,10 @@ type BazelArtifact struct {
15971607
// BuildArgs are additional args to pass to `bazel build`.
15981608
// For example: `["-flag", "--otherflag"]`.
15991609
BuildArgs []string `yaml:"args,omitempty"`
1610+
1611+
// PlatformMappings configure the --platforms flag for `bazel build`
1612+
// based on the configured skaffold target platform.
1613+
PlatformMappings []BazelPlatformMapping `yaml:"platforms,omitempty"`
16001614
}
16011615

16021616
// KoArtifact builds images using [ko](https://github.com/google/ko).

0 commit comments

Comments
 (0)