Merge pull request #52 from ledhed2222/mac-code-signing-fix #6
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: Build Native Installers | |
| on: | |
| push: | |
| tags: | |
| - 'v*' # Only builds on version tags like v2.4.3 | |
| workflow_dispatch: # Manual trigger from the GitHub UI | |
| jobs: | |
| macos: | |
| runs-on: macos-latest # ARM runner (Apple Silicon, works on Intel via Rosetta 2) | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Set up JDK 21 | |
| uses: actions/setup-java@v4 | |
| with: | |
| distribution: temurin | |
| java-version: 21 | |
| - name: Extract version from pom.xml | |
| id: version | |
| run: | | |
| VERSION=$(mvn help:evaluate -Dexpression=project.version -q -DforceStdout) | |
| echo "version=$VERSION" >> $GITHUB_OUTPUT | |
| echo "Building version: $VERSION" | |
| - name: Import Code Signing Certificate | |
| env: | |
| CERTIFICATE_BASE64: ${{ secrets.MACOS_CERTIFICATE }} | |
| CERTIFICATE_PASSWORD: ${{ secrets.MACOS_CERTIFICATE_PWD }} | |
| KEYCHAIN_PASSWORD: ${{ secrets.MACOS_CERTIFICATE_PWD }} | |
| run: | | |
| # Create variables | |
| CERTIFICATE_PATH=$RUNNER_TEMP/certificate.p12 | |
| KEYCHAIN_PATH=$RUNNER_TEMP/app-signing.keychain-db | |
| # Decode certificate | |
| echo -n "$CERTIFICATE_BASE64" | base64 --decode -o $CERTIFICATE_PATH | |
| # Create temporary keychain | |
| security create-keychain -p "$KEYCHAIN_PASSWORD" $KEYCHAIN_PATH | |
| security set-keychain-settings -lut 21600 $KEYCHAIN_PATH | |
| security unlock-keychain -p "$KEYCHAIN_PASSWORD" $KEYCHAIN_PATH | |
| # Import certificate to keychain | |
| security import $CERTIFICATE_PATH -P "$CERTIFICATE_PASSWORD" -A -t cert -f pkcs12 -k $KEYCHAIN_PATH | |
| security list-keychain -d user -s $KEYCHAIN_PATH | |
| # Enable codesigning from a non user interactive shell | |
| security set-key-partition-list -S apple-tool:,apple:,codesign: -s -k "$KEYCHAIN_PASSWORD" $KEYCHAIN_PATH | |
| - name: Build .jar | |
| run: mvn clean package | |
| - name: Build app bundle with jpackage | |
| env: | |
| APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }} | |
| run: | | |
| # Get the certificate identity name | |
| CERT_IDENTITY=$(security find-identity -v -p codesigning | grep "Developer ID Application" | head -1 | sed -n 's/.*"\(.*\)"/\1/p') | |
| echo "Using certificate: $CERT_IDENTITY" | |
| # First create just the app-image (app bundle), not DMG yet | |
| jpackage \ | |
| --type app-image \ | |
| --name EWItool \ | |
| --input target \ | |
| --main-jar EWItool-${{ steps.version.outputs.version }}.jar \ | |
| --main-class com.github.ledhed2222.ewitool.Main \ | |
| --dest target \ | |
| --app-version ${{ steps.version.outputs.version }} \ | |
| --vendor "Ledhed2222" \ | |
| --icon src/main/resources/logo.icns | |
| - name: Sign app bundle with hardened runtime | |
| run: | | |
| CERT_IDENTITY=$(security find-identity -v -p codesigning | grep "Developer ID Application" | head -1 | sed -n 's/.*"\(.*\)"/\1/p') | |
| # Sign all nested binaries, libraries, and frameworks with hardened runtime | |
| find target/EWItool.app/Contents -type f \( -name "*.dylib" -o -name "*.jnilib" -o -perm +111 \) | while read file; do | |
| echo "Signing: $file" | |
| codesign --force --sign "$CERT_IDENTITY" --timestamp --options runtime "$file" || true | |
| done | |
| # Sign the app bundle itself | |
| codesign --force --sign "$CERT_IDENTITY" --timestamp --options runtime --deep target/EWItool.app | |
| # Verify signature | |
| codesign --verify --deep --strict --verbose=2 target/EWItool.app | |
| - name: Create and sign DMG | |
| run: | | |
| CERT_IDENTITY=$(security find-identity -v -p codesigning | grep "Developer ID Application" | head -1 | sed -n 's/.*"\(.*\)"/\1/p') | |
| # Create DMG from signed app bundle | |
| hdiutil create -volname EWItool -srcfolder target/EWItool.app -ov -format UDZO target/EWItool-${{ steps.version.outputs.version }}.dmg | |
| # Sign the DMG | |
| codesign --force --sign "$CERT_IDENTITY" --timestamp target/EWItool-${{ steps.version.outputs.version }}.dmg | |
| # Verify DMG signature | |
| codesign --verify --verbose=4 target/EWItool-${{ steps.version.outputs.version }}.dmg | |
| - name: Notarize DMG | |
| env: | |
| APPLE_ID: ${{ secrets.APPLE_ID }} | |
| APPLE_APP_PASSWORD: ${{ secrets.APPLE_APP_PASSWORD }} | |
| APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }} | |
| run: | | |
| # Submit for notarization and capture submission ID | |
| SUBMIT_OUTPUT=$(xcrun notarytool submit target/EWItool-${{ steps.version.outputs.version }}.dmg \ | |
| --apple-id "$APPLE_ID" \ | |
| --password "$APPLE_APP_PASSWORD" \ | |
| --team-id "$APPLE_TEAM_ID" \ | |
| --wait 2>&1) | |
| echo "$SUBMIT_OUTPUT" | |
| # Extract submission ID | |
| SUBMISSION_ID=$(echo "$SUBMIT_OUTPUT" | grep "id:" | head -1 | awk '{print $2}') | |
| echo "Submission ID: $SUBMISSION_ID" | |
| # Check if notarization succeeded | |
| if echo "$SUBMIT_OUTPUT" | grep -q "status: Accepted"; then | |
| echo "Notarization succeeded!" | |
| # Staple the notarization ticket | |
| xcrun stapler staple target/EWItool-${{ steps.version.outputs.version }}.dmg | |
| # Verify notarization | |
| xcrun stapler validate target/EWItool-${{ steps.version.outputs.version }}.dmg | |
| else | |
| echo "Notarization failed. Getting log..." | |
| xcrun notarytool log "$SUBMISSION_ID" \ | |
| --apple-id "$APPLE_ID" \ | |
| --password "$APPLE_APP_PASSWORD" \ | |
| --team-id "$APPLE_TEAM_ID" | |
| exit 1 | |
| fi | |
| - name: Rename DMG | |
| run: | | |
| mv target/EWItool-${{ steps.version.outputs.version }}.dmg target/EWItool-${{ steps.version.outputs.version }}-macos.dmg | |
| - name: Upload to gh release | |
| uses: softprops/action-gh-release@v1 | |
| with: | |
| files: target/*-macos.dmg | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| windows: | |
| runs-on: windows-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Set up JDK 21 | |
| uses: actions/setup-java@v4 | |
| with: | |
| distribution: temurin | |
| java-version: 21 | |
| - name: Extract version from pom.xml | |
| id: version | |
| shell: pwsh | |
| run: | | |
| [xml]$pom = Get-Content pom.xml | |
| $VERSION = $pom.project.version | |
| echo "version=$VERSION" >> $env:GITHUB_OUTPUT | |
| echo "Building version: $VERSION" | |
| - name: Build .jar | |
| run: mvn clean package | |
| - name: Convert PNG to ICO for Windows | |
| run: | | |
| # jpackage will use PNG on Windows if ICO not available | |
| # We'll use the PNG file directly | |
| - name: Run jpackage for Windows | |
| run: | | |
| jpackage ` | |
| --type exe ` | |
| --name EWItool ` | |
| --input target ` | |
| --main-jar EWItool-${{ steps.version.outputs.version }}.jar ` | |
| --main-class com.github.ledhed2222.ewitool.Main ` | |
| --dest target ` | |
| --app-version ${{ steps.version.outputs.version }} ` | |
| --vendor "Ledhed2222" ` | |
| --icon src/main/resources/logo.png ` | |
| --win-dir-chooser ` | |
| --win-menu ` | |
| --win-shortcut | |
| - name: Upload to gh release | |
| uses: softprops/action-gh-release@v1 | |
| with: | |
| files: target/*.exe | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| linux: | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Set up JDK 21 | |
| uses: actions/setup-java@v4 | |
| with: | |
| distribution: temurin | |
| java-version: 21 | |
| - name: Extract version from pom.xml | |
| id: version | |
| run: | | |
| VERSION=$(mvn help:evaluate -Dexpression=project.version -q -DforceStdout) | |
| echo "version=$VERSION" >> $GITHUB_OUTPUT | |
| echo "Building version: $VERSION" | |
| - name: Install jpackage dependencies | |
| run: | | |
| sudo apt-get update | |
| sudo apt-get install -y libfreetype6-dev libasound2-dev fakeroot rpm | |
| - name: Build .jar | |
| run: mvn clean package | |
| - name: Run jpackage for Linux (DEB) | |
| run: | | |
| jpackage \ | |
| --type deb \ | |
| --name ewitool \ | |
| --input target \ | |
| --main-jar EWItool-${{ steps.version.outputs.version }}.jar \ | |
| --main-class com.github.ledhed2222.ewitool.Main \ | |
| --dest target \ | |
| --app-version ${{ steps.version.outputs.version }} \ | |
| --vendor "Ledhed2222" \ | |
| --icon src/main/resources/logo.png \ | |
| --linux-shortcut | |
| - name: Run jpackage for Linux (RPM) | |
| run: | | |
| jpackage \ | |
| --type rpm \ | |
| --name ewitool \ | |
| --input target \ | |
| --main-jar EWItool-${{ steps.version.outputs.version }}.jar \ | |
| --main-class com.github.ledhed2222.ewitool.Main \ | |
| --dest target \ | |
| --app-version ${{ steps.version.outputs.version }} \ | |
| --vendor "Ledhed2222" \ | |
| --icon src/main/resources/logo.png \ | |
| --linux-shortcut | |
| - name: Upload to gh release | |
| uses: softprops/action-gh-release@v1 | |
| with: | |
| files: | | |
| target/*.deb | |
| target/*.rpm | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} |