Skip to content

Commit

Permalink
fix(release): add multi-arch/platform support
Browse files Browse the repository at this point in the history
This commit adds multi-architecture (amd64 and arm64) and multi-platform (Windows, macOS, Linux) builds for all binaries within the project.
  • Loading branch information
mvprowess committed Sep 24, 2024
1 parent f06faf2 commit 0753c6b
Show file tree
Hide file tree
Showing 3 changed files with 168 additions and 110 deletions.
8 changes: 6 additions & 2 deletions .github/workflows/release.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,12 @@ jobs:
path: dist
github-token: ${{ secrets.GITHUB_TOKEN }}
repository: ${{ github.repository }}
run-id: ${{github.event.client_payload.run_id }}
run-id: ${{ github.event.client_payload.run_id }}

- name: Build final SHA256 checksums
run: |
scripts/release.sh checksums
- name: Upload artifacts to Release-Please GitHub release
run: |
gh release upload ${{ needs.release.outputs.tag }} dist/*.tar.gz dist/*.txt
gh release upload ${{ needs.release.outputs.tag }} dist/*.tar.gz dist/CHECKSUMS.txt
44 changes: 20 additions & 24 deletions .github/workflows/testing.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -20,30 +20,13 @@ concurrency:
group: "${{ github.workflow }}@${{ github.event.pull_request.head.label || github.head_ref || github.ref }}"

jobs:
info:
name: Gather information
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4

- name: Get Go Version
run: |
VERSION=$(bash scripts/status.sh | grep GO_VERSION | cut -d' ' -f 2)
echo "go_version=$VERSION" >> "$GITHUB_OUTPUT"
- name: Get Bazel Version
run: |
VERSION=$(cat .bazelversion)
echo "bazel_version=$VERSION" >> "$GITHUB_OUTPUT"
test:
name: Test
strategy:
matrix:
os: [ubuntu-latest]
os: [ubuntu-latest, windows-latest, macos-latest]
arch: [amd64, arm64]
runs-on: ${{ matrix.os }}
needs: [info]
env:
CACHE_PATH: ${{ matrix.os == 'macos-latest' && '/private/var/tmp/_bazel_runner/' || '~/.cache/bazel' }}
steps:
Expand All @@ -65,19 +48,32 @@ jobs:
restore-keys: |
${{ runner.os }}-bazel-
- name: Determine Bazel platform
id: platform
run: |
os="${{ runner.os }}"
platform="linux"
case "$os" in
Windows) platform="windows" ;;
macOS) platform="darwin" ;;
esac
final=$(printf "@io_bazel_rules_go//go/toolchain:%s_%s" "$platform" ${{ matrix.arch }})
echo "platform=$final" >> "$GITHUB_OUTPUT"
- name: Build Bazel artifacts
run: |
bazel --output_user_root=${{ env.CACHE_PATH }} build //...
bazel --output_user_root=${{ env.CACHE_PATH }} build --platforms=${{ steps.platform.outputs.platform }} //...
- name: Test Bazel artifacts
run: |
bazel --output_user_root=${{ env.CACHE_PATH }} test //...
bazel --output_user_root=${{ env.CACHE_PATH }} test --platforms=${{ steps.platform.outputs.platform }} //...
# Fail here
# Fail here if tests didn't succeed
- name: Generate Release artifacts
if: ${{ success() }}
run: |
bash scripts/release.sh
scripts/release.sh executables
scripts/release.sh tarballs
- name: Upload Release artifacts
if: ${{ success() }}
Expand All @@ -90,7 +86,7 @@ jobs:
dispatch:
runs-on: ubuntu-latest
needs: [info, test]
needs: [test]
steps:
- name: Dispatch a release workflow run
if: ${{ !failure() }}
Expand Down
226 changes: 142 additions & 84 deletions scripts/release.sh
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,28 @@ license="$(lib::paths::root)/LICENSE"
PKGS=()
LABELS=()

# multi-arch builds
ARCH=('amd64' 'arm64')

# ----------------------
# 'help' usage function
# ----------------------
function release::usage() {
echo
echo "Usage: $(basename "${0}") <COMMAND>"
echo
echo "executables - Build gopskit executables"
echo "tarballs - Build gopskit distribution tarballs"
echo "checksums - Calculate the SHA256 checksums"
echo "cleanup - Clean-up temporary build directories"
echo "help - Print this usage information"
echo
}

# ----------------------
# 'create_directories' function
# ----------------------
function create_directories() {
function release::lib::create_directories() {
if [[ ! -d "$BUILD_DIR" ]]; then
log::yellow "Creating build directory: $BUILD_DIR"
mkdir -p "$BUILD_DIR"
Expand All @@ -57,89 +75,119 @@ function create_directories() {
# ----------------------
# 'build_executables' function
# ----------------------
function build_executables() {
bazel --output_user_root="$BAZEL_CACHE_PATH" build //... 2>/dev/null
function release::build_executables() {
# create build directories
release::lib::create_directories
rc=$?
if [[ $rc -ne 0 ]]; then
log::red "Bazel build failed. Could not build executables!"
return 1
log::red "Could not create build directories!"
return "$rc"
fi

log::green "Built 'gopskit' executables!"
for arch in "${ARCH[@]}"; do
# build
log::yellow "Building 'gopskit' executables for architecture: $arch"
platform=$(printf "@io_bazel_rules_go//go/toolchain:%s_%s" "$PLATFORM" "$arch")
bazel --output_user_root="$BAZEL_CACHE_PATH" build --stamp --platforms="$platform" //...
rc=$?
if [[ $rc -ne 0 ]]; then
log::red "Bazel build failed. Could not build executables!"
return 1
fi
log::green "Built 'gopskit' executables for architecture: $arch!"

#copy
for lbl in "${LABELS[@]}"; do
pkg=$(echo "$lbl" | cut -d':' -f 2)
log::yellow "Copying $pkg binary to $BUILD_TMP_DIR"

output=$(bazel --output_user_root="$BAZEL_CACHE_PATH" cquery \
--output=files --platforms="$platform" "$lbl" 2>/dev/null)
arch_pkg=$(printf "%s_%s" "$pkg" "$arch")
out_pkg=$([ "$PLATFORM" == "windows" ] && echo "$arch_pkg.exe" || echo "$arch_pkg") # append .exe on Windows
destination=$(printf "%s/%s" "$BUILD_TMP_DIR" "$out_pkg")
cp "$output" "$destination"
done

done
return 0
}

# ----------------------
# 'build_tarballs' function
# ----------------------
function build_tarballs() {
for lbl in "${LABELS[@]}"; do
pkg=$(echo "$lbl" | cut -d':' -f 2)
log::yellow "Copying $pkg binary to $BUILD_TMP_DIR"

output=$(bazel --output_user_root="$BAZEL_CACHE_PATH" cquery --output=files "$lbl" 2>/dev/null)
destination=$BUILD_TMP_DIR
cp "$output" "$destination"
done

function release::build_tarballs() {
log::yellow "Copying package LICENSE to $BUILD_TMP_DIR"
cp "$license" "$BUILD_TMP_DIR"

for pkg in "${PKGS[@]}"; do
log::yellow "Building tarball for $pkg"
output=$(printf "%s/%s_%s.tar.gz" "$BUILD_DIR" "$pkg" "$PLATFORM")
for arch in "${ARCH[@]}"; do
for pkg in "${PKGS[@]}"; do
log::yellow "Building tarball for $pkg"
input=$(printf "%s_%s" "$pkg" "$arch")
output=$(printf "%s/%s_%s_%s.tar.gz" "$BUILD_DIR" "$pkg" "$PLATFORM" "$arch")

tar czfvP "$output" -C "$BUILD_TMP_DIR" "$input" LICENSE >/dev/null
rc=$?
if [[ $rc -ne 0 ]]; then
log::red "Could not build tarball for package: $pkg and architecture $arch"
return "$rc"
fi
done

log::yellow "Building 'gopskit' tarball for architecture: $arch"
tarb=$(printf "%s/gopskit_%s_%s.tar.gz" "$BUILD_DIR" "$PLATFORM" "$arch")
tar czfvP "$tarb" -C "$BUILD_TMP_DIR" "${PKGS[@]/%/_$arch}" "LICENSE" >/dev/null
rc=$?
if [[ $rc -ne 0 ]]; then
log::red "Could not build 'gopskit' tarball"
return "$rc"
fi
done

log::yellow "Changing working directory to $BUILD_DIR"
old_wd=$(pwd)
cd "$BUILD_DIR"

tar czfvP "$output" -C "$BUILD_TMP_DIR" "$pkg" LICENSE >/dev/null
file=$(printf "%s_checksums.txt" "$PLATFORM")
[ -e "$file" ] && rm -f "$file"
for dtar in *.tar.gz; do
sha256sum "$dtar" >>"$file"
rc=$?
if [[ $rc -ne 0 ]]; then
log::red "Could not build tarball for package: $pkg"
log::red "Could not calculate SHA256 checksums for tarball: $dtar"
return "$rc"
fi
done

log::yellow "Building 'gopskit' tarball"
tarb=$(printf "%s/gopskit_%s.tar.gz" "$BUILD_DIR" "$PLATFORM")
tar czfvP "$tarb" -C "$BUILD_TMP_DIR" "${PKGS[@]}" "LICENSE" >/dev/null
rc=$?
if [[ $rc -ne 0 ]]; then
log::red "Could not build 'gopskit' tarball"
return "$rc"
fi
# switch back
cd "$old_wd"

log::green "Built 'gopskit' executables!"
log::green "Built 'gopskit' distribution tarballs!"
return 0
}

# ----------------------
# 'calculate_checksums' function
# ----------------------
function calculate_checksums() {
function release::calculate_checksums() {
log::yellow "Changing working directory to $BUILD_DIR"
old_pwd=$(pwd)
old_wd=$(pwd)
cd "$BUILD_DIR"

for pkg in "${PKGS[@]}"; do
log::yellow "Calculating checksums for $pkg"
output=$(printf "%s_%s.tar.gz" "$pkg" "$PLATFORM")
sha256sum "$output" >>"$BUILD_DIR/checksums.txt"
file="CHECKSUMS.txt"
[ -e "$file" ] && rm -f "$file"
for dtar in *.txt; do
echo "# SHA256" >>"$file"
cat "$dtar" >>"$file"
rc=$?
if [[ $rc -ne 0 ]]; then
log::red "Could not calculate SHA256 checksums for package: $pkg"
log::red "Could not calculate SHA256 checksums for tarball: $dtar"
return "$rc"
fi
done

log::yellow "Calculating checksums for 'gopskit'"
tarba=$(printf "gopskit_%s.tar.gz" "$PLATFORM")
sha256sum "$tarba" >>"$BUILD_DIR/checksums.txt"
rc=$?
if [[ $rc -ne 0 ]]; then
log::red "Could not calculate SHA256 checksums for 'gopskit' tarball"
return "$rc"
fi

# switch back
cd "$old_pwd"
cd "$old_wd"

log::green "Calculated 'gopskit' SHA256 checksums!"
return 0
Expand All @@ -149,6 +197,8 @@ function calculate_checksums() {
# MAIN
# --------------------------------
function main() {
local cmd=${1}

# initialize constants
raw=$(bazel --output_user_root="$BAZEL_CACHE_PATH" query 'kind("go_binary", //...)' 2>/dev/null)
while IFS="$(printf '\n')" read -r line; do LABELS+=("$line"); done <<<"$raw"
Expand All @@ -170,43 +220,51 @@ function main() {
fi
fi

# create build directories
create_directories
rc=$?
if [[ $rc -ne 0 ]]; then
log::red "Could not create build directories!"
return "$rc"
fi

# build Go binaries
build_executables
rc=$?
if [[ $rc -ne 0 ]]; then
log::red "Could not build 'gopskit' executables!"
return "$rc"
fi

# build tarballs
build_tarballs
rc=$?
if [[ $rc -ne 0 ]]; then
log::red "Could not build 'gopskit' tarballs!"
return "$rc"
fi

# checksums
calculate_checksums
rc=$?
if [[ $rc -ne 0 ]]; then
log::red "Could not calculate 'gopskit' checksums!"
return "$rc"
fi

# cleanup
if [[ -d "$BUILD_TMP_DIR" ]]; then
log::yellow "Removing temporary directory within build directory: $BUILD_TMP_DIR"
rm -rf "$BUILD_TMP_DIR"
fi
case "${cmd}" in
executables)
release::build_executables
rc=$?
if [[ $rc -ne 0 ]]; then
log::red "Could not build 'gopskit' executables!"
return "$rc"
fi
;;
tarballs)
release::build_tarballs
rc=$?
if [[ $rc -ne 0 ]]; then
log::red "Could not build 'gopskit' tarballs!"
return "$rc"
fi
;;
checksums)
release::calculate_checksums
rc=$?
if [[ $rc -ne 0 ]]; then
log::red "Could not calculate 'gopskit' checksums!"
return "$rc"
fi
;;
cleanup)
if [[ -d "$BUILD_TMP_DIR" ]]; then
log::yellow "Removing temporary directory within build directory: $BUILD_TMP_DIR"
rm -rf "$BUILD_TMP_DIR"
fi
rc=$?
if [[ $rc -ne 0 ]]; then
log::red "Could not cleanup 'gopskit' build directories!"
return "$rc"
fi
;;
help)
release::usage
return $?
;;
*)
log::red "Unknown command: ${cmd}. See 'help' command for usage information:"
release::usage
;;
esac

log::green "release.sh finished!"
}
Expand Down

0 comments on commit 0753c6b

Please sign in to comment.