name: Build Desktop on: pull_request: types: [opened, synchronize] branches-ignore: - 'l10n_master' - 'cf-pages' paths: - 'apps/desktop/**' - 'libs/**' - '*' - '!*.md' - '!*.txt' - '.github/workflows/build-desktop.yml' push: branches: - 'main' - 'rc' - 'hotfix-rc-desktop' paths: - 'apps/desktop/**' - 'libs/**' - '*' - '!*.md' - '!*.txt' - '.github/workflows/build-desktop.yml' workflow_call: inputs: {} workflow_dispatch: inputs: sdk_branch: description: "Custom SDK branch" required: false type: string defaults: run: shell: bash jobs: electron-verify: name: Verify Electron Version runs-on: ubuntu-22.04 steps: - name: Check out repo uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: ref: ${{ github.event.pull_request.head.sha }} - name: Verify run: | PACKAGE_VERSION=$(jq -r .devDependencies.electron package.json) ELECTRON_BUILDER_VERSION=$(jq -r .electronVersion ./apps/desktop/electron-builder.json) if [[ "$PACKAGE_VERSION" == "$ELECTRON_BUILDER_VERSION" ]]; then echo "Versions matches" else echo "Version missmatch, package.json: $PACKAGE_VERSION, electron-builder.json: $ELECTRON_BUILDER_VERSION" exit 1 fi setup: name: Setup runs-on: ubuntu-22.04 outputs: package_version: ${{ steps.retrieve-version.outputs.package_version }} release_channel: ${{ steps.release-channel.outputs.channel }} build_number: ${{ steps.increment-version.outputs.build_number }} rc_branch_exists: ${{ steps.branch-check.outputs.rc_branch_exists }} hotfix_branch_exists: ${{ steps.branch-check.outputs.hotfix_branch_exists }} node_version: ${{ steps.retrieve-node-version.outputs.node_version }} has_secrets: ${{ steps.check-secrets.outputs.has_secrets }} defaults: run: working-directory: apps/desktop steps: - name: Check out repo uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: ref: ${{ github.event.pull_request.head.sha }} - name: Get Package Version id: retrieve-version run: | PKG_VERSION=$(jq -r .version src/package.json) echo "package_version=$PKG_VERSION" >> $GITHUB_OUTPUT - name: Increment Version id: increment-version run: | BUILD_NUMBER=$(expr 3000 + $GITHUB_RUN_NUMBER) echo "Setting build number to $BUILD_NUMBER" echo "build_number=$BUILD_NUMBER" >> $GITHUB_OUTPUT - name: Get Version Channel id: release-channel run: | case "${{ steps.retrieve-version.outputs.package_version }}" in *"alpha"*) echo "channel=alpha" >> $GITHUB_OUTPUT echo "[!] We do not yet support 'alpha'" exit 1 ;; *"beta"*) echo "channel=beta" >> $GITHUB_OUTPUT ;; *) echo "channel=latest" >> $GITHUB_OUTPUT ;; esac - name: Check if special branches exist id: branch-check run: | if [[ $(git ls-remote --heads origin rc) ]]; then echo "rc_branch_exists=1" >> $GITHUB_OUTPUT else echo "rc_branch_exists=0" >> $GITHUB_OUTPUT fi if [[ $(git ls-remote --heads origin hotfix-rc-desktop) ]]; then echo "hotfix_branch_exists=1" >> $GITHUB_OUTPUT else echo "hotfix_branch_exists=0" >> $GITHUB_OUTPUT fi - name: Get Node Version id: retrieve-node-version working-directory: ./ run: | NODE_NVMRC=$(cat .nvmrc) NODE_VERSION=${NODE_NVMRC/v/''} echo "node_version=$NODE_VERSION" >> $GITHUB_OUTPUT - name: Check secrets id: check-secrets env: AZURE_KV_CI_SERVICE_PRINCIPAL: ${{ secrets.AZURE_KV_CI_SERVICE_PRINCIPAL }} run: | has_secrets=${{ secrets.AZURE_KV_CI_SERVICE_PRINCIPAL != '' }} echo "has_secrets=$has_secrets" >> $GITHUB_OUTPUT linux: name: Linux Build # Note, before updating the ubuntu version of the workflow, ensure the snap base image # is equal or greater than the new version. Otherwise there might be GLIBC version issues. # The snap base for desktop is defined in `apps/desktop/electron-builder.json` # We are currently running on 20.04 until the Ubuntu 24.04 release is available, as moving # to 22.04 now breaks users who are on 20.04 due to mismatched GLIBC versions. runs-on: ubuntu-20.04 needs: setup env: _PACKAGE_VERSION: ${{ needs.setup.outputs.package_version }} _NODE_VERSION: ${{ needs.setup.outputs.node_version }} NODE_OPTIONS: --max_old_space_size=4096 defaults: run: working-directory: apps/desktop steps: - name: Check out repo uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: ref: ${{ github.event.pull_request.head.sha }} - name: Set up Node uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0 with: cache: 'npm' cache-dependency-path: '**/package-lock.json' node-version: ${{ env._NODE_VERSION }} - name: Set up environment run: | sudo apt-get update sudo apt-get -y install pkg-config libxss-dev rpm musl-dev musl-tools flatpak flatpak-builder - name: Set up Snap run: sudo snap install snapcraft --classic - name: Print environment run: | node --version npm --version snap --version snapcraft --version || echo 'snapcraft unavailable' - name: Install Node dependencies run: npm ci working-directory: ./ - name: Download SDK Artifacts if: ${{ inputs.sdk_branch != '' }} uses: bitwarden/gh-actions/download-artifacts@main with: github_token: ${{secrets.GITHUB_TOKEN}} workflow: build-wasm-internal.yml workflow_conclusion: success branch: ${{ inputs.sdk_branch }} artifacts: sdk-internal repo: bitwarden/sdk-internal path: ../sdk-internal if_no_artifact_found: fail - name: Override SDK if: ${{ inputs.sdk_branch != '' }} working-directory: ./ run: | ls -l ../ npm link ../sdk-internal - name: Cache Native Module uses: actions/cache@6849a6489940f00c2f30c0fb92c6274307ccb58a # v4.1.2 id: cache with: path: | apps/desktop/desktop_native/napi/*.node apps/desktop/desktop_native/dist/* ${{ env.RUNNER_TEMP }}/.cargo/registry ${{ env.RUNNER_TEMP }}/.cargo/git key: rust-${{ runner.os }}-${{ hashFiles('apps/desktop/desktop_native/**/*') }} - name: Build Native Module if: steps.cache.outputs.cache-hit != 'true' working-directory: apps/desktop/desktop_native env: PKG_CONFIG_ALLOW_CROSS: true PKG_CONFIG_ALL_STATIC: true TARGET: musl run: | rustup target add x86_64-unknown-linux-musl node build.js cross-platform - name: Build application run: npm run dist:lin - name: Upload .deb artifact uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3 with: name: Bitwarden-${{ env._PACKAGE_VERSION }}-amd64.deb path: apps/desktop/dist/Bitwarden-${{ env._PACKAGE_VERSION }}-amd64.deb if-no-files-found: error - name: Upload .rpm artifact uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3 with: name: Bitwarden-${{ env._PACKAGE_VERSION }}-x86_64.rpm path: apps/desktop/dist/Bitwarden-${{ env._PACKAGE_VERSION }}-x86_64.rpm if-no-files-found: error - name: Upload .freebsd artifact uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3 with: name: Bitwarden-${{ env._PACKAGE_VERSION }}-x64.freebsd path: apps/desktop/dist/Bitwarden-${{ env._PACKAGE_VERSION }}-x64.freebsd if-no-files-found: error - name: Upload .snap artifact uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3 with: name: bitwarden_${{ env._PACKAGE_VERSION }}_amd64.snap path: apps/desktop/dist/bitwarden_${{ env._PACKAGE_VERSION }}_amd64.snap if-no-files-found: error - name: Upload .AppImage artifact uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3 with: name: Bitwarden-${{ env._PACKAGE_VERSION }}-x86_64.AppImage path: apps/desktop/dist/Bitwarden-${{ env._PACKAGE_VERSION }}-x86_64.AppImage if-no-files-found: error - name: Upload auto-update artifact uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3 with: name: ${{ needs.setup.outputs.release_channel }}-linux.yml path: apps/desktop/dist/${{ needs.setup.outputs.release_channel }}-linux.yml if-no-files-found: error - name: Build flatpak working-directory: apps/desktop run: | sudo flatpak remote-add --if-not-exists flathub https://flathub.org/repo/flathub.flatpakrepo sudo npm run pack:lin:flatpak - name: Upload flatpak artifact uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3 with: name: com.bitwarden.desktop.flatpak path: apps/desktop/dist/com.bitwarden.desktop.flatpak if-no-files-found: error windows: name: Windows Build runs-on: windows-2022 needs: - setup defaults: run: shell: pwsh working-directory: apps/desktop env: _PACKAGE_VERSION: ${{ needs.setup.outputs.package_version }} _NODE_VERSION: ${{ needs.setup.outputs.node_version }} NODE_OPTIONS: --max_old_space_size=4096 steps: - name: Check out repo uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: ref: ${{ github.event.pull_request.head.sha }} - name: Set up Node uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0 with: cache: 'npm' cache-dependency-path: '**/package-lock.json' node-version: ${{ env._NODE_VERSION }} - name: Install AST run: dotnet tool install --global AzureSignTool --version 4.0.1 - name: Set up environmentF run: choco install checksum --no-progress - name: Rust shell: pwsh run: | rustup target install i686-pc-windows-msvc rustup target install aarch64-pc-windows-msvc - name: Print environment run: | node --version npm --version choco --version rustup show - name: Login to Azure if: ${{ needs.setup.outputs.has_secrets == 'true' }} uses: Azure/login@e15b166166a8746d1a47596803bd8c1b595455cf # v1.6.0 with: creds: ${{ secrets.AZURE_KV_CI_SERVICE_PRINCIPAL }} - name: Retrieve secrets id: retrieve-secrets if: ${{ needs.setup.outputs.has_secrets == 'true' }} uses: bitwarden/gh-actions/get-keyvault-secrets@main with: keyvault: "bitwarden-ci" secrets: "code-signing-vault-url, code-signing-client-id, code-signing-tenant-id, code-signing-client-secret, code-signing-cert-name" - name: Install Node dependencies run: npm ci working-directory: ./ - name: Download SDK Artifacts if: ${{ inputs.sdk_branch != '' && needs.setup.outputs.has_secrets == 'true' }} uses: bitwarden/gh-actions/download-artifacts@main with: github_token: ${{secrets.GITHUB_TOKEN}} workflow: build-wasm-internal.yml workflow_conclusion: success branch: ${{ inputs.sdk_branch }} artifacts: sdk-internal repo: bitwarden/sdk-internal path: ../sdk-internal if_no_artifact_found: fail - name: Override SDK if: ${{ inputs.sdk_branch != '' && needs.setup.outputs.has_secrets == 'true' }} working-directory: ./ run: | ls -l ../ npm link ../sdk-internal - name: Cache Native Module uses: actions/cache@6849a6489940f00c2f30c0fb92c6274307ccb58a # v4.1.2 id: cache with: path: | apps/desktop/desktop_native/napi/*.node apps/desktop/desktop_native/dist/* key: rust-${{ runner.os }}-${{ hashFiles('apps/desktop/desktop_native/**/*') }} - name: Build Native Module if: steps.cache.outputs.cache-hit != 'true' working-directory: apps/desktop/desktop_native run: node build.js cross-platform - name: Build run: | npm run build - name: Pack if: ${{ needs.setup.outputs.has_secrets == 'false' }} run: | npm run pack:win - name: Pack & Sign (dev) if: ${{ needs.setup.outputs.has_secrets == 'true' }} env: ELECTRON_BUILDER_SIGN: 1 SIGNING_VAULT_URL: ${{ steps.retrieve-secrets.outputs.code-signing-vault-url }} SIGNING_CLIENT_ID: ${{ steps.retrieve-secrets.outputs.code-signing-client-id }} SIGNING_TENANT_ID: ${{ steps.retrieve-secrets.outputs.code-signing-tenant-id }} SIGNING_CLIENT_SECRET: ${{ steps.retrieve-secrets.outputs.code-signing-client-secret }} SIGNING_CERT_NAME: ${{ steps.retrieve-secrets.outputs.code-signing-cert-name }} run: | npm run pack:win - name: Rename appx files for store if: ${{ needs.setup.outputs.has_secrets == 'true' }} run: | Copy-Item "./dist/Bitwarden-${{ env._PACKAGE_VERSION }}-ia32.appx" ` -Destination "./dist/Bitwarden-${{ env._PACKAGE_VERSION }}-ia32-store.appx" Copy-Item "./dist/Bitwarden-${{ env._PACKAGE_VERSION }}-x64.appx" ` -Destination "./dist/Bitwarden-${{ env._PACKAGE_VERSION }}-x64-store.appx" Copy-Item "./dist/Bitwarden-${{ env._PACKAGE_VERSION }}-arm64.appx" ` -Destination "./dist/Bitwarden-${{ env._PACKAGE_VERSION }}-arm64-store.appx" - name: Package for Chocolatey if: ${{ needs.setup.outputs.has_secrets == 'true' }} run: | Copy-Item -Path ./stores/chocolatey -Destination ./dist/chocolatey -Recurse Copy-Item -Path ./dist/nsis-web/Bitwarden-Installer-${{ env._PACKAGE_VERSION }}.exe ` -Destination ./dist/chocolatey $checksum = checksum -t sha256 ./dist/chocolatey/Bitwarden-Installer-${{ env._PACKAGE_VERSION }}.exe $chocoInstall = "./dist/chocolatey/tools/chocolateyinstall.ps1" (Get-Content $chocoInstall).replace('__version__', "$env:_PACKAGE_VERSION").replace('__checksum__', $checksum) | Set-Content $chocoInstall choco pack ./dist/chocolatey/bitwarden.nuspec --version "$env:_PACKAGE_VERSION" --out ./dist/chocolatey - name: Fix NSIS artifact names for auto-updater if: ${{ needs.setup.outputs.has_secrets == 'true' }} run: | Rename-Item -Path .\dist\nsis-web\Bitwarden-${{ env._PACKAGE_VERSION }}-ia32.nsis.7z ` -NewName bitwarden-${{ env._PACKAGE_VERSION }}-ia32.nsis.7z Rename-Item -Path .\dist\nsis-web\Bitwarden-${{ env._PACKAGE_VERSION }}-x64.nsis.7z ` -NewName bitwarden-${{ env._PACKAGE_VERSION }}-x64.nsis.7z Rename-Item -Path .\dist\nsis-web\Bitwarden-${{ env._PACKAGE_VERSION }}-arm64.nsis.7z ` -NewName bitwarden-${{ env._PACKAGE_VERSION }}-arm64.nsis.7z - name: Upload portable exe artifact uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3 with: name: Bitwarden-Portable-${{ env._PACKAGE_VERSION }}.exe path: apps/desktop/dist/Bitwarden-Portable-${{ env._PACKAGE_VERSION }}.exe if-no-files-found: error - name: Upload installer exe artifact if: ${{ needs.setup.outputs.has_secrets == 'true' }} uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3 with: name: Bitwarden-Installer-${{ env._PACKAGE_VERSION }}.exe path: apps/desktop/dist/nsis-web/Bitwarden-Installer-${{ env._PACKAGE_VERSION }}.exe if-no-files-found: error - name: Upload appx ia32 artifact if: ${{ needs.setup.outputs.has_secrets == 'true' }} uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3 with: name: Bitwarden-${{ env._PACKAGE_VERSION }}-ia32.appx path: apps/desktop/dist/Bitwarden-${{ env._PACKAGE_VERSION }}-ia32.appx if-no-files-found: error - name: Upload store appx ia32 artifact if: ${{ needs.setup.outputs.has_secrets == 'true' }} uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3 with: name: Bitwarden-${{ env._PACKAGE_VERSION }}-ia32-store.appx path: apps/desktop/dist/Bitwarden-${{ env._PACKAGE_VERSION }}-ia32-store.appx if-no-files-found: error - name: Upload NSIS ia32 artifact if: ${{ needs.setup.outputs.has_secrets == 'true' }} uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3 with: name: bitwarden-${{ env._PACKAGE_VERSION }}-ia32.nsis.7z path: apps/desktop/dist/nsis-web/bitwarden-${{ env._PACKAGE_VERSION }}-ia32.nsis.7z if-no-files-found: error - name: Upload appx x64 artifact if: ${{ needs.setup.outputs.has_secrets == 'true' }} uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3 with: name: Bitwarden-${{ env._PACKAGE_VERSION }}-x64.appx path: apps/desktop/dist/Bitwarden-${{ env._PACKAGE_VERSION }}-x64.appx if-no-files-found: error - name: Upload store appx x64 artifact if: ${{ needs.setup.outputs.has_secrets == 'true' }} uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3 with: name: Bitwarden-${{ env._PACKAGE_VERSION }}-x64-store.appx path: apps/desktop/dist/Bitwarden-${{ env._PACKAGE_VERSION }}-x64-store.appx if-no-files-found: error - name: Upload NSIS x64 artifact if: ${{ needs.setup.outputs.has_secrets == 'true' }} uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3 with: name: bitwarden-${{ env._PACKAGE_VERSION }}-x64.nsis.7z path: apps/desktop/dist/nsis-web/bitwarden-${{ env._PACKAGE_VERSION }}-x64.nsis.7z if-no-files-found: error - name: Upload appx ARM64 artifact if: ${{ needs.setup.outputs.has_secrets == 'true' }} uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3 with: name: Bitwarden-${{ env._PACKAGE_VERSION }}-arm64.appx path: apps/desktop/dist/Bitwarden-${{ env._PACKAGE_VERSION }}-arm64.appx if-no-files-found: error - name: Upload store appx ARM64 artifact if: ${{ needs.setup.outputs.has_secrets == 'true' }} uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3 with: name: Bitwarden-${{ env._PACKAGE_VERSION }}-arm64-store.appx path: apps/desktop/dist/Bitwarden-${{ env._PACKAGE_VERSION }}-arm64-store.appx if-no-files-found: error - name: Upload NSIS ARM64 artifact if: ${{ needs.setup.outputs.has_secrets == 'true' }} uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3 with: name: bitwarden-${{ env._PACKAGE_VERSION }}-arm64.nsis.7z path: apps/desktop/dist/nsis-web/bitwarden-${{ env._PACKAGE_VERSION }}-arm64.nsis.7z if-no-files-found: error - name: Upload nupkg artifact if: ${{ needs.setup.outputs.has_secrets == 'true' }} uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3 with: name: bitwarden.${{ env._PACKAGE_VERSION }}.nupkg path: apps/desktop/dist/chocolatey/bitwarden.${{ env._PACKAGE_VERSION }}.nupkg if-no-files-found: error - name: Upload auto-update artifact if: ${{ needs.setup.outputs.has_secrets == 'true' }} uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3 with: name: ${{ needs.setup.outputs.release_channel }}.yml path: apps/desktop/dist/nsis-web/${{ needs.setup.outputs.release_channel }}.yml if-no-files-found: error macos-build: name: MacOS Build runs-on: macos-13 needs: - setup env: _PACKAGE_VERSION: ${{ needs.setup.outputs.package_version }} _NODE_VERSION: ${{ needs.setup.outputs.node_version }} NODE_OPTIONS: --max_old_space_size=4096 defaults: run: working-directory: apps/desktop steps: - name: Check out repo uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: ref: ${{ github.event.pull_request.head.sha }} - name: Set up Node uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0 with: cache: 'npm' cache-dependency-path: '**/package-lock.json' node-version: ${{ env._NODE_VERSION }} - name: Set up Node-gyp run: python3 -m pip install setuptools - name: Rust shell: pwsh run: rustup target install aarch64-apple-darwin - name: Print environment run: | node --version npm --version rustup show echo "GitHub ref: $GITHUB_REF" echo "GitHub event: $GITHUB_EVENT" - name: Cache Build id: build-cache uses: actions/cache@6849a6489940f00c2f30c0fb92c6274307ccb58a # v4.1.2 with: path: apps/desktop/build key: ${{ runner.os }}-${{ github.run_id }}-build - name: Cache Safari id: safari-cache uses: actions/cache@6849a6489940f00c2f30c0fb92c6274307ccb58a # v4.1.2 with: path: apps/browser/dist/Safari key: ${{ runner.os }}-${{ github.run_id }}-safari-extension - name: Login to Azure if: ${{ needs.setup.outputs.has_secrets == 'true' }} uses: Azure/login@e15b166166a8746d1a47596803bd8c1b595455cf # v1.6.0 with: creds: ${{ secrets.AZURE_KV_CI_SERVICE_PRINCIPAL }} - name: Download Provisioning Profiles secrets if: ${{ needs.setup.outputs.has_secrets == 'true' }} env: ACCOUNT_NAME: bitwardenci CONTAINER_NAME: profiles run: | mkdir -p $HOME/secrets az storage blob download --account-name $ACCOUNT_NAME --container-name $CONTAINER_NAME \ --name bitwarden_desktop_appstore.provisionprofile \ --file $HOME/secrets/bitwarden_desktop_appstore.provisionprofile \ --output none - name: Get certificates if: ${{ needs.setup.outputs.has_secrets == 'true' }} run: | mkdir -p $HOME/certificates az keyvault secret show --id https://bitwarden-ci.vault.azure.net/certificates/bitwarden-desktop-key | jq -r .value | base64 -d > $HOME/certificates/bitwarden-desktop-key.p12 az keyvault secret show --id https://bitwarden-ci.vault.azure.net/certificates/appstore-app-cert | jq -r .value | base64 -d > $HOME/certificates/appstore-app-cert.p12 az keyvault secret show --id https://bitwarden-ci.vault.azure.net/certificates/appstore-installer-cert | jq -r .value | base64 -d > $HOME/certificates/appstore-installer-cert.p12 az keyvault secret show --id https://bitwarden-ci.vault.azure.net/certificates/devid-app-cert | jq -r .value | base64 -d > $HOME/certificates/devid-app-cert.p12 az keyvault secret show --id https://bitwarden-ci.vault.azure.net/certificates/devid-installer-cert | jq -r .value | base64 -d > $HOME/certificates/devid-installer-cert.p12 az keyvault secret show --id https://bitwarden-ci.vault.azure.net/certificates/macdev-cert | jq -r .value | base64 -d > $HOME/certificates/macdev-cert.p12 - name: Set up keychain if: ${{ needs.setup.outputs.has_secrets == 'true' }} env: KEYCHAIN_PASSWORD: ${{ secrets.KEYCHAIN_PASSWORD }} run: | security create-keychain -p $KEYCHAIN_PASSWORD build.keychain security default-keychain -s build.keychain security unlock-keychain -p $KEYCHAIN_PASSWORD build.keychain security set-keychain-settings -lut 1200 build.keychain security import "$HOME/certificates/bitwarden-desktop-key.p12" -k build.keychain -P "" \ -T /usr/bin/codesign -T /usr/bin/security -T /usr/bin/productbuild security import "$HOME/certificates/devid-app-cert.p12" -k build.keychain -P "" \ -T /usr/bin/codesign -T /usr/bin/security -T /usr/bin/productbuild security import "$HOME/certificates/devid-installer-cert.p12" -k build.keychain -P "" \ -T /usr/bin/codesign -T /usr/bin/security -T /usr/bin/productbuild security import "$HOME/certificates/appstore-app-cert.p12" -k build.keychain -P "" \ -T /usr/bin/codesign -T /usr/bin/security -T /usr/bin/productbuild security import "$HOME/certificates/appstore-installer-cert.p12" -k build.keychain -P "" \ -T /usr/bin/codesign -T /usr/bin/security -T /usr/bin/productbuild security import "$HOME/certificates/macdev-cert.p12" -k build.keychain -P "" \ -T /usr/bin/codesign -T /usr/bin/security -T /usr/bin/productbuild security set-key-partition-list -S apple-tool:,apple:,codesign: -s -k $KEYCHAIN_PASSWORD build.keychain - name: Set up provisioning profiles if: ${{ needs.setup.outputs.has_secrets == 'true' }} run: | cp $HOME/secrets/bitwarden_desktop_appstore.provisionprofile \ $GITHUB_WORKSPACE/apps/desktop/bitwarden_desktop_appstore.provisionprofile - name: Increment version shell: pwsh env: BUILD_NUMBER: ${{ needs.setup.outputs.build_number }} run: | $package = Get-Content -Raw -Path electron-builder.json | ConvertFrom-Json $package | Add-Member -MemberType NoteProperty -Name buildVersion -Value "$env:BUILD_NUMBER" $package | ConvertTo-Json -Depth 32 | Set-Content -Path electron-builder.json "### MacOS build number: $env:BUILD_NUMBER" | Out-File -FilePath $env:GITHUB_STEP_SUMMARY -Append - name: Install Node dependencies run: npm ci working-directory: ./ - name: Download SDK Artifacts if: ${{ inputs.sdk_branch != '' && needs.setup.outputs.has_secrets == 'true' }} uses: bitwarden/gh-actions/download-artifacts@main with: github_token: ${{secrets.GITHUB_TOKEN}} workflow: build-wasm-internal.yml workflow_conclusion: success branch: ${{ inputs.sdk_branch }} artifacts: sdk-internal repo: bitwarden/sdk-internal path: ../sdk-internal if_no_artifact_found: fail - name: Override SDK if: ${{ inputs.sdk_branch != '' && needs.setup.outputs.has_secrets == 'true' }} working-directory: ./ run: | ls -l ../ npm link ../sdk-internal - name: Cache Native Module uses: actions/cache@6849a6489940f00c2f30c0fb92c6274307ccb58a # v4.1.2 id: cache with: path: | apps/desktop/desktop_native/napi/*.node apps/desktop/desktop_native/dist/* key: rust-${{ runner.os }}-${{ hashFiles('apps/desktop/desktop_native/**/*') }} - name: Build Native Module if: steps.cache.outputs.cache-hit != 'true' working-directory: apps/desktop/desktop_native run: node build.js cross-platform - name: Build application (dev) run: npm run build browser-build: name: Browser Build needs: setup if: ${{ needs.setup.outputs.has_secrets == 'true' }} uses: ./.github/workflows/build-browser.yml secrets: inherit macos-package-github: name: MacOS Package GitHub Release Assets runs-on: macos-13 if: ${{ needs.setup.outputs.has_secrets == 'true' }} needs: - browser-build - macos-build - setup env: _PACKAGE_VERSION: ${{ needs.setup.outputs.package_version }} _NODE_VERSION: ${{ needs.setup.outputs.node_version }} NODE_OPTIONS: --max_old_space_size=4096 defaults: run: working-directory: apps/desktop steps: - name: Check out repo uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: ref: ${{ github.event.pull_request.head.sha }} - name: Set up Node uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0 with: cache: 'npm' cache-dependency-path: '**/package-lock.json' node-version: ${{ env._NODE_VERSION }} - name: Set up Node-gyp run: python3 -m pip install setuptools - name: Rust shell: pwsh run: rustup target install aarch64-apple-darwin - name: Print environment run: | node --version npm --version rustup show echo "GitHub ref: $GITHUB_REF" echo "GitHub event: $GITHUB_EVENT" - name: Get Build Cache id: build-cache uses: actions/cache@6849a6489940f00c2f30c0fb92c6274307ccb58a # v4.1.2 with: path: apps/desktop/build key: ${{ runner.os }}-${{ github.run_id }}-build - name: Setup Safari Cache id: safari-cache uses: actions/cache@6849a6489940f00c2f30c0fb92c6274307ccb58a # v4.1.2 with: path: apps/browser/dist/Safari key: ${{ runner.os }}-${{ github.run_id }}-safari-extension - name: Login to Azure uses: Azure/login@e15b166166a8746d1a47596803bd8c1b595455cf # v1.6.0 with: creds: ${{ secrets.AZURE_KV_CI_SERVICE_PRINCIPAL }} - name: Download Provisioning Profiles secrets env: ACCOUNT_NAME: bitwardenci CONTAINER_NAME: profiles run: | mkdir -p $HOME/secrets az storage blob download --account-name $ACCOUNT_NAME --container-name $CONTAINER_NAME \ --name bitwarden_desktop_appstore.provisionprofile \ --file $HOME/secrets/bitwarden_desktop_appstore.provisionprofile \ --output none - name: Get certificates run: | mkdir -p $HOME/certificates az keyvault secret show --id https://bitwarden-ci.vault.azure.net/certificates/bitwarden-desktop-key | jq -r .value | base64 -d > $HOME/certificates/bitwarden-desktop-key.p12 az keyvault secret show --id https://bitwarden-ci.vault.azure.net/certificates/appstore-app-cert | jq -r .value | base64 -d > $HOME/certificates/appstore-app-cert.p12 az keyvault secret show --id https://bitwarden-ci.vault.azure.net/certificates/appstore-installer-cert | jq -r .value | base64 -d > $HOME/certificates/appstore-installer-cert.p12 az keyvault secret show --id https://bitwarden-ci.vault.azure.net/certificates/devid-app-cert | jq -r .value | base64 -d > $HOME/certificates/devid-app-cert.p12 az keyvault secret show --id https://bitwarden-ci.vault.azure.net/certificates/devid-installer-cert | jq -r .value | base64 -d > $HOME/certificates/devid-installer-cert.p12 az keyvault secret show --id https://bitwarden-ci.vault.azure.net/certificates/macdev-cert | jq -r .value | base64 -d > $HOME/certificates/macdev-cert.p12 - name: Set up keychain env: KEYCHAIN_PASSWORD: ${{ secrets.KEYCHAIN_PASSWORD }} run: | security create-keychain -p $KEYCHAIN_PASSWORD build.keychain security default-keychain -s build.keychain security unlock-keychain -p $KEYCHAIN_PASSWORD build.keychain security set-keychain-settings -lut 1200 build.keychain security import "$HOME/certificates/bitwarden-desktop-key.p12" -k build.keychain -P "" \ -T /usr/bin/codesign -T /usr/bin/security -T /usr/bin/productbuild security import "$HOME/certificates/devid-app-cert.p12" -k build.keychain -P "" \ -T /usr/bin/codesign -T /usr/bin/security -T /usr/bin/productbuild security import "$HOME/certificates/devid-installer-cert.p12" -k build.keychain -P "" \ -T /usr/bin/codesign -T /usr/bin/security -T /usr/bin/productbuild security import "$HOME/certificates/appstore-app-cert.p12" -k build.keychain -P "" \ -T /usr/bin/codesign -T /usr/bin/security -T /usr/bin/productbuild security import "$HOME/certificates/appstore-installer-cert.p12" -k build.keychain -P "" \ -T /usr/bin/codesign -T /usr/bin/security -T /usr/bin/productbuild security import "$HOME/certificates/macdev-cert.p12" -k build.keychain -P "" \ -T /usr/bin/codesign -T /usr/bin/security -T /usr/bin/productbuild security set-key-partition-list -S apple-tool:,apple:,codesign: -s -k $KEYCHAIN_PASSWORD build.keychain - name: Set up provisioning profiles run: | cp $HOME/secrets/bitwarden_desktop_appstore.provisionprofile \ $GITHUB_WORKSPACE/apps/desktop/bitwarden_desktop_appstore.provisionprofile - name: Increment version shell: pwsh env: BUILD_NUMBER: ${{ needs.setup.outputs.build_number }} run: | $package = Get-Content -Raw -Path electron-builder.json | ConvertFrom-Json $package | Add-Member -MemberType NoteProperty -Name buildVersion -Value "$env:BUILD_NUMBER" $package | ConvertTo-Json -Depth 32 | Set-Content -Path electron-builder.json Write-Output "### MacOS GitHub build number: $env:BUILD_NUMBER" - name: Install Node dependencies run: npm ci working-directory: ./ - name: Download SDK Artifacts if: ${{ inputs.sdk_branch != '' }} uses: bitwarden/gh-actions/download-artifacts@main with: github_token: ${{secrets.GITHUB_TOKEN}} workflow: build-wasm-internal.yml workflow_conclusion: success branch: ${{ inputs.sdk_branch }} artifacts: sdk-internal repo: bitwarden/sdk-internal path: ../sdk-internal if_no_artifact_found: fail - name: Override SDK if: ${{ inputs.sdk_branch != '' }} working-directory: ./ run: | ls -l ../ npm link ../sdk-internal - name: Cache Native Module uses: actions/cache@6849a6489940f00c2f30c0fb92c6274307ccb58a # v4.1.2 id: cache with: path: | apps/desktop/desktop_native/napi/*.node apps/desktop/desktop_native/dist/* key: rust-${{ runner.os }}-${{ hashFiles('apps/desktop/desktop_native/**/*') }} - name: Build Native Module if: steps.cache.outputs.cache-hit != 'true' working-directory: apps/desktop/desktop_native run: node build.js cross-platform - name: Build if: steps.build-cache.outputs.cache-hit != 'true' run: npm run build - name: Download Browser artifact uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8 with: path: ${{ github.workspace }}/browser-build-artifacts - name: Unzip Safari artifact run: | SAFARI_DIR=$(find $GITHUB_WORKSPACE/browser-build-artifacts -name 'dist-safari-*.zip') echo $SAFARI_DIR unzip $SAFARI_DIR/dist-safari.zip -d $GITHUB_WORKSPACE/browser-build-artifacts - name: Load Safari extension for .dmg run: | mkdir PlugIns cp -r $GITHUB_WORKSPACE/browser-build-artifacts/Safari/dmg/build/Release/safari.appex PlugIns/safari.appex - name: Set up private auth key run: | mkdir ~/private_keys cat << EOF > ~/private_keys/AuthKey_6TV9MKN3GP.p8 ${{ secrets.APP_STORE_CONNECT_AUTH_KEY }} EOF - name: Build application (dist) env: APP_STORE_CONNECT_TEAM_ISSUER: ${{ secrets.APP_STORE_CONNECT_TEAM_ISSUER }} APP_STORE_CONNECT_AUTH_KEY: 6TV9MKN3GP APP_STORE_CONNECT_AUTH_KEY_PATH: ~/private_keys/AuthKey_6TV9MKN3GP.p8 CSC_FOR_PULL_REQUEST: true run: npm run pack:mac - name: Upload .zip artifact uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3 with: name: Bitwarden-${{ env._PACKAGE_VERSION }}-universal-mac.zip path: apps/desktop/dist/Bitwarden-${{ env._PACKAGE_VERSION }}-universal-mac.zip if-no-files-found: error - name: Upload .dmg artifact uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3 with: name: Bitwarden-${{ env._PACKAGE_VERSION }}-universal.dmg path: apps/desktop/dist/Bitwarden-${{ env._PACKAGE_VERSION }}-universal.dmg if-no-files-found: error - name: Upload .dmg blockmap artifact uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3 with: name: Bitwarden-${{ env._PACKAGE_VERSION }}-universal.dmg.blockmap path: apps/desktop/dist/Bitwarden-${{ env._PACKAGE_VERSION }}-universal.dmg.blockmap if-no-files-found: error - name: Upload auto-update artifact uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3 with: name: ${{ needs.setup.outputs.release_channel }}-mac.yml path: apps/desktop/dist/${{ needs.setup.outputs.release_channel }}-mac.yml if-no-files-found: error macos-package-mas: name: MacOS Package Prod Release Asset runs-on: macos-13 if: ${{ needs.setup.outputs.has_secrets == 'true' }} needs: - browser-build - macos-build - setup env: _PACKAGE_VERSION: ${{ needs.setup.outputs.package_version }} _NODE_VERSION: ${{ needs.setup.outputs.node_version }} NODE_OPTIONS: --max_old_space_size=4096 defaults: run: working-directory: apps/desktop steps: - name: Check out repo uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: ref: ${{ github.event.pull_request.head.sha }} - name: Set up Node uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0 with: cache: 'npm' cache-dependency-path: '**/package-lock.json' node-version: ${{ env._NODE_VERSION }} - name: Set up Node-gyp run: python3 -m pip install setuptools - name: Rust shell: pwsh run: rustup target install aarch64-apple-darwin - name: Print environment run: | node --version npm --version rustup show echo "GitHub ref: $GITHUB_REF" echo "GitHub event: $GITHUB_EVENT" - name: Get Build Cache id: build-cache uses: actions/cache@6849a6489940f00c2f30c0fb92c6274307ccb58a # v4.1.2 with: path: apps/desktop/build key: ${{ runner.os }}-${{ github.run_id }}-build - name: Setup Safari Cache id: safari-cache uses: actions/cache@6849a6489940f00c2f30c0fb92c6274307ccb58a # v4.1.2 with: path: apps/browser/dist/Safari key: ${{ runner.os }}-${{ github.run_id }}-safari-extension - name: Login to Azure uses: Azure/login@e15b166166a8746d1a47596803bd8c1b595455cf # v1.6.0 with: creds: ${{ secrets.AZURE_KV_CI_SERVICE_PRINCIPAL }} - name: Retrieve Slack secret id: retrieve-slack-secret uses: bitwarden/gh-actions/get-keyvault-secrets@main with: keyvault: bitwarden-ci secrets: "slack-bot-token" - name: Download Provisioning Profiles secrets env: ACCOUNT_NAME: bitwardenci CONTAINER_NAME: profiles run: | mkdir -p $HOME/secrets az storage blob download --account-name $ACCOUNT_NAME --container-name $CONTAINER_NAME \ --name bitwarden_desktop_appstore.provisionprofile \ --file $HOME/secrets/bitwarden_desktop_appstore.provisionprofile \ --output none - name: Get certificates run: | mkdir -p $HOME/certificates az keyvault secret show --id https://bitwarden-ci.vault.azure.net/certificates/bitwarden-desktop-key | jq -r .value | base64 -d > $HOME/certificates/bitwarden-desktop-key.p12 az keyvault secret show --id https://bitwarden-ci.vault.azure.net/certificates/appstore-app-cert | jq -r .value | base64 -d > $HOME/certificates/appstore-app-cert.p12 az keyvault secret show --id https://bitwarden-ci.vault.azure.net/certificates/appstore-installer-cert | jq -r .value | base64 -d > $HOME/certificates/appstore-installer-cert.p12 az keyvault secret show --id https://bitwarden-ci.vault.azure.net/certificates/devid-app-cert | jq -r .value | base64 -d > $HOME/certificates/devid-app-cert.p12 az keyvault secret show --id https://bitwarden-ci.vault.azure.net/certificates/devid-installer-cert | jq -r .value | base64 -d > $HOME/certificates/devid-installer-cert.p12 az keyvault secret show --id https://bitwarden-ci.vault.azure.net/certificates/macdev-cert | jq -r .value | base64 -d > $HOME/certificates/macdev-cert.p12 - name: Set up keychain env: KEYCHAIN_PASSWORD: ${{ secrets.KEYCHAIN_PASSWORD }} run: | security create-keychain -p $KEYCHAIN_PASSWORD build.keychain security default-keychain -s build.keychain security unlock-keychain -p $KEYCHAIN_PASSWORD build.keychain security set-keychain-settings -lut 1200 build.keychain security import "$HOME/certificates/bitwarden-desktop-key.p12" -k build.keychain -P "" \ -T /usr/bin/codesign -T /usr/bin/security -T /usr/bin/productbuild security import "$HOME/certificates/devid-app-cert.p12" -k build.keychain -P "" \ -T /usr/bin/codesign -T /usr/bin/security -T /usr/bin/productbuild security import "$HOME/certificates/devid-installer-cert.p12" -k build.keychain -P "" \ -T /usr/bin/codesign -T /usr/bin/security -T /usr/bin/productbuild security import "$HOME/certificates/appstore-app-cert.p12" -k build.keychain -P "" \ -T /usr/bin/codesign -T /usr/bin/security -T /usr/bin/productbuild security import "$HOME/certificates/appstore-installer-cert.p12" -k build.keychain -P "" \ -T /usr/bin/codesign -T /usr/bin/security -T /usr/bin/productbuild security import "$HOME/certificates/macdev-cert.p12" -k build.keychain -P "" \ -T /usr/bin/codesign -T /usr/bin/security -T /usr/bin/productbuild security set-key-partition-list -S apple-tool:,apple:,codesign: -s -k $KEYCHAIN_PASSWORD build.keychain - name: Set up provisioning profiles run: | cp $HOME/secrets/bitwarden_desktop_appstore.provisionprofile \ $GITHUB_WORKSPACE/apps/desktop/bitwarden_desktop_appstore.provisionprofile - name: Increment version shell: pwsh env: BUILD_NUMBER: ${{ needs.setup.outputs.build_number }} run: | $package = Get-Content -Raw -Path electron-builder.json | ConvertFrom-Json $package | Add-Member -MemberType NoteProperty -Name buildVersion -Value "$env:BUILD_NUMBER" $package | ConvertTo-Json -Depth 32 | Set-Content -Path electron-builder.json Write-Output "### MacOS App Store build number: $env:BUILD_NUMBER" - name: Install Node dependencies run: npm ci working-directory: ./ - name: Download SDK Artifacts if: ${{ inputs.sdk_branch != '' }} uses: bitwarden/gh-actions/download-artifacts@main with: github_token: ${{secrets.GITHUB_TOKEN}} workflow: build-wasm-internal.yml workflow_conclusion: success branch: ${{ inputs.sdk_branch }} artifacts: sdk-internal repo: bitwarden/sdk-internal path: ../sdk-internal if_no_artifact_found: fail - name: Override SDK if: ${{ inputs.sdk_branch != '' }} working-directory: ./ run: | ls -l ../ npm link ../sdk-internal - name: Cache Native Module uses: actions/cache@6849a6489940f00c2f30c0fb92c6274307ccb58a # v4.1.2 id: cache with: path: | apps/desktop/desktop_native/napi/*.node apps/desktop/desktop_native/dist/* key: rust-${{ runner.os }}-${{ hashFiles('apps/desktop/desktop_native/**/*') }} - name: Build Native Module if: steps.cache.outputs.cache-hit != 'true' working-directory: apps/desktop/desktop_native run: node build.js cross-platform - name: Build if: steps.build-cache.outputs.cache-hit != 'true' run: npm run build - name: Download Browser artifact uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8 with: path: ${{ github.workspace }}/browser-build-artifacts - name: Unzip Safari artifact run: | SAFARI_DIR=$(find $GITHUB_WORKSPACE/browser-build-artifacts -name 'dist-safari-*.zip') echo $SAFARI_DIR unzip $SAFARI_DIR/dist-safari.zip -d $GITHUB_WORKSPACE/browser-build-artifacts - name: Load Safari extension for App Store run: | mkdir PlugIns cp -r $GITHUB_WORKSPACE/browser-build-artifacts/Safari/mas/build/Release/safari.appex PlugIns/safari.appex - name: Set up private auth key run: | mkdir ~/private_keys cat << EOF > ~/private_keys/AuthKey_6TV9MKN3GP.p8 ${{ secrets.APP_STORE_CONNECT_AUTH_KEY }} EOF - name: Build application for App Store env: APP_STORE_CONNECT_TEAM_ISSUER: ${{ secrets.APP_STORE_CONNECT_TEAM_ISSUER }} APP_STORE_CONNECT_AUTH_KEY: 6TV9MKN3GP APP_STORE_CONNECT_AUTH_KEY_PATH: ~/private_keys/AuthKey_6TV9MKN3GP.p8 CSC_FOR_PULL_REQUEST: true run: npm run pack:mac:mas - name: Upload .pkg artifact uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3 with: name: Bitwarden-${{ env._PACKAGE_VERSION }}-universal.pkg path: apps/desktop/dist/mas-universal/Bitwarden-${{ env._PACKAGE_VERSION }}-universal.pkg if-no-files-found: error - name: Deploy to TestFlight id: testflight-deploy if: | github.event_name != 'pull_request_target' && (github.ref == 'refs/heads/main' || github.ref == 'refs/heads/rc' || github.ref == 'refs/heads/hotfix-rc-desktop') env: APP_STORE_CONNECT_TEAM_ISSUER: ${{ secrets.APP_STORE_CONNECT_TEAM_ISSUER }} APP_STORE_CONNECT_AUTH_KEY: 6TV9MKN3GP run: | xcrun altool \ --upload-app \ --type macos \ --file "$(find ./dist/mas-universal/Bitwarden*.pkg)" \ --apiKey $APP_STORE_CONNECT_AUTH_KEY \ --apiIssuer $APP_STORE_CONNECT_TEAM_ISSUER - name: Post message to a Slack channel id: slack-message if: | github.event_name != 'pull_request_target' && (github.ref == 'refs/heads/main' || github.ref == 'refs/heads/rc' || github.ref == 'refs/heads/hotfix-rc-desktop') uses: slackapi/slack-github-action@37ebaef184d7626c5f204ab8d3baff4262dd30f0 # v1.27.0 with: channel-id: C074F5UESQ0 payload: | { "blocks": [ { "type": "section", "text": { "type": "mrkdwn", "text": "Desktop client v${{ env._PACKAGE_VERSION }} <${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}|build ${{ env.BUILD_NUMBER }}> success on *${{ github.ref_name }}*" } } ] } env: SLACK_BOT_TOKEN: ${{ steps.retrieve-slack-secret.outputs.slack-bot-token }} BUILD_NUMBER: ${{ needs.setup.outputs.build_number }} macos-package-dev: name: MacOS Package Dev Release Asset runs-on: macos-13 if: ${{ needs.setup.outputs.has_secrets == 'true' }} needs: - browser-build - macos-build - setup env: _PACKAGE_VERSION: ${{ needs.setup.outputs.package_version }} _NODE_VERSION: ${{ needs.setup.outputs.node_version }} NODE_OPTIONS: --max_old_space_size=4096 defaults: run: working-directory: apps/desktop steps: - name: Check out repo uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: ref: ${{ github.event.pull_request.head.sha }} - name: Set up Node uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0 with: cache: 'npm' cache-dependency-path: '**/package-lock.json' node-version: ${{ env._NODE_VERSION }} - name: Set up Node-gyp run: python3 -m pip install setuptools - name: Print environment run: | node --version npm --version echo "GitHub ref: $GITHUB_REF" echo "GitHub event: $GITHUB_EVENT" - name: Get Build Cache id: build-cache uses: actions/cache@6849a6489940f00c2f30c0fb92c6274307ccb58a # v4.1.2 with: path: apps/desktop/build key: ${{ runner.os }}-${{ github.run_id }}-build - name: Setup Safari Cache id: safari-cache uses: actions/cache@6849a6489940f00c2f30c0fb92c6274307ccb58a # v4.1.2 with: path: apps/browser/dist/Safari key: ${{ runner.os }}-${{ github.run_id }}-safari-extension - name: Login to Azure uses: Azure/login@e15b166166a8746d1a47596803bd8c1b595455cf # v1.6.0 with: creds: ${{ secrets.AZURE_KV_CI_SERVICE_PRINCIPAL }} - name: Download Provisioning Profiles secrets env: ACCOUNT_NAME: bitwardenci CONTAINER_NAME: profiles run: | mkdir -p $HOME/secrets az storage blob download --account-name $ACCOUNT_NAME --container-name $CONTAINER_NAME \ --name bitwarden_desktop_appstore.provisionprofile \ --file $HOME/secrets/bitwarden_desktop_appstore.provisionprofile \ --output none - name: Get certificates run: | mkdir -p $HOME/certificates az keyvault secret show --id https://bitwarden-ci.vault.azure.net/certificates/bitwarden-desktop-key | jq -r .value | base64 -d > $HOME/certificates/bitwarden-desktop-key.p12 az keyvault secret show --id https://bitwarden-ci.vault.azure.net/certificates/appstore-app-cert | jq -r .value | base64 -d > $HOME/certificates/appstore-app-cert.p12 az keyvault secret show --id https://bitwarden-ci.vault.azure.net/certificates/appstore-installer-cert | jq -r .value | base64 -d > $HOME/certificates/appstore-installer-cert.p12 az keyvault secret show --id https://bitwarden-ci.vault.azure.net/certificates/devid-app-cert | jq -r .value | base64 -d > $HOME/certificates/devid-app-cert.p12 az keyvault secret show --id https://bitwarden-ci.vault.azure.net/certificates/devid-installer-cert | jq -r .value | base64 -d > $HOME/certificates/devid-installer-cert.p12 az keyvault secret show --id https://bitwarden-ci.vault.azure.net/certificates/macdev-cert | jq -r .value | base64 -d > $HOME/certificates/macdev-cert.p12 - name: Set up keychain env: KEYCHAIN_PASSWORD: ${{ secrets.KEYCHAIN_PASSWORD }} run: | security create-keychain -p $KEYCHAIN_PASSWORD build.keychain security default-keychain -s build.keychain security unlock-keychain -p $KEYCHAIN_PASSWORD build.keychain security set-keychain-settings -lut 1200 build.keychain security import "$HOME/certificates/bitwarden-desktop-key.p12" -k build.keychain -P "" \ -T /usr/bin/codesign -T /usr/bin/security -T /usr/bin/productbuild security import "$HOME/certificates/devid-app-cert.p12" -k build.keychain -P "" \ -T /usr/bin/codesign -T /usr/bin/security -T /usr/bin/productbuild security import "$HOME/certificates/devid-installer-cert.p12" -k build.keychain -P "" \ -T /usr/bin/codesign -T /usr/bin/security -T /usr/bin/productbuild security import "$HOME/certificates/appstore-app-cert.p12" -k build.keychain -P "" \ -T /usr/bin/codesign -T /usr/bin/security -T /usr/bin/productbuild security import "$HOME/certificates/appstore-installer-cert.p12" -k build.keychain -P "" \ -T /usr/bin/codesign -T /usr/bin/security -T /usr/bin/productbuild security import "$HOME/certificates/macdev-cert.p12" -k build.keychain -P "" \ -T /usr/bin/codesign -T /usr/bin/security -T /usr/bin/productbuild security set-key-partition-list -S apple-tool:,apple:,codesign: -s -k $KEYCHAIN_PASSWORD build.keychain - name: Set up provisioning profiles run: | cp $HOME/secrets/bitwarden_desktop_appstore.provisionprofile \ $GITHUB_WORKSPACE/apps/desktop/bitwarden_desktop_appstore.provisionprofile - name: Increment version shell: pwsh env: BUILD_NUMBER: ${{ needs.setup.outputs.build_number }} run: | $package = Get-Content -Raw -Path electron-builder.json | ConvertFrom-Json $package | Add-Member -MemberType NoteProperty -Name buildVersion -Value "$env:BUILD_NUMBER" $package | ConvertTo-Json -Depth 32 | Set-Content -Path electron-builder.json Write-Output "### MacOS Dev build number: $env:BUILD_NUMBER" - name: Install Node dependencies run: npm ci working-directory: ./ - name: Download SDK Artifacts if: ${{ inputs.sdk_branch != '' }} uses: bitwarden/gh-actions/download-artifacts@main with: github_token: ${{secrets.GITHUB_TOKEN}} workflow: build-wasm-internal.yml workflow_conclusion: success branch: ${{ inputs.sdk_branch }} artifacts: sdk-internal repo: bitwarden/sdk-internal path: ../sdk-internal if_no_artifact_found: fail - name: Override SDK if: ${{ inputs.sdk_branch != '' }} working-directory: ./ run: | ls -l ../ npm link ../sdk-internal - name: Cache Native Module uses: actions/cache@6849a6489940f00c2f30c0fb92c6274307ccb58a # v4.1.2 id: cache with: path: | apps/desktop/desktop_native/napi/*.node apps/desktop/desktop_native/dist/* key: rust-${{ runner.os }}-${{ hashFiles('apps/desktop/desktop_native/**/*') }} - name: Build Native Module if: steps.cache.outputs.cache-hit != 'true' working-directory: apps/desktop/desktop_native run: node build.js cross-platform - name: Build if: steps.build-cache.outputs.cache-hit != 'true' run: npm run build - name: Download Browser artifact uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8 with: path: ${{ github.workspace }}/browser-build-artifacts - name: Unzip Safari artifact run: | SAFARI_DIR=$(find $GITHUB_WORKSPACE/browser-build-artifacts -name 'dist-safari-*.zip') echo $SAFARI_DIR unzip $SAFARI_DIR/dist-safari.zip -d $GITHUB_WORKSPACE/browser-build-artifacts - name: Load Safari extension for App Store run: | mkdir PlugIns cp -r $GITHUB_WORKSPACE/browser-build-artifacts/Safari/masdev/build/Release/safari.appex PlugIns/safari.appex - name: Set up private auth key run: | mkdir ~/private_keys cat << EOF > ~/private_keys/AuthKey_6TV9MKN3GP.p8 ${{ secrets.APP_STORE_CONNECT_AUTH_KEY }} EOF - name: Build dev application for App Store env: APP_STORE_CONNECT_TEAM_ISSUER: ${{ secrets.APP_STORE_CONNECT_TEAM_ISSUER }} APP_STORE_CONNECT_AUTH_KEY_PATH: ~/private_keys/AuthKey_6TV9MKN3GP.p8 run: npm run pack:mac:masdev - name: Zip masdev asset run: | cd dist/mas-dev-universal zip -r Bitwarden-${{ env._PACKAGE_VERSION }}-masdev-universal.zip Bitwarden.app - name: Upload masdev artifact uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3 with: name: Bitwarden-${{ env._PACKAGE_VERSION }}-masdev-universal.zip path: apps/desktop/dist/mas-dev-universal/Bitwarden-${{ env._PACKAGE_VERSION }}-masdev-universal.zip if-no-files-found: error crowdin-push: name: Crowdin Push if: github.ref == 'refs/heads/main' needs: - linux - windows - macos-package-github - macos-package-mas runs-on: ubuntu-22.04 steps: - name: Check out repo uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: ref: ${{ github.event.pull_request.head.sha }} - name: Login to Azure uses: Azure/login@e15b166166a8746d1a47596803bd8c1b595455cf # v1.6.0 with: creds: ${{ secrets.AZURE_KV_CI_SERVICE_PRINCIPAL }} - name: Retrieve secrets id: retrieve-secrets uses: bitwarden/gh-actions/get-keyvault-secrets@main with: keyvault: "bitwarden-ci" secrets: "crowdin-api-token" - name: Upload Sources uses: crowdin/github-action@30849777a3cba6ee9a09e24e195272b8287a0a5b # v1.20.4 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} CROWDIN_API_TOKEN: ${{ steps.retrieve-secrets.outputs.crowdin-api-token }} CROWDIN_PROJECT_ID: "299360" with: config: apps/desktop/crowdin.yml crowdin_branch_name: main upload_sources: true upload_translations: false check-failures: name: Check for failures if: always() runs-on: ubuntu-22.04 needs: - electron-verify - browser-build - setup - linux - windows - macos-build - macos-package-github - macos-package-mas - crowdin-push steps: - name: Check if any job failed if: | github.event_name != 'pull_request_target' && (github.ref == 'refs/heads/main' || github.ref == 'refs/heads/rc' || github.ref == 'refs/heads/hotfix-rc-desktop') && contains(needs.*.result, 'failure') run: exit 1 - name: Login to Azure - Prod Subscription uses: Azure/login@e15b166166a8746d1a47596803bd8c1b595455cf # v1.6.0 if: failure() with: creds: ${{ secrets.AZURE_KV_CI_SERVICE_PRINCIPAL }} - name: Retrieve secrets id: retrieve-secrets if: failure() uses: bitwarden/gh-actions/get-keyvault-secrets@main with: keyvault: "bitwarden-ci" secrets: "devops-alerts-slack-webhook-url" - name: Notify Slack on failure uses: act10ns/slack@44541246747a30eb3102d87f7a4cc5471b0ffb7d # v2.1.0 if: failure() env: SLACK_WEBHOOK_URL: ${{ steps.retrieve-secrets.outputs.devops-alerts-slack-webhook-url }} with: status: ${{ job.status }}