diff --git a/.github/packaging/Dockerfile.tgz b/.github/packaging/Dockerfile.tgz new file mode 100644 index 000000000000..96bdd8aff720 --- /dev/null +++ b/.github/packaging/Dockerfile.tgz @@ -0,0 +1,41 @@ +# Build container for linux tarball packaging of avalanchego and subnet-evm. +# +# Based on Ubuntu 22.04 (glibc 2.35) to match the jammy target users +# already consume. Source tree is bind-mounted at runtime, not COPY'd. +# +# Usage (via build-builder-image.sh, which fetches GO_CHECKSUM automatically): +# DOCKERFILE=Dockerfile.tgz .github/packaging/scripts/build-builder-image.sh +# docker run --rm -v .:/build -v ./build/tgz:/output avalanchego-tgz-builder ... + +FROM ubuntu:22.04 + +ARG GO_VERSION=INVALID +ARG GO_CHECKSUM=INVALID +ARG TARGETARCH + +ENV DEBIAN_FRONTEND=noninteractive + +# Install build dependencies +# - gcc, libc6-dev: required for cgo (CGO_ENABLED=1 in scripts/constants.sh) +# - gnupg2: GPG signing of tarballs +# - git: version detection in build scripts +# - ca-certificates, curl: Go download +RUN apt-get update \ + && apt-get install -y --no-install-recommends \ + ca-certificates \ + curl \ + gcc \ + git \ + gnupg2 \ + libc6-dev \ + && rm -rf /var/lib/apt/lists/* + +# Install Go (with SHA256 verification) +RUN curl -fsSL -o /tmp/go.tar.gz \ + "https://go.dev/dl/go${GO_VERSION}.linux-${TARGETARCH}.tar.gz" \ + && echo "${GO_CHECKSUM} /tmp/go.tar.gz" | sha256sum -c - \ + && tar -C /usr/local -xzf /tmp/go.tar.gz \ + && rm /tmp/go.tar.gz +ENV PATH="/usr/local/go/bin:${PATH}" + +WORKDIR /build diff --git a/.github/packaging/Taskfile.yml b/.github/packaging/Taskfile.yml index 8d1def282896..1141f5c39ebd 100644 --- a/.github/packaging/Taskfile.yml +++ b/.github/packaging/Taskfile.yml @@ -1,6 +1,8 @@ -# RPM packaging tasks for avalanchego and subnet-evm. +# Packaging tasks for avalanchego and subnet-evm. # -# Builds RPMs inside a Rocky Linux 9 container (glibc 2.34) with GPG signing. +# - RPMs build inside a Rocky Linux 9 container (glibc 2.34) with GPG signing. +# - Linux tarballs build inside an Ubuntu 22.04 container (glibc 2.35) with +# detached GPG signatures and validate in a fresh ubuntu:22.04 container. # PACKAGING_TAG defaults to v0.0.0 for local testing; set for release builds. version: '3' @@ -31,6 +33,18 @@ vars: PACKAGING_DOCKER_IMAGE: avalanchego-rpm-builder PACKAGING_OUTPUT_DIR: '{{.REPO_ROOT}}/build/rpm' + # Map uname -m to deb/tarball arch names (aarch64 -> arm64). + PACKAGING_TGZ_HOST_ARCH: + sh: | + arch=$(uname -m) + case "${arch}" in + x86_64) echo "amd64" ;; + arm64|aarch64) echo "arm64" ;; + *) echo "${arch}" ;; + esac + PACKAGING_TGZ_DOCKER_IMAGE: avalanchego-tgz-builder + PACKAGING_TGZ_OUTPUT_DIR: '{{.REPO_ROOT}}/build/tgz' + tasks: default: desc: Lists available packaging tasks @@ -114,3 +128,54 @@ tasks: GIT_COMMIT: '{{.PACKAGING_GIT_COMMIT}}' cmds: - cmd: '{{.REPO_ROOT}}/.github/packaging/scripts/validate-rpm.sh' + + build-tgz-builder-docker-image: + desc: Builds the linux tarball builder Docker image + internal: true + env: + GO_VERSION: '{{.PACKAGING_GO_VERSION}}' + DOCKER_IMAGE: '{{.PACKAGING_TGZ_DOCKER_IMAGE}}' + DOCKERFILE: 'Dockerfile.tgz' + CONTEXT_DIR: '{{.REPO_ROOT}}/.github/packaging' + cmds: + - cmd: '{{.REPO_ROOT}}/.github/packaging/scripts/build-builder-image.sh' + + build-tarballs: + desc: Builds linux tarballs for avalanchego and subnet-evm in a container + vars: + TGZ_TAG: '{{.PACKAGING_TAG}}' + deps: [build-tgz-builder-docker-image] + cmds: + - cmd: mkdir -p {{.PACKAGING_TGZ_OUTPUT_DIR}} + - cmd: >- + docker run --rm + --platform linux/{{.PACKAGING_TGZ_HOST_ARCH}} + -v {{.REPO_ROOT}}:/build + -v {{.PACKAGING_TGZ_OUTPUT_DIR}}:/output + {{if .GPG_KEY_FILE}}-v {{.GPG_KEY_FILE}}:{{.GPG_KEY_FILE}}:ro{{end}} + -e PACKAGING_TAG={{.TGZ_TAG}} + -e OUTPUT_DIR=/output + -e AVALANCHEGO_COMMIT={{.PACKAGING_GIT_COMMIT}} + {{if .GPG_KEY_FILE}}-e GPG_KEY_FILE{{end}} + {{if .GPG_PASSPHRASE}}-e GPG_PASSPHRASE{{end}} + {{.PACKAGING_TGZ_DOCKER_IMAGE}} + .github/packaging/scripts/build-tgz.sh + + validate-tarballs: + desc: Validates tarballs by verifying signatures and smoke testing in a fresh container + cmds: + - cmd: >- + TAG={{.PACKAGING_TAG}} + GIT_COMMIT={{.PACKAGING_GIT_COMMIT}} + {{.REPO_ROOT}}/.github/packaging/scripts/validate-tgz.sh + + test-build-tarballs: + desc: Builds and validates linux tarballs end-to-end + cmds: + - task: build-tarballs + - task: validate-tarballs + + upload-tarballs: + desc: Uploads built tarballs and signatures to S3 (requires BUCKET, TGZ_ARCH, AWS creds) + cmds: + - cmd: '{{.REPO_ROOT}}/.github/packaging/scripts/upload-tgz.sh' diff --git a/.github/packaging/scripts/build-builder-image.sh b/.github/packaging/scripts/build-builder-image.sh index f134922fa6cf..4d649b6d35a1 100755 --- a/.github/packaging/scripts/build-builder-image.sh +++ b/.github/packaging/scripts/build-builder-image.sh @@ -1,6 +1,6 @@ #!/usr/bin/env bash -# Build the RPM builder Docker image with Go checksum verification. +# Build a packaging builder Docker image with Go checksum verification. # # Fetches the SHA256 checksum for the Go tarball from go.dev release # metadata and passes it to the Docker build for integrity verification. @@ -9,6 +9,9 @@ # GO_VERSION - Go version to install (e.g., "1.24.12") # DOCKER_IMAGE - Name for the built Docker image # CONTEXT_DIR - Path to the Dockerfile directory +# +# Optional env vars: +# DOCKERFILE - Dockerfile name within CONTEXT_DIR (default: "Dockerfile") set -euo pipefail @@ -16,12 +19,14 @@ set -euo pipefail : "${DOCKER_IMAGE:?DOCKER_IMAGE must be set}" : "${CONTEXT_DIR:?CONTEXT_DIR must be set}" +DOCKERFILE="${DOCKERFILE:-Dockerfile}" + command -v jq >/dev/null 2>&1 || { echo "ERROR: jq is required but not found on PATH" >&2; exit 1; } # Map host arch to Go's naming convention arch=$(uname -m) case "${arch}" in - x86_64) goarch="amd64" ;; + x86_64) goarch="amd64" ;; aarch64|arm64) goarch="arm64" ;; *) echo "Unsupported arch: ${arch}" >&2; exit 1 ;; esac @@ -50,8 +55,15 @@ if [[ "${build_driver}" == "docker-container" ]]; then build_flags+=(--load) fi +# Pin the build to the host arch we resolved goarch / GO_CHECKSUM for. +# Without this, DOCKER_DEFAULT_PLATFORM (commonly set on Apple Silicon) +# could make Docker's TARGETARCH diverge from the checksum we computed, +# causing the Dockerfile's Go SHA256 verification to fail. +build_flags+=(--platform "linux/${goarch}") + docker build "${build_flags[@]}" \ --build-arg GO_VERSION="${GO_VERSION}" \ --build-arg GO_CHECKSUM="${checksum}" \ + -f "${CONTEXT_DIR}/${DOCKERFILE}" \ -t "${DOCKER_IMAGE}" \ "${CONTEXT_DIR}" diff --git a/.github/packaging/scripts/build-tgz.sh b/.github/packaging/scripts/build-tgz.sh new file mode 100755 index 000000000000..55651dfe11f6 --- /dev/null +++ b/.github/packaging/scripts/build-tgz.sh @@ -0,0 +1,159 @@ +#!/usr/bin/env bash + +# Build and sign linux tarballs for avalanchego and subnet-evm inside the container. +# +# Required env vars: +# PACKAGING_TAG - Git tag (e.g., "v1.14.1") +# OUTPUT_DIR - Directory for the output tarballs (bind-mounted from host) +# +# Optional env vars: +# GPG_KEY_FILE - Path to GPG private key for signing +# GPG_PASSPHRASE - Passphrase for the GPG key +# AVALANCHEGO_COMMIT - Git commit hash (auto-detected if not set) +# +# Target architecture is derived from `uname -m` inside the container. +# The container runs at the platform pinned by the docker run --platform +# flag (host arch), so the produced filenames always match the binaries. + +set -euo pipefail + +: "${PACKAGING_TAG:?PACKAGING_TAG must be set}" +: "${OUTPUT_DIR:?OUTPUT_DIR must be set}" + +REPO_ROOT="/build" +TAG="${PACKAGING_TAG}" + +# Map uname -m to deb-style arch (aarch64 -> arm64). Computed inside the +# container, so it reflects the actual platform the binaries are built +# for, regardless of any caller-supplied env vars. +host_arch=$(uname -m) +case "${host_arch}" in + x86_64) ARCH="amd64" ;; + aarch64|arm64) ARCH="arm64" ;; + *) echo "Unsupported arch: ${host_arch}" >&2; exit 1 ;; +esac + +mkdir -p "${OUTPUT_DIR}" + +# Remove stale tarballs, signatures, and the exported public key from +# any previous run. Tar would overwrite same-tag tarballs, but on +# persistent runners or after a failed cleanup, build/tgz can carry +# over tarballs from a different tag — and the workflow's S3 upload +# step matches *.tar.gz with a wildcard, so stale archives would be +# republished alongside the current release. +rm -f "${OUTPUT_DIR}"/*.tar.gz "${OUTPUT_DIR}"/*.tar.gz.sig "${OUTPUT_DIR}/GPG-KEY-avalanchego" + +echo "=== Building tarballs for ${ARCH} (tag: ${TAG}) ===" + +# ── Step 1: Build binaries ──────────────────────────────────────── + +# In CI, the bind-mounted source tree is owned by the host user. Mark it +# as safe so that git works inside the container (needed by older build +# scripts that resolve the commit hash via git rather than AVALANCHEGO_COMMIT). +if ! git -C "${REPO_ROOT}" rev-parse HEAD &>/dev/null; then + git config --global --add safe.directory "${REPO_ROOT}" +fi + +# shellcheck disable=SC1091 +source "${REPO_ROOT}/scripts/constants.sh" +# shellcheck disable=SC1091 +source "${REPO_ROOT}/scripts/git_commit.sh" + +# shellcheck disable=SC2154 +echo "Git commit: ${git_commit}" + +# Disable Go's automatic VCS stamping — the commit hash is passed +# explicitly via AVALANCHEGO_COMMIT and -ldflags instead. +export GOFLAGS="${GOFLAGS:-} -buildvcs=false" + +echo "Building avalanchego..." +"${REPO_ROOT}/scripts/build.sh" +# shellcheck disable=SC2154 +AVALANCHEGO_BINARY="${avalanchego_path}" + +echo "Building subnet-evm..." +SUBNET_EVM_BINARY="${REPO_ROOT}/build/subnet-evm" +# Build from subnet-evm directory — build.sh uses relative glob "plugin/"*.go +(cd "${REPO_ROOT}/graft/subnet-evm" && ./scripts/build.sh "${SUBNET_EVM_BINARY}") + +echo "Binaries built:" +echo " avalanchego: ${AVALANCHEGO_BINARY}" +echo " subnet-evm: ${SUBNET_EVM_BINARY}" + +# ── Step 2: GPG setup ───────────────────────────────────────────── + +# Tri-state behavior: +# - GPG_KEY_FILE unset → unsigned build (local dev OK) +# - GPG_KEY_FILE set but empty → CI signing secret missing/blank, +# fail closed (no silent unsigned +# release artifacts) +# - GPG_KEY_FILE set and non-empty → sign each archive + +if [[ -z "${GPG_KEY_FILE:-}" ]]; then + echo "No GPG key provided, skipping tarball signing." + sign_archive() { :; } + GPG_SIGNING_ENABLED=false +elif [[ ! -s "${GPG_KEY_FILE}" ]]; then + echo "ERROR: GPG_KEY_FILE is set (${GPG_KEY_FILE}) but the file is empty." >&2 + echo " Refusing to produce unsigned release artifacts." >&2 + echo " Verify that the GPG signing secret (e.g. RPM_GPG_PRIVATE_KEY) is configured." >&2 + exit 1 +else + GNUPGHOME=$(mktemp -d) + export GNUPGHOME + trap 'gpgconf --kill gpg-agent 2>/dev/null || true; rm -rf "${GNUPGHOME}"' EXIT + + echo "Importing GPG key for tarball signing..." + gpg --batch --import "${GPG_KEY_FILE}" + + sign_archive() { + local archive="$1" + echo "Signing ${archive}..." + printf '%s' "${GPG_PASSPHRASE:-}" | gpg --batch --yes --detach-sign \ + --pinentry-mode loopback \ + --passphrase-fd 0 \ + "${archive}" + echo "Verifying signature for ${archive}..." + gpg --batch --verify "${archive}.sig" "${archive}" + } + + GPG_SIGNING_ENABLED=true +fi + +# ── Step 3: Stage and tar each binary ───────────────────────────── + +STAGE_DIR=$(mktemp -d) + +stage_and_tar() { + local package="$1" + local binary="$2" + local archive="${OUTPUT_DIR}/${package}-linux-${ARCH}-${TAG}.tar.gz" + local stage="${STAGE_DIR}/${package}-${TAG}" + + mkdir -p "${stage}" + cp "${binary}" "${stage}/" + + echo "Creating ${archive}..." + (cd "${STAGE_DIR}" && tar -czvf "${archive}" "${package}-${TAG}") + sign_archive "${archive}" +} + +stage_and_tar "avalanchego" "${AVALANCHEGO_BINARY}" +stage_and_tar "subnet-evm" "${SUBNET_EVM_BINARY}" + +rm -rf "${STAGE_DIR}" + +# ── Step 4: Export public key (for validation container only) ───── +# +# The public key is used by validate-tgz.sh to verify signatures in a +# fresh container. It is NOT uploaded to S3 or as a GitHub artifact — +# the public key is distributed via the existing S3 location only. + +if [[ "${GPG_SIGNING_ENABLED}" == "true" ]]; then + PUB_KEY_FILE="${OUTPUT_DIR}/GPG-KEY-avalanchego" + gpg --batch --armor --export "security@avalabs.org" > "${PUB_KEY_FILE}" + echo "GPG public key exported to: ${PUB_KEY_FILE} (validation use only)" +fi + +echo "=== Tarball build complete ===" +ls -la "${OUTPUT_DIR}" diff --git a/.github/packaging/scripts/upload-tgz.sh b/.github/packaging/scripts/upload-tgz.sh new file mode 100755 index 000000000000..f8f337c77c97 --- /dev/null +++ b/.github/packaging/scripts/upload-tgz.sh @@ -0,0 +1,25 @@ +#!/usr/bin/env bash + +# Upload built linux tarballs and detached signatures to S3. +# +# Required env vars: +# BUCKET - Target S3 bucket name +# TGZ_ARCH - Tarball architecture suffix in the S3 path ("amd64" or "arm64") +# +# Uploads only `*.tar.gz` and `*.tar.gz.sig` from build/tgz/. Explicitly +# excludes `GPG-KEY-avalanchego` — the public key is distributed via the +# existing S3 key location, not republished alongside each release. + +set -euo pipefail + +: "${BUCKET:?BUCKET must be set}" +: "${TGZ_ARCH:?TGZ_ARCH must be set}" + +REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../../.." && pwd)" +TGZ_DIR="${REPO_ROOT}/build/tgz" +S3_DEST="s3://${BUCKET}/linux/binaries/ubuntu/jammy/${TGZ_ARCH}/" + +echo "=== Uploading tarballs from ${TGZ_DIR} to ${S3_DEST} ===" +find "${TGZ_DIR}" -maxdepth 1 \ + \( -name '*.tar.gz' -o -name '*.tar.gz.sig' \) \ + -exec aws s3 cp {} "${S3_DEST}" \; diff --git a/.github/packaging/scripts/validate-tgz.sh b/.github/packaging/scripts/validate-tgz.sh new file mode 100755 index 000000000000..9f01d276e979 --- /dev/null +++ b/.github/packaging/scripts/validate-tgz.sh @@ -0,0 +1,115 @@ +#!/usr/bin/env bash + +# Post-build validation of linux tarballs. +# +# Verifies detached signatures and runs smoke tests in a fresh Ubuntu +# container, mirroring how a downstream consumer would verify and use +# the released artifacts. +# +# Required env vars: +# TAG - Git tag (e.g., "v1.14.1") +# GIT_COMMIT - Full git commit hash used to build the binaries +# +# Target architecture is derived from `uname -m`. The validation +# container is launched with --platform pinned to host arch, matching +# the arch the tarballs were built for, so this always lines up. + +set -euo pipefail + +: "${TAG:?TAG must be set}" +: "${GIT_COMMIT:?GIT_COMMIT must be set}" + +# Map uname -m to deb-style arch (aarch64 -> arm64). The script owns its +# own arch determination — we don't accept TGZ_ARCH from env, since +# Task v3 forwards parent shell env vars in a way that would let a +# caller-supplied TGZ_ARCH= mislabel the validation lookup. +arch=$(uname -m) +case "${arch}" in + x86_64) TGZ_ARCH="amd64" ;; + arm64|aarch64) TGZ_ARCH="arm64" ;; + *) echo "Unsupported arch: ${arch}" >&2; exit 1 ;; +esac +# Export so the validation container (launched below) sees it via `-e TGZ_ARCH`. +export TGZ_ARCH + +REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../../.." && pwd)" +TGZ_DIR="${REPO_ROOT}/build/tgz" + +# Verify expected files exist +for f in \ + "avalanchego-linux-${TGZ_ARCH}-${TAG}.tar.gz" \ + "subnet-evm-linux-${TGZ_ARCH}-${TAG}.tar.gz" \ +; do + if [[ ! -f "${TGZ_DIR}/${f}" ]]; then + echo "ERROR: expected file not found: ${TGZ_DIR}/${f}" >&2 + exit 1 + fi +done + +echo "=== Validating tarballs in fresh Ubuntu 22.04 container ===" +# Pin --platform to host arch (TGZ_ARCH is always host arch here) so +# DOCKER_DEFAULT_PLATFORM doesn't cause Docker to try a non-host +# manifest of ubuntu:22.04 and fail to launch. +docker run --rm \ + --platform "linux/${TGZ_ARCH}" \ + -v "${TGZ_DIR}:/tgz:ro" \ + -e TAG \ + -e TGZ_ARCH \ + -e GIT_COMMIT \ + ubuntu:22.04 \ + bash -euxc ' + export DEBIAN_FRONTEND=noninteractive + apt-get update + apt-get install -y --no-install-recommends gnupg2 ca-certificates + + # Verify signatures if public key available + if [[ -f /tgz/GPG-KEY-avalanchego ]]; then + gpg --batch --import /tgz/GPG-KEY-avalanchego + gpg --batch --verify "/tgz/avalanchego-linux-${TGZ_ARCH}-${TAG}.tar.gz.sig" \ + "/tgz/avalanchego-linux-${TGZ_ARCH}-${TAG}.tar.gz" + gpg --batch --verify "/tgz/subnet-evm-linux-${TGZ_ARCH}-${TAG}.tar.gz.sig" \ + "/tgz/subnet-evm-linux-${TGZ_ARCH}-${TAG}.tar.gz" + else + echo "Skipping GPG verification (unsigned build)" + fi + + # Extract both tarballs + mkdir -p /work + cd /work + tar -xzf "/tgz/avalanchego-linux-${TGZ_ARCH}-${TAG}.tar.gz" + tar -xzf "/tgz/subnet-evm-linux-${TGZ_ARCH}-${TAG}.tar.gz" + + # Smoke test avalanchego + AVA_BIN="/work/avalanchego-${TAG}/avalanchego" + if [[ ! -x "${AVA_BIN}" ]]; then + echo "ERROR: avalanchego binary not found or not executable" >&2 + exit 1 + fi + ava_output=$("${AVA_BIN}" --version) + echo "avalanchego --version: ${ava_output}" + if [[ "${ava_output}" != avalanchego/* ]]; then + echo "ERROR: --version output does not start with avalanchego/" >&2 + exit 1 + fi + if [[ "${ava_output}" != *"${GIT_COMMIT}"* ]]; then + echo "ERROR: avalanchego --version output does not contain expected commit ${GIT_COMMIT}" >&2 + exit 1 + fi + + # Smoke test subnet-evm + EVM_BIN="/work/subnet-evm-${TAG}/subnet-evm" + if [[ ! -x "${EVM_BIN}" ]]; then + echo "ERROR: subnet-evm binary not found or not executable" >&2 + exit 1 + fi + evm_output=$("${EVM_BIN}" --version) + echo "subnet-evm --version: ${evm_output}" + if [[ "${evm_output}" != *"${GIT_COMMIT}"* ]]; then + echo "ERROR: subnet-evm --version output does not contain expected commit ${GIT_COMMIT}" >&2 + exit 1 + fi + + echo "All tarball validations passed" + ' + +echo "=== Tarball validation complete ===" diff --git a/.github/workflows/build-linux-binaries.yml b/.github/workflows/build-linux-binaries.yml index cba0665400c7..4f0287098de2 100644 --- a/.github/workflows/build-linux-binaries.yml +++ b/.github/workflows/build-linux-binaries.yml @@ -14,8 +14,15 @@ env: FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true jobs: - build-x86_64-binaries-tarball: - runs-on: ubuntu-22.04 + build-tarball: + strategy: + matrix: + include: + - arch: amd64 + runner: ubuntu-22.04 + - arch: arm64 + runner: ubuntu-22.04-arm + runs-on: ${{ matrix.runner }} permissions: id-token: write contents: read @@ -25,15 +32,6 @@ jobs: - uses: ./.github/actions/setup-go-for-project - - run: go version - - - name: Build the avalanchego binaries - run: ./scripts/run_task.sh build - - - name: Build subnet-evm plugin - working-directory: ./graft/subnet-evm - run: ./scripts/run_task.sh build - - name: Install aws cli run: sudo snap install aws-cli --classic @@ -44,112 +42,66 @@ jobs: role-session-name: githubrolesession aws-region: us-east-1 - - name: Try to get tag from git - if: "${{ github.event.inputs.tag == '' }}" - id: get_tag_from_git - run: | - echo "TAG=${GITHUB_REF/refs\/tags\//}" >> "$GITHUB_ENV" - shell: bash - - - name: Try to get tag from workflow dispatch - if: "${{ github.event.inputs.tag != '' }}" - id: get_tag_from_workflow - run: | - echo "TAG=${{ github.event.inputs.tag }}" >> "$GITHUB_ENV" - shell: bash - - - name: Create tgz package structure and upload to S3 - run: ./.github/workflows/build-tgz-pkg.sh + - name: Import GPG key env: - PKG_ROOT: /tmp/avalanchego - TAG: ${{ env.TAG }} - BUCKET: ${{ secrets.BUCKET }} - ARCH: "amd64" - RELEASE: "jammy" - - - name: Save avalanchego as Github artifact - uses: actions/upload-artifact@v6 - with: - name: avalanchego-amd64 - path: /tmp/avalanchego/avalanchego-linux-amd64-${{ env.TAG }}.tar.gz - - - name: Save subnet-evm as Github artifact - uses: actions/upload-artifact@v6 - with: - name: subnet-evm-amd64 - path: /tmp/avalanchego/subnet-evm-linux-amd64-${{ env.TAG }}.tar.gz - - - name: Cleanup + PRIVATE_KEY: ${{ secrets.RPM_GPG_PRIVATE_KEY }} run: | - rm -rf ./build - rm -rf /tmp/avalanchego - - build-arm64-binaries-tarball: - runs-on: ubuntu-22.04-arm - permissions: - id-token: write - contents: read - - steps: - - uses: actions/checkout@v5 - - - uses: ./.github/actions/setup-go-for-project - - - run: go version - - - name: Build the avalanchego binaries - run: ./scripts/run_task.sh build - - - name: Build subnet-evm plugin - working-directory: ./graft/subnet-evm - run: ./scripts/run_task.sh build - - - name: Install aws cli - run: sudo snap install aws-cli --classic - - - name: Configure AWS credentials - uses: aws-actions/configure-aws-credentials@v6 - with: - role-to-assume: ${{ secrets.AWS_DEPLOY_SA_ROLE_ARN }} - role-session-name: githubrolesession - aws-region: us-east-1 + GPG_KEY_FILE="$(mktemp)" + chmod 600 "${GPG_KEY_FILE}" + printf '%s' "${PRIVATE_KEY}" > "${GPG_KEY_FILE}" + printf 'GPG_KEY_FILE=%s\n' "${GPG_KEY_FILE}" >> "$GITHUB_ENV" + shell: bash - name: Try to get tag from git if: "${{ github.event.inputs.tag == '' }}" - id: get_tag_from_git run: | echo "TAG=${GITHUB_REF/refs\/tags\//}" >> "$GITHUB_ENV" shell: bash - name: Try to get tag from workflow dispatch if: "${{ github.event.inputs.tag != '' }}" - id: get_tag_from_workflow + env: + INPUT_TAG: ${{ github.event.inputs.tag }} run: | - echo "TAG=${{ github.event.inputs.tag }}" >> "$GITHUB_ENV" + echo "TAG=${INPUT_TAG}" >> "$GITHUB_ENV" shell: bash - - name: Create tgz package structure and upload to S3 - run: ./.github/workflows/build-tgz-pkg.sh + - name: Build and validate tarballs + run: ./scripts/run_task.sh --taskfile .github/packaging/Taskfile.yml test-build-tarballs + env: + PACKAGING_TAG: ${{ env.TAG }} + GPG_KEY_FILE: ${{ env.GPG_KEY_FILE }} + GPG_PASSPHRASE: ${{ secrets.RPM_GPG_PASSPHRASE }} + + - name: Upload tarballs to S3 + run: ./scripts/run_task.sh --taskfile .github/packaging/Taskfile.yml upload-tarballs env: - PKG_ROOT: /tmp/avalanchego - TAG: ${{ env.TAG }} BUCKET: ${{ secrets.BUCKET }} - ARCH: "arm64" - RELEASE: "jammy" + TGZ_ARCH: ${{ matrix.arch }} - name: Save avalanchego as Github artifact uses: actions/upload-artifact@v6 with: - name: avalanchego-arm64 - path: /tmp/avalanchego/avalanchego-linux-arm64-${{ env.TAG }}.tar.gz + name: avalanchego-${{ matrix.arch }} + path: | + build/tgz/avalanchego-linux-${{ matrix.arch }}-${{ env.TAG }}.tar.gz + build/tgz/avalanchego-linux-${{ matrix.arch }}-${{ env.TAG }}.tar.gz.sig - name: Save subnet-evm as Github artifact uses: actions/upload-artifact@v6 with: - name: subnet-evm-arm64 - path: /tmp/avalanchego/subnet-evm-linux-arm64-${{ env.TAG }}.tar.gz + name: subnet-evm-${{ matrix.arch }} + path: | + build/tgz/subnet-evm-linux-${{ matrix.arch }}-${{ env.TAG }}.tar.gz + build/tgz/subnet-evm-linux-${{ matrix.arch }}-${{ env.TAG }}.tar.gz.sig - name: Cleanup + if: always() run: | - rm -rf ./build - rm -rf /tmp/avalanchego + if [[ -n "${GPG_KEY_FILE:-}" ]]; then + rm -f "${GPG_KEY_FILE}" + fi + # build/plugins/ is created as root by the containerized + # subnet-evm build, so plain rm -rf would fail to recurse + # into it as the unprivileged runner user on linux runners. + sudo rm -rf ./build diff --git a/.github/workflows/build-tgz-pkg.sh b/.github/workflows/build-tgz-pkg.sh deleted file mode 100755 index 39290e575305..000000000000 --- a/.github/workflows/build-tgz-pkg.sh +++ /dev/null @@ -1,27 +0,0 @@ -#!/usr/bin/env bash - -set -euo pipefail - -AVALANCHE_ROOT=$PKG_ROOT/avalanchego-$TAG - -mkdir -p "$AVALANCHE_ROOT" - -OK=$(cp ./build/avalanchego "$AVALANCHE_ROOT") -if [[ $OK -ne 0 ]]; then - exit "$OK"; -fi - - -echo "Build avalanchego tgz package..." -cd "$PKG_ROOT" -echo "Tag: $TAG" -tar -czvf "avalanchego-linux-$ARCH-$TAG.tar.gz" "avalanchego-$TAG" -aws s3 cp "avalanchego-linux-$ARCH-$TAG.tar.gz" "s3://$BUCKET/linux/binaries/ubuntu/$RELEASE/$ARCH/" - -echo "Build subnet-evm tgz package..." -SUBNET_EVM_ROOT=$PKG_ROOT/subnet-evm-$TAG -mkdir -p "$SUBNET_EVM_ROOT" -cp "${GITHUB_WORKSPACE:-$PWD}/build/subnet-evm" "$SUBNET_EVM_ROOT/" -cd "$PKG_ROOT" -tar -czvf "subnet-evm-linux-$ARCH-$TAG.tar.gz" "subnet-evm-$TAG" -aws s3 cp "subnet-evm-linux-$ARCH-$TAG.tar.gz" "s3://$BUCKET/linux/binaries/ubuntu/$RELEASE/$ARCH/"