Skip to content

🚀 MildStack Release #5

🚀 MildStack Release

🚀 MildStack Release #5

name: 🚀 MildStack Release
on:
push:
tags:
- 'v*'
workflow_dispatch:
inputs:
release_tag:
description: 'Release tag to use for manual release, for example v0.0.3'
required: false
type: string
publish_release:
description: 'Publish a GitHub release after the build finishes'
required: true
default: false
type: boolean
draft_release:
description: 'Create the GitHub release as draft'
required: true
default: true
type: boolean
permissions:
contents: read
concurrency:
group: mildstack-release-${{ github.ref_name || github.run_id }}
cancel-in-progress: true
jobs:
build-cli:
name: Build CLI Binaries
runs-on: ubuntu-latest
timeout-minutes: 20
steps:
- name: Check out Git repository
uses: actions/checkout@v4
- name: Set up Go
uses: actions/setup-go@v5
with:
go-version: '1.26.2'
cache: true
- name: Install Node.js
uses: actions/setup-node@v4
with:
node-version: 22.12
cache: 'npm'
cache-dependency-path: apps/desktop/package-lock.json
- name: Install dependencies
working-directory: apps/desktop
run: npm ci --prefer-offline
env:
npm_config_fetch_retries: 5
npm_config_fetch_retry_mintimeout: 20000
npm_config_fetch_retry_maxtimeout: 120000
- name: Build Go CLI binaries
working-directory: apps/desktop
run: npm run build:cli
- name: Upload CLI artifacts
uses: actions/upload-artifact@v4
with:
name: release-cli-binaries
path: apps/desktop/resources/bin/
if-no-files-found: error
retention-days: 7
build-desktop:
name: Build Desktop (${{ matrix.label }})
needs: build-cli
runs-on: ${{ matrix.os }}
timeout-minutes: 35
strategy:
fail-fast: false
matrix:
include:
- os: macos-latest
label: macOS
platform: mac
artifact_name: desktop-dist-macos
release_files: |
apps/desktop/dist/*.dmg
apps/desktop/dist/*.zip
apps/desktop/dist/*.zip.blockmap
apps/desktop/dist/latest-mac.yml
- os: windows-latest
label: Windows
platform: win
artifact_name: desktop-dist-windows
release_files: |
apps/desktop/dist/*-setup.exe
apps/desktop/dist/*.exe.blockmap
apps/desktop/dist/latest.yml
- os: ubuntu-latest
label: Linux
platform: linux
artifact_name: desktop-dist-linux
release_files: |
apps/desktop/dist/*.AppImage
apps/desktop/dist/*.AppImage.blockmap
apps/desktop/dist/*.deb
apps/desktop/dist/latest-linux.yml
steps:
- name: Check out Git repository
uses: actions/checkout@v4
- name: Install Node.js
uses: actions/setup-node@v4
with:
node-version: 22.12
cache: 'npm'
cache-dependency-path: apps/desktop/package-lock.json
- name: Install dependencies
working-directory: apps/desktop
run: npm ci --prefer-offline
env:
npm_config_fetch_retries: 5
npm_config_fetch_retry_mintimeout: 20000
npm_config_fetch_retry_maxtimeout: 120000
- name: Download CLI artifacts
uses: actions/download-artifact@v4
with:
name: release-cli-binaries
path: apps/desktop/resources/bin/
- name: Make binaries executable
if: runner.os != 'Windows'
run: find apps/desktop/resources/bin -type f -exec chmod +x {} +
- name: Clean dist directory
shell: bash
run: rm -rf apps/desktop/dist
- name: Sync desktop version from release tag
if: startsWith(github.ref, 'refs/tags/v') || (github.event_name == 'workflow_dispatch' && inputs.release_tag != '')
shell: bash
run: |
source_tag="${GITHUB_REF_NAME}"
if [[ "${GITHUB_EVENT_NAME}" == "workflow_dispatch" ]]; then
source_tag="${{ inputs.release_tag }}"
fi
if [[ ! "$source_tag" =~ ^v[0-9]+\.[0-9]+\.[0-9]+([-.][0-9A-Za-z.-]+)?$ ]]; then
echo "Invalid release tag: ${source_tag}"
exit 1
fi
release_version="${source_tag#v}"
npm pkg set version="$release_version" --prefix apps/desktop
- name: Build Electron app source
working-directory: apps/desktop
run: npm run build
env:
NODE_OPTIONS: '--max-old-space-size=8192'
- name: Build Electron app
working-directory: apps/desktop
run: npx --no-install electron-builder --${{ matrix.platform }} --publish never
env:
NODE_OPTIONS: '--max-old-space-size=8192'
CSC_IDENTITY_AUTO_DISCOVERY: 'false'
- name: Verify macOS app code signature consistency
if: matrix.platform == 'mac'
shell: bash
run: |
app_paths="$(find apps/desktop/dist -maxdepth 3 -type d -name "MildStack Desktop.app" | sort)"
if [[ -z "$app_paths" ]]; then
echo "No macOS app bundle found under apps/desktop/dist"
exit 1
fi
while IFS= read -r app_path; do
[[ -z "$app_path" ]] && continue
echo "Verifying: $app_path"
codesign --verify --deep --strict --verbose=2 "$app_path"
codesign -dv --verbose=4 "$app_path" 2>&1 | sed -n '1,40p'
done <<< "$app_paths"
- name: Upload packaged release artifacts
if: startsWith(github.ref, 'refs/tags/v') || github.event_name == 'workflow_dispatch'
uses: actions/upload-artifact@v4
with:
name: ${{ matrix.artifact_name }}
path: ${{ matrix.release_files }}
if-no-files-found: error
retention-days: 7
publish-release:
name: Publish GitHub Release
if: startsWith(github.ref, 'refs/tags/v') || (github.event_name == 'workflow_dispatch' && inputs.publish_release)
needs: build-desktop
runs-on: ubuntu-latest
timeout-minutes: 15
environment: release
permissions:
contents: write
steps:
- name: Validate manual release tag
if: github.event_name == 'workflow_dispatch'
shell: bash
run: |
if [[ -z "${{ inputs.release_tag }}" ]]; then
echo "release_tag is required when publish_release is enabled."
exit 1
fi
if [[ ! "${{ inputs.release_tag }}" =~ ^v[0-9]+\.[0-9]+\.[0-9]+([-.][0-9A-Za-z.-]+)?$ ]]; then
echo "Invalid release tag: ${{ inputs.release_tag }}"
exit 1
fi
- name: Download macOS release artifacts
uses: actions/download-artifact@v4
with:
name: desktop-dist-macos
path: release-assets/macos
- name: Download Windows release artifacts
uses: actions/download-artifact@v4
with:
name: desktop-dist-windows
path: release-assets/windows
- name: Download Linux release artifacts
uses: actions/download-artifact@v4
with:
name: desktop-dist-linux
path: release-assets/linux
- name: Publish curated release assets
uses: softprops/action-gh-release@v2
with:
tag_name: ${{ github.event_name == 'workflow_dispatch' && inputs.release_tag || github.ref_name }}
target_commitish: ${{ github.sha }}
draft: ${{ github.event_name == 'workflow_dispatch' && inputs.draft_release || false }}
files: |
release-assets/macos/*
release-assets/windows/*
release-assets/linux/*
fail_on_unmatched_files: true
generate_release_notes: false
body: |
Download the asset that matches your platform:
- macOS Apple Silicon: `*-mac-arm64.dmg`
- macOS Intel: `*-mac-x64.dmg`
- Windows x64: `*-windows-x64-setup.exe`
- Windows ARM64: `*-windows-arm64-setup.exe`
- Linux AppImage (recommended): `*-linux-x64.AppImage` or `*-linux-arm64.AppImage`
- Linux Debian/Ubuntu: `*-linux-amd64.deb` or `*-linux-arm64.deb`
For auto-update, keep the companion files generated alongside those installers:
- macOS: `latest-mac.yml`, `*.zip`, `*.zip.blockmap`
- Windows: `latest.yml`, `*.exe.blockmap`
- Linux: `latest-linux.yml`, `*.AppImage.blockmap`