geth/.github/workflows/release.yml

207 lines
7.7 KiB
YAML

name: Release
on:
push:
tags:
- "v*"
workflow_dispatch:
inputs:
prerelease:
description: "Mark the GitHub release as a prerelease"
required: false
default: "true"
type: choice
options: ["true", "false"]
permissions:
contents: write
env:
CARGO_TERM_COLOR: always
jobs:
build:
name: build ${{ matrix.target }}
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
include:
- os: ubuntu-latest
target: linux-x86_64
binary: geth
- os: macos-15-intel
target: macos-x86_64
binary: geth
- os: macos-15
target: macos-aarch64
binary: geth
- os: windows-latest
target: windows-x86_64
binary: geth.exe
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Install Rust toolchain
uses: dtolnay/rust-toolchain@stable
- name: Cache Cargo
uses: Swatinem/rust-cache@v2
- name: Build release binary
run: cargo build --release -p geth
- name: Package Unix artifact
if: runner.os != 'Windows'
shell: bash
run: |
set -euo pipefail
version="${GITHUB_REF_NAME:-manual}"
pkg="geth-${version}-${{ matrix.target }}"
mkdir -p "${pkg}" dist
cp "target/release/${{ matrix.binary }}" "${pkg}/"
cp README.md "${pkg}/"
cp LICENSE-* "${pkg}/"
cp -R docs "${pkg}/docs"
tar -czf "dist/${pkg}.tar.gz" "${pkg}"
if command -v sha256sum >/dev/null 2>&1; then
sha256sum "dist/${pkg}.tar.gz" | awk '{ print $1 }' > "dist/${pkg}.tar.gz.sha256"
else
shasum -a 256 "dist/${pkg}.tar.gz" | awk '{ print $1 }' > "dist/${pkg}.tar.gz.sha256"
fi
- name: Smoke-test Unix artifact
if: runner.os != 'Windows'
shell: bash
run: |
set -euo pipefail
version="${GITHUB_REF_NAME:-manual}"
pkg="geth-${version}-${{ matrix.target }}"
expected="$(cat "dist/${pkg}.tar.gz.sha256")"
if command -v sha256sum >/dev/null 2>&1; then
actual="$(sha256sum "dist/${pkg}.tar.gz" | awk '{ print $1 }')"
else
actual="$(shasum -a 256 "dist/${pkg}.tar.gz" | awk '{ print $1 }')"
fi
test "${actual}" = "${expected}"
case "${version}" in
v[0-9]*) test "$(scripts/install.sh --version "${version}" --print-asset)" = "${pkg}.tar.gz" ;;
esac
mkdir -p smoke
tar -xzf "dist/${pkg}.tar.gz" -C smoke
"smoke/${pkg}/${{ matrix.binary }}" --version
installer_version="${version}"
case "${installer_version}" in
v[0-9]*) ;;
*) installer_version="v0.0.0-smoke" ;;
esac
scripts/install.sh \
--version "${installer_version}" \
--archive "dist/${pkg}.tar.gz" \
--install-dir "${PWD}/smoke/install/bin" \
--no-modify-path
"smoke/install/bin/geth" --version
printf '%064d\n' 0 > smoke/bad.sha256
if scripts/install.sh \
--version "${installer_version}" \
--archive "dist/${pkg}.tar.gz" \
--checksum "smoke/bad.sha256" \
--install-dir "${PWD}/smoke/rejected" \
--no-modify-path; then
echo "installer accepted an invalid checksum" >&2
exit 1
fi
test -f "smoke/${pkg}/README.md"
test -f "smoke/${pkg}/LICENSE-MIT"
test -f "smoke/${pkg}/LICENSE-APACHE"
test -d "smoke/${pkg}/docs"
- name: Package Windows artifact
if: runner.os == 'Windows'
shell: pwsh
run: |
$version = if ($env:GITHUB_REF_NAME) { $env:GITHUB_REF_NAME } else { "manual" }
$pkg = "geth-$version-${{ matrix.target }}"
New-Item -ItemType Directory -Force -Path $pkg, dist | Out-Null
Copy-Item "target/release/${{ matrix.binary }}" "$pkg/"
Copy-Item README.md "$pkg/"
Copy-Item LICENSE-* "$pkg/"
Copy-Item docs "$pkg/docs" -Recurse
Compress-Archive -Path "$pkg/*" -DestinationPath "dist/$pkg.zip" -Force
(Get-FileHash -LiteralPath "dist/$pkg.zip" -Algorithm SHA256).Hash.ToLowerInvariant() |
Set-Content -NoNewline "dist/$pkg.zip.sha256"
- name: Smoke-test Windows artifact
if: runner.os == 'Windows'
shell: pwsh
run: |
$version = if ($env:GITHUB_REF_NAME) { $env:GITHUB_REF_NAME } else { "manual" }
$pkg = "geth-$version-${{ matrix.target }}"
$expected = (Get-Content -LiteralPath "dist/$pkg.zip.sha256" -Raw).Trim()
$actual = (Get-FileHash -LiteralPath "dist/$pkg.zip" -Algorithm SHA256).Hash.ToLowerInvariant()
if ($actual -ne $expected) { throw "release archive checksum mismatch" }
if ($version -match '^v[0-9]') {
$installerAsset = & scripts/install.ps1 -Version $version -PrintAsset
if ($installerAsset -ne "$pkg.zip") { throw "installer selected $installerAsset instead of $pkg.zip" }
}
New-Item -ItemType Directory -Force -Path smoke | Out-Null
Expand-Archive -Path "dist/$pkg.zip" -DestinationPath "smoke/$pkg" -Force
& "smoke/$pkg/${{ matrix.binary }}" --version
$installerVersion = if ($version -match '^v[0-9]') { $version } else { 'v0.0.0-smoke' }
$installerArgs = @{
Version = $installerVersion
ArchivePath = "dist/$pkg.zip"
InstallDir = "$pwd/smoke/install/bin"
NoModifyPath = $true
}
& scripts/install.ps1 @installerArgs
& "smoke/install/bin/geth.exe" --version
Set-Content -NoNewline -LiteralPath "smoke/bad.sha256" -Value ('0' * 64)
$invalidChecksumArgs = $installerArgs.Clone()
$invalidChecksumArgs['ChecksumPath'] = "smoke/bad.sha256"
$invalidChecksumArgs['InstallDir'] = "$pwd/smoke/rejected"
$checksumRejected = $false
try { & scripts/install.ps1 @invalidChecksumArgs } catch { $checksumRejected = $true }
if (-not $checksumRejected) { throw "installer accepted an invalid checksum" }
if (!(Test-Path "smoke/$pkg/README.md")) { throw "README.md missing from archive" }
if (!(Test-Path "smoke/$pkg/LICENSE-MIT")) { throw "LICENSE-MIT missing from archive" }
if (!(Test-Path "smoke/$pkg/LICENSE-APACHE")) { throw "LICENSE-APACHE missing from archive" }
if (!(Test-Path "smoke/$pkg/docs")) { throw "docs missing from archive" }
- name: Upload artifact
uses: actions/upload-artifact@v4
with:
name: geth-${{ matrix.target }}
path: dist/*
if-no-files-found: error
github-release:
name: publish GitHub release
runs-on: ubuntu-latest
needs: build
if: startsWith(github.ref, 'refs/tags/') || github.event_name == 'workflow_dispatch'
steps:
- name: Checkout installer entrypoints
uses: actions/checkout@v4
- name: Download artifacts
uses: actions/download-artifact@v4
with:
path: dist
merge-multiple: true
- name: Add installer entrypoints and aggregate checksums
shell: bash
run: |
set -euo pipefail
cp scripts/install.sh scripts/install.ps1 dist/
cd dist
sha256sum geth-*.tar.gz geth-*.zip install.sh install.ps1 > SHA256SUMS
- name: Publish release
uses: softprops/action-gh-release@v2
with:
files: dist/*
prerelease: ${{ github.event_name == 'workflow_dispatch' && github.event.inputs.prerelease == 'true' }}
generate_release_notes: true