Release #10
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Release | |
| on: | |
| push: | |
| tags: | |
| - 'v*.*.*' | |
| workflow_dispatch: | |
| inputs: | |
| version: | |
| description: 'Version to release (e.g., 1.3.1)' | |
| required: true | |
| type: string | |
| # Grant GITHUB_TOKEN the permissions required to make releases | |
| permissions: | |
| contents: write | |
| jobs: | |
| build-and-release: | |
| runs-on: macos-15 | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v4 | |
| - name: Setup Xcode | |
| uses: maxim-lobanov/setup-xcode@v1 | |
| with: | |
| xcode-version: 'latest-stable' | |
| - name: Check Swift version | |
| run: | | |
| swift --version | |
| echo "Xcode version:" | |
| xcodebuild -version | |
| - name: Get version | |
| id: get_version | |
| run: | | |
| if [ "${{ github.event.inputs.version }}" != "" ]; then | |
| echo "VERSION=${{ github.event.inputs.version }}" >> $GITHUB_OUTPUT | |
| echo "TAG=v${{ github.event.inputs.version }}" >> $GITHUB_OUTPUT | |
| else | |
| echo "VERSION=${GITHUB_REF#refs/tags/v}" >> $GITHUB_OUTPUT | |
| echo "TAG=${GITHUB_REF#refs/tags/}" >> $GITHUB_OUTPUT | |
| fi | |
| - name: Update version in code | |
| run: | | |
| VERSION="${{ steps.get_version.outputs.VERSION }}" | |
| sed -i '' "s/static let current: String = \".*\"/static let current: String = \"$VERSION\"/" Sources/CiteBar/AppVersion.swift | |
| BUILD_NUMBER=$(date +%s) | |
| sed -i '' "s/static let build: String = \".*\"/static let build: String = \"$BUILD_NUMBER\"/" Sources/CiteBar/AppVersion.swift | |
| - name: Calculate DMG name (same as Makefile) | |
| id: dmg_name | |
| run: | | |
| # Extract version from AppVersion.swift (same as Makefile) | |
| VERSION=$(grep 'static let current' Sources/CiteBar/AppVersion.swift | cut -d'"' -f2) | |
| # Get architecture and date for DMG naming (match Makefile format exactly) | |
| ARCH=$(uname -m) | |
| if [ "$ARCH" = "x86_64" ]; then | |
| ARCH_NAME="intel" | |
| elif [ "$ARCH" = "arm64" ]; then | |
| ARCH_NAME="arm64" | |
| else | |
| ARCH_NAME="$ARCH" | |
| fi | |
| BUILD_DATE=$(date +%Y%m%d) | |
| DMG_NAME="CiteBar-${VERSION}-${ARCH_NAME}-${BUILD_DATE}" | |
| echo "VERSION_FROM_FILE=$VERSION" >> $GITHUB_OUTPUT | |
| echo "ARCH_NAME=$ARCH_NAME" >> $GITHUB_OUTPUT | |
| echo "BUILD_DATE=$BUILD_DATE" >> $GITHUB_OUTPUT | |
| echo "DMG_NAME=$DMG_NAME" >> $GITHUB_OUTPUT | |
| echo "Calculated DMG name: $DMG_NAME" | |
| echo "Version from file: $VERSION" | |
| - name: Build and Package | |
| run: | | |
| # Verify version was updated correctly | |
| UPDATED_VERSION=$(grep 'static let current' Sources/CiteBar/AppVersion.swift | cut -d'"' -f2) | |
| echo "Updated version in code: $UPDATED_VERSION" | |
| echo "Expected version: ${{ steps.get_version.outputs.VERSION }}" | |
| echo "DMG name will be: ${{ steps.dmg_name.outputs.DMG_NAME }}" | |
| # Create properly configured app bundle with Sparkle framework, rpath fixes, and signing | |
| make package | |
| - name: Create DMG | |
| run: | | |
| # Use Makefile to create DMG (it will handle everything properly) | |
| make dmg | |
| # Get the actual DMG file created by Makefile | |
| MAKEFILE_DMG=$(ls dist/*.dmg | head -1) | |
| EXPECTED_DMG="dist/${{ steps.dmg_name.outputs.DMG_NAME }}.dmg" | |
| echo "Makefile created: $MAKEFILE_DMG" | |
| echo "Expected filename: $EXPECTED_DMG" | |
| if [ "$MAKEFILE_DMG" != "$EXPECTED_DMG" ]; then | |
| mv "$MAKEFILE_DMG" "$EXPECTED_DMG" | |
| echo "Renamed DMG: $MAKEFILE_DMG -> $EXPECTED_DMG" | |
| else | |
| echo "DMG filename is already correct" | |
| fi | |
| # Verify the final DMG exists | |
| if [ ! -f "$EXPECTED_DMG" ]; then | |
| echo "Error: Expected DMG file not found: $EXPECTED_DMG" | |
| echo "Available files in dist/:" | |
| ls -la dist/ | |
| exit 1 | |
| fi | |
| - name: Generate Appcast | |
| run: | | |
| # Get file size and calculate SHA256 | |
| DMG_FILE="dist/${{ steps.dmg_name.outputs.DMG_NAME }}.dmg" | |
| DMG_SIZE=$(stat -f%z "$DMG_FILE") | |
| DMG_SHA256=$(shasum -a 256 "$DMG_FILE" | cut -d' ' -f1) | |
| CURRENT_DATE=$(date -u +"%a, %d %b %Y %H:%M:%S %Z") | |
| # Generate release notes from AppVersion.swift | |
| RELEASE_NOTES_HTML=$(swift scripts/extract-release-notes.swift html) | |
| # Create appcast.xml | |
| cat > appcast.xml << EOF | |
| <?xml version="1.0" encoding="utf-8"?> | |
| <rss version="2.0" xmlns:sparkle="http://www.andymatuschak.org/xml-namespaces/sparkle" xmlns:dc="http://purl.org/dc/elements/1.1/"> | |
| <channel> | |
| <title>CiteBar</title> | |
| <description>Citation Tracking for Academics</description> | |
| <language>en</language> | |
| <link>https://github.com/hichipli/CiteBar</link> | |
| <item> | |
| <title>Version ${{ steps.dmg_name.outputs.VERSION_FROM_FILE }}</title> | |
| <pubDate>$CURRENT_DATE</pubDate> | |
| <description><![CDATA[ | |
| $RELEASE_NOTES_HTML | |
| ]]></description> | |
| <enclosure url="https://github.com/hichipli/CiteBar/releases/download/${{ steps.get_version.outputs.TAG }}/${{ steps.dmg_name.outputs.DMG_NAME }}.dmg" | |
| sparkle:version="${{ steps.dmg_name.outputs.VERSION_FROM_FILE }}" | |
| sparkle:shortVersionString="${{ steps.dmg_name.outputs.VERSION_FROM_FILE }}" | |
| sparkle:sha256Sum="$DMG_SHA256" | |
| length="$DMG_SIZE" | |
| type="application/octet-stream" /> | |
| <sparkle:minimumSystemVersion>13.0</sparkle:minimumSystemVersion> | |
| </item> | |
| </channel> | |
| </rss> | |
| EOF | |
| - name: Create Release | |
| run: | | |
| # Generate release notes from AppVersion.swift | |
| RELEASE_NOTES_MARKDOWN=$(swift scripts/extract-release-notes.swift markdown) | |
| echo "$RELEASE_NOTES_MARKDOWN" > release-notes.md | |
| - name: Publish Release | |
| uses: softprops/action-gh-release@v1 | |
| with: | |
| tag_name: ${{ steps.get_version.outputs.TAG }} | |
| name: CiteBar ${{ steps.dmg_name.outputs.VERSION_FROM_FILE }} | |
| body_path: release-notes.md | |
| draft: false | |
| prerelease: false | |
| files: | | |
| dist/${{ steps.dmg_name.outputs.DMG_NAME }}.dmg | |
| appcast.xml | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} |