fix(ci): handle dirty workspace on self-hosted runner re-runs #45
Workflow file for this run
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 SAM | |
| on: | |
| push: | |
| tags: | |
| - '[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9].*' | |
| workflow_dispatch: | |
| inputs: | |
| version: | |
| description: 'Version number (e.g., 20251213.1)' | |
| required: true | |
| type: string | |
| env: | |
| XCODE_VERSION: '26.2' | |
| MACOS_VERSION: '14.0' | |
| permissions: | |
| contents: write | |
| jobs: | |
| build-sign-notarize-package: | |
| name: Build, Sign, Notarize, and Package | |
| runs-on: [self-hosted] | |
| outputs: | |
| version: ${{ steps.version.outputs.VERSION }} | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| with: | |
| submodules: recursive | |
| fetch-depth: 0 | |
| clean: true | |
| - name: Set up Xcode | |
| uses: maxim-lobanov/setup-xcode@v1 | |
| with: | |
| xcode-version: ${{ env.XCODE_VERSION }} | |
| - name: Download Metal Toolchain | |
| run: | | |
| echo "Downloading Metal Toolchain for Xcode ${{ env.XCODE_VERSION }}..." | |
| sudo xcodebuild -downloadComponent MetalToolchain || echo "Metal Toolchain already installed or download failed" | |
| - name: Extract version from tag | |
| id: version | |
| env: | |
| EVENT_NAME: ${{ github.event_name }} | |
| INPUT_VERSION: ${{ github.event.inputs.version }} | |
| run: | | |
| if [ "$EVENT_NAME" = "workflow_dispatch" ]; then | |
| VERSION="$INPUT_VERSION" | |
| else | |
| VERSION=${GITHUB_REF#refs/tags/} | |
| fi | |
| echo "VERSION=$VERSION" >> $GITHUB_OUTPUT | |
| echo "Building version: $VERSION" | |
| - name: Update version in Info.plist | |
| env: | |
| VERSION: ${{ steps.version.outputs.VERSION }} | |
| run: | | |
| /usr/libexec/PlistBuddy -c "Set :CFBundleShortVersionString $VERSION" Info.plist | |
| UPDATED_VERSION=$(/usr/libexec/PlistBuddy -c "Print :CFBundleShortVersionString" Info.plist) | |
| if [ "$UPDATED_VERSION" != "$VERSION" ]; then | |
| echo "ERROR: Version update failed" | |
| exit 1 | |
| fi | |
| - name: Build release package | |
| run: make build-release | |
| - name: Sign and notarize | |
| run: | | |
| if [ -f /Users/andrew/.sam_runner_env ]; then | |
| source /Users/andrew/.sam_runner_env | |
| fi | |
| make sign-only-release | |
| - name: Verify distribution files | |
| env: | |
| VERSION: ${{ steps.version.outputs.VERSION }} | |
| run: | | |
| if [ ! -f "dist/SAM-${VERSION}.dmg" ]; then | |
| echo "ERROR: DMG not found" | |
| exit 1 | |
| fi | |
| if [ ! -f "dist/SAM-${VERSION}.zip" ]; then | |
| echo "ERROR: ZIP not found" | |
| exit 1 | |
| fi | |
| echo "Distribution files ready:" | |
| ls -lh dist/SAM-${VERSION}.* | |
| - name: Update appcast.xml | |
| env: | |
| SPARKLE_PRIVATE_KEY: ${{ secrets.SPARKLE_PRIVATE_KEY }} | |
| VERSION: ${{ steps.version.outputs.VERSION }} | |
| run: | | |
| # Create temporary file for private key | |
| TEMP_KEY_FILE=$(mktemp) | |
| echo "$SPARKLE_PRIVATE_KEY" > "$TEMP_KEY_FILE" | |
| chmod 600 "$TEMP_KEY_FILE" | |
| # Update appcast with signature | |
| ./scripts/update_appcast.sh "${VERSION}" "dist/SAM-${VERSION}.zip" "$TEMP_KEY_FILE" | |
| # Clean up temporary key file | |
| rm -f "$TEMP_KEY_FILE" | |
| - name: Commit and push appcast changes | |
| env: | |
| VERSION: ${{ steps.version.outputs.VERSION }} | |
| run: | | |
| git config user.name "GitHub Actions" | |
| git config user.email "actions@github.com" | |
| # Stash local changes (e.g. appcast.xml from update step) | |
| # so we can cleanly switch to main | |
| git stash --include-untracked || true | |
| git fetch origin main | |
| git checkout main | |
| git pull origin main | |
| git stash pop || true | |
| git add appcast.xml | |
| if git diff --staged --quiet; then | |
| echo "No changes to appcast.xml" | |
| else | |
| git commit -m "chore(release): update appcast.xml for v${VERSION}" | |
| git push origin main | |
| fi | |
| - name: Create GitHub Release | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| VERSION: ${{ steps.version.outputs.VERSION }} | |
| run: | | |
| # Write release notes to a temp file | |
| NOTES_FILE=$(mktemp) | |
| printf '%s\n' \ | |
| '## Downloads' \ | |
| '' \ | |
| "- **[SAM-${VERSION}.dmg](https://github.com/SyntheticAutonomicMind/SAM/releases/download/${VERSION}/SAM-${VERSION}.dmg)** - Recommended installer" \ | |
| "- **[SAM-${VERSION}.zip](https://github.com/SyntheticAutonomicMind/SAM/releases/download/${VERSION}/SAM-${VERSION}.zip)** - For Sparkle updates" \ | |
| '' \ | |
| '## Installation' \ | |
| '' \ | |
| '1. Download and open the DMG file' \ | |
| '2. Drag SAM.app to your Applications folder' \ | |
| '3. Launch SAM from Applications' \ | |
| > "$NOTES_FILE" | |
| # Create release and upload assets using gh CLI (more reliable for large files) | |
| gh release create "${VERSION}" \ | |
| --title "SAM ${VERSION}" \ | |
| --notes-file "$NOTES_FILE" \ | |
| --generate-notes \ | |
| "dist/SAM-${VERSION}.dmg" \ | |
| "dist/SAM-${VERSION}.zip" | |
| rm -f "$NOTES_FILE" |