name: "Build Electron App" description: "Builds and packages the Electron app for different platforms" inputs: os: description: "One of the supported platforms: macos, linux, windows" required: true arch: description: "The architecture to build for: x64, arm64" required: true extension: description: "Platform specific extensions to copy in the output: dmg, deb, rpm, exe, zip" required: true runs: using: composite steps: # Certificate setup - name: Import Apple certificates if: inputs.os == 'macos' uses: apple-actions/import-codesign-certs@v3 with: p12-file-base64: ${{ env.APPLE_APP_CERTIFICATE_BASE64 }} p12-password: ${{ env.APPLE_APP_CERTIFICATE_PASSWORD }} keychain: build keychain-password: ${{ github.run_id }} - name: Install Installer certificate if: inputs.os == 'macos' uses: apple-actions/import-codesign-certs@v3 with: p12-file-base64: ${{ env.APPLE_INSTALLER_CERTIFICATE_BASE64 }} p12-password: ${{ env.APPLE_INSTALLER_CERTIFICATE_PASSWORD }} keychain: build keychain-password: ${{ github.run_id }} # We don't need to create a keychain here because we're using the build keychain that was created in the previous step create-keychain: false - name: Verify certificates if: inputs.os == 'macos' shell: bash run: | echo "Available signing identities:" security find-identity -v -p codesigning build.keychain - name: Set up Python and other macOS dependencies if: ${{ inputs.os == 'macos' }} shell: bash run: | brew install python-setuptools brew install create-dmg - name: Install dependencies for RPM and Flatpak package building if: ${{ inputs.os == 'linux' }} shell: bash run: | sudo apt-get update && sudo apt-get install rpm flatpak-builder elfutils flatpak remote-add --user --if-not-exists flathub https://flathub.org/repo/flathub.flatpakrepo FLATPAK_ARCH=$(if [[ ${{ inputs.arch }} = 'arm64' ]]; then echo 'aarch64'; else echo 'x86_64'; fi) FLATPAK_VERSION='24.08' flatpak install --user --no-deps --arch $FLATPAK_ARCH --assumeyes runtime/org.freedesktop.Platform/$FLATPAK_ARCH/$FLATPAK_VERSION runtime/org.freedesktop.Sdk/$FLATPAK_ARCH/$FLATPAK_VERSION org.electronjs.Electron2.BaseApp/$FLATPAK_ARCH/$FLATPAK_VERSION # Build setup - name: Install dependencies shell: bash run: npm ci - name: Update build info shell: bash run: npm run chore:update-build-info # Critical debugging configuration - name: Run electron-forge build with enhanced logging shell: bash env: # Pass through required environment variables for signing and notarization APPLE_TEAM_ID: ${{ env.APPLE_TEAM_ID }} APPLE_ID: ${{ env.APPLE_ID }} APPLE_ID_PASSWORD: ${{ env.APPLE_ID_PASSWORD }} run: | # Map OS names to Electron Forge platform names if [ "${{ inputs.os }}" = "macos" ]; then PLATFORM="darwin" elif [ "${{ inputs.os }}" = "windows" ]; then PLATFORM="win32" else PLATFORM="${{ inputs.os }}" fi npm run electron-forge:make -- \ --arch=${{ inputs.arch }} \ --platform=$PLATFORM # Add DMG signing step - name: Sign DMG if: inputs.os == 'macos' shell: bash run: | echo "Signing DMG file..." dmg_file=$(find ./dist -name "*.dmg" -print -quit) if [ -n "$dmg_file" ]; then echo "Found DMG: $dmg_file" # Get the first valid signing identity from the keychain SIGNING_IDENTITY=$(security find-identity -v -p codesigning build.keychain | grep "Developer ID Application" | head -1 | sed -E 's/.*"([^"]+)".*/\1/') if [ -z "$SIGNING_IDENTITY" ]; then echo "Error: No valid Developer ID Application certificate found in keychain" exit 1 fi echo "Using signing identity: $SIGNING_IDENTITY" # Sign the DMG codesign --force --sign "$SIGNING_IDENTITY" --options runtime --timestamp "$dmg_file" # Notarize the DMG xcrun notarytool submit "$dmg_file" --apple-id "$APPLE_ID" --password "$APPLE_ID_PASSWORD" --team-id "$APPLE_TEAM_ID" --wait # Staple the notarization ticket xcrun stapler staple "$dmg_file" else echo "No DMG found to sign" fi - name: Verify code signing if: inputs.os == 'macos' shell: bash run: | echo "Verifying code signing for all artifacts..." # First check the .app bundle echo "Looking for .app bundle..." app_bundle=$(find ./dist -name "*.app" -print -quit) if [ -n "$app_bundle" ]; then echo "Found app bundle: $app_bundle" echo "Verifying app bundle signing..." codesign --verify --deep --strict --verbose=2 "$app_bundle" echo "Displaying app bundle signing info..." codesign --display --verbose=2 "$app_bundle" echo "Checking entitlements..." codesign --display --entitlements :- "$app_bundle" echo "Checking notarization status..." xcrun stapler validate "$app_bundle" || echo "Warning: App bundle not notarized yet" else echo "No .app bundle found to verify" fi # Then check DMG if it exists echo "Looking for DMG..." dmg_file=$(find ./dist -name "*.dmg" -print -quit) if [ -n "$dmg_file" ]; then echo "Found DMG: $dmg_file" echo "Verifying DMG signing..." codesign --verify --deep --strict --verbose=2 "$dmg_file" echo "Displaying DMG signing info..." codesign --display --verbose=2 "$dmg_file" echo "Checking DMG notarization..." xcrun stapler validate "$dmg_file" || echo "Warning: DMG not notarized yet" else echo "No DMG found to verify" fi # Finally check ZIP if it exists echo "Looking for ZIP..." zip_file=$(find ./dist -name "*.zip" -print -quit) if [ -n "$zip_file" ]; then echo "Found ZIP: $zip_file" echo "Note: ZIP files are not code signed, but their contents should be" fi - name: Prepare artifacts shell: bash run: | mkdir -p upload if [ "${{ inputs.os }}" = "macos" ]; then # For macOS, we need to look in specific directories based on the maker echo "Collecting macOS artifacts..." # Look for DMG files recursively echo "Looking for DMG files..." dmg_file=$(find ./dist -name "*.dmg" -print -quit) if [ -n "$dmg_file" ]; then echo "Found DMG: $dmg_file" cp "$dmg_file" "upload/TriliumNextNotes-${{ github.ref_name }}-macos-${{ inputs.arch }}.dmg" else echo "Warning: No DMG file found" fi # Look for ZIP files recursively echo "Looking for ZIP files..." zip_file=$(find ./dist -name "*.zip" -print -quit) if [ -n "$zip_file" ]; then echo "Found ZIP: $zip_file" cp "$zip_file" "upload/TriliumNextNotes-${{ github.ref_name }}-macos-${{ inputs.arch }}.zip" else echo "Warning: No ZIP file found" fi else # For other platforms, use the existing logic but with better error handling echo "Collecting artifacts for ${{ inputs.os }}..." for ext in ${{ inputs.extension }}; do echo "Looking for .$ext files..." file=$(find ./dist -name "*.$ext" -print -quit) if [ -n "$file" ]; then echo "Found $file for extension $ext" cp "$file" "upload/TriliumNextNotes-${{ github.ref_name }}-${{ inputs.os }}-${{ inputs.arch }}.$ext" else echo "Warning: No file found with extension .$ext" fi done fi echo "Final contents of upload directory:" ls -la upload/