name: Release on: push: tags: - "v*" workflow_dispatch: inputs: version: description: "Release version, for example 0.1.0" required: true default: "0.1.0" permissions: contents: write jobs: macos-arm64-dmg: name: Build macOS ARM64 DMG runs-on: macos-26 steps: - name: Check out repository uses: actions/checkout@v6 with: submodules: recursive - name: Resolve version id: version shell: bash run: | if [[ "${GITHUB_REF_TYPE}" == "tag" ]]; then VERSION="${GITHUB_REF_NAME#v}" TAG_NAME="${GITHUB_REF_NAME}" else VERSION="${{ inputs.version }}" TAG_NAME="v${VERSION}" fi echo "version=$VERSION" >> "$GITHUB_OUTPUT" echo "tag_name=$TAG_NAME" >> "$GITHUB_OUTPUT" echo "Version: $VERSION" - name: Show build environment run: | uname -a swift --version xcodebuild -version xcode-select -p xcrun --sdk macosx --show-sdk-version - name: Verify macOS 26 SDK shell: bash run: | SDK_VERSION="$(xcrun --sdk macosx --show-sdk-version)" SDK_MAJOR="${SDK_VERSION%%.*}" if [[ "$SDK_MAJOR" != "26" ]]; then echo "Expected macOS 26 SDK, got macOS $SDK_VERSION" >&2 exit 1 fi - name: Install dependencies run: brew install aria2 dylibbundler - name: Fetch media engines run: | mkdir -p Sources/Firelink # Download latest yt-dlp for macOS curl -fsSL https://github.com/yt-dlp/yt-dlp/releases/latest/download/yt-dlp_macos -o Sources/Firelink/yt-dlp chmod +x Sources/Firelink/yt-dlp # Download latest FFmpeg release build for macOS ARM64 from Martin Riedl's build server curl -fsSL "https://ffmpeg.martin-riedl.de/redirect/latest/macos/arm64/release/ffmpeg.zip" -o ffmpeg.zip unzip -q -o ffmpeg.zip -d Sources/Firelink rm ffmpeg.zip chmod +x Sources/Firelink/ffmpeg test -x Sources/Firelink/yt-dlp test -x Sources/Firelink/ffmpeg - name: Build app bundle env: MARKETING_VERSION: ${{ steps.version.outputs.version }} BUILD_NUMBER: ${{ github.run_number }} run: Scripts/create_app_bundle.sh - name: Verify ARM64 binary run: | file build/Firelink.app/Contents/MacOS/Firelink lipo -archs build/Firelink.app/Contents/MacOS/Firelink | grep -qx arm64 codesign --verify --deep --strict build/Firelink.app - name: Create DMG env: VERSION: ${{ steps.version.outputs.version }} ARCH: arm64 run: Scripts/create_dmg.sh - name: Upload workflow artifact uses: actions/upload-artifact@v7 with: name: Firelink-${{ steps.version.outputs.version }}-mac-arm64-dmg path: dist/*.dmg if-no-files-found: error - name: Publish GitHub release if: github.ref_type == 'tag' || github.event_name == 'workflow_dispatch' env: GH_TOKEN: ${{ github.token }} run: | VERSION="${{ steps.version.outputs.version }}" TAG_NAME="${{ steps.version.outputs.tag_name }}" awk '/^## \['"$VERSION"'\]/{flag=1; next} /^## \[/{if(flag) exit} flag' CHANGELOG.md > release_notes.md test -s release_notes.md if gh release view "$TAG_NAME" >/dev/null 2>&1; then gh release upload "$TAG_NAME" dist/*.dmg --clobber gh release edit "$TAG_NAME" --notes-file release_notes.md else gh release create "$TAG_NAME" dist/*.dmg --title "$TAG_NAME" --notes-file release_notes.md --verify-tag fi - name: Update Sparkle appcast if: github.ref_type == 'tag' || github.event_name == 'workflow_dispatch' env: GH_TOKEN: ${{ github.token }} SPARKLE_ED_PRIVATE_KEY: ${{ secrets.SPARKLE_ED_PRIVATE_KEY }} run: | if [[ -z "${SPARKLE_ED_PRIVATE_KEY}" ]]; then echo "Missing SPARKLE_ED_PRIVATE_KEY repository secret; cannot update appcast.xml" >&2 exit 1 fi VERSION="${{ steps.version.outputs.version }}" TAG_NAME="${{ steps.version.outputs.tag_name }}" BUILD_NUMBER="${{ github.run_number }}" DMG_PATH="dist/Firelink-${VERSION}-mac-arm64.dmg" DMG_URL="https://github.com/nimbold/Firelink/releases/download/${TAG_NAME}/Firelink-${VERSION}-mac-arm64.dmg" RELEASE_NOTES_URL="https://github.com/nimbold/Firelink/releases/tag/${TAG_NAME}" PUB_DATE="$(LC_ALL=C date -u '+%a, %d %b %Y %H:%M:%S +0000')" SIGN_OUTPUT="$(printf '%s' "$SPARKLE_ED_PRIVATE_KEY" | .build/artifacts/sparkle/Sparkle/bin/sign_update --ed-key-file - "$DMG_PATH")" ED_SIGNATURE="$(printf '%s\n' "$SIGN_OUTPUT" | sed -n 's/.*sparkle:edSignature="\([^"]*\)".*/\1/p' | head -1)" LENGTH="$(stat -f%z "$DMG_PATH" 2>/dev/null || stat -c%s "$DMG_PATH")" if [[ -z "$ED_SIGNATURE" || -z "$LENGTH" ]]; then echo "Failed to extract Sparkle signature or DMG length" >&2 printf '%s\n' "$SIGN_OUTPUT" >&2 exit 1 fi git fetch origin main git checkout main git pull --ff-only origin main cat > appcast.xml < Firelink Updates https://github.com/nimbold/Firelink Most recent updates for Firelink en Version ${VERSION} 14.0 arm64 ${RELEASE_NOTES_URL} ${PUB_DATE} XML xmllint --noout appcast.xml git config user.name "github-actions[bot]" git config user.email "41898282+github-actions[bot]@users.noreply.github.com" git add appcast.xml if git diff --cached --quiet; then echo "appcast.xml already up to date" else git commit -m "chore(release): update appcast for ${VERSION}" git push origin main fi