name: macOS Release Build on: workflow_call: inputs: build-version: description: 'The version to build' required: true type: string release-branch: description: 'The branch to build' required: true type: string jobs: mac-build: name: Unify macOS (Universal) runs-on: 'macos-26' strategy: fail-fast: false steps: - name: Checkout repository uses: actions/checkout@v4 with: submodules: recursive token: ${{ secrets.DEPLOY_KEY }} - name: Setup Node.js uses: actions/setup-node@v4 with: node-version-file: '.nvmrc' - name: Setup Python uses: actions/setup-python@v5 # note: This will use the version defined in '.python-version' by default - name: Setup Git run: | git config --global user.email "mauro-balades@users.noreply.github.com" git config --global user.name "mauro-balades" - name: Install system dependencies run: | brew update brew install cairo gnu-tar mercurial sudo pip install setuptools brew uninstall --ignore-dependencies python3.12 -f export PATH="$(python3 -m site --user-base)/bin":$PATH python3 -m pip install --user mercurial rm '/usr/local/bin/2to3-3.11' '/usr/local/bin/2to3-3.12' '/usr/local/bin/2to3' rm '/usr/local/bin/idle3.11' '/usr/local/bin/idle3.12' '/usr/local/bin/idle3' rm '/usr/local/bin/pydoc3.11' '/usr/local/bin/pydoc3.12' '/usr/local/bin/pydoc3' rm '/usr/local/bin/python3.11' '/usr/local/bin/python3.12' '/usr/local/bin/python3' rm '/usr/local/bin/python3.11-config' '/usr/local/bin/python3.12-config' '/usr/local/bin/python3-config' brew install watchman cargo install apple-codesign - name: Force usage of gnu-tar run: | echo 'export PATH="/usr/local/opt/gnu-tar/libexec/gnubin:$PATH"' >> ~/.bash_profile echo 'export PATH="/usr/local/opt/gnu-tar/libexec/gnubin:$PATH"' >> ~/.zsh source ~/.bash_profile - name: Install dependencies run: | npm ci - name: Load surfer CI setup run: npm run surfer -- ci --brand ${{ inputs.release-branch }} --display-version ${{ inputs.build-version }} - name: Download Firefox source and dependencies run: npm run download - name: Bootstrap run: | cd engine export SURFER_PLATFORM="darwin" export PATH="$(python3 -m site --user-base)/bin":$PATH ./mach --no-interactive bootstrap --application-choice browser --no-system-changes || true cd .. - name: Import run: npm run import - name: Populate mozconfig env: SURFER_MOZCONFIG_ONLY: true run: | npm run build cd engine ./mach configure - name: Download x86_64 DMG from artifacts uses: actions/download-artifact@v4 with: name: zen-x86_64-apple-darwin-dist.dmg - name: Download aarch64 DMG from artifacts uses: actions/download-artifact@v4 with: name: zen-aarch64-apple-darwin-dist.dmg - name: Remove any existing .app folders run: | set -x cd engine rm -rf "./obj-x86_64-apple-darwin/" || true rm -rf "./obj-aarch64-apple-darwin/" || true - name: Extract .app from dmg run: | set -ex cd engine echo "Extracting x86_64 .app from dmg" mkdir -p ./obj-x86_64-apple-darwin/dist mkdir -p ./obj-aarch64-apple-darwin/dist ./mach python -m mozbuild.action.unpack_dmg \ ../zen-x86_64-apple-darwin-dist.dmg \ ./obj-x86_64-apple-darwin/dist echo "Extracting aarch64 .app from dmg" ./mach python -m mozbuild.action.unpack_dmg \ ../zen-aarch64-apple-darwin-dist.dmg \ ./obj-aarch64-apple-darwin/dist - name: Find first .app folder name run: | cd engine/obj-x86_64-apple-darwin/dist export APP_NAME=${{ inputs.release-branch == 'twilight' && 'Twilight' || 'Zen' }} echo "APP_NAME=$APP_NAME" >> $GITHUB_ENV echo "APP_NAME=$APP_NAME" - name: List .app folders run: | ls engine/ echo "--------------------" cd engine/obj-x86_64-apple-darwin/dist find . -maxdepth 1 -name "*.app" -type d cd ../.. - name: create .p12 for codesign 🖊️ run: | cd engine echo "${{ secrets.macOS_CERTIFICATES_P12_For_App_BASE64 }}" > cert.txt base64 --decode -i cert.txt -o zenCert.p12 echo "${{ secrets.macOS_CERTIFICATES_P12_PASSWORD }}" > zenpCertPassword.passwd - name: Remove certificate sensitive information run: | rm engine/cert.txt || true - name: Import provisioning profile for .app run: | echo "${{ secrets.macOS_PROVISIONING_PROFILE }}" | base64 --decode > ./engine/Zen_Browser.provisionprofile ls -la - name: Unify architectures run: | cd engine ./mach python "./toolkit/mozapps/installer/unify.py" "./obj-x86_64-apple-darwin/dist/${{ env.APP_NAME }}.app" "./obj-aarch64-apple-darwin/dist/${{ env.APP_NAME }}.app" echo "Merged aaarch64 into x86_64!" - name: Import APPLE DEVELOPER ID CERTIFICATE for .app uses: Apple-Actions/import-codesign-certs@v3 with: p12-file-base64: ${{ secrets.macOS_CERTIFICATES_P12_For_App_BASE64 }} p12-password: ${{ secrets.macOS_CERTIFICATES_P12_PASSWORD }} - name: Copy provisioning profile for .app (embedded in .app) run: | cd engine echo "Copying provisioning profile for .app on both architectures (${{ env.APP_NAME }})" cp ./Zen_Browser.provisionprofile "./embedded.provisionprofile" - name: Sign .app run: | cd engine # TODO: Change it to "production" once we figure out the issue with the webauth ./mach macos-sign -v -r -c "release" -e "production" -a "./obj-x86_64-apple-darwin/dist/${{ env.APP_NAME }}.app" --rcodesign-p12-file zenCert.p12 --rcodesign-p12-password-file zenpCertPassword.passwd - name: Create DMG run: | cd engine ./mach python -m mozbuild.action.make_dmg \ --volume-name "${{ env.APP_NAME }}" \ --background ./browser/branding/${{ inputs.release-branch }}/background.png \ --icon ./browser/branding/${{ inputs.release-branch }}/firefox.icns \ --dsstore ./browser/branding/${{ inputs.release-branch }}/dsstore \ ./obj-x86_64-apple-darwin/dist/ ../zen-macOS-universal-temp.dmg - name: Remove sensitive information run: | rm -f ./engine/Zen_Browser.provisionprofile - name: Sign .dmg run: | set -ex hdiutil convert zen-macOS-universal-temp.dmg -format UDZO -imagekey zlib-level=9 -o zen.macos-universal.dmg codesign -s "${{ secrets.macOS_AppleDeveloperId }}" zen.macos-universal.dmg xcrun notarytool submit "zen.macos-universal.dmg" \ --apple-id "${{ secrets.macOS_AppleAccountId }}" \ --team-id "${{ secrets.macOS_AppleDeveloperIdTeamId }}" \ --password "${{ secrets.macOS_AppleDeveloperIdPassword }}" \ --no-s3-acceleration \ --wait xcrun stapler staple "zen.macos-universal.dmg" - name: Download host mar uses: actions/download-artifact@v4 with: name: zen-macos-host-mar - name: Upload build artifact uses: actions/upload-artifact@v4 with: retention-days: 5 name: zen.macos-universal.dmg path: ./zen.macos-universal.dmg - name: Download platform.ini uses: actions/download-artifact@v4 with: name: platform.ini - name: Package for mar env: JUST_MAR: true run: | # we don't need it anymore set -ex rm -rf ./engine/obj-aarch64-apple-darwin mkdir -p ./engine/obj-x86_64-apple-darwin/dist/bin mv ./platform.ini ./engine/obj-x86_64-apple-darwin/dist/bin/platform.ini export SURFER_PLATFORM="darwin" export ZEN_RELEASE=1 # full path to zen-macos-host-mar export MAR=$(pwd)/zen-macos-host-mar chmod +x $MAR echo "MAR=$MAR" npm run package -- --verbose mv ./dist/output.mar ./macos.mar - name: Upload build artifact (.mar) uses: actions/upload-artifact@v4 with: retention-days: 5 name: macos.mar path: ./macos.mar - name: Upload build artifact (update manifests) uses: actions/upload-artifact@v4 with: retention-days: 5 name: macos_update_manifest path: ./dist/update