Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
116 changes: 106 additions & 10 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,14 @@ on:

jobs:
build:
name: Build and Release
name: Build binaries
runs-on: ubuntu-latest

permissions:
Comment on lines 9 to +12
contents: read

steps:
- name: Checkout code
uses: actions/checkout@v3
uses: actions/checkout@v4
with:
fetch-depth: 0 # Fetch all history for version info

Expand All @@ -21,21 +23,115 @@ jobs:
with:
go-version: '1.21'

- name: Make build script executable
run: chmod +x scripts/build.sh
- name: Make scripts executable
run: chmod +x scripts/build.sh scripts/package.sh

- name: Build binaries
run: SKIP_PACKAGE=1 ./scripts/build.sh ${GITHUB_REF#refs/tags/}

- name: Upload unsigned build artifacts
uses: actions/upload-artifact@v4
with:
name: unsigned-dist
path: dist/*
if-no-files-found: error
retention-days: 1

sign-windows:
name: Sign Windows binaries
runs-on: windows-2022
needs: build
environment: release-signing
permissions:
contents: read
id-token: write

steps:
- name: Download unsigned build artifacts
uses: actions/download-artifact@v4
with:
name: unsigned-dist
path: dist

- name: Azure login
uses: azure/login@v3
with:
client-id: ${{ secrets.AZURE_CLIENT_ID }}
tenant-id: ${{ secrets.AZURE_TENANT_ID }}
subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }}

- name: Sign Windows binaries with Azure Artifact Signing
uses: azure/artifact-signing-action@v1
with:
endpoint: ${{ vars.AZURE_CODESIGN_ENDPOINT }}
signing-account-name: ${{ vars.AZURE_CODESIGN_ACCOUNT_NAME }}
certificate-profile-name: ${{ vars.AZURE_CODESIGN_CERTIFICATE_PROFILE }}
files-folder: ${{ github.workspace }}\dist
files-folder-filter: git-flow-*-windows-*.exe
file-digest: SHA256
timestamp-rfc3161: http://timestamp.acs.microsoft.com
Comment thread
MichalBerner marked this conversation as resolved.
timestamp-digest: SHA256

- name: Verify Windows signatures
shell: pwsh
run: |
$files = Get-ChildItem -Path "$env:GITHUB_WORKSPACE\dist" -Filter "git-flow-*-windows-*.exe"
if ($files.Count -eq 0) {
throw "No Windows executables found to verify."
}

foreach ($file in $files) {
$signature = Get-AuthenticodeSignature -FilePath $file.FullName
if ($signature.Status -ne "Valid") {
Write-Error "Invalid signature for $($file.Name): $($signature.Status) $($signature.StatusMessage)"
exit 1
}
Write-Host "Verified signature for $($file.Name)"
}

- name: Upload signed build artifacts
uses: actions/upload-artifact@v4
with:
name: signed-dist
path: dist/*
if-no-files-found: error
retention-days: 1

release:
name: Package and release
runs-on: ubuntu-latest
needs: sign-windows
permissions:
contents: write

steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Download signed build artifacts
uses: actions/download-artifact@v4
with:
name: signed-dist
path: dist

- name: Make packaging script executable
run: chmod +x scripts/package.sh

- name: Restore Unix executable permissions
run: chmod +x dist/git-flow-*-darwin-* dist/git-flow-*-linux-*

- name: Package signed artifacts
run: ./scripts/package.sh ${GITHUB_REF#refs/tags/}

- name: Check if preview release
id: check_preview
run: |
if [[ ${{ github.ref }} =~ ^refs/tags/v.*-(alpha|beta|rc)\. ]]; then
if [[ "${GITHUB_REF_NAME}" =~ ^v.*-(alpha|beta|rc)\. ]]; then
echo "is_preview=true" >> $GITHUB_OUTPUT
else
echo "is_preview=false" >> $GITHUB_OUTPUT
fi

- name: Build binaries
run: ./scripts/build.sh ${GITHUB_REF#refs/tags/}

- name: Extract release notes from CHANGELOG
id: changelog
run: |
Expand Down Expand Up @@ -79,4 +175,4 @@ jobs:
## Checksums
SHA-256 checksums for the release artifacts are available in the checksums.txt file.
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
34 changes: 30 additions & 4 deletions RELEASING.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,28 @@ We follow [Keep a Changelog](https://keepachangelog.com/). Only **user-facing ch

## Release Process

### Release Signing Setup

Windows release executables are signed with Azure Artifact Signing before archives and checksums are created. The release workflow uses GitHub Actions OIDC.

Configure a GitHub environment named `release-signing` with these secrets:

- `AZURE_CLIENT_ID`
- `AZURE_TENANT_ID`
- `AZURE_SUBSCRIPTION_ID`

Configure the same environment with these variables:

- `AZURE_CODESIGN_ENDPOINT`
- `AZURE_CODESIGN_ACCOUNT_NAME`
- `AZURE_CODESIGN_CERTIFICATE_PROFILE`

The Azure identity must have the `Artifact Signing Certificate Profile Signer` role on the certificate profile. Configure the Entra federated credential for this GitHub environment subject:

```text
repo:gittower/git-flow-next:environment:release-signing
```

### 1. Determine Version Bump

Review commits since last release:
Expand Down Expand Up @@ -93,10 +115,13 @@ git push origin vX.Y.Z

The `.github/workflows/release.yml` workflow automatically:

1. Builds binaries for all platforms (darwin, linux, windows)
2. Creates GitHub release with artifacts
3. Generates checksums
4. Marks as prerelease if tag contains `-alpha`, `-beta`, or `-rc`
1. Builds raw binaries for all platforms (darwin, linux, windows)
2. Signs Windows `.exe` files with Azure Artifact Signing
3. Verifies Windows Authenticode signatures
4. Creates archives containing the signed Windows executables
5. Generates checksums after signing and packaging
6. Creates GitHub release with artifacts
7. Marks as prerelease if tag contains `-alpha`, `-beta`, or `-rc`

### 7. Update Homebrew Tap

Expand Down Expand Up @@ -143,6 +168,7 @@ These are automatically marked as prereleases on GitHub.
- [ ] Committed: `chore: Bump version to X.Y.Z`
- [ ] Pushed to main
- [ ] Created and pushed tag
- [ ] Verified Windows signing job succeeded
- [ ] Verified GitHub release was created
- [ ] Updated Homebrew tap (`./update_formula.rb`)
- [ ] Updated website documentation (if commands changed)
32 changes: 6 additions & 26 deletions scripts/build.sh
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
#!/bin/bash

set -euo pipefail

# Get version from command line or use "dev" as default
VERSION=${1:-dev}
BINARY_NAME="git-flow"
Expand Down Expand Up @@ -64,31 +66,9 @@ if [[ ${#MISSING_BINARIES[@]} -gt 0 ]]; then
exit 1
fi

# Create archives for each binary
echo "Creating archives..."

# macOS
echo "Creating darwin archives..."
tar czf "$BUILD_DIR/${PACKAGE_NAME}-${VERSION}-darwin-amd64.tar.gz" -C "$BUILD_DIR" "${BINARY_NAME}-${VERSION}-darwin-amd64"
tar czf "$BUILD_DIR/${PACKAGE_NAME}-${VERSION}-darwin-arm64.tar.gz" -C "$BUILD_DIR" "${BINARY_NAME}-${VERSION}-darwin-arm64"

# Linux
echo "Creating linux archives..."
tar czf "$BUILD_DIR/${PACKAGE_NAME}-${VERSION}-linux-amd64.tar.gz" -C "$BUILD_DIR" "${BINARY_NAME}-${VERSION}-linux-amd64"
tar czf "$BUILD_DIR/${PACKAGE_NAME}-${VERSION}-linux-arm64.tar.gz" -C "$BUILD_DIR" "${BINARY_NAME}-${VERSION}-linux-arm64"
tar czf "$BUILD_DIR/${PACKAGE_NAME}-${VERSION}-linux-386.tar.gz" -C "$BUILD_DIR" "${BINARY_NAME}-${VERSION}-linux-386"

# Windows (using zip instead of tar.gz)
echo "Creating windows archives..."
if command -v zip >/dev/null 2>&1; then
(cd "$BUILD_DIR" && zip "${PACKAGE_NAME}-${VERSION}-windows-amd64.zip" "${BINARY_NAME}-${VERSION}-windows-amd64.exe")
(cd "$BUILD_DIR" && zip "${PACKAGE_NAME}-${VERSION}-windows-386.zip" "${BINARY_NAME}-${VERSION}-windows-386.exe")
if [[ "${SKIP_PACKAGE:-}" == "1" ]]; then
echo "Build complete! Binaries are in the $BUILD_DIR directory"
else
echo "Warning: zip command not found, skipping Windows archives"
"$(dirname "$0")/package.sh" "$VERSION"
echo "Build complete! Artifacts are in the $BUILD_DIR directory"
fi

# Generate checksums
echo "Generating checksums..."
(cd "$BUILD_DIR" && shasum -a 256 * > "${PACKAGE_NAME}-${VERSION}-checksums.txt")

echo "Build complete! Artifacts are in the $BUILD_DIR directory"
67 changes: 67 additions & 0 deletions scripts/package.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
#!/bin/bash

set -euo pipefail

# Get version from command line or use "dev" as default
VERSION=${1:-dev}
BINARY_NAME="git-flow"
PACKAGE_NAME="git-flow-next"

# Build directory
BUILD_DIR="dist"

echo "Packaging $PACKAGE_NAME version $VERSION..."

# Verify all binaries are present before packaging
echo "Verifying binaries..."
MISSING_BINARIES=()

for binary in "${BINARY_NAME}-${VERSION}-darwin-amd64" "${BINARY_NAME}-${VERSION}-darwin-arm64" \
"${BINARY_NAME}-${VERSION}-linux-amd64" "${BINARY_NAME}-${VERSION}-linux-arm64" "${BINARY_NAME}-${VERSION}-linux-386" \
"${BINARY_NAME}-${VERSION}-windows-amd64.exe" "${BINARY_NAME}-${VERSION}-windows-386.exe"; do
if [[ ! -f "$BUILD_DIR/$binary" ]]; then
MISSING_BINARIES+=("$binary")
fi
done

if [[ ${#MISSING_BINARIES[@]} -gt 0 ]]; then
echo "Error: The following binaries were not found:"
for binary in "${MISSING_BINARIES[@]}"; do
echo " - $binary"
done
exit 1
fi

# Remove generated artifacts for this version so checksums describe the final outputs.
rm -f "$BUILD_DIR/${PACKAGE_NAME}-${VERSION}-"*.tar.gz \
"$BUILD_DIR/${PACKAGE_NAME}-${VERSION}-"*.zip \
"$BUILD_DIR/${PACKAGE_NAME}-${VERSION}-checksums.txt"

# Create archives for each binary
echo "Creating archives..."

# macOS
echo "Creating darwin archives..."
tar czf "$BUILD_DIR/${PACKAGE_NAME}-${VERSION}-darwin-amd64.tar.gz" -C "$BUILD_DIR" "${BINARY_NAME}-${VERSION}-darwin-amd64"
tar czf "$BUILD_DIR/${PACKAGE_NAME}-${VERSION}-darwin-arm64.tar.gz" -C "$BUILD_DIR" "${BINARY_NAME}-${VERSION}-darwin-arm64"

# Linux
echo "Creating linux archives..."
tar czf "$BUILD_DIR/${PACKAGE_NAME}-${VERSION}-linux-amd64.tar.gz" -C "$BUILD_DIR" "${BINARY_NAME}-${VERSION}-linux-amd64"
tar czf "$BUILD_DIR/${PACKAGE_NAME}-${VERSION}-linux-arm64.tar.gz" -C "$BUILD_DIR" "${BINARY_NAME}-${VERSION}-linux-arm64"
tar czf "$BUILD_DIR/${PACKAGE_NAME}-${VERSION}-linux-386.tar.gz" -C "$BUILD_DIR" "${BINARY_NAME}-${VERSION}-linux-386"

# Windows (using zip instead of tar.gz)
echo "Creating windows archives..."
if command -v zip >/dev/null 2>&1; then
(cd "$BUILD_DIR" && zip "${PACKAGE_NAME}-${VERSION}-windows-amd64.zip" "${BINARY_NAME}-${VERSION}-windows-amd64.exe")
(cd "$BUILD_DIR" && zip "${PACKAGE_NAME}-${VERSION}-windows-386.zip" "${BINARY_NAME}-${VERSION}-windows-386.exe")
else
echo "Warning: zip command not found, skipping Windows archives"
fi

# Generate checksums
echo "Generating checksums..."
(cd "$BUILD_DIR" && shasum -a 256 * > "${PACKAGE_NAME}-${VERSION}-checksums.txt")

Comment thread
MichalBerner marked this conversation as resolved.
echo "Packaging complete! Artifacts are in the $BUILD_DIR directory"