Skip to content

PM-28324: Add a guard that conditionally forces a popout depending on platform #49165

PM-28324: Add a guard that conditionally forces a popout depending on platform

PM-28324: Add a guard that conditionally forces a popout depending on platform #49165

Workflow file for this run

# This workflow will run in the context of the source of the PR.
# On a PR from a fork, the workflow will not have access to secrets, and so any parts of the build that require secrets will not run.
# If additional artifacts are needed, the failed "build-browser-target.yml" workflow held up by the check-run should be re-run.
name: Build Browser
on:
pull_request:
types: [opened, synchronize]
branches-ignore:
- 'l10n_master'
- 'cf-pages'
paths:
- 'apps/browser/**'
- 'libs/**'
- '*'
- '!*.md'
- '!*.txt'
push:
branches:
- 'main'
- 'rc'
- 'hotfix-rc-browser'
paths:
- 'apps/browser/**'
- 'libs/**'
- '*'
- '!*.md'
- '!*.txt'
- '.github/workflows/build-browser.yml'
workflow_call:
inputs: {}
workflow_dispatch:
inputs:
sdk_branch:
description: "Custom SDK branch"
required: false
type: string
defaults:
run:
shell: bash
permissions:
contents: read
jobs:
setup:
name: Setup
runs-on: ubuntu-22.04
outputs:
repo_url: ${{ steps.gen_vars.outputs.repo_url }}
adj_build_number: ${{ steps.gen_vars.outputs.adj_build_number }}
node_version: ${{ steps.retrieve-node-version.outputs.node_version }}
has_secrets: ${{ steps.check-secrets.outputs.has_secrets }}
steps:
- name: Check out repo
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with:
ref: ${{ github.event.pull_request.head.sha }}
persist-credentials: false
- name: Get Package Version
id: gen_vars
run: |
repo_url="https://github.com/$GITHUB_REPOSITORY.git"
adj_build_num=${GITHUB_SHA:0:7}
echo "repo_url=$repo_url" >> "$GITHUB_OUTPUT"
echo "adj_build_number=$adj_build_num" >> "$GITHUB_OUTPUT"
- 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
run: |
has_secrets=${{ secrets.AZURE_CLIENT_ID != '' }}
echo "has_secrets=$has_secrets" >> "$GITHUB_OUTPUT"
locales-test:
name: Locales Test
runs-on: ubuntu-22.04
needs:
- setup
defaults:
run:
working-directory: apps/browser
steps:
- name: Check out repo
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with:
ref: ${{ github.event.pull_request.head.sha }}
persist-credentials: false
- name: Testing locales - extName length
run: |
found_error=false
echo "Locales Test"
echo "============"
echo "extName string must be 40 characters or less"
echo
for locale_path in src/_locales/*/messages.json; do
locale=$(basename "$(dirname "$locale_path")")
string_length=$(jq '.extName.message | length' "$locale_path")
if [ "$string_length" -gt 40 ]; then
echo "$locale: $string_length"
found_error=true
fi
done
if $found_error; then
echo
echo "Please fix 'extName' for the locales listed above."
exit 1
else
echo "Test passed!"
fi
build-source:
name: Build browser source - ${{matrix.license_type.readable}}
runs-on: ubuntu-22.04
needs:
- setup
- locales-test
strategy:
matrix:
license_type:
- include_bitwarden_license_folder: false
archive_name_prefix: ""
readable: "open source license"
- include_bitwarden_license_folder: true
archive_name_prefix: "bit-"
readable: "commercial license"
env:
_BUILD_NUMBER: ${{ needs.setup.outputs.adj_build_number }}
_NODE_VERSION: ${{ needs.setup.outputs.node_version }}
steps:
- name: Check out repo
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with:
ref: ${{ github.event.pull_request.head.sha }}
persist-credentials: false
- name: Set up Node
uses: actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444 # v5.0.0
with:
cache: 'npm'
cache-dependency-path: '**/package-lock.json'
node-version: ${{ env._NODE_VERSION }}
- name: Print environment
run: |
node --version
npm --version
- name: Build sources for reviewers
run: |
# Include hidden files in glob copy
shopt -s dotglob
# Remove ".git" directory
rm -r .git
# Copy root level files to source directory
mkdir browser-source
FILES=$(find . -maxdepth 1 -type f)
for FILE in $FILES; do cp "$FILE" browser-source/; done
# Copy apps/browser to the Browser source directory
mkdir -p browser-source/apps/browser
cp -r apps/browser/* browser-source/apps/browser
# Copy bitwarden_license/bit-browser to the Browser source directory
if [[ ${{matrix.license_type.include_bitwarden_license_folder}} == "true" ]]; then
mkdir -p browser-source/bitwarden_license/bit-browser
cp -r bitwarden_license/bit-browser/* browser-source/bitwarden_license/bit-browser
fi
# Copy libs to Browser source directory
mkdir browser-source/libs
cp -r libs/* browser-source/libs
zip -r browser-source.zip browser-source
- name: Upload browser source
uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0
with:
name: ${{matrix.license_type.archive_name_prefix}}browser-source-${{ env._BUILD_NUMBER }}.zip
path: browser-source.zip
if-no-files-found: error
build:
name: Build ${{ matrix.browser.name }} - ${{ matrix.license_type.readable }}
runs-on: ubuntu-22.04
needs:
- setup
- locales-test
- build-source
env:
_BUILD_NUMBER: ${{ needs.setup.outputs.adj_build_number }}
_NODE_VERSION: ${{ needs.setup.outputs.node_version }}
strategy:
matrix:
license_type:
- build_prefix: ""
artifact_prefix: ""
source_archive_name_prefix: ""
archive_name_prefix: ""
npm_command_prefix: "dist:"
npm_package_dev_prefix: "package:dev:"
readable: "open source license"
type: "oss"
- build_prefix: "bit-"
artifact_prefix: "bit-"
source_archive_name_prefix: "bit-"
archive_name_prefix: "bit-"
npm_command_prefix: "dist:bit:"
npm_package_dev_prefix: "package:bit:dev:"
readable: "commercial license"
type: "commercial"
browser:
- name: "chrome"
npm_command_suffix: "chrome"
archive_name: "dist-chrome.zip"
artifact_name: "dist-chrome-MV3"
artifact_name_dev: "dev-chrome-MV3"
archive_name_dev: "dev-chrome.zip"
- name: "edge"
npm_command_suffix: "edge"
archive_name: "dist-edge.zip"
artifact_name: "dist-edge-MV3"
- name: "firefox"
npm_command_suffix: "firefox"
archive_name: "dist-firefox.zip"
artifact_name: "dist-firefox"
- name: "firefox-mv3"
npm_command_suffix: "firefox:mv3"
archive_name: "dist-firefox.zip"
artifact_name: "DO-NOT-USE-FOR-PROD-dist-firefox-MV3"
- name: "opera-mv3"
npm_command_suffix: "opera:mv3"
archive_name: "dist-opera.zip"
artifact_name: "dist-opera-MV3"
steps:
- name: Check out repo
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with:
ref: ${{ github.event.pull_request.head.sha }}
persist-credentials: false
- name: Set up Node
uses: actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444 # v5.0.0
with:
cache: 'npm'
cache-dependency-path: '**/package-lock.json'
node-version: ${{ env._NODE_VERSION }}
- name: Print environment
run: |
node --version
npm --version
- name: Download browser source
uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6.0.0
with:
name: ${{matrix.license_type.source_archive_name_prefix}}browser-source-${{ env._BUILD_NUMBER }}.zip
- name: Unzip browser source artifact
run: |
unzip browser-source.zip
rm browser-source.zip
- name: NPM setup
run: npm ci
working-directory: browser-source/
- name: Remove commercial packages
if: ${{ matrix.license_type.type == 'oss' }}
run: rm -rf node_modules/@bitwarden/commercial-sdk-internal
working-directory: browser-source/
- 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: browser-source/
run: npm link ../sdk-internal
- name: Check source file size
if: ${{ startsWith(matrix.browser.name, 'firefox') }}
run: |
# Declare variable as indexed array
declare -a FILES
# Search for source files that are greater than 5M
TARGET_DIR='./browser-source/apps/browser'
while IFS=' ' read -r RESULT; do
FILES+=("$RESULT")
done < <(find "$TARGET_DIR" -size +5M)
# Validate results and provide messaging
if [[ ${#FILES[@]} -ne 0 ]]; then
echo "File(s) exceeds size limit: 5MB"
for FILE in "${FILES[@]}"; do
echo "- $(du --si "$FILE")"
done
echo "ERROR Firefox rejects extension uploads that contain files larger than 5MB"
# Invoke failure
exit 1
fi
- name: Build extension
run: npm run ${{matrix.license_type.npm_command_prefix}}${{ matrix.browser.npm_command_suffix }}
working-directory: browser-source/apps/browser
- name: Upload extension artifact
uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0
with:
name: ${{ matrix.license_type.artifact_prefix }}${{ matrix.browser.artifact_name }}-${{ env._BUILD_NUMBER }}.zip
path: browser-source/apps/browser/dist/${{matrix.license_type.archive_name_prefix}}${{ matrix.browser.archive_name }}
if-no-files-found: error
- name: Package dev extension
if: ${{ matrix.browser.archive_name_dev != '' }}
run: npm run ${{ matrix.license_type.npm_package_dev_prefix }}${{ matrix.browser.npm_command_suffix }}
working-directory: browser-source/apps/browser
- name: Upload dev extension artifact
if: ${{ matrix.browser.archive_name_dev != '' }}
uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0
with:
name: ${{ matrix.license_type.artifact_prefix }}${{ matrix.browser.artifact_name_dev }}-${{ env._BUILD_NUMBER }}.zip
path: browser-source/apps/browser/dist/${{matrix.license_type.archive_name_prefix}}${{ matrix.browser.archive_name_dev }}
if-no-files-found: error
build-safari:
name: Build Safari - ${{ matrix.license_type.readable }}
runs-on: macos-15
permissions:
contents: read
id-token: write
needs:
- setup
- locales-test
if: ${{ needs.setup.outputs.has_secrets == 'true' }}
strategy:
matrix:
license_type:
- build_prefix: ""
artifact_prefix: ""
archive_name_prefix: ""
npm_command_prefix: "dist:"
readable: "open source license"
type: "oss"
- build_prefix: "bit-"
artifact_prefix: "bit-"
archive_name_prefix: "bit-"
npm_command_prefix: "dist:bit:"
readable: "commercial license"
type: "commercial"
env:
_BUILD_NUMBER: ${{ needs.setup.outputs.adj_build_number }}
_NODE_VERSION: ${{ needs.setup.outputs.node_version }}
steps:
- name: Check out repo
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with:
ref: ${{ github.event.pull_request.head.sha }}
persist-credentials: false
- name: Set up Node
uses: actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444 # v5.0.0
with:
cache: 'npm'
cache-dependency-path: '**/package-lock.json'
node-version: ${{ env._NODE_VERSION }}
- name: Print environment
run: |
node --version
npm --version
- name: Log in to Azure
uses: bitwarden/gh-actions/azure-login@main
with:
subscription_id: ${{ secrets.AZURE_SUBSCRIPTION_ID }}
tenant_id: ${{ secrets.AZURE_TENANT_ID }}
client_id: ${{ secrets.AZURE_CLIENT_ID }}
- name: Get Azure Key Vault secrets
id: get-kv-secrets
uses: bitwarden/gh-actions/get-keyvault-secrets@main
with:
keyvault: gh-clients
secrets: "KEYCHAIN-PASSWORD"
- 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: Log out from Azure
uses: bitwarden/gh-actions/azure-logout@main
- name: Set up keychain
env:
KEYCHAIN_PASSWORD: ${{ steps.get-kv-secrets.outputs.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: NPM setup
run: npm ci
working-directory: ./
- name: Remove commercial packages
if: ${{ matrix.license_type.type == 'oss' }}
run: rm -rf node_modules/@bitwarden/commercial-sdk-internal
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: |
npm link ../sdk-internal
- name: Build Safari extension
run: npm run ${{matrix.license_type.npm_command_prefix}}safari
working-directory: apps/browser
- name: Zip Safari build artifact
run: |
cd apps/browser/dist
zip ${{matrix.license_type.archive_name_prefix }}dist-safari.zip ./Safari/**/build/Release/safari.appex -r
pwd
ls -la
- name: Upload Safari artifact
uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0
with:
name: ${{matrix.license_type.archive_name_prefix}}dist-safari-${{ env._BUILD_NUMBER }}.zip
path: apps/browser/dist/${{matrix.license_type.archive_name_prefix}}dist-safari.zip
if-no-files-found: error
crowdin-push:
name: Crowdin Push
if: github.event_name != 'pull_request_target' && github.ref == 'refs/heads/main'
runs-on: ubuntu-22.04
permissions:
contents: write
pull-requests: write
id-token: write
needs:
- build
- build-safari
steps:
- name: Check out repo
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with:
ref: ${{ github.event.pull_request.head.sha }}
persist-credentials: false
- name: Log in to Azure
uses: bitwarden/gh-actions/azure-login@main
with:
subscription_id: ${{ secrets.AZURE_SUBSCRIPTION_ID }}
tenant_id: ${{ secrets.AZURE_TENANT_ID }}
client_id: ${{ secrets.AZURE_CLIENT_ID }}
- name: Retrieve secrets
id: retrieve-secrets
uses: bitwarden/gh-actions/get-keyvault-secrets@main
with:
keyvault: "bitwarden-ci"
secrets: "crowdin-api-token"
- name: Log out from Azure
uses: bitwarden/gh-actions/azure-logout@main
- name: Upload Sources
uses: crowdin/github-action@08713f00a50548bfe39b37e8f44afb53e7a802d4 # v2.12.0
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
CROWDIN_API_TOKEN: ${{ steps.retrieve-secrets.outputs.crowdin-api-token }}
CROWDIN_PROJECT_ID: "268134"
with:
config: apps/browser/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
permissions:
contents: read
id-token: write
needs:
- setup
- locales-test
- build-source
- build
- build-safari
- 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-browser')
&& contains(needs.*.result, 'failure')
run: exit 1
- name: Log in to Azure
if: failure()
uses: bitwarden/gh-actions/azure-login@main
with:
subscription_id: ${{ secrets.AZURE_SUBSCRIPTION_ID }}
tenant_id: ${{ secrets.AZURE_TENANT_ID }}
client_id: ${{ secrets.AZURE_CLIENT_ID }}
- 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: Log out from Azure
if: failure()
uses: bitwarden/gh-actions/azure-logout@main
- 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 }}