Skip to content

Commit

Permalink
Merge pull request #18 from fasterci/ap/transitions
Browse files Browse the repository at this point in the history
add transitions
  • Loading branch information
apesternikov committed Mar 6, 2024
2 parents a5fe703 + ba304ae commit 8aee881
Show file tree
Hide file tree
Showing 9 changed files with 1,163 additions and 151 deletions.
984 changes: 836 additions & 148 deletions MODULE.bazel.lock

Large diffs are not rendered by default.

9 changes: 6 additions & 3 deletions skylib/kustomize/kustomize.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -396,8 +396,9 @@ def imagePushStatements(
files = []):
statements = ""
trans_img_pushes = depset(transitive = [obj[GitopsArtifactsInfo].image_pushes for obj in kustomize_objs]).to_list()
trans_img_pushes = [push for push in trans_img_pushes if push.files_to_run.executable]
statements += "\n".join([
"echo pushing {}".format(exe[GitopsPushInfo].repository)
"echo pushing {}".format(exe[GitopsPushInfo].repository if GitopsPushInfo in exe else "")
for exe in trans_img_pushes
]) + "\n"
statements += "\n".join([
Expand Down Expand Up @@ -514,10 +515,12 @@ def _kubectl_impl(ctx):
files += [ctx.executable._template_engine, ctx.file._info_file]

if ctx.attr.push:
trans_img_pushes = depset(transitive = [obj[GitopsArtifactsInfo].image_pushes for obj in ctx.attr.srcs if obj.files_to_run.executable]).to_list()
pushes = [obj[GitopsArtifactsInfo].image_pushes for obj in ctx.attr.srcs]
trans_img_pushes = depset(transitive = pushes).to_list()
trans_img_pushes = [push for push in trans_img_pushes if push.files_to_run.executable]
statements += "\n".join([
"# {}\n".format(exe[GitopsPushInfo].image_label) +
"echo pushing {}".format(exe[GitopsPushInfo].repository)
"echo pushing {}".format(exe[GitopsPushInfo].repository if GitopsPushInfo in exe else "")
for exe in trans_img_pushes
]) + "\n"
statements += "\n".join([
Expand Down
35 changes: 35 additions & 0 deletions transitions/BUILD.bazel
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# Copyright 2022 The Bazel Authors. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

load("@bazel_skylib//rules:common_settings.bzl", "bool_flag")

package(
default_visibility = ["//visibility:public"],
)

# Whether to enable platform transitions for images. Could be disabled if running on linux/x86 platform (e.g. CI).
bool_flag(
name = "enable",
build_setting_default = True,
)

config_setting(
name = "enabled",
flag_values = {"@io_bazel_rules_docker//transitions:enable": "true"},
)

config_setting(
name = "disabled",
flag_values = {"@io_bazel_rules_docker//transitions:enable": "false"},
)
151 changes: 151 additions & 0 deletions transitions/tests/BUILD.bazel
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
load("@bazel_skylib//rules:write_file.bzl", "write_file")
load("@io_bazel_rules_go//go:def.bzl", "go_binary", "go_library")
load("@aspect_bazel_lib//lib:diff_test.bzl", "diff_test")
load("//transitions:transitions.bzl", "platform_transition_binary", "platform_transition_filegroup")

platform(
name = "armv7_linux",
constraint_values = [
"@platforms//os:linux",
"@platforms//cpu:armv7",
],
)

platform(
name = "x86_64_linux",
constraint_values = [
"@platforms//os:linux",
"@platforms//cpu:x86_64",
"@io_bazel_rules_go//go/toolchain:cgo_off", # https://github.com/bazelbuild/rules_go/pull/3390
],
)

platform(
name = "arm64_linux",
constraint_values = [
"@platforms//os:linux",
"@platforms//cpu:arm64",
"@io_bazel_rules_go//go/toolchain:cgo_off", # https://github.com/bazelbuild/rules_go/pull/3390
],
)

config_setting(
name = "is_x86",
constraint_values = [
"@platforms//cpu:x86_64",
],
)

# Simple test fixture that produces something different depending on the
# target platform.
filegroup(
name = "platform_description",
srcs = select({
":is_x86": ["linux_x86.txt"],
"//conditions:default": ["linux_arm.txt"],
}),
)

platform_transition_filegroup(
name = "for_x86",
srcs = ["platform_description"],
target_platform = ":x86_64_linux",
)

platform_transition_filegroup(
name = "for_arm",
srcs = ["platform_description"],
target_platform = ":armv7_linux",
)

genrule(
name = "for_x86_path",
srcs = [":for_x86"],
outs = ["for_x86_path.txt"],
cmd = "echo $(rootpath :for_x86) > $@",
)

genrule(
name = "for_arm_path",
srcs = [":for_arm"],
outs = ["for_arm_path.txt"],
cmd = "echo $(rootpath :for_arm) > $@",
)

write_file(
name = "expected_x86_path",
out = "expected_x86_path.txt",
content = [
"transitions/tests/linux_x86.txt",
"",
],
)

write_file(
name = "expected_arm_path",
out = "expected_arm_path.txt",
content = [
"transitions/tests/linux_arm.txt",
"",
],
)

diff_test(
name = "test_x86",
file1 = ":for_x86_path",
file2 = ":expected_x86_path",
)

diff_test(
name = "test_arm",
file1 = ":for_arm_path",
file2 = ":expected_arm_path",
)

go_binary(
name = "test_transition_binary",
embed = [":transitions_lib"],
tags = ["manual"],
visibility = ["//visibility:public"],
)

platform_transition_binary(
name = "transitioned_go_binary_x86_64",
binary = ":test_transition_binary",
target_platform = "x86_64_linux",
)

platform_transition_binary(
name = "transitioned_go_binary_arm64",
binary = ":test_transition_binary",
target_platform = "arm64_linux",
)

sh_test(
name = "test_go_binary_is_x86_64",
srcs = ["test_file_type_contains.sh"],
args = [
"$(rootpath :transitioned_go_binary_x86_64)",
"x86-64",
],
data = [":transitioned_go_binary_x86_64"],
tags = ["manual"],
)

sh_test(
name = "test_go_binary_is_arm64",
srcs = ["test_file_type_contains.sh"],
args = [
"$(rootpath :transitioned_go_binary_arm64)",
"aarch64",
],
data = [":transitioned_go_binary_arm64"],
tags = ["manual"],
)

go_library(
name = "transitions_lib",
srcs = ["main.go"],
importpath = "github.com/aspect-build/bazel-lib/lib/tests/transitions",
visibility = ["//visibility:private"],
)
1 change: 1 addition & 0 deletions transitions/tests/linux_arm.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Linux ARMv7
1 change: 1 addition & 0 deletions transitions/tests/linux_x86.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Linux x86
7 changes: 7 additions & 0 deletions transitions/tests/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package main

import "fmt"

func main() {
fmt.Println("Hello World!")
}
9 changes: 9 additions & 0 deletions transitions/tests/test_file_type_contains.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#!/usr/bin/env bash

# Test whether the output of `file` contains a text string.
#
# Usage: test_file_type_contains.sh <filePath> <text>

set -o errexit -o nounset -o pipefail

file --dereference "$1" | grep -q "$2"
117 changes: 117 additions & 0 deletions transitions/transitions.bzl
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
"Rules for working with transitions."

load("@bazel_skylib//lib:paths.bzl", "paths")

def _transition_platform_impl(settings, attr):
if not attr.transition_enabled:
return None
if not settings["@rules_gitops//transitions:enable"]:
return None
return {"//command_line_option:platforms": str(attr.target_platform)}

# Transition from any input configuration to one that includes the
# --platforms command-line flag.
_transition_platform = transition(
implementation = _transition_platform_impl,
inputs = ["@rules_gitops//transitions:enable"],
outputs = ["//command_line_option:platforms"],
)

def _platform_transition_filegroup_impl(ctx):
files = []
runfiles = ctx.runfiles()
for src in ctx.attr.srcs:
files.append(src[DefaultInfo].files)

runfiles = runfiles.merge_all([src[DefaultInfo].default_runfiles for src in ctx.attr.srcs])
return [DefaultInfo(
files = depset(transitive = files),
runfiles = runfiles,
)]

platform_transition_filegroup = rule(
_platform_transition_filegroup_impl,
attrs = {
# Required to Opt-in to the transitions feature.
"_allowlist_function_transition": attr.label(
default = "@bazel_tools//tools/allowlists/function_transition_allowlist",
),
"target_platform": attr.label(
doc = "The target platform to transition the srcs.",
mandatory = True,
),
"transition_enabled": attr.bool(
doc = "Whether to enable the transition. Disable this to opt-out of the transition for go or other rules that don't need it. --@rules_gitops//transitions:enable=false will override this.",
default = True,
),
"srcs": attr.label_list(
allow_empty = False,
cfg = _transition_platform,
doc = "The input to be transitioned to the target platform.",
),
},
doc = "Transitions the srcs to use the provided platform. The filegroup will contain artifacts for the target platform if .",
)

def _platform_transition_binary_impl(ctx):
# We need to forward the DefaultInfo provider from the underlying rule.
# Unfortunately, we can't do this directly, because Bazel requires that the executable to run
# is actually generated by this rule, so we need to symlink to it, and generate a synthetic
# forwarding DefaultInfo.

result = []
binary = ctx.attr.binary[0]

default_info = binary[DefaultInfo]
files = default_info.files
new_executable = None
original_executable = default_info.files_to_run.executable
runfiles = default_info.default_runfiles

if not original_executable:
fail("Cannot transition a 'binary' that is not executable")

new_executable_name = ctx.attr.basename if ctx.attr.basename else original_executable.basename

# In order for the symlink to have the same basename as the original
# executable (important in the case of proto plugins), put it in a
# subdirectory named after the label to prevent collisions.
new_executable = ctx.actions.declare_file(paths.join(ctx.label.name, new_executable_name))
ctx.actions.symlink(
output = new_executable,
target_file = original_executable,
is_executable = True,
)
files = depset(direct = [new_executable], transitive = [files])
runfiles = runfiles.merge(ctx.runfiles([new_executable]))

result.append(
DefaultInfo(
files = files,
runfiles = runfiles,
executable = new_executable,
),
)

return result

platform_transition_binary = rule(
implementation = _platform_transition_binary_impl,
attrs = {
"basename": attr.string(),
"binary": attr.label(allow_files = True, cfg = _transition_platform),
"target_platform": attr.label(
doc = "The target platform to transition the binary.",
mandatory = True,
),
"transition_enabled": attr.bool(
doc = "Whether to enable the transition. Disable this to opt-out of the transition for go or other rules that don't need it. --@rules_gitops//transitions:enable=false will override this.",
default = True,
),
"_allowlist_function_transition": attr.label(
default = "@bazel_tools//tools/allowlists/function_transition_allowlist",
),
},
executable = True,
doc = "Transitions the binary to use the provided platform.",
)

0 comments on commit 8aee881

Please sign in to comment.