name: Build release artifacts # Builds each platform natively on a v* tag and publishes one Gitea release. # # Runners required. None are registered yet, and a job with no matching runner # queues silently rather than failing, so register all three before tagging: # ubuntu-latest Linux AppImage # windows-latest Windows NSIS installer + portable zip # macos-arm64 macOS dmg + zip, both architectures (M-series builds both) # # Nothing cross-builds any more: dmg requires macOS, and the Windows exe needs # rcedit on Windows to get its icon and version resources. # # All output is unsigned. Once certificates exist: for macOS drop mac.identity # from package.json and remove CSC_IDENTITY_AUTO_DISCOVERY; for Windows add the # cert secrets. Until then users hit Gatekeeper and SmartScreen warnings. on: push: tags: - 'v*' workflow_dispatch: jobs: linux: runs-on: ubuntu-latest defaults: run: working-directory: desktop-client steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 with: node-version: '22' # Runs only here rather than in all three jobs: it is a repo-wide check, # and this job uses bash, which is not guaranteed on the Windows runner. - name: Verify tag matches package.json version if: startsWith(github.ref, 'refs/tags/v') run: | pkg_version=$(node -p "require('./package.json').version") tag_version="${GITHUB_REF_NAME#v}" if [ "$pkg_version" != "$tag_version" ]; then echo "Tag $GITHUB_REF_NAME does not match package.json version $pkg_version." >&2 echo "Bump package.json before tagging, or artifacts will be misnamed." >&2 exit 1 fi - name: Install dependencies run: npm ci - name: Run tests run: npm test - name: Build AppImage run: npx electron-builder --linux AppImage --publish never - uses: actions/upload-artifact@v3 with: name: linux path: desktop-client/dist/*.AppImage if-no-files-found: error windows: runs-on: windows-latest defaults: run: working-directory: desktop-client steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 with: node-version: '22' - name: Install dependencies run: npm ci - name: Run tests run: npm test - name: Build installer and portable zip run: npx electron-builder --win nsis zip --publish never - uses: actions/upload-artifact@v3 with: name: windows path: | desktop-client/dist/*.exe desktop-client/dist/*-win-*.zip if-no-files-found: error macos: runs-on: macos-arm64 defaults: run: working-directory: desktop-client env: # No Developer ID yet: stop electron-builder auto-discovering an identity, # which otherwise fails the build on a real Mac rather than building unsigned. CSC_IDENTITY_AUTO_DISCOVERY: 'false' steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 with: node-version: '22' - name: Install dependencies run: npm ci - name: Run tests run: npm test - name: Build dmg and zip (both architectures) run: npx electron-builder --mac --x64 --arm64 --publish never - uses: actions/upload-artifact@v3 with: name: macos path: | desktop-client/dist/*.dmg desktop-client/dist/*-mac-*.zip if-no-files-found: error publish: # Separate job so only one process touches the release: parallel build jobs # would race to create it and one would fail on the duplicate tag. needs: [linux, windows, macos] if: startsWith(github.ref, 'refs/tags/v') runs-on: ubuntu-latest steps: - uses: actions/download-artifact@v3 with: path: artifacts - name: Create release and attach artifacts env: TOKEN: ${{ secrets.RELEASE_TOKEN }} API: ${{ github.server_url }}/api/v1/repos/${{ github.repository }} run: | set -euo pipefail if [ -z "${TOKEN:-}" ]; then echo "RELEASE_TOKEN secret is not set." >&2 exit 1 fi release_id=$(curl -sf -H "Authorization: token $TOKEN" \ "$API/releases/tags/$GITHUB_REF_NAME" \ | node -p "JSON.parse(require('fs').readFileSync(0,'utf8')).id" 2>/dev/null || true) if [ -z "${release_id:-}" ]; then release_id=$(curl -sf -X POST -H "Authorization: token $TOKEN" \ -H "Content-Type: application/json" \ -d "{\"tag_name\":\"$GITHUB_REF_NAME\",\"name\":\"$GITHUB_REF_NAME\"}" \ "$API/releases" \ | node -p "JSON.parse(require('fs').readFileSync(0,'utf8')).id") fi found=0 for f in $(find artifacts -type f \( -name '*.AppImage' -o -name '*.zip' -o -name '*.dmg' -o -name '*.exe' \)); do name=$(basename "$f") echo "Attaching $name" curl -sf -X POST -H "Authorization: token $TOKEN" \ -F "attachment=@$f" \ "$API/releases/$release_id/assets?name=$name" -o /dev/null found=$((found + 1)) done if [ "$found" -eq 0 ]; then echo "No artifacts found to attach." >&2 exit 1 fi echo "Attached $found artifacts to release $release_id"