Skip to content

Installer Release

Installer Release #12

name: Installer Release
on:
workflow_dispatch:
inputs:
dry_run:
description: 'Perform a dry run (no actual release)'
type: boolean
default: false
required: false
env:
GO_VERSION: '1.24.2'
permissions:
contents: write
issues: write
pull-requests: write
jobs:
calculate-version:
name: Calculate Release Version
runs-on: ubuntu-latest
defaults:
run:
working-directory: ./installer/go
outputs:
version: ${{ steps.semantic.outputs.new_release_version }}
new-release-published: ${{ steps.semantic.outputs.new_release_published }}
steps:
- name: Checkout
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with:
fetch-depth: 0
token: ${{ secrets.GITHUB_TOKEN }}
- name: Setup Node.js
uses: actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444 # v5.0.0
with:
node-version: '20'
- name: Calculate next version
id: semantic
uses: cycjimmy/semantic-release-action@9cc899c47e6841430bbaedb43de1560a568dfd16 # v4.1.1
with:
semantic_version: 23.0.3
working_directory: ./installer/go
extra_plugins: |
@semantic-release/[email protected]
@semantic-release/[email protected]
dry_run: true
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
build-artifacts:
name: Build Multi-Platform Binaries
runs-on: ubuntu-latest
needs: calculate-version
if: needs.calculate-version.outputs.new-release-published == 'true' || github.event.inputs.dry_run == 'true'
defaults:
run:
working-directory: ./installer/go
strategy:
fail-fast: false
matrix:
include:
- goos: linux
goarch: amd64
output: flowfuse-device-installer-linux-amd64
- goos: linux
goarch: arm64
output: flowfuse-device-installer-linux-arm64
- goos: linux
goarch: arm
output: flowfuse-device-installer-linux-arm
- goos: windows
goarch: amd64
output: flowfuse-device-installer-windows-amd64.exe
- goos: darwin
goarch: amd64
output: flowfuse-device-installer-darwin-amd64
- goos: darwin
goarch: arm64
output: flowfuse-device-installer-darwin-arm64
steps:
- name: Checkout
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with:
fetch-depth: 0
token: ${{ secrets.GITHUB_TOKEN }}
- name: Set up Go
uses: actions/setup-go@44694675825211faa026b3c33043df3e48a5fa00 # v6.0.0
with:
go-version: ${{ env.GO_VERSION }}
cache-dependency-path: "**/go.sum"
- name: Download dependencies
run: go mod download
- name: Build binary for ${{ matrix.goos }}/${{ matrix.goarch }}
env:
GOOS: ${{ matrix.goos }}
GOARCH: ${{ matrix.goarch }}
VERSION: ${{ needs.calculate-version.outputs.version }}
CGO_ENABLED: 0
run: |
echo "Building ${{ matrix.output }} for ${{ matrix.goos }}/${{ matrix.goarch }}..."
echo "Using version: ${VERSION:-${{ github.sha }}}"
# Create output directory structure
mkdir -p artifacts
# Build with version from semantic-release
go build -ldflags "-X main.instVersion=${VERSION:-${{ github.sha }}} -s -w" -o artifacts/${{ matrix.output }} main.go
# Verify the binary was created
if [ ! -f "artifacts/${{ matrix.output }}" ]; then
echo "❌ Binary was not created: ${{ matrix.output }}"
exit 1
fi
echo "✅ Binary created: ${{ matrix.output }}"
ls -la artifacts/${{ matrix.output }}
# Test the version output (only for native builds to avoid cross-compilation issues)
if [[ "${{ matrix.goos }}" == "linux" && "${{ matrix.goarch }}" == "amd64" ]]; then
echo "Testing version output:"
./artifacts/${{ matrix.output }} --version || echo "Version test completed"
fi
- name: Upload build artifacts
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
with:
name: ${{ matrix.output }}
path: installer/go/artifacts/${{ matrix.output }}
retention-days: 1
release:
name: Release
runs-on: ubuntu-latest
needs: [calculate-version, build-artifacts]
if: needs.calculate-version.outputs.new-release-published == 'true' && github.event.inputs.dry_run != 'true'
defaults:
run:
working-directory: ./installer/go
steps:
- name: Checkout
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with:
fetch-depth: 0 # Required for semantic-release to analyze full commit history
token: ${{ secrets.GITHUB_TOKEN }}
- name: Setup Node.js
uses: actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444 # v5.0.0
with:
node-version: '20'
- name: Download all artifacts
uses: actions/download-artifact@634f93cb2916e3fdff6788551b99b062d0335ce0 # v5.0.0
with:
path: artifacts
pattern: flowfuse-device-installer-*
merge-multiple: true
- name: Prepare artifacts for release
run: |
echo "Preparing release artifacts..."
mkdir -p release-artifacts
# Move and verify all artifacts
find ../../artifacts -name "flowfuse-device-installer-*" -type f -exec cp {} release-artifacts/ \;
echo "Available artifacts:"
ls -la release-artifacts/
# Verify we have all expected binaries
expected_files=(
"flowfuse-device-installer-linux-amd64"
"flowfuse-device-installer-linux-arm64"
"flowfuse-device-installer-linux-arm"
"flowfuse-device-installer-windows-amd64.exe"
"flowfuse-device-installer-darwin-amd64"
"flowfuse-device-installer-darwin-arm64"
)
missing_files=()
for file in "${expected_files[@]}"; do
if [ ! -f "release-artifacts/$file" ]; then
missing_files+=("$file")
fi
done
if [ ${#missing_files[@]} -ne 0 ]; then
echo "❌ Missing expected artifacts:"
printf '%s\n' "${missing_files[@]}"
exit 1
fi
echo "✅ All expected artifacts are present"
- name: Perform release
uses: cycjimmy/semantic-release-action@9cc899c47e6841430bbaedb43de1560a568dfd16 # v4.1.1
with:
semantic_version: 23.0.3
working_directory: ./installer/go
extra_plugins: |
@semantic-release/[email protected]
@semantic-release/[email protected]
dry_run: false
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
update-installer-scripts:
name: Update Download Scripts
runs-on: ubuntu-latest
needs: [calculate-version, release]
if: needs.calculate-version.outputs.new-release-published == 'true' && github.event.inputs.dry_run != 'true'
steps:
- name: Generate a token
id: generate_token
uses: tibdex/github-app-token@3beb63f4bd073e61482598c45c71c1019b59b73a # v2.1.0
with:
app_id: ${{ secrets.GH_BOT_APP_ID }}
private_key: ${{ secrets.GH_BOT_APP_KEY }}
- name: Checkout
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with:
fetch-depth: 0
token: ${{ steps.generate_token.outputs.token }}
- name: Configure Git
run: |
git config user.name "$GitHub Actions Bot"
git config user.email "[email protected]"
- name: Update scripts
run: |
VERSION="${{ needs.calculate-version.outputs.version }}"
echo "Updating installer scripts to version: $VERSION"
# Update scripts
sed -i "s/^RELEASE=.*/RELEASE=\"$VERSION\"/" ./installer/get.sh
sed -i "s/^\$RELEASE = .*/\$RELEASE = \"$VERSION\"/" ./installer/get.ps1
# Verify changes
echo "Updated get.sh:"
grep "^RELEASE=" ./installer/get.sh
echo "Updated get.ps1:"
grep "^\$RELEASE = " ./installer/get.ps1
- name: Commit and push changes
env:
GITHUB_TOKEN: ${{ steps.generate_token.outputs.token }}
run: |
VERSION="${{ needs.calculate-version.outputs.version }}"
# Ensure there are changes to commit
if git diff --quiet; then
echo "No changes to commit"
exit 0
fi
# Stage, commit, and push changes
git add ./installer/get.sh ./installer/get.ps1
git commit -m "chore: update installer scripts to version $VERSION"
git push origin main