chore: bring in multi-platform releases rules for copy_to_directory golang binary (#306)

This commit is contained in:
Greg Magolan 2023-01-01 16:14:48 -08:00 committed by GitHub
parent 4ad1dc2398
commit b5e5edc158
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 257 additions and 0 deletions

19
tools/BUILD.bazel Normal file
View File

@ -0,0 +1,19 @@
load(":release.bzl", "multi_platform_go_binaries", "release")
exports_files([
"create_release.sh",
])
multi_platform_go_binaries(
name = "copy_to_directory",
embed = ["//tools/copy_to_directory:copy_to_directory_lib"],
tags = ["manual"],
)
release(
name = "release",
tags = ["manual"],
targets = [
":copy_to_directory",
],
)

View File

@ -0,0 +1,14 @@
load("@io_bazel_rules_go//go:def.bzl", "go_binary", "go_library")
go_library(
name = "copy_to_directory_lib",
srcs = ["main.go"],
importpath = "github.com/aspect-build/bazel-lib/tools/copy_to_directory",
visibility = ["//visibility:public"],
)
go_binary(
name = "copy_to_directory",
embed = [":copy_to_directory_lib"],
visibility = ["//visibility:public"],
)

View File

@ -0,0 +1,7 @@
package main
import "fmt"
func main() {
fmt.Println("Not yet implemented!")
}

21
tools/create_release.sh Executable file
View File

@ -0,0 +1,21 @@
#!/bin/bash
set -o errexit -o nounset -o pipefail
echo '#!/bin/bash'
echo 'set -o errexit -o nounset -o pipefail'
# shellcheck disable=SC2016
echo 'dst=$1'
# shellcheck disable=SC2016
echo 'mkdir -p "${dst}"'
for artifact in "$@"; do
echo "echo \"Copying ${artifact} to \${dst}\""
echo "if [ -d \"${artifact}\" ]; then"
echo " for f in \"${artifact}\"/*; do"
echo " cp \"\${f}\" \"\${dst}\""
echo " done"
echo "else"
echo " cp \"${artifact}\" \"\${dst}\""
echo "fi"
done

73
tools/hashes.bzl Normal file
View File

@ -0,0 +1,73 @@
"""Rule for generating integrity files
Default output is a .sha256 file but .sha1 and .md5 files are also available
via output groups.
Based on https://github.com/bazelbuild/examples/blob/main/rules/implicit_output/hash.bzl
"""
def _impl(ctx):
# Create actions to generate the three output files.
# Actions are run only when the corresponding file is requested.
md5out = ctx.actions.declare_file("{}.md5".format(ctx.file.src.basename))
ctx.actions.run_shell(
outputs = [md5out],
inputs = [ctx.file.src],
command = "ROOT=$PWD && cd {} && md5sum {} > $ROOT/{}".format(ctx.file.src.dirname, ctx.file.src.basename, md5out.path),
)
sha1out = ctx.actions.declare_file("{}.sha1".format(ctx.file.src.basename))
ctx.actions.run_shell(
outputs = [sha1out],
inputs = [ctx.file.src],
command = "ROOT=$PWD && cd {} && sha1sum {} > $ROOT/{}".format(ctx.file.src.dirname, ctx.file.src.basename, sha1out.path),
)
sha256out = ctx.actions.declare_file("{}.sha256".format(ctx.file.src.basename))
ctx.actions.run_shell(
outputs = [sha256out],
inputs = [ctx.file.src],
command = "ROOT=$PWD && cd {dirname} && $ROOT/{sha256sum} {basename} > $ROOT/{path}".format(
dirname = ctx.file.src.dirname,
sha256sum = ctx.executable._sha256sum.path,
basename = ctx.file.src.basename,
path = sha256out.path,
),
tools = [ctx.executable._sha256sum],
)
# By default (if you run `bazel build` on this target, or if you use it as a
# source of another target), only the sha256 is computed.
return [
DefaultInfo(
files = depset([sha256out]),
),
OutputGroupInfo(
md5 = depset([md5out]),
sha1 = depset([sha1out]),
sha256 = depset([sha256out]),
),
]
_hashes = rule(
implementation = _impl,
attrs = {
"src": attr.label(
allow_single_file = True,
mandatory = True,
),
"_sha256sum": attr.label(
executable = True,
cfg = "exec",
default = "//tools/sha256sum",
),
},
)
def hashes(name, src, **kwargs):
_hashes(
name = name,
src = src,
**kwargs
)

77
tools/release.bzl Normal file
View File

@ -0,0 +1,77 @@
"""This module provides the macros for performing a release.
"""
load("@io_bazel_rules_go//go:def.bzl", "go_binary")
load(":hashes.bzl", "hashes")
PLATFORMS = [
struct(os = "darwin", arch = "amd64", ext = "", gc_linkopts = ["-s", "-w"]),
struct(os = "darwin", arch = "arm64", ext = "", gc_linkopts = ["-s", "-w"]),
struct(os = "linux", arch = "amd64", ext = "", gc_linkopts = ["-s", "-w"]),
struct(os = "linux", arch = "arm64", ext = "", gc_linkopts = ["-s", "-w"]),
struct(os = "windows", arch = "amd64", ext = ".exe", gc_linkopts = []),
]
def multi_platform_go_binaries(name, embed, prefix = "", **kwargs):
"""The multi_platform_go_binaries macro creates a go_binary for each platform.
Args:
name: the name of the filegroup containing all go_binary targets produced
by this macro.
embed: the list of targets passed to each go_binary target in this
macro.
prefix: an optional prefix added to the output Go binary file name.
**kwargs: extra arguments.
"""
targets = []
for platform in PLATFORMS:
target_name = "{}-{}-{}".format(name, platform.os, platform.arch)
target_label = Label("//{}:{}".format(native.package_name(), target_name))
go_binary(
name = target_name,
out = "{}{}-{}_{}{}".format(prefix, name, platform.os, platform.arch, platform.ext),
embed = embed,
gc_linkopts = platform.gc_linkopts,
goarch = platform.arch,
goos = platform.os,
pure = "on",
visibility = ["//visibility:public"],
**kwargs
)
hashes_name = "{}_hashes".format(target_name)
hashes_label = Label("//{}:{}".format(native.package_name(), hashes_name))
hashes(
name = hashes_name,
src = target_label,
**kwargs
)
targets.extend([target_label, hashes_label])
native.filegroup(
name = name,
srcs = targets,
**kwargs
)
def release(name, targets, **kwargs):
"""The release macro creates the artifact copier script.
It's an executable script that copies all artifacts produced by the given
targets into the provided destination. See .github/workflows/release.yml.
Args:
name: the name of the genrule.
targets: a list of filegroups passed to the artifact copier.
**kwargs: extra arguments.
"""
native.genrule(
name = name,
srcs = targets,
outs = ["release.sh"],
executable = True,
cmd = "./$(location //tools:create_release.sh) {locations} > \"$@\"".format(
locations = " ".join(["$(locations {})".format(target) for target in targets]),
),
tools = ["//tools:create_release.sh"],
**kwargs
)

View File

@ -0,0 +1,14 @@
load("@io_bazel_rules_go//go:def.bzl", "go_binary", "go_library")
go_library(
name = "sha256sum_lib",
srcs = ["main.go"],
importpath = "github.com/aspect-build/bazel-lib/tools/sha256sum",
visibility = ["//visibility:private"],
)
go_binary(
name = "sha256sum",
embed = [":sha256sum_lib"],
visibility = ["//visibility:public"],
)

32
tools/sha256sum/main.go Normal file
View File

@ -0,0 +1,32 @@
package main
import (
"crypto/sha256"
"fmt"
"io"
"log"
"os"
)
func main() {
var input io.Reader
var filename string
if len(os.Args) == 1 {
input = os.Stdin
filename = "-"
} else {
f, err := os.Open(os.Args[1])
if err != nil {
log.Fatal(err)
}
defer f.Close()
input = f
filename = os.Args[1]
}
hash := sha256.New()
if _, err := io.Copy(hash, input); err != nil {
log.Fatal(err)
}
fmt.Printf("%x %s\n", hash.Sum(nil), filename)
}