melodia scraper: decode XML entities in sitemap slugs #25
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: Build & Release | |
| on: | |
| push: | |
| branches: [main] | |
| tags: ['v*'] | |
| pull_request: | |
| branches: [main] | |
| # Cancel in-progress runs for the same branch | |
| concurrency: | |
| group: ${{ github.workflow }}-${{ github.ref }} | |
| cancel-in-progress: true | |
| env: | |
| SCHEME: TopPresenter | |
| PRODUCT_NAME: TopPresenter | |
| XCODE_VERSION: '16.0' | |
| jobs: | |
| build: | |
| name: Build & Package | |
| runs-on: macos-15 | |
| timeout-minutes: 30 | |
| outputs: | |
| version: ${{ steps.package.outputs.VERSION }} | |
| prerelease_tag: ${{ steps.package.outputs.PRERELEASE_TAG }} | |
| prerelease_version: ${{ steps.package.outputs.PRERELEASE_VERSION }} | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v4 | |
| - name: Select Xcode | |
| run: sudo xcode-select -s /Applications/Xcode_${{ env.XCODE_VERSION }}.app/Contents/Developer | |
| - name: Show Xcode version | |
| run: xcodebuild -version | |
| - name: Resolve dependencies | |
| run: xcodebuild -resolvePackageDependencies -scheme "$SCHEME" -project "$PRODUCT_NAME.xcodeproj" | |
| - name: Build | |
| run: | | |
| xcodebuild \ | |
| -scheme "$SCHEME" \ | |
| -project "$PRODUCT_NAME.xcodeproj" \ | |
| -configuration Release \ | |
| -derivedDataPath build \ | |
| -destination 'platform=macOS' \ | |
| CODE_SIGN_IDENTITY="-" \ | |
| CODE_SIGNING_REQUIRED=NO \ | |
| CODE_SIGNING_ALLOWED=NO \ | |
| DEVELOPMENT_TEAM="" \ | |
| clean build | |
| - name: Run Unit Tests | |
| run: | | |
| xcodebuild \ | |
| -scheme "$SCHEME" \ | |
| -project "$PRODUCT_NAME.xcodeproj" \ | |
| -destination 'platform=macOS' \ | |
| -resultBundlePath TestResults.xcresult \ | |
| CODE_SIGN_IDENTITY="-" \ | |
| CODE_SIGNING_REQUIRED=NO \ | |
| CODE_SIGNING_ALLOWED=NO \ | |
| DEVELOPMENT_TEAM="" \ | |
| test || true | |
| - name: Package app | |
| id: package | |
| run: | | |
| APP_PATH="build/Build/Products/Release/$PRODUCT_NAME.app" | |
| if [ ! -d "$APP_PATH" ]; then | |
| echo "❌ App not found at $APP_PATH" | |
| find build -name "*.app" -type d | |
| exit 1 | |
| fi | |
| # Get version info | |
| VERSION=$(/usr/libexec/PlistBuddy -c "Print :CFBundleShortVersionString" "$APP_PATH/Contents/Info.plist" 2>/dev/null || echo "1.0") | |
| BUILD=$(/usr/libexec/PlistBuddy -c "Print :CFBundleVersion" "$APP_PATH/Contents/Info.plist" 2>/dev/null || echo "1") | |
| # Alpha counter is PER VERSION: bumping MARKETING_VERSION restarts at alpha.1 | |
| git fetch --tags --force --quiet | |
| ALPHA_N=$(( $(git tag -l "v$VERSION-alpha.*" | wc -l | tr -d ' ') + 1 )) | |
| echo "VERSION=$VERSION" >> $GITHUB_ENV | |
| echo "BUILD=$BUILD" >> $GITHUB_ENV | |
| echo "PRERELEASE_VERSION=$VERSION-alpha.${ALPHA_N}" >> $GITHUB_ENV | |
| echo "PRERELEASE_TAG=v$VERSION-alpha.${ALPHA_N}" >> $GITHUB_ENV | |
| echo "VERSION=$VERSION" >> $GITHUB_OUTPUT | |
| echo "PRERELEASE_VERSION=$VERSION-alpha.${ALPHA_N}" >> $GITHUB_OUTPUT | |
| echo "PRERELEASE_TAG=v$VERSION-alpha.${ALPHA_N}" >> $GITHUB_OUTPUT | |
| # Create ZIP | |
| cd "build/Build/Products/Release" | |
| ditto -c -k --keepParent "$PRODUCT_NAME.app" "$PRODUCT_NAME-$VERSION.zip" | |
| mv "$PRODUCT_NAME-$VERSION.zip" "$GITHUB_WORKSPACE/" | |
| # Create DMG | |
| hdiutil create -volname "$PRODUCT_NAME" \ | |
| -srcfolder "$PRODUCT_NAME.app" \ | |
| -ov -format UDZO \ | |
| "$GITHUB_WORKSPACE/$PRODUCT_NAME-$VERSION.dmg" | |
| - name: Upload artifact | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: TopPresenter-${{ env.VERSION }} | |
| path: | | |
| TopPresenter-*.zip | |
| TopPresenter-*.dmg | |
| retention-days: 30 | |
| # Unique pre-release on every push to main | |
| pre-release: | |
| name: Pre-release (Alpha) | |
| needs: build | |
| if: github.ref == 'refs/heads/main' && github.event_name == 'push' | |
| runs-on: macos-15 | |
| permissions: | |
| contents: write | |
| steps: | |
| - name: Download artifact | |
| uses: actions/download-artifact@v4 | |
| with: | |
| pattern: TopPresenter-* | |
| merge-multiple: true | |
| - name: Get short SHA | |
| run: echo "SHORT_SHA=${GITHUB_SHA::7}" >> $GITHUB_ENV | |
| - name: Create alpha pre-release | |
| uses: softprops/action-gh-release@v2 | |
| with: | |
| tag_name: ${{ needs.build.outputs.prerelease_tag }} | |
| name: "TopPresenter ${{ needs.build.outputs.prerelease_version }}" | |
| prerelease: true | |
| generate_release_notes: true | |
| body: | | |
| ### ⚡ Automatic Alpha Build | |
| **Version:** `${{ needs.build.outputs.prerelease_version }}` | |
| **Tag:** `${{ needs.build.outputs.prerelease_tag }}` | |
| **Commit:** `${{ github.sha }}` | |
| **Branch:** `main` | |
| **Built:** ${{ github.event.head_commit.timestamp }} | |
| > ⚠️ This is an unsigned build. To open on macOS: | |
| > Right-click the app → Open → Open (bypass Gatekeeper). | |
| > Or run: `xattr -cr TopPresenter.app` | |
| --- | |
| **Commit message:** ${{ github.event.head_commit.message }} | |
| files: | | |
| TopPresenter-*.zip | |
| TopPresenter-*.dmg | |
| # Stable release on final version tags (v1.0.0, v1.1.0, etc.) | |
| release: | |
| name: Stable Release | |
| needs: build | |
| if: startsWith(github.ref, 'refs/tags/v') && !contains(github.ref_name, '-') | |
| runs-on: macos-15 | |
| permissions: | |
| contents: write | |
| steps: | |
| - name: Download artifact | |
| uses: actions/download-artifact@v4 | |
| with: | |
| pattern: TopPresenter-* | |
| merge-multiple: true | |
| - name: Create stable release | |
| uses: softprops/action-gh-release@v2 | |
| with: | |
| name: "TopPresenter ${{ github.ref_name }}" | |
| generate_release_notes: true | |
| body: | | |
| ### 🎉 TopPresenter ${{ github.ref_name }} | |
| > ⚠️ This is an unsigned build. To open on macOS: | |
| > Right-click the app → Open → Open (bypass Gatekeeper). | |
| > Or run: `xattr -cr TopPresenter.app` | |
| files: | | |
| TopPresenter-*.zip | |
| TopPresenter-*.dmg |