Files
gman/.github/workflows/release.yml
2025-09-13 12:57:23 -06:00

587 lines
22 KiB
YAML

name: Create release
permissions:
pull-requests: write
contents: write
on:
workflow_dispatch:
inputs:
bump_type:
description: "Specify the type of version bump"
required: true
default: "patch"
type: choice
options:
- patch
- minor
- major
jobs:
bump-version:
name: bump-version
runs-on: ubuntu-latest
steps:
- name: Configure SSH for Git
if: env.ACT != 'true'
run: |
mkdir -p ~/.ssh
echo "${{ secrets.RELEASE_BOT_SSH_KEY }}" > ~/.ssh/id_ed25519
chmod 600 ~/.ssh/id_ed25519
ssh-keyscan -H github.com >> ~/.ssh/known_hosts
- name: Checkout repository
if: env.ACT != 'true'
uses: actions/checkout@v3
with:
ssh-key: ${{ secrets.RELEASE_BOT_SSH_KEY }}
fetch-depth: 0
- name: Checkout repository
if: env.ACT == 'true'
uses: actions/checkout@v3
with:
fetch-depth: 0
- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: "3.10"
- name: Install Commitizen
run: |
python -m pip install --upgrade pip
pip install commitizen
npm install -g conventional-changelog-cli
- name: Configure Git user
run: |
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
- name: Bump version with Commitizen
run: |
cz bump --yes --increment ${{ github.event.inputs.bump_type }}
- name: Amend commit message to include '[skip ci]'
run: |
git commit --amend --no-edit -m "$(git log -1 --pretty=%B) [skip ci]"
- name: Install Rust stable
uses: dtolnay/rust-toolchain@stable
- name: Get the new version tag
id: version
run: |
mkdir -p artifacts
NEW_TAG=$(cz version --project)
echo "New version: $NEW_TAG"
echo "version=$NEW_TAG" >> $GITHUB_ENV
echo "$NEW_TAG" > artifacts/release-version
- name: Get the previous version tag
id: prev_version
run: |
PREV_TAG=$(git describe --tags --abbrev=0 ${GITHUB_SHA}^)
echo "Previous tag: $PREV_TAG"
echo "prev_version=$PREV_TAG" >> $GITHUB_ENV
- name: Bump Cargo.toml version
shell: bash
working-directory: ${{ github.workspace }}
env:
VERSION: ${{ env.version }}
run: |
set -euo pipefail
: "${VERSION:?env.version is empty}"
# Ignore Act's local artifact dir noise
echo artifacts/ >> .git/info/exclude || true
# Edit the version line right after name="gman"
sed -E -i '
/^[[:space:]]*name[[:space:]]*=[[:space:]]*"gman"[[:space:]]*$/ {
n
s|^[[:space:]]*version[[:space:]]*=[[:space:]]*"[^"]*"|version = "'"$VERSION"'"|
}
' Cargo.toml
cargo update || true
# Git config that helps in Act
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
git config --global --add safe.directory "$GITHUB_WORKSPACE"
git status --porcelain
git diff --name-only -- Cargo.toml Cargo.lock || true
if ! git diff --quiet -- Cargo.toml Cargo.lock; then
git add -u -- Cargo.toml Cargo.lock
git commit -m "chore: bump Cargo.toml to $VERSION"
else
echo "No changes to commit (already at $VERSION)"
fi
- name: Generate changelog for the version bump
id: changelog
run: |
changelog=$(conventional-changelog -p angular -i CHANGELOG.md -s --from ${{ env.prev_version }} --to ${{ env.version }})
echo "$changelog" > artifacts/changelog.md
echo "changelog_body=$(cat artifacts/changelog.md)" >> $GITHUB_ENV
- name: Push changes
if: env.ACT != 'true'
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
git push origin --follow-tags
- name: Upload artifacts
uses: actions/upload-artifact@v4
with:
path: artifacts
- name: Upload the changed Cargo files (Act)
if: env.ACT == 'true'
uses: actions/upload-artifact@v4
with:
name: bumped-cargo-files
path: |
Cargo.toml
Cargo.lock
build-release-artifacts:
name: build-release
needs: [bump-version]
runs-on: ${{ matrix.job.os }}
env:
RUST_BACKTRACE: 1
strategy:
fail-fast: true
matrix:
# prettier-ignore
job:
- { name: "macOS-arm64", os: "macOS-latest", target: "aarch64-apple-darwin", artifact_suffix: "macos-arm64", use-cross: true }
- { name: "macOS-amd64", os: "macOS-latest", target: "x86_64-apple-darwin", artifact_suffix: "macos" }
- { name: "windows-amd64", os: "windows-latest", target: "x86_64-pc-windows-msvc", artifact_suffix: "windows" }
- { name: "windows-aarch64", os: "windows-latest", target: "aarch64-pc-windows-msvc", artifact_suffix: "windows-aarch64", use-cross: true }
- { name: "linux-gnu", os: "ubuntu-latest", target: "x86_64-unknown-linux-gnu", artifact_suffix: "linux" }
- { name: "linux-musl", os: "ubuntu-latest", target: "x86_64-unknown-linux-musl", artifact_suffix: "linux-musl", use-cross: true, }
- { name: "linux-aarch64-gnu", os: "ubuntu-latest", target: "aarch64-unknown-linux-gnu", artifact_suffix: "aarch64-gnu", use-cross: true, test-bin: "--bin gman" }
- { name: "linux-aarch64-musl", os: "ubuntu-latest", target: "aarch64-unknown-linux-musl", artifact_suffix: "aarch64-musl", use-cross: true, test-bin: "--bin gman" }
- { name: "linux-arm-gnu", os: "ubuntu-latest", target: "arm-unknown-linux-gnueabi", artifact_suffix: "armv6-gnu", use-cross: true, test-bin: "--bin gman" }
- { name: "linux-arm-musl", os: "ubuntu-latest", target: "arm-unknown-linux-musleabihf", artifact_suffix: "armv6-musl", use-cross: true, test-bin: "--bin gman" }
- { name: "linux-armv7-gnu", os: "ubuntu-latest", target: "armv7-unknown-linux-gnueabihf", artifact_suffix: "armv7-gnu", use-cross: true, test-bin: "--bin gman" }
- { name: "linux-armv7-musl", os: "ubuntu-latest", target: "armv7-unknown-linux-musleabihf", artifact_suffix: "armv7-musl", use-cross: true, test-bin: "--bin gman" }
rust: [stable]
steps:
- name: Check if actor is repository owner
if: ${{ github.actor != github.repository_owner && env.ACT != 'true' }}
run: |
echo "You are not authorized to run this workflow."
exit 1
- name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 1
- name: Ensure repository is up-to-date
if: env.ACT != 'true'
run: |
git fetch --all
git pull
- name: Get bumped Cargo files (Act)
if: env.ACT == 'true'
uses: actions/download-artifact@v4
with:
name: bumped-cargo-files
path: ${{ github.workspace }}
- uses: actions/cache@v3
name: Cache Cargo registry
with:
path: ~/.cargo/registry
key: ${{ runner.os }}-cargo-registry-${{ hashFiles('Cargo.lock') }}
- uses: actions/cache@v3
if: startsWith(matrix.job.name, 'linux-')
with:
path: ~/.cargo/bin
key: ${{ runner.os }}-cargo-bin-${{ hashFiles('.github/workflows/release.yml') }}
- uses: dtolnay/rust-toolchain@stable
name: Set Rust toolchain
with:
targets: ${{ matrix.job.target }}
- uses: taiki-e/setup-cross-toolchain-action@v1
with:
# NB: sets CARGO_BUILD_TARGET evar - do not need --target flag in build
target: ${{ matrix.job.target }}
- uses: taiki-e/install-action@cross
if: ${{ matrix.job.use-cross }}
- name: Installing needed Ubuntu dependencies
if: matrix.job.os == 'ubuntu-latest'
shell: bash
run: |
sudo apt-get -y update
case ${{ matrix.job.target }} in
arm*-linux-*) sudo apt-get -y install gcc-arm-linux-gnueabihf ;;
aarch64-*-linux-*) sudo apt-get -y install gcc-aarch64-linux-gnu ;;
esac
- name: Install bindgen + clang toolchain (for aws-lc on musl/ARM)
if: matrix.job.os == 'ubuntu-latest' && contains(matrix.job.target, 'musl') && (startsWith(matrix.job.target, 'arm-') || startsWith(matrix.job.target, 'armv7-') || startsWith(matrix.job.target, 'aarch64-'))
shell: bash
run: |
sudo apt-get -y install clang llvm-dev libclang-dev pkg-config cmake build-essential
cargo install --locked bindgen-cli
# Make sure libclang is visible if needed (version may differ):
echo "LIBCLANG_PATH=$(llvm-config --libdir)" >> $GITHUB_ENV
- name: OpenSSL (vendored) toolchain for musl
if: startsWith(matrix.job.name, 'linux-') && contains(matrix.job.target, 'musl')
shell: bash
run: |
# Tools needed for building vendored OpenSSL
sudo apt-get -y update
sudo apt-get -y install musl-tools pkg-config perl make cmake
# Let openssl-sys know we're cross-compiling and want static
echo "OPENSSL_STATIC=1" >> $GITHUB_ENV
echo "PKG_CONFIG_ALLOW_CROSS=1" >> $GITHUB_ENV
# Set the right C compiler per musl target (some provided by taiki-e/setup-cross-toolchain-action)
case "${{ matrix.job.target }}" in
x86_64-unknown-linux-musl)
echo "CC_x86_64_unknown_linux_musl=musl-gcc" >> $GITHUB_ENV
;;
aarch64-unknown-linux-musl)
# If your toolchain action installs aarch64-linux-musl-gcc, use that:
echo "CC_aarch64_unknown_linux_musl=aarch64-linux-musl-gcc" >> $GITHUB_ENV
;;
arm-unknown-linux-musleabihf)
echo "CC_arm_unknown_linux_musleabihf=arm-linux-musleabihf-gcc" >> $GITHUB_ENV
;;
armv7-unknown-linux-musleabihf)
echo "CC_armv7_unknown_linux_musleabihf=armv7-linux-musleabihf-gcc" >> $GITHUB_ENV
;;
esac
- name: Build
run: cargo build --release --verbose --target=${{ matrix.job.target }} --locked
- name: Verify file
shell: bash
run: |
file target/${{ matrix.job.target }}/release/gman
- name: Test
if: matrix.job.target != 'aarch64-apple-darwin' && matrix.job.target != 'aarch64-pc-windows-msvc'
run: cargo test --release --verbose --target=${{ matrix.job.target }} ${{ matrix.job.test-bin }}
- name: Packaging final binary (Windows)
if: matrix.job.os == 'windows-latest'
shell: bash
run: |
cd target/${{ matrix.job.target }}/release
BINARY_NAME=gman.exe
if [ "${{ matrix.job.target }}" != "aarch64-pc-windows-msvc" ]; then
# strip the binary
strip $BINARY_NAME
fi
RELEASE_NAME=gman-${{ matrix.job.artifact_suffix }}
mkdir -p artifacts
tar czvf $RELEASE_NAME.tar.gz $BINARY_NAME
# create sha checksum files
certutil -hashfile $RELEASE_NAME.tar.gz sha256 | grep -E [A-Fa-f0-9]{64} > $RELEASE_NAME.sha256
echo "RELEASE_NAME=$RELEASE_NAME" >> $GITHUB_ENV
- name: Packaging final binary (macOS and Linux)
if: matrix.job.os != 'windows-latest'
shell: bash
run: |
# set the right strip executable
STRIP="strip";
case ${{ matrix.job.target }} in
arm*-linux-*) STRIP="arm-linux-gnueabihf-strip" ;;
aarch64-*-linux-*) STRIP="aarch64-linux-gnu-strip" ;;
esac;
cd target/${{ matrix.job.target }}/release
BINARY_NAME=gman
# strip the binary
"$STRIP" "$BINARY_NAME"
RELEASE_NAME=gman-${{ matrix.job.artifact_suffix }}
tar czvf $RELEASE_NAME.tar.gz $BINARY_NAME
# create sha checksum files
shasum -a 256 $RELEASE_NAME.tar.gz > $RELEASE_NAME.sha256
echo "RELEASE_NAME=$RELEASE_NAME" >> $GITHUB_ENV
- name: Add artifacts
run: |
mkdir -p artifacts
cp target/${{ matrix.job.target }}/release/${{ env.RELEASE_NAME }}.tar.gz artifacts/
cp target/${{ matrix.job.target }}/release/${{ env.RELEASE_NAME }}.sha256 artifacts/
- name: Upload artifacts
uses: actions/upload-artifact@v4
with:
name: artifacts-${{ env.RELEASE_NAME }}
path: artifacts
overwrite: true
publish-github-release:
name: publish-github-release
needs: [build-release-artifacts]
runs-on: ubuntu-latest
steps:
- name: Check if actor is repository owner
if: ${{ github.actor != github.repository_owner && env.ACT != 'true' }}
run: |
echo "You are not authorized to run this workflow."
exit 1
- name: Checkout repository
uses: actions/checkout@v3
with:
fetch-depth: 0
- name: Download all artifacts
uses: actions/download-artifact@v4
with:
path: artifacts
merge-multiple: true
- name: Ensure repository is up-to-date
if: env.ACT != 'true'
run: |
git fetch --all
git pull
- name: Set environment variables
run: |
release_version="$(cat ./artifacts/release-version)"
echo "RELEASE_VERSION=$release_version" >> $GITHUB_ENV
changelog_body="$(cat ./artifacts/changelog.md)"
echo "changelog_body=$(cat artifacts/changelog.md)" >> $GITHUB_ENV
- name: Validate release environment variables
run: |
echo "Release version: ${{ env.RELEASE_VERSION }}"
echo "Changelog body: ${{ env.changelog_body }}"
- name: Create a GitHub Release
if: env.ACT != 'true'
uses: softprops/action-gh-release@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
files: |
artifacts/gman-macos-arm64.tar.gz
artifacts/gman-macos-arm64.sha256
artifacts/gman-macos.tar.gz
artifacts/gman-macos.sha256
artifacts/gman-windows.tar.gz
artifacts/gman-windows.sha256
artifacts/gman-windows-aarch64.tar.gz
artifacts/gman-windows-aarch64.sha256
artifacts/gman-linux.tar.gz
artifacts/gman-linux.sha256
artifacts/gman-linux-musl.tar.gz
artifacts/gman-linux-musl.sha256
artifacts/gman-aarch64-gnu.tar.gz
artifacts/gman-aarch64-gnu.sha256
artifacts/gman-aarch64-musl.tar.gz
artifacts/gman-aarch64-musl.sha256
artifacts/gman-armv6-gnu.tar.gz
artifacts/gman-armv6-gnu.sha256
artifacts/gman-armv6-musl.tar.gz
artifacts/gman-armv6-musl.sha256
artifacts/gman-armv7-gnu.tar.gz
artifacts/gman-armv7-gnu.sha256
artifacts/gman-armv7-musl.tar.gz
artifacts/gman-armv7-musl.sha256
tag_name: v${{ env.RELEASE_VERSION }}
name: "v${{ env.RELEASE_VERSION }}"
body: ${{ env.changelog_body }}
draft: false
prerelease: false
- name: Upload artifacts
uses: actions/upload-artifact@v4
with:
path: artifacts
overwrite: true
publish-chocolatey-package:
needs: [publish-github-release]
name: Publish Chocolatey Package
runs-on: windows-latest
steps:
- name: Check if actor is repository owner
if: ${{ github.actor != github.repository_owner && env.ACT != 'true' }}
run: |
echo "You are not authorized to run this workflow."
exit 1
- name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 1
- name: Get release artifacts
uses: actions/download-artifact@v4
with:
path: artifacts
merge-multiple: true
- name: Set release assets and version
shell: pwsh
run: |
# Read the first column from the SHA256 file
$windows_sha = Get-Content ./artifacts/gman-windows.sha256 | ForEach-Object { $_.Split(' ')[0] }
Add-Content -Path $env:GITHUB_ENV -Value "WINDOWS_SHA=$windows_sha"
# Read the release version from the release-version file
$release_version = Get-Content ./artifacts/release-version
Add-Content -Path $env:GITHUB_ENV -Value "RELEASE_VERSION=$release_version"
- name: Validate release environment variables
run: |
echo "Release SHA windows: ${{ env.WINDOWS_SHA }}"
echo "Release version: ${{ env.RELEASE_VERSION }}"
- name: Package and Publish package to Chocolatey
if: env.ACT != 'true'
run: |
mkdir ./deployment/chocolatey/tools
# Run packaging script
python "./deployment/chocolatey/packager.py" ${{ env.RELEASE_VERSION }} "./deployment/chocolatey/gman.nuspec.template" "./deployment/chocolatey/gman.nuspec" ${{ env.WINDOWS_SHA }}
python "./deployment/chocolatey/packager.py" ${{ env.RELEASE_VERSION }} "./deployment/chocolatey/chocolateyinstall.ps1.template" "./deployment/chocolatey/tools/chocolateyinstall.ps1" ${{ env.WINDOWS_SHA }}
# Publish to Chocolatey
cd ./deployment/chocolatey
choco pack
echo y | choco install gman -dv -s .
$version = gman --version
$version = $version -replace " ", "."
choco push $version.nupkg -s https://push.chocolatey.org/ --api-key ${{ secrets.CHOCOLATEY_API_KEY }};
publish-homebrew-formula:
needs: [publish-github-release]
name: Update Homebrew formulas
runs-on: ubuntu-latest
steps:
- name: Check if actor is repository owner
if: ${{ github.actor != github.repository_owner && env.ACT != 'true' }}
run: |
echo "You are not authorized to run this workflow."
exit 1
- name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 1
- name: Get release artifacts
uses: actions/download-artifact@v4
with:
path: artifacts
merge-multiple: true
- name: Set release assets and version
shell: bash
run: |
# Set environment variables
macos_sha="$(cat ./artifacts/gman-macos.sha256 | awk '{print $1}')"
echo "MACOS_SHA=$macos_sha" >> $GITHUB_ENV
macos_sha_arm="$(cat ./artifacts/gman-macos-arm64.sha256 | awk '{print $1}')"
echo "MACOS_SHA_ARM=$macos_sha_arm" >> $GITHUB_ENV
linux_sha="$(cat ./artifacts/gman-linux-musl.sha256 | awk '{print $1}')"
echo "LINUX_SHA=$linux_sha" >> $GITHUB_ENV
release_version="$(cat ./artifacts/release-version)"
echo "RELEASE_VERSION=$release_version" >> $GITHUB_ENV
- name: Validate release environment variables
run: |
echo "Release SHA macos: ${{ env.MACOS_SHA }}"
echo "Release SHA macos-arm: ${{ env.MACOS_SHA_ARM }}"
echo "Release SHA linux musl: ${{ env.LINUX_SHA }}"
echo "Release version: ${{ env.RELEASE_VERSION }}"
- name: Execute Homebrew packaging script
if: env.ACT != 'true'
run: |
# run packaging script
python "./deployment/homebrew/packager.py" ${{ env.RELEASE_VERSION }} "./deployment/homebrew/gman.rb.template" "./gman.rb" ${{ env.MACOS_SHA }} ${{ env.MACOS_SHA_ARM }} ${{ env.LINUX_SHA }}
- name: Push changes to Homebrew tap
if: env.ACT != 'true'
env:
TOKEN: ${{ secrets.GMAN_GITHUB_TOKEN }}
run: |
# push to Git
git config --global user.name "Dark-Alex-17"
git config --global user.email "alex.j.tusa@gmail.com"
git clone https://Dark-Alex-17:${{ secrets.GMAN_GITHUB_TOKEN }}@github.com/Dark-Alex-17/homebrew-gman.git
rm homebrew-gman/Formula/gman.rb
cp gman.rb homebrew-gman/Formula
cd homebrew-gman
git add .
git diff-index --quiet HEAD || git commit -am "Update formula for G-Man release ${{ env.RELEASE_VERSION }}"
git push https://$TOKEN@github.com/Dark-Alex-17/homebrew-gman.git
publish-crate:
needs: publish-github-release
name: Publish Crate
runs-on: ubuntu-latest
steps:
- name: Check if actor is repository owner
if: ${{ github.actor != github.repository_owner && env.ACT != 'true' }}
run: |
echo "You are not authorized to run this workflow."
exit 1
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Get bumped Cargo files (Act)
if: env.ACT == 'true'
uses: actions/download-artifact@v4
with:
name: bumped-cargo-files
path: ${{ github.workspace }}
- name: Ensure repository is up-to-date
if: env.ACT != 'true'
run: |
git fetch --all
git pull
- uses: actions/cache@v3
name: Cache Cargo registry
with:
path: ~/.cargo/registry
key: ${{ runner.os }}-cargo-registry-${{ hashFiles('Cargo.lock') }}
- uses: actions/cache@v3
with:
path: ~/.cargo/bin
key: ${{ runner.os }}-cargo-bin-${{ hashFiles('.github/workflows/release.yml') }}
- name: Install Rust stable
uses: dtolnay/rust-toolchain@stable
- uses: katyo/publish-crates@v2
if: env.ACT != 'true'
with:
registry-token: ${{ secrets.CARGO_REGISTRY_TOKEN }}