From 7dae2cf464f4f505c197df266808b42b6d906a1d Mon Sep 17 00:00:00 2001 From: Alex Eagle Date: Tue, 17 Sep 2024 13:42:41 -0700 Subject: [PATCH] chore: add windows release --- .bazelrc | 16 +++---- .github/workflows/build.yaml | 66 ++++++++++++++++++++++++++ .github/workflows/release.yml | 32 ++++++------- WORKSPACE | 86 +++++++++++++++++++++------------- release/BUILD.bazel | 36 ++++++++++++-- release/bazelisk_artifacts.bzl | 48 ++++++++++--------- release/release.bzl | 2 +- tools/workspace_status.js | 33 +++++++++++++ workspace_status.sh | 41 ---------------- 9 files changed, 232 insertions(+), 128 deletions(-) create mode 100644 .github/workflows/build.yaml create mode 100755 tools/workspace_status.js delete mode 100755 workspace_status.sh diff --git a/.bazelrc b/.bazelrc index aae36b1ae..f4640cd9c 100644 --- a/.bazelrc +++ b/.bazelrc @@ -7,15 +7,9 @@ import %workspace%/.aspect/bazelrc/javascript.bazelrc import %workspace%/.aspect/bazelrc/performance.bazelrc ### YOUR PROJECT SPECIFIC OPTIONS GO HERE ### +common --enable_platform_specific_config -# Allow our init template folders to contain BUILD.bazel without it being a subpackage -# To update, run: -# find pkg/aspect/init/template -type d | paste -d, -s - | awk '{ print "common --deleted_packages="$1 }' -common --deleted_packages=pkg/aspect/init/template,pkg/aspect/init/template/tools,pkg/aspect/init/template/tools/format - -common --workspace_status_command "${PWD}/workspace_status.sh" - -common:release -c opt --stamp +common:release -c opt --stamp --workspace_status_command="node tools/workspace_status.js" # bzlmod causes issues with LLVM toolchain common --noenable_bzlmod @@ -24,8 +18,10 @@ common --noenable_bzlmod common --noincompatible_disallow_empty_glob # Don't try and auto detect the cc toolchain, as we use our own gcc toolchains. -common --action_env=BAZEL_DO_NOT_DETECT_CPP_TOOLCHAIN=1 -common --incompatible_enable_cc_toolchain_resolution --incompatible_enable_proto_toolchain_resolution +common:linux --action_env=BAZEL_DO_NOT_DETECT_CPP_TOOLCHAIN=1 +common --incompatible_enable_proto_toolchain_resolution + +build:windows --sandbox_add_mount_pair=C:\Temp # Tell Bazel to pass the right flags for llvm-ar, not libtool, only needed on linux. # See https://github.com/bazelbuild/bazel/blob/5c75d0acec21459bbb13520817e3806e1507e907/tools/cpp/unix_cc_toolchain_config.bzl#L1000-L1024 diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml new file mode 100644 index 000000000..7d1d07905 --- /dev/null +++ b/.github/workflows/build.yaml @@ -0,0 +1,66 @@ +name: build +on: + push: + branches: ['main'] + pull_request: + workflow_call: + outputs: + windows: + description: 'Windows binaries' + value: ${{jobs.build_windows.outputs.artifact}} + linux: + description: 'Linux and MacOS binaries' + value: ${{jobs.build.outputs.artifact}} +jobs: + build: + name: darwin and linux + runs-on: ubuntu-latest + outputs: + artifact: ${{steps.upload.outputs.artifact-url}} + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 # Needed to see tags + - run: | + bazel run --config=release //release -- /tmp/aspect/release + - uses: actions/upload-artifact@v4 + id: upload + with: + name: linux + retention-days: 1 + path: /tmp/aspect/release + # Cross-compiling to Windows is too hard. Just build on a windows runner instead. + build_windows: + name: windows + runs-on: windows-2022 + outputs: + artifact: ${{steps.upload.outputs.artifact-url}} + env: + USE_BAZEL_VERSION: 7.2.1 + BAZELISK_BASE_URL: https://github.com/bazelbuild/bazel/releases/download + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 # Needed to see tags + - uses: bazel-contrib/setup-bazel@0.9.0 + with: + # Avoid downloading Bazel every time. + bazelisk-cache: true + # Store build cache per workflow. + disk-cache: ${{ github.workflow }} + # Share repository cache between workflows. + repository-cache: true + - run: bazel build --config=release //release:release.windows + - run: bazel-bin/release/release.windows.sh "C:\Temp\release" + shell: bash + # Verify that we built a functional executable + - name: smoke test + run: | + cp $(bazel cquery --config=release --output=files //release:aspect-windows-x86_64.exe) aspect.exe + ./aspect.exe --help + - uses: actions/upload-artifact@v4 + id: upload + with: + name: windows + retention-days: 1 + path: C:\Temp\release diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index c0825ac10..4081fa334 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -1,34 +1,30 @@ name: Release on: + # Allow manual testing by invoking this workflow from the GH web UI + workflow_dispatch: push: tags: - '202*.*.*' jobs: - build: + build_all: + uses: ./.github/workflows/build.yaml + release: runs-on: ubuntu-latest + needs: build_all steps: - - name: Checkout - uses: actions/checkout@v4 + - uses: actions/checkout@v4 + - uses: actions/download-artifact@v4 with: - fetch-depth: 0 - - name: Build release artifacts - run: | - if [ -n "$(git status --porcelain)" ]; then - >&2 echo "ERROR: the git state is not clean, aborting build..." - exit 1 - fi - rm -rf /tmp/aspect/release - bazel run --config=release //release -- /tmp/aspect/release - if /tmp/aspect/release/aspect-linux_amd64 version | grep '(with local changes)'; then - >&2 echo "ERROR: the release contained changes in the git state and the release will not be produced" - exit 1 - fi + merge-multiple: true + - run: shasum -a 256 aspect* > SHA256.txt - name: Prepare workspace snippet run: .github/workflows/install_snippet.sh > release_notes.txt - name: Create GitHub draft release and upload artifacts - uses: softprops/action-gh-release@v1 + uses: softprops/action-gh-release@v2 with: # Use GH feature to populate the changelog automatically generate_release_notes: true body_path: release_notes.txt - files: /tmp/aspect/release/* + files: | + aspect* + SHA256.txt diff --git a/WORKSPACE b/WORKSPACE index 1ec81b2aa..c95588dd6 100644 --- a/WORKSPACE +++ b/WORKSPACE @@ -2,6 +2,26 @@ workspace(name = "build_aspect_cli") load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") +HERMETIC_CC_TOOLCHAIN_VERSION = "v3.1.1" + +http_archive( + name = "hermetic_cc_toolchain", + sha256 = "907745bf91555f77e8234c0b953371e6cac5ba715d1cf12ff641496dd1bce9d1", + urls = [ + "https://mirror.bazel.build/github.com/uber/hermetic_cc_toolchain/releases/download/{0}/hermetic_cc_toolchain-{0}.tar.gz".format(HERMETIC_CC_TOOLCHAIN_VERSION), + "https://github.com/uber/hermetic_cc_toolchain/releases/download/{0}/hermetic_cc_toolchain-{0}.tar.gz".format(HERMETIC_CC_TOOLCHAIN_VERSION), + ], +) + +load("@hermetic_cc_toolchain//toolchain:defs.bzl", zig_toolchains = "toolchains") + +zig_toolchains() + +register_toolchains( + "@zig_sdk//toolchain:windows_amd64", + "@zig_sdk//toolchain:windows_arm64", +) + http_archive( name = "bazel_features", sha256 = "2cd9e57d4c38675d321731d65c15258f3a66438ad531ae09cb8bb14217dc8572", @@ -82,6 +102,35 @@ filegroup( ) """ +load("@com_grail_bazel_toolchain//toolchain:rules.bzl", "llvm_toolchain") + +llvm_toolchain( + name = "llvm_toolchain", + llvm_version = "14.0.0", + sha256 = { + "darwin-aarch64": "1b8975db6b638b308c1ee437291f44cf8f67a2fb926eb2e6464efd180e843368", + "linux-x86_64": "564fcbd79c991e93fdf75f262fa7ac6553ec1dd04622f5d7db2a764c5dc7fac6", + }, + strip_prefix = { + "darwin-aarch64": "clang+llvm-14.0.0-arm64-apple-darwin", + "linux-x86_64": "clang+llvm-14.0.0-x86_64-linux-gnu", + }, + sysroot = { + "darwin-aarch64": "@sysroot_darwin_universal//:sysroot", + "darwin-x86_64": "@sysroot_darwin_universal//:sysroot", + "linux-aarch64": "@org_chromium_sysroot_linux_arm64//:sysroot", + "linux-x86_64": "@org_chromium_sysroot_linux_x86_64//:sysroot", + }, + urls = { + "darwin-aarch64": ["https://github.com/aspect-forks/llvm-project/releases/download/aspect-release-14.0.0/clang+llvm-14.0.0-arm64-apple-darwin.tar.xz"], + "linux-x86_64": ["https://github.com/aspect-forks/llvm-project/releases/download/aspect-release-14.0.0/clang+llvm-14.0.0-x86_64-linux-gnu.tar.xz"], + }, +) + +load("//platforms/toolchains:defs.bzl", "register_llvm_toolchains") + +register_llvm_toolchains() + http_archive( name = "org_chromium_sysroot_linux_arm64", build_file_content = _SYSROOT_LINUX_BUILD_FILE, @@ -108,9 +157,11 @@ http_archive( http_archive( name = "io_bazel_rules_go", - sha256 = "6244c70a3102bacd9f823b666258d4d66550cd499f3cf957000b46bebf3a8c1f", - strip_prefix = "rules_go-9d1456e778a36dab6d5cab3f68af3060cc869e2f", - urls = ["https://github.com/bazelbuild/rules_go/archive/9d1456e778a36dab6d5cab3f68af3060cc869e2f.zip"], + sha256 = "67b4d1f517ba73e0a92eb2f57d821f2ddc21f5bc2bd7a231573f11bd8758192e", + urls = [ + "https://mirror.bazel.build/github.com/bazelbuild/rules_go/releases/download/v0.50.0/rules_go-v0.50.0.zip", + "https://github.com/bazelbuild/rules_go/releases/download/v0.50.0/rules_go-v0.50.0.zip", + ], ) http_archive( @@ -273,35 +324,6 @@ load("@bazel_skylib//:workspace.bzl", "bazel_skylib_workspace") bazel_skylib_workspace() -load("@com_grail_bazel_toolchain//toolchain:rules.bzl", "llvm_toolchain") - -llvm_toolchain( - name = "llvm_toolchain", - llvm_version = "14.0.0", - sha256 = { - "darwin-aarch64": "1b8975db6b638b308c1ee437291f44cf8f67a2fb926eb2e6464efd180e843368", - "linux-x86_64": "564fcbd79c991e93fdf75f262fa7ac6553ec1dd04622f5d7db2a764c5dc7fac6", - }, - strip_prefix = { - "darwin-aarch64": "clang+llvm-14.0.0-arm64-apple-darwin", - "linux-x86_64": "clang+llvm-14.0.0-x86_64-linux-gnu", - }, - sysroot = { - "darwin-aarch64": "@sysroot_darwin_universal//:sysroot", - "darwin-x86_64": "@sysroot_darwin_universal//:sysroot", - "linux-aarch64": "@org_chromium_sysroot_linux_arm64//:sysroot", - "linux-x86_64": "@org_chromium_sysroot_linux_x86_64//:sysroot", - }, - urls = { - "darwin-aarch64": ["https://github.com/aspect-forks/llvm-project/releases/download/aspect-release-14.0.0/clang+llvm-14.0.0-arm64-apple-darwin.tar.xz"], - "linux-x86_64": ["https://github.com/aspect-forks/llvm-project/releases/download/aspect-release-14.0.0/clang+llvm-14.0.0-x86_64-linux-gnu.tar.xz"], - }, -) - -load("//platforms/toolchains:defs.bzl", "register_llvm_toolchains") - -register_llvm_toolchains() - load("@buildifier_prebuilt//:defs.bzl", "buildifier_prebuilt_register_toolchains") buildifier_prebuilt_register_toolchains() diff --git a/release/BUILD.bazel b/release/BUILD.bazel index 1475ad5f0..af32059d2 100644 --- a/release/BUILD.bazel +++ b/release/BUILD.bazel @@ -1,4 +1,5 @@ load("@aspect_bazel_lib//lib:expand_template.bzl", "expand_template") +load("@aspect_bazel_lib//lib:transitions.bzl", "platform_transition_filegroup") load("@bazel_skylib//:bzl_library.bzl", "bzl_library") load(":bazelisk_artifacts.bzl", "bazelisk_artifacts") load(":release.bzl", "multi_platform_binaries", "release") @@ -18,8 +19,26 @@ expand_template( template = ["0.0.0-PLACEHOLDER"], ) +platform_transition_filegroup( + name = "aspect-windows-x86_64.exe", + srcs = ["//cmd/aspect"], + tags = ["manual"], + target_compatible_with = [ + "@platforms//os:windows", + "@platforms//cpu:x86_64", + ], + target_platform = "@zig_sdk//platform:windows_x86_64", +) + bazelisk_artifacts( - name = "aspect_bazelisk_artifacts", + name = "windows_artifacts", + tags = ["manual"], + version_file = ":aspect_version", + windows_x86_64 = ":aspect-windows-x86_64.exe", +) + +bazelisk_artifacts( + name = "linux_and_darwin_artifacts", darwin_arm64 = ":aspect-macos-aarch64", darwin_x86_64 = ":aspect-macos-x86_64", linux_arm64 = ":aspect-linux-aarch64", @@ -33,7 +52,16 @@ release( tags = ["manual"], targets = [ ":aspect", - ":aspect_bazelisk_artifacts", + ":linux_and_darwin_artifacts", + ], +) + +release( + name = "release.windows", + tags = ["manual"], + targets = [ + ":aspect-windows-x86_64.exe", + ":windows_artifacts", ], ) @@ -50,7 +78,7 @@ sh_binary( srcs = ["delivery.sh"], data = [ ":aspect", - ":aspect_bazelisk_artifacts", + ":linux_and_darwin_artifacts", ], ) @@ -61,7 +89,7 @@ sh_binary( srcs = ["delivery.sh"], data = [ ":aspect", - ":aspect_bazelisk_artifacts", + ":linux_and_darwin_artifacts", ], tags = ["deliverable"], ) diff --git a/release/bazelisk_artifacts.bzl b/release/bazelisk_artifacts.bzl index 4039e2b68..f3edb50a5 100644 --- a/release/bazelisk_artifacts.bzl +++ b/release/bazelisk_artifacts.bzl @@ -7,22 +7,18 @@ release for Bazelisk downloads. _ATTRS = { "darwin_arm64": attr.label( doc = "The artifact for the darwin-arm64 platform.", - mandatory = True, allow_single_file = True, ), "darwin_x86_64": attr.label( doc = "The artifact for the darwin-x86_64 platform.", - mandatory = True, allow_single_file = True, ), "linux_arm64": attr.label( doc = "The artifact for the linux-arm64 platform.", - mandatory = True, allow_single_file = True, ), "linux_x86_64": attr.label( doc = "The artifact for the linux-arm64 platform.", - mandatory = True, allow_single_file = True, ), "version_file": attr.label( @@ -30,6 +26,10 @@ _ATTRS = { mandatory = True, allow_single_file = True, ), + "windows_x86_64": attr.label( + doc = "The artifact for the windows-x86_64 platform.", + allow_single_file = True, + ), "_sha256sum": attr.label( executable = True, cfg = "exec", @@ -39,27 +39,31 @@ _ATTRS = { def _impl(ctx): outdir = ctx.actions.declare_directory(ctx.label.name) - - inputs = [ - ctx.file.version_file, - ctx.file.darwin_arm64, - ctx.file.darwin_x86_64, - ctx.file.linux_arm64, - ctx.file.linux_x86_64, - ] - + inputs = [ctx.file.version_file] args = ctx.actions.args() args.add(ctx.executable._sha256sum.path) args.add(outdir.path) args.add(ctx.file.version_file) - args.add(ctx.file.darwin_arm64) - args.add("darwin-arm64") - args.add(ctx.file.darwin_x86_64) - args.add("darwin-x86_64") - args.add(ctx.file.linux_arm64) - args.add("linux-arm64") - args.add(ctx.file.linux_x86_64) - args.add("linux-x86_64") + + if ctx.attr.windows_x86_64: + inputs.append(ctx.file.windows_x86_64) + args.add(ctx.file.windows_x86_64) + args.add("windows-x86_64.exe") + else: + inputs.extend([ + ctx.file.darwin_arm64, + ctx.file.darwin_x86_64, + ctx.file.linux_arm64, + ctx.file.linux_x86_64, + ]) + args.add(ctx.file.darwin_arm64) + args.add("darwin-arm64") + args.add(ctx.file.darwin_x86_64) + args.add("darwin-x86_64") + args.add(ctx.file.linux_arm64) + args.add("linux-arm64") + args.add(ctx.file.linux_x86_64) + args.add("linux-x86_64") ctx.actions.run_shell( outputs = [outdir], @@ -77,7 +81,7 @@ version="$(< "${version_file}")" mkdir -p "${output_dir}" while (("$#")); do - # Read args three at a time + # Read args in pairs artifact_path="$1" platform_suffix="$2" shift 2 diff --git a/release/release.bzl b/release/release.bzl index c70f90e39..a3d4f1343 100644 --- a/release/release.bzl +++ b/release/release.bzl @@ -73,7 +73,7 @@ def release(name, targets, **kwargs): native.genrule( name = name, srcs = targets, - outs = ["release.sh"], + outs = [name + ".sh"], executable = True, cmd = "./$(location //release:create_release.sh) {locations} > \"$@\"".format( locations = " ".join(["$(locations {})".format(target) for target in targets]), diff --git a/tools/workspace_status.js b/tools/workspace_status.js new file mode 100755 index 000000000..a35947993 --- /dev/null +++ b/tools/workspace_status.js @@ -0,0 +1,33 @@ +#!/usr/bin/env node +// This script is called by Bazel when it needs info about the git state. +// The --workspace_status_command flag tells Bazel the location of this script. +// This is configured in `/.bazelrc`. +import { execSync } from 'node:child_process'; + +// "stable" keys, should remain constant over rebuilds, therefore changed values will cause a +// rebuild of any stamped action that uses ctx.info_file or genrule with stamp = True +// Note, BUILD_USER is automatically available in the stable-status.txt, it matches $USER +const has_local_changes = execSync('git status --porcelain').length > 0; +console.log(`STABLE_BUILD_SCM_SHA ${execSync('git rev-parse HEAD')}`); +console.log(`STABLE_BUILD_SCM_LOCAL_CHANGES ${has_local_changes}`); + +const gitTags = execSync('git tag'); +if (gitTags.length > 0) { + // Follows https://blog.aspect.build/versioning-releases-from-a-monorepo + const monorepo_version = execSync( + `git describe --tags --long --match="[0-9][0-9][0-9][0-9].[0-9][0-9]"`, + { encoding: 'utf-8' } + ) + .replace('-', '.') + .replace('-g', '-'); + + // Variant of monorepo_version that conforms with the version scheme Bazelisk supports. + // It assumes the upstream `bazel` binary releases are the only ones referenced, + // so we are forced to adopt a matching scheme. + // https://github.com/bazelbuild/bazelisk/blob/47f60477721681a117cbf905784ee5220100e68b/versions/versions.go#L20-L25 + const bazelisk_compat_version = monorepo_version.split('-')[0]; + console.log( + `STABLE_ASPECT_CLI_BAZELISK_COMPAT_VERSION ${bazelisk_compat_version}` + ); + console.log(`STABLE_ASPECT_CLI_VERSION ${monorepo_version}`); +} diff --git a/workspace_status.sh b/workspace_status.sh deleted file mode 100755 index a7df8627e..000000000 --- a/workspace_status.sh +++ /dev/null @@ -1,41 +0,0 @@ -#!/usr/bin/env bash -# This script is called by Bazel when it needs info about the git state. -# The --workspace_status_command flag tells Bazel the location of this script. -# This is configured in `/.bazelrc`. -set -o pipefail -o errexit -o nounset - -function has_local_changes { - if [ "$(git status --porcelain)" != "" ]; then - echo dirty - else - echo clean - fi -} - -# "volatile" keys, these will not cause a re-build because they're assumed to change on every build -# and its okay to use a stale value in a stamped binary -echo "BUILD_TIME $(date "+%Y-%m-%d %H:%M:%S %Z")" - -# "stable" keys, should remain constant over rebuilds, therefore changed values will cause a -# rebuild of any stamped action that uses ctx.info_file or genrule with stamp = True -# Note, BUILD_USER is automatically available in the stable-status.txt, it matches $USER -echo "STABLE_BUILD_SCM_SHA $(git rev-parse HEAD)" -echo "STABLE_BUILD_SCM_LOCAL_CHANGES $(has_local_changes)" - -if [ "$(git tag | wc -l)" -gt 0 ]; then - # Follows https://blog.aspect.build/versioning-releases-from-a-monorepo - monorepo_version=$( - git describe --tags --long --match="[0-9][0-9][0-9][0-9].[0-9][0-9]" | - sed -e 's/-/./;s/-g/-/' - ) - - # Variant of monorepo_version that conforms with the version scheme Bazelisk supports. - # It assumes the upstream `bazel` binary releases are the only ones referenced, - # so we are forced to adopt a matching scheme. - # https://github.com/bazelbuild/bazelisk/blob/47f60477721681a117cbf905784ee5220100e68b/versions/versions.go#L20-L25 - # shellcheck disable=SC2001 - bazelisk_compat_version=$(sed 's/-.*//' <<<"$monorepo_version") - - echo "STABLE_ASPECT_CLI_BAZELISK_COMPAT_VERSION ${bazelisk_compat_version}" - echo "STABLE_ASPECT_CLI_VERSION ${monorepo_version}" -fi