From f9e2cca33055c83b5682c52d21d66ffe908f3012 Mon Sep 17 00:00:00 2001 From: Scott Minor Date: Thu, 11 Jul 2024 11:51:44 -0400 Subject: [PATCH] github: Add release workflows This change implements two workflows that together implement the release process. The first workflow is manually triggered, takes a human-specified semver version string, and creates an automated commit that updates the version string in the required places, and then tags the new commit. The second workflow is triggered on release semver tags, and performs the build and creates the release. Tested: no - these workflows are hard to test manually, and will likely require trial+error on Github itself. Bug: linear/CUS-332 --- .bazelrc | 3 ++ .github/workflows/release.yml | 31 ++++++++++++++++ BUILD | 9 +++++ cmd/engflow_auth/BUILD | 4 +++ infra/BUILD | 0 infra/release.sh | 67 +++++++++++++++++++++++++++++++++++ infra/visibility.bzl | 5 +++ 7 files changed, 119 insertions(+) create mode 100644 .github/workflows/release.yml create mode 100644 infra/BUILD create mode 100755 infra/release.sh create mode 100644 infra/visibility.bzl diff --git a/.bazelrc b/.bazelrc index 93ad7c8..f678853 100644 --- a/.bazelrc +++ b/.bazelrc @@ -20,3 +20,6 @@ build:noninteractive --show_timestamps build:noninteractive --announce_rc build:noninteractive --test_output=summary build:noninteractive --keep_going + +build:release --config=noninteractive +build:release --stamp diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..3a94baf --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,31 @@ +name: "release" + +on: + workflow_dispatch: + inputs: + version: + type: string + description: Version of engflow_auth to release; must be a semver version string, starting with `v` + required: true + +permissions: + contents: write + +jobs: + release: + runs-on: + - self-hosted + - os=linux + - arch=x64 + - os_distribution=debian + - os_version=12 + - revision=d04e89854b3931f4aaced77aa3a2fcad5834b3a6 + timeout-minutes: 10 + + steps: + - uses: actions/checkout@v4 + - name: release + run: | + infra/release.sh "${{ github.events.inputs.version }}" + env: + GITHUB_TOKEN: ${{ github.token }} diff --git a/BUILD b/BUILD index b0bf57a..6d645fb 100644 --- a/BUILD +++ b/BUILD @@ -2,3 +2,12 @@ load("@gazelle//:def.bzl", "gazelle") # gazelle:prefix github.com/EngFlow/auth gazelle(name = "gazelle") + +filegroup( + name = "release_artifacts", + srcs = [ + "//cmd/engflow_auth:engflow_auth_linux_x64", + "//cmd/engflow_auth:engflow_auth_macos_arm64", + "//cmd/engflow_auth:engflow_auth_windows_x64", + ], +) diff --git a/cmd/engflow_auth/BUILD b/cmd/engflow_auth/BUILD index cad88f5..632a289 100644 --- a/cmd/engflow_auth/BUILD +++ b/cmd/engflow_auth/BUILD @@ -1,4 +1,5 @@ load("@rules_go//go:def.bzl", "go_binary", "go_cross_binary", "go_library", "go_test") +load("//infra:visibility.bzl", "RELEASE_ARTIFACT") go_library( name = "engflow_auth_lib", @@ -40,16 +41,19 @@ go_cross_binary( name = "engflow_auth_macos_arm64", platform = "@rules_go//go/toolchain:darwin_arm64_cgo", target = ":engflow_auth", + visibility = RELEASE_ARTIFACT, ) go_cross_binary( name = "engflow_auth_windows_x64", platform = "@rules_go//go/toolchain:windows_amd64_cgo", target = ":engflow_auth", + visibility = RELEASE_ARTIFACT, ) go_cross_binary( name = "engflow_auth_linux_x64", platform = "@rules_go//go/toolchain:linux_amd64_cgo", target = ":engflow_auth", + visibility = RELEASE_ARTIFACT, ) diff --git a/infra/BUILD b/infra/BUILD new file mode 100644 index 0000000..e69de29 diff --git a/infra/release.sh b/infra/release.sh new file mode 100755 index 0000000..412ccfe --- /dev/null +++ b/infra/release.sh @@ -0,0 +1,67 @@ +#!/usr/bin/env bash + +set -o nounset -o pipefail -o errexit +[[ "${SCRIPT_DEBUG:-"off"}" == "on" ]] && set -o xtrace + +if [[ "$#" -ne 1 ]]; then + echo "Want 1 argument; got $# arguments" + exit 1 +fi + +# Taken from https://semver.org/, with a `v` prepended +readonly SEMVER_REGEX='^v(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$' +readonly RELEASE_VERSION="$1" +readonly GH_CLI_URL='https://storage.googleapis.com/engflow-tools-public/github.com/cli/cli/releases/download/v2.52.0/gh_2.52.0_linux_amd64.tar.gz' +readonly GH_CLI_EXPECTED_SHA256='3ea6ed8b2585f406a064cecd7e1501e58f56c8e7ca764ae1f3483d1b8ed68826' + +# Check that supplied version string follows semver +if ! grep --quiet --extended-regexp "${SEMVER_REGEX}" <<<${RELEASE_VERSION}; then + echo "Supplied version string '${RELEASE_VERSION}' does not follow semver; exiting" + exit 1 +fi + +function cleanup { + rm -rf "${GH_CLI_DIR}" +} + +# Download and verify Github CLI +# TODO(CUS-353): Remove this after installing Github CLI in the self-hosted +# environment (run via Docker?) +readonly GH_CLI_DIR="$(mktemp -d -t 'gh_cli_XXXXXXXX')" +curl --silent --location "${GH_CLI_URL}" \ + | tee >(sha256sum - > "${GH_CLI_DIR}/archive_checksum.txt") \ + | tar \ + -C "${GH_CLI_DIR}" \ + --strip-components 1 \ + -xzf \ + - +trap 'cleanup' EXIT +readonly GH_CLI="${GH_CLI_DIR}/bin/gh" +readonly GH_CLI_ACTUAL_SHA256="$(cat ${GH_CLI_DIR}/archive_checksum.txt | awk '{ print $1 }')" +if [[ "${GH_CLI_ACTUAL_SHA256}" != "${GH_CLI_EXPECTED_SHA256}" ]]; then + echo "SHA256 for Github CLI tarball ${GH_CLI_ACTUAL_SHA256} doesn't match expected value ${GH_CLI_ACTUAL_SHA256}; exiting" + exit 1 +fi + +# Check that the current commit is on either `main` or a release branch +readonly EXPECTED_RELEASE_BRANCH="$(sed --regexp-extended 's|(v[0-9]+.[0-9]+).[0-9]+|release/\1|' <<<${RELEASE_VERSION})" +if ! git branch \ + --contains "$(git rev-parse HEAD)" \ + | grep --quiet --extended-regexp "main|${EXPECTED_RELEASE_BRANCH}"; then + echo "Commit $(git rev-parse HEAD) is not on main or release branch ${EXPECTED_RELEASE_BRANCH}; exiting" + exit 1 +fi + +# Build release artifacts +bazel build \ + --config=release \ + -- \ + //:release_artifacts + +# Create release +${GH_CLI} release create \ + "v${RELEASE_VERSION}" \ + --generate-notes \ + "$(realpath bazel-out/k8-fastbuild-ST-*/bin/cmd/engflow_auth/engflow_auth_linux_x64)#engflow_auth (Linux, x64)" \ + "$(realpath bazel-out/k8-fastbuild-ST-*/bin/cmd/engflow_auth/engflow_auth_macos_arm64)#engflow_auth (macOS, arm64)" \ + "$(realpath bazel-out/k8-fastbuild-ST-*/bin/cmd/engflow_auth/engflow_auth_windows_x64)#engflow_auth (Windows, x64)" diff --git a/infra/visibility.bzl b/infra/visibility.bzl new file mode 100644 index 0000000..6d54a11 --- /dev/null +++ b/infra/visibility.bzl @@ -0,0 +1,5 @@ +"""Contains visibility constants to reduce duplication, increase BUILD file readability""" + +# Visibility used for artifacts that get released, which are defined by +# filegroup(s) in the top-level BUILD file. +RELEASE_ARTIFACT = ["//:__pkg__"]