name: Mac Store Release on Release
on:
  push:
    tags:
      - v*
  workflow_dispatch:
    inputs: {}

jobs:
  mac-store-release:
    runs-on: macos-15
    env:
      UNSPLASH_KEY: ${{ secrets.UNSPLASH_KEY }}
      UNSPLASH_CLIENT_ID: ${{ secrets.UNSPLASH_CLIENT_ID }}

    steps:
      - name: Harden Runner
        uses: step-security/harden-runner@9af89fc71515a100421586dfdb3dc9c984fbf411 # v2.19.4
        with:
          egress-policy: audit
          allowed-endpoints: >
            api.github.com:443
            github.com:443
            objects.githubusercontent.com:443
            registry.npmjs.org:443
            rubygems.org:443
            index.rubygems.org:443
            www.apple.com:443
            appstoreconnect.apple.com:443
            api.appstoreconnect.apple.com:443
            contentdelivery.itunes.apple.com:443
            idmsa.apple.com:443

      - uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6
        with:
          node-version: 22
      - name: Check out Git repository
        uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v6
        with:
          persist-credentials: false
      # work around for npm installs from git+https://github.com/johannesjo/J2M.git
      - name: Reconfigure git to use HTTP authentication
        run: >
          git config --global url."https://github.com/".insteadOf
          ssh://git@github.com/

      - name: Install Apple WWDR intermediate certificate
        run: |
          curl -fsSL https://www.apple.com/certificateauthority/AppleWWDRCAG4.cer -o /tmp/AppleWWDRCAG4.cer
          sudo security add-trusted-cert -d -r trustRoot -k /Library/Keychains/System.keychain /tmp/AppleWWDRCAG4.cer

      - name: Get npm cache directory
        id: npm-cache-dir
        run: |
          echo "dir=$(npm config get cache)" >> $GITHUB_OUTPUT
      - uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v5
        id: npm-cache # use this to check for `cache-hit` ==> if: steps.npm-cache.outputs.cache-hit != 'true'
        with:
          path: ${{ steps.npm-cache-dir.outputs.dir }}
          key: ${{ runner.os }}-node22-${{ hashFiles('**/package-lock.json') }}
          restore-keys: |
            ${{ runner.os }}-node22-

      - name: Configure signing keychain
        env:
          MAC_CERTS: ${{ secrets.mac_certs }}
          MAC_CERTS_PASSWORD: ${{ secrets.mac_certs_password }}
        run: |
          CERT_PATH="$RUNNER_TEMP/mac-certs.p12"
          KEYCHAIN_NAME="build.keychain"
          KEYCHAIN_PATH="$HOME/Library/Keychains/${KEYCHAIN_NAME}-db"
          echo "$MAC_CERTS" | base64 --decode > "$CERT_PATH"
          echo "=== DIAGNOSTIC: Decoded .p12 SHA256 ==="
          shasum -a 256 "$CERT_PATH"
          echo "========================================"
          security create-keychain -p "" "$KEYCHAIN_NAME"
          security set-keychain-settings -lut 21600 "$KEYCHAIN_PATH"
          security unlock-keychain -p "" "$KEYCHAIN_PATH"
          curl -fsSL https://www.apple.com/certificateauthority/AppleWWDRCAG4.cer -o "$RUNNER_TEMP/AppleWWDRCAG4.cer"
          security import "$RUNNER_TEMP/AppleWWDRCAG4.cer" -k "$KEYCHAIN_PATH" -T /usr/bin/codesign
          security import "$CERT_PATH" -k "$KEYCHAIN_PATH" -P "$MAC_CERTS_PASSWORD" -T /usr/bin/codesign -T /usr/bin/security -T /usr/bin/pkgbuild -T /usr/bin/productbuild
          security list-keychains -s "$KEYCHAIN_PATH" "$HOME/Library/Keychains/login.keychain-db"
          security default-keychain -s "$KEYCHAIN_PATH"
          security set-key-partition-list -S apple-tool:,apple: -k "" "$KEYCHAIN_PATH"
          security find-identity -v -p codesigning "$KEYCHAIN_PATH"
          security find-identity -v -p macappstore "$KEYCHAIN_PATH"
          {
            echo "CSC_KEYCHAIN=$KEYCHAIN_PATH"
            echo "CSC_LINK=file://$CERT_PATH"
            echo "CSC_KEY_PASSWORD=$MAC_CERTS_PASSWORD"
          } >> "$GITHUB_ENV"

      - name: List available signing identities codesigning
        run: security find-identity -v -p codesigning

      - name: List available signing identities macappstore
        run: security find-identity -v -p macappstore

      - name: Workaround for nx issue and dmg licence issue
        run: npm install @nx/nx-darwin-arm64 dmg-license

      - name: Install npm Packages
        #  if: steps.npm-cache.outputs.cache-hit != 'true'
        run: npm i

      - run: 'echo "$PROVISION_PROFILE" | base64 --decode > embedded.provisionprofile'
        shell: bash
        env:
          PROVISION_PROFILE: ${{secrets.mas_provision_profile}}

      - name: Verify provisioning profile certificate
        run: |
          security cms -D -i embedded.provisionprofile > /tmp/profile.plist
          python3 << 'EOF'
          import plistlib
          import subprocess
          import hashlib

          with open('/tmp/profile.plist', 'rb') as f:
              plist_data = plistlib.load(f)

          cert_data = plist_data['DeveloperCertificates'][0]
          fingerprint = hashlib.sha1(cert_data).hexdigest().upper()

          # Write to temp file and extract subject
          with open('/tmp/cert.der', 'wb') as f:
              f.write(cert_data)

          result = subprocess.run(['openssl', 'x509', '-in', '/tmp/cert.der', '-inform', 'DER',
                                  '-noout', '-subject', '-fingerprint', '-sha1'],
                                 capture_output=True, text=True)

          print("=== PROVISIONING PROFILE CERTIFICATE ===")
          print(result.stdout)
          print(f"SHA1 Fingerprint: {fingerprint}")
          print("========================================")
          EOF

      - run: npm run env # Generate env.generated.ts

      #      - name: Lint
      #        run: npm run lint
      #
      #      - name: Test Unit
      #        run: npm run test

      #      - name: Test E2E
      #        run: npm run e2e

      - name: Build Frontend & Electron
        run: npm run build

      - name: Build Electron app
        run: npm run dist:mac:mas:buildOnly

      - name: Verify code signing used in built app
        run: |
          echo "=== Checking code signature of main executable ==="
          codesign -dv --verbose=4 ".tmp/app-builds/mas-universal/Super Productivity.app" 2>&1 | grep -E "Authority|Identifier|Signature"
          echo ""
          echo "=== Checking provisioning profile embedded in app ==="
          security cms -D -i ".tmp/app-builds/mas-universal/Super Productivity.app/Contents/embedded.provisionprofile" > /tmp/built-profile.plist
          python3 << 'EOF'
          import plistlib
          import subprocess
          import hashlib

          with open('/tmp/built-profile.plist', 'rb') as f:
              plist_data = plistlib.load(f)

          cert_data = plist_data['DeveloperCertificates'][0]
          fingerprint = hashlib.sha1(cert_data).hexdigest().upper()

          print(f"Provisioning profile expects certificate: {fingerprint}")
          EOF

      - run: ls .tmp/app-builds
        shell: bash

      - name: Set up Ruby and fastlane
        # Pinned by SHA per repo policy. ruby-version is required: with no
        # .ruby-version file in the repo the action errors out rather than
        # using system Ruby. bundler-cache runs `bundle install` and caches the
        # ~210-gem fastlane tree so it isn't reinstalled each run.
        uses: ruby/setup-ruby@d45b1a4e94b71acab930e56e79c6aa188764e7f9 # v1.316.0
        with:
          ruby-version: '3.3'
          bundler-cache: true

      - name: Prepare App Store release notes
        run: node tools/prepare-appstore-release-notes.js

      # Upload the MAS .pkg to App Store Connect and (for final release tags)
      # submit it for review with automatic release on approval. Pre-release
      # tags (any tag containing "-", e.g. -rc.0/-beta.1) and manual runs only
      # upload the build. The "-" check is case-insensitive by construction,
      # unlike contains(...,'RC'); the repo's RC tags are mostly lowercase.
      - name: Upload to App Store Connect and submit for review
        env:
          ASC_KEY_ID: ${{ secrets.mac_api_key_id }}
          ASC_ISSUER_ID: ${{ secrets.mac_api_key_issuer_id }}
          ASC_KEY_CONTENT: ${{ secrets.mac_api_key }}
          SUBMIT_FOR_REVIEW: ${{ startsWith(github.ref, 'refs/tags/v') && !contains(github.ref, '-') }}
        run: |
          set -euo pipefail
          shopt -s nullglob
          pkgs=(.tmp/app-builds/mas-universal/super*.pkg)
          if [ ${#pkgs[@]} -ne 1 ]; then
            echo "Expected exactly 1 .pkg, found ${#pkgs[@]}: ${pkgs[*]:-none}"
            exit 1
          fi
          export PKG_PATH="${pkgs[0]}"
          echo "Submitting $PKG_PATH (submit_for_review=$SUBMIT_FOR_REVIEW)"
          bundle exec fastlane mac release
