@@ -193,20 +193,22 @@ jobs:
193193
194194 # Import Application certificate
195195 if [ -n "$APPLE_APP_CERT_BASE64" ]; then
196- echo "=== Importing Developer ID Application Certificate ==="
196+ echo "=== Importing 3rd Party Mac Developer Application Certificate ==="
197197 echo "$APPLE_APP_CERT_BASE64" | base64 -d > app_cert.p12
198- security import app_cert.p12 -k temp.keychain -P "$APPLE_CERT_PASSWORD" -A
198+ security import app_cert.p12 -k temp.keychain -P "$APPLE_CERT_PASSWORD" -T /usr/bin/codesign -T /usr/bin/security
199199 rm app_cert.p12
200200 echo "✅ Application certificate imported"
201201 fi
202202
203- # Import Installer certificate
203+ # Import Installer certificate with productsign ACL
204204 if [ -n "$APPLE_INSTALLER_CERT_BASE64" ]; then
205- echo "=== Importing Developer ID Installer Certificate ==="
205+ echo "=== Importing 3rd Party Mac Developer Installer Certificate ==="
206206 echo "$APPLE_INSTALLER_CERT_BASE64" | base64 -d > installer_cert.p12
207- security import installer_cert.p12 -k temp.keychain -P "$APPLE_CERT_PASSWORD" -A
207+ # CRITICAL: Must include -T /usr/bin/productsign for installer cert to work
208+ # The -p codesigning policy doesn't include installer certs (different EKU)
209+ security import installer_cert.p12 -k temp.keychain -P "$APPLE_CERT_PASSWORD" -T /usr/bin/codesign -T /usr/bin/productsign -T /usr/bin/security
208210 rm installer_cert.p12
209- echo "✅ Installer certificate imported"
211+ echo "✅ Installer certificate imported with productsign ACL "
210212 fi
211213
212214 # Download and import Apple WWDR intermediate certificate (required for cert chain validation)
@@ -274,9 +276,14 @@ jobs:
274276
275277 - name : Build macOS app (MAS target - Universal)
276278 env :
277- # Enable code signing if certificates are available
279+ # Application signing certificate (for codesign)
278280 CSC_LINK : ${{ secrets.APPLE_APP_CERT_BASE64 }}
279281 CSC_KEY_PASSWORD : ${{ secrets.APPLE_CERT_PASSWORD }}
282+ # Installer signing certificate (for productsign) - CRITICAL for MAS PKG
283+ # electron-builder uses these separate env vars because installer certs
284+ # have different Extended Key Usage and aren't found by -p codesigning policy
285+ CSC_INSTALLER_LINK : ${{ secrets.APPLE_INSTALLER_CERT_BASE64 }}
286+ CSC_INSTALLER_KEY_PASSWORD : ${{ secrets.APPLE_CERT_PASSWORD }}
280287 APPLE_DEVELOPER_ID : ${{ secrets.APPLE_DEVELOPER_ID }}
281288 APPLE_CERT_PASSWORD : ${{ secrets.APPLE_CERT_PASSWORD }}
282289 run : |
@@ -285,10 +292,14 @@ jobs:
285292 security list-keychains -d user -s "$HOME/Library/Keychains/temp.keychain-db" "$HOME/Library/Keychains/login.keychain-db"
286293 security default-keychain -s temp.keychain
287294
288- # Verify installer identity is available
289- echo "=== Checking for installer identity ==="
290- security find-identity -v -p codesigning temp.keychain | grep -i "installer" || echo "Warning: No installer identity found in temp.keychain"
291- security find-identity -v temp.keychain | grep -i "installer" || echo "Warning: No installer identity found"
295+ # Verify identities are available
296+ echo "=== Checking for signing identities ==="
297+ echo "Application identities (codesigning policy):"
298+ security find-identity -v -p codesigning temp.keychain | grep -i "3rd Party Mac Developer Application" || echo " No app signing identity found"
299+
300+ echo ""
301+ echo "Installer identities (no policy filter - installer certs have different EKU):"
302+ security find-identity -v temp.keychain | grep -i "3rd Party Mac Developer Installer" || echo " No installer identity found"
292303
293304 # Run the build
294305 npm run private:build:mac
@@ -389,7 +400,7 @@ jobs:
389400 retention-days : 90
390401
391402 build-linux :
392- name : Build Linux ( Snap Store)
403+ name : Build Linux & Publish to Snap Store
393404 runs-on : ubuntu-latest
394405
395406 steps :
@@ -407,84 +418,57 @@ jobs:
407418 with :
408419 python-version : ' 3.11'
409420
410- - name : Get version from tag
411- id : version
412- run : |
413- if [ "${{ github.ref_type }}" = "tag" ]; then
414- VERSION="${{ github.ref_name }}"
415- VERSION="${VERSION#v}"
416- elif [ -n "${{ github.event.inputs.version }}" ]; then
417- VERSION="${{ github.event.inputs.version }}"
418- else
419- VERSION=$(node -p "require('./package.json').version")
420- fi
421- echo "VERSION=$VERSION" >> $GITHUB_OUTPUT
422- echo "Building version: $VERSION"
423-
424421 - name : Install dependencies
425422 run : npm ci
426423 timeout-minutes : 15
427424
428425 - name : Install Snapcraft
429- run : |
430- sudo snap install snapcraft --classic
426+ run : sudo snap install snapcraft --classic
431427
432428 - name : Build application
433429 run : npm run private:compile
434430
435431 - name : Build Linux packages
436432 run : npm run private:build:linux
437433
438- - name : Import GPG key for signing
439- env :
440- GPG_PRIVATE_KEY : ${{ secrets.GPG_PRIVATE_KEY }}
434+ - name : List built files
441435 run : |
442- if [ -z "$GPG_PRIVATE_KEY" ]; then
443- echo "⚠️ GPG_PRIVATE_KEY not set - skipping GPG signing"
444- exit 0
445- fi
446-
447- echo "=== Importing GPG Key ==="
448- echo "$GPG_PRIVATE_KEY" | gpg --batch --import
449-
450- # Configure GPG agent
451- echo "allow-preset-passphrase" > ~/.gnupg/gpg-agent.conf
452- gpg-connect-agent reloadagent /bye
453-
454- # Verify import
455- echo "Imported keys:"
456- gpg --list-secret-keys --keyid-format LONG | sed 's/\([A-F0-9]\{12\}\)[A-F0-9]\{4\}/\1XXXX/g'
457-
458- - name : Sign Linux packages with GPG
436+ echo "=== Built files ==="
437+ find dist -type f \( -name "*.snap" -o -name "*.AppImage" \) -exec ls -lh {} \;
438+
439+ - name : Publish to Snap Store
440+ if : |
441+ startsWith(github.ref, 'refs/tags/') &&
442+ !contains(github.ref_name, '-beta') &&
443+ !contains(github.ref_name, '-alpha') &&
444+ !contains(github.ref_name, '-rc')
459445 env :
460- GPG_PRIVATE_KEY : ${{ secrets.GPG_PRIVATE_KEY }}
461- GPG_KEY_ID : ${{ secrets.GPG_KEY_ID }}
462- GPG_PASSPHRASE : ${{ secrets.GPG_PASSPHRASE }}
446+ SNAPCRAFT_STORE_CREDENTIALS : ${{ secrets.SNAPCRAFT_STORE_CREDENTIALS }}
463447 run : |
464- if [ -z "$GPG_PRIVATE_KEY" ]; then
465- echo "⚠️ Skipping GPG signing"
448+ if [ -z "$SNAPCRAFT_STORE_CREDENTIALS" ]; then
449+ echo "=== Snap Store Submission ==="
450+ echo "⚠️ SNAPCRAFT_STORE_CREDENTIALS not configured."
451+ echo ""
452+ echo "To enable automatic publishing:"
453+ echo " 1. Run: snapcraft export-login --snaps=allow2automate --channels=stable,candidate,beta,edge credentials.txt"
454+ echo " 2. Add contents as SNAPCRAFT_STORE_CREDENTIALS secret in GitHub"
466455 exit 0
467456 fi
468457
469- echo "=== Signing Linux Packages ==="
458+ SNAP=$(find dist -name "*.snap" | head -n 1)
459+ if [ -z "$SNAP" ]; then
460+ echo "❌ No snap file found"
461+ exit 1
462+ fi
470463
471- for pkg in dist/*.snap dist/*.AppImage dist/*.deb dist/*.rpm; do
472- if [ -f "$pkg" ]; then
473- echo "Signing: $(basename $pkg)"
474- echo "$GPG_PASSPHRASE" | gpg --batch --yes --passphrase-fd 0 \
475- --pinentry-mode loopback -u "$GPG_KEY_ID" \
476- --detach-sign --armor "$pkg"
464+ echo "=== Publishing to Snap Store ==="
465+ echo "Snap: $SNAP"
477466
478- if [ -f "$pkg.asc" ]; then
479- echo " ✅ Signature created"
480- fi
481- fi
482- done
467+ echo "$SNAPCRAFT_STORE_CREDENTIALS" | snapcraft login --with -
468+ snapcraft upload "$SNAP" --release=stable
483469
484- - name : List built files
485- run : |
486- echo "=== Built files ==="
487- find dist -type f \( -name "*.snap" -o -name "*.AppImage" -o -name "*.deb" -o -name "*.rpm" -o -name "*.asc" \) -exec ls -lh {} \;
470+ echo "✅ Published to Snap Store"
471+ echo "View at: https://snapcraft.io/allow2automate"
488472
489473 - name : Upload Linux artifacts
490474 uses : actions/upload-artifact@v4
@@ -493,9 +477,6 @@ jobs:
493477 path : |
494478 dist/*.snap
495479 dist/*.AppImage
496- dist/*.deb
497- dist/*.rpm
498- dist/*.asc
499480 retention-days : 90
500481
501482 create-release :
@@ -819,65 +800,3 @@ jobs:
819800 echo "✅ Submitted to Mac App Store"
820801 echo "Check status at: https://appstoreconnect.apple.com"
821802
822- submit-snap-store :
823- name : Submit to Snap Store
824- needs : build-linux
825- runs-on : ubuntu-latest
826- if : |
827- startsWith(github.ref, 'refs/tags/') &&
828- !contains(github.ref_name, '-beta') &&
829- !contains(github.ref_name, '-alpha') &&
830- !contains(github.ref_name, '-rc') &&
831- github.event.inputs.skip_store_submission != 'true'
832-
833- steps :
834- - name : Download Linux artifact
835- uses : actions/download-artifact@v4
836- with :
837- name : linux-packages
838- path : artifacts
839-
840- - name : Install Snapcraft
841- run : |
842- sudo snap install snapcraft --classic
843-
844- - name : List artifacts
845- run : |
846- echo "=== Downloaded artifacts ==="
847- find artifacts -type f -exec ls -lh {} \;
848-
849- - name : Submit to Snap Store
850- env :
851- SNAPCRAFT_STORE_CREDENTIALS : ${{ secrets.SNAPCRAFT_STORE_CREDENTIALS }}
852- run : |
853- if [ -z "$SNAPCRAFT_STORE_CREDENTIALS" ]; then
854- echo "=== Snap Store Submission ==="
855- echo "Automatic submission not configured."
856- echo ""
857- echo "To enable, add SNAPCRAFT_STORE_CREDENTIALS secret:"
858- echo " 1. Run: snapcraft export-login --snaps=allow2automate --channels=stable credentials.txt"
859- echo " 2. Add contents of credentials.txt as SNAPCRAFT_STORE_CREDENTIALS secret"
860- echo ""
861- echo "Manual submission: snapcraft upload <snap-file>"
862- exit 0
863- fi
864-
865- echo "=== Submitting to Snap Store ==="
866-
867- # Find the snap file
868- SNAP=$(find artifacts -name "*.snap" | head -n 1)
869-
870- if [ -z "$SNAP" ]; then
871- echo "❌ No snap file found"
872- exit 1
873- fi
874-
875- echo "Uploading: $SNAP"
876-
877- # Login and upload
878- echo "$SNAPCRAFT_STORE_CREDENTIALS" | snapcraft login --with -
879-
880- snapcraft upload "$SNAP" --release=stable
881-
882- echo "✅ Submitted to Snap Store"
883- echo "Check status at: https://snapcraft.io/allow2automate"
0 commit comments