Files
gemini-nexus/.github/workflows/publish.yaml

241 lines
7.8 KiB
YAML

name: Publish Release
on:
workflow_run:
workflows: ['Release']
types: [completed]
workflow_dispatch:
inputs:
dry_run:
description: 'Build artifacts only, skip uploading to GitHub Release'
required: false
type: boolean
default: true
allow_update_published_release:
description: 'Allow uploading assets to an already published release'
required: false
type: boolean
default: false
jobs:
check-release:
name: Check for new release
runs-on: ubuntu-latest
if: github.event_name == 'workflow_dispatch' || github.event.workflow_run.conclusion == 'success'
permissions:
contents: read
outputs:
tag: ${{ steps.get_tag.outputs.tag }}
has_release: ${{ steps.get_tag.outputs.has_release }}
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Get latest release tag
id: get_tag
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
version="$(node -e "process.stdout.write(require('./package.json').version)")"
tag="v$version"
echo "tag=$tag" >> "$GITHUB_OUTPUT"
echo "has_release=true" >> "$GITHUB_OUTPUT"
else
tag=$(gh release list --limit 1 --json tagName --jq '.[0].tagName // empty')
if [ -n "$tag" ]; then
echo "tag=$tag" >> "$GITHUB_OUTPUT"
echo "has_release=true" >> "$GITHUB_OUTPUT"
echo "Found release: $tag"
else
echo "has_release=false" >> "$GITHUB_OUTPUT"
echo "No release found, skipping build."
fi
fi
build:
needs: check-release
if: needs.check-release.outputs.has_release == 'true'
strategy:
fail-fast: false
matrix:
include:
- os: windows-latest
platform: win32
arch: x64
- os: windows-11-arm
platform: win32
arch: arm64
- os: macos-15-intel
platform: darwin
arch: x64
- os: macos-14
platform: darwin
arch: arm64
- os: ubuntu-latest
platform: linux
arch: x64
- os: ubuntu-24.04-arm
platform: linux
arch: arm64
runs-on: ${{ matrix.os }}
permissions:
contents: read
steps:
- name: Checkout git repo
uses: actions/checkout@v4
- name: Install pnpm
uses: pnpm/action-setup@v4
- name: Install Node and NPM
uses: actions/setup-node@v4
with:
node-version: 20
cache: 'pnpm'
- name: Install Linux dependencies
if: matrix.platform == 'linux'
run: |
sudo apt-get update
sudo apt-get install -y fakeroot rpm libsecret-1-dev pkg-config
- name: Ensure WiX Toolset
if: matrix.platform == 'win32' && matrix.arch == 'x64'
shell: powershell
run: |
$installed = choco list --local-only wixtoolset --exact --limit-output
if (-not $installed) {
choco install wixtoolset --version=3.14.0 -y
} elseif ($installed -match '^wixtoolset\|3\.14(\.|$)') {
Write-Host "WiX Toolset already compatible: $installed"
} else {
Write-Host "Incompatible WiX Toolset detected: $installed"
choco upgrade wixtoolset --version=3.14.0 --allow-downgrade -y
}
# Ensure 7zip is available for Squirrel.Windows zip operations
choco install 7zip -y
- name: Install dependencies
run: pnpm install --frozen-lockfile
- name: Make Artifacts
if: matrix.platform != 'darwin'
env:
NODE_OPTIONS: --max-old-space-size=8192
SENTRY_DSN: ${{ secrets.SENTRY_DSN }}
SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }}
SENTRY_ORG: ${{ secrets.SENTRY_ORG }}
SENTRY_PROJECT: ${{ secrets.SENTRY_PROJECT }}
run: pnpm run make -- --platform=${{ matrix.platform }} --arch=${{ matrix.arch }}
# DMG creation may be flaky on GitHub macOS runners, so retry the full darwin make.
- name: Make Artifacts (darwin with retry)
if: matrix.platform == 'darwin'
uses: nick-fields/retry@v3
with:
max_attempts: 3
timeout_minutes: 20
retry_wait_seconds: 20
command: pnpm run make -- --platform=${{ matrix.platform }} --arch=${{ matrix.arch }}
env:
NODE_OPTIONS: --max-old-space-size=8192
SENTRY_DSN: ${{ secrets.SENTRY_DSN }}
SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }}
SENTRY_ORG: ${{ secrets.SENTRY_ORG }}
SENTRY_PROJECT: ${{ secrets.SENTRY_PROJECT }}
- name: Upload Build Artifacts
uses: actions/upload-artifact@v4
with:
name: make-${{ matrix.platform }}-${{ matrix.arch }}
path: |
out/make/**/*.exe
out/make/**/*.dmg
out/make/**/*.zip
out/make/**/*.AppImage
out/make/**/*.deb
out/make/**/*.rpm
out/make/**/*.msi
out/make/**/*.yml
out/make/**/*.txt
if-no-files-found: error
retention-days: 14
- name: Dry-run summary
if: github.event_name == 'workflow_dispatch' && github.event.inputs.dry_run == 'true'
run: |
echo "Dry run enabled: build artifacts generated and uploaded; release publish step will be skipped."
publish:
name: Publish Release
needs: [check-release, build]
runs-on: ubuntu-latest
if: needs.build.result == 'success' && (github.event_name != 'workflow_dispatch' || github.event.inputs.dry_run != 'true')
permissions:
contents: write
steps:
- name: Checkout git repo
uses: actions/checkout@v4
- name: Download Build Artifacts
uses: actions/download-artifact@v4
with:
pattern: make-*
merge-multiple: true
path: release-assets
- name: Resolve release tag
id: release_tag
run: |
tag="${{ needs.check-release.outputs.tag }}"
if [ -z "$tag" ]; then
version="$(node -e "process.stdout.write(require('./package.json').version)")"
tag="v$version"
fi
echo "tag=$tag" >> "$GITHUB_OUTPUT"
echo "Using release tag: $tag"
- name: Upload assets to release
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
RELEASE_TAG: ${{ steps.release_tag.outputs.tag }}
run: |
mapfile -t files < <(find release-assets -type f \( \
-name '*.exe' -o \
-name '*.dmg' -o \
-name '*.zip' -o \
-name '*.AppImage' -o \
-name '*.deb' -o \
-name '*.rpm' -o \
-name '*.msi' -o \
-name '*.yml' -o \
-name '*.txt' \
\) | sort)
if [ "${#files[@]}" -eq 0 ]; then
echo "::error::No release assets found under release-assets/"
exit 1
fi
printf 'Uploading %s assets to %s\n' "${#files[@]}" "$RELEASE_TAG"
# Upload files sequentially with retries to prevent GitHub API rate limits and 404/502 errors
for file in "${files[@]}"; do
echo "Uploading $file..."
if ! gh release upload "$RELEASE_TAG" "$file" --clobber; then
echo "::warning::Failed to upload $file. Retrying in 5 seconds..."
sleep 5
if ! gh release upload "$RELEASE_TAG" "$file" --clobber; then
echo "::error::Failed to upload $file after retry."
exit 1
fi
fi
done