mirror of
https://github.com/bitwarden/browser
synced 2025-12-24 12:13:39 +00:00
* feat: create copy of desktop build for PR target * chore: add temporary file to trigger ci * fix: remove check-run from regular desktop build * feat: change browser build to not use pr target * fix: skip build-safari if secret is not available * feat: skip safari build if secrets are not available * feat: let windows desktop build without secrets * fix: has_secrets not being output correctly * feat: let macos desktop build without secrets * feat: don't build browser as part of desktop * feat: change CLI to pull_request * feat: let web build without secrets * feat: tweak lint to run on PR and not just push * feat: add PR target workflows * fix: remove wip files * fix: lint on hotfix-rc branches * feat: add new workflows to CODEOWNERS * fix: remove workflow_dispatch pull_request_target are only intended to be used with contributor PRs and we cannot dispatch builds for these branches so there was no point having that option.
440 lines
14 KiB
YAML
440 lines
14 KiB
YAML
name: Build Web
|
|
|
|
on:
|
|
pull_request:
|
|
types: [opened, synchronize]
|
|
branches-ignore:
|
|
- 'l10n_master'
|
|
- 'cf-pages'
|
|
paths:
|
|
- 'apps/web/**'
|
|
- 'libs/**'
|
|
- '*'
|
|
- '!*.md'
|
|
- '!*.txt'
|
|
- '.github/workflows/build-web.yml'
|
|
push:
|
|
branches:
|
|
- 'main'
|
|
- 'rc'
|
|
- 'hotfix-rc-web'
|
|
paths:
|
|
- 'apps/web/**'
|
|
- 'libs/**'
|
|
- '*'
|
|
- '!*.md'
|
|
- '!*.txt'
|
|
- '.github/workflows/build-web.yml'
|
|
release:
|
|
types: [published]
|
|
workflow_call:
|
|
inputs: {}
|
|
workflow_dispatch:
|
|
inputs:
|
|
custom_tag_extension:
|
|
description: "Custom image tag extension"
|
|
required: false
|
|
sdk_branch:
|
|
description: "Custom SDK branch"
|
|
required: false
|
|
type: string
|
|
|
|
env:
|
|
_AZ_REGISTRY: bitwardenprod.azurecr.io
|
|
|
|
jobs:
|
|
setup:
|
|
name: Setup
|
|
runs-on: ubuntu-22.04
|
|
outputs:
|
|
version: ${{ steps.version.outputs.value }}
|
|
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@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
|
with:
|
|
ref: ${{ github.event.pull_request.head.sha }}
|
|
|
|
- name: Get GitHub sha as version
|
|
id: version
|
|
run: echo "value=${GITHUB_SHA:0:7}" >> $GITHUB_OUTPUT
|
|
|
|
- name: Get Node Version
|
|
id: retrieve-node-version
|
|
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
|
|
|
|
build-artifacts:
|
|
name: Build artifacts
|
|
runs-on: ubuntu-22.04
|
|
needs:
|
|
- setup
|
|
env:
|
|
_VERSION: ${{ needs.setup.outputs.version }}
|
|
_NODE_VERSION: ${{ needs.setup.outputs.node_version }}
|
|
strategy:
|
|
matrix:
|
|
include:
|
|
- name: "selfhosted-open-source"
|
|
npm_command: "dist:oss:selfhost"
|
|
- name: "cloud-COMMERCIAL"
|
|
npm_command: "dist:bit:cloud"
|
|
- name: "selfhosted-COMMERCIAL"
|
|
npm_command: "dist:bit:selfhost"
|
|
- name: "cloud-QA"
|
|
npm_command: "build:bit:qa"
|
|
git_metadata: true
|
|
- name: "ee"
|
|
npm_command: "build:bit:ee"
|
|
git_metadata: true
|
|
- name: "cloud-euprd"
|
|
npm_command: "build:bit:euprd"
|
|
- name: "cloud-euqa"
|
|
npm_command: "build:bit:euqa"
|
|
git_metadata: true
|
|
- name: "cloud-usdev"
|
|
npm_command: "build:bit:usdev"
|
|
git_metadata: true
|
|
|
|
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: Print environment
|
|
run: |
|
|
whoami
|
|
node --version
|
|
npm --version
|
|
docker --version
|
|
echo "GitHub ref: $GITHUB_REF"
|
|
echo "GitHub event: $GITHUB_EVENT"
|
|
|
|
- name: Install dependencies
|
|
run: npm ci
|
|
|
|
- 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: Add Git metadata to build version
|
|
working-directory: apps/web
|
|
if: matrix.git_metadata
|
|
run: |
|
|
VERSION=$( jq -r ".version" package.json)
|
|
jq --arg version "$VERSION+${GITHUB_SHA:0:7}" '.version = $version' package.json > package.json.tmp
|
|
mv package.json.tmp package.json
|
|
|
|
- name: Build ${{ matrix.name }}
|
|
working-directory: apps/web
|
|
run: npm run ${{ matrix.npm_command }}
|
|
|
|
- name: Package artifact
|
|
working-directory: apps/web
|
|
run: zip -r web-${{ env._VERSION }}-${{ matrix.name }}.zip build
|
|
|
|
- name: Upload ${{ matrix.name }} artifact
|
|
uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0
|
|
with:
|
|
name: web-${{ env._VERSION }}-${{ matrix.name }}.zip
|
|
path: apps/web/web-${{ env._VERSION }}-${{ matrix.name }}.zip
|
|
if-no-files-found: error
|
|
|
|
|
|
build-containers:
|
|
name: Build Docker images
|
|
runs-on: ubuntu-22.04
|
|
permissions:
|
|
security-events: write
|
|
id-token: write
|
|
needs:
|
|
- setup
|
|
- build-artifacts
|
|
strategy:
|
|
fail-fast: false
|
|
matrix:
|
|
include:
|
|
- artifact_name: cloud-QA
|
|
image_name: web-qa-cloud
|
|
- artifact_name: ee
|
|
image_name: web-ee
|
|
- artifact_name: selfhosted-COMMERCIAL
|
|
image_name: web
|
|
env:
|
|
_VERSION: ${{ needs.setup.outputs.version }}
|
|
steps:
|
|
- name: Check out repo
|
|
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
|
with:
|
|
ref: ${{ github.event.pull_request.head.sha }}
|
|
|
|
- name: Check Branch to Publish
|
|
env:
|
|
PUBLISH_BRANCHES: "main,rc,hotfix-rc-web"
|
|
id: publish-branch-check
|
|
run: |
|
|
IFS="," read -a publish_branches <<< $PUBLISH_BRANCHES
|
|
|
|
if [[ " ${publish_branches[*]} " =~ " ${GITHUB_REF:11} " ]]; then
|
|
echo "is_publish_branch=true" >> $GITHUB_ENV
|
|
else
|
|
echo "is_publish_branch=false" >> $GITHUB_ENV
|
|
fi
|
|
|
|
########## ACRs ##########
|
|
- name: Login to Prod Azure
|
|
if: ${{ needs.setup.outputs.has_secrets == 'true' }}
|
|
uses: Azure/login@e15b166166a8746d1a47596803bd8c1b595455cf # v1.6.0
|
|
with:
|
|
creds: ${{ secrets.AZURE_PROD_KV_CREDENTIALS }}
|
|
|
|
- name: Log into Prod container registry
|
|
if: ${{ needs.setup.outputs.has_secrets == 'true' }}
|
|
run: az acr login -n bitwardenprod
|
|
|
|
- name: Login to Azure - CI Subscription
|
|
if: ${{ needs.setup.outputs.has_secrets == 'true' }}
|
|
uses: Azure/login@e15b166166a8746d1a47596803bd8c1b595455cf # v1.6.0
|
|
with:
|
|
creds: ${{ secrets.AZURE_KV_CI_SERVICE_PRINCIPAL }}
|
|
|
|
- name: Retrieve github PAT secrets
|
|
if: ${{ needs.setup.outputs.has_secrets == 'true' }}
|
|
id: retrieve-secret-pat
|
|
uses: bitwarden/gh-actions/get-keyvault-secrets@main
|
|
with:
|
|
keyvault: "bitwarden-ci"
|
|
secrets: "github-pat-bitwarden-devops-bot-repo-scope"
|
|
|
|
- name: Download ${{ matrix.artifact_name }} artifact
|
|
uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8
|
|
with:
|
|
name: web-${{ env._VERSION }}-${{ matrix.artifact_name }}.zip
|
|
path: apps/web
|
|
|
|
########## Generate image tag and build Docker image ##########
|
|
- name: Generate Docker image tag
|
|
id: tag
|
|
run: |
|
|
if [[ "${GITHUB_EVENT_NAME}" == "pull_request_target" ]]; then
|
|
IMAGE_TAG=$(echo "${GITHUB_HEAD_REF}" | sed "s#/#-#g")
|
|
else
|
|
IMAGE_TAG=$(echo "${GITHUB_REF_NAME}" | sed "s#/#-#g")
|
|
fi
|
|
|
|
if [[ "$IMAGE_TAG" == "main" ]]; then
|
|
IMAGE_TAG=dev
|
|
fi
|
|
|
|
TAG_EXTENSION=${{ github.event.inputs.custom_tag_extension }}
|
|
|
|
if [[ $TAG_EXTENSION ]]; then
|
|
IMAGE_TAG=$IMAGE_TAG-$TAG_EXTENSION
|
|
fi
|
|
|
|
echo "image_tag=$IMAGE_TAG" >> $GITHUB_OUTPUT
|
|
|
|
########## Build Image ##########
|
|
- name: Extract artifact
|
|
working-directory: apps/web
|
|
run: unzip web-${{ env._VERSION }}-${{ matrix.artifact_name }}.zip
|
|
|
|
- name: Generate image full name
|
|
id: image-name
|
|
env:
|
|
IMAGE_TAG: ${{ steps.tag.outputs.image_tag }}
|
|
PROJECT_NAME: ${{ matrix.image_name }}
|
|
run: echo "name=$_AZ_REGISTRY/${PROJECT_NAME}:${IMAGE_TAG}" >> $GITHUB_OUTPUT
|
|
|
|
- name: Build Docker image
|
|
if: ${{ needs.setup.outputs.has_secrets == 'true' }}
|
|
id: build-docker
|
|
uses: docker/build-push-action@67a2d409c0a876cbe6b11854e3e25193efe4e62d # v6.12.0
|
|
with:
|
|
context: apps/web
|
|
file: apps/web/Dockerfile
|
|
platforms: linux/amd64
|
|
push: true
|
|
tags: ${{ steps.image-name.outputs.name }}
|
|
secrets: |
|
|
"GH_PAT=${{ steps.retrieve-secret-pat.outputs.github-pat-bitwarden-devops-bot-repo-scope }}"
|
|
|
|
- name: Install Cosign
|
|
if: github.event_name != 'pull_request_target' && github.ref == 'refs/heads/main'
|
|
uses: sigstore/cosign-installer@dc72c7d5c4d10cd6bcb8cf6e3fd625a9e5e537da # v3.7.0
|
|
|
|
- name: Sign image with Cosign
|
|
if: github.event_name != 'pull_request_target' && github.ref == 'refs/heads/main'
|
|
env:
|
|
DIGEST: ${{ steps.build-docker.outputs.digest }}
|
|
TAGS: ${{ steps.image-name.outputs.name }}
|
|
run: |
|
|
IFS="," read -a tags <<< "${TAGS}"
|
|
images=""
|
|
for tag in "${tags[@]}"; do
|
|
images+="${tag}@${DIGEST} "
|
|
done
|
|
cosign sign --yes ${images}
|
|
|
|
- name: Scan Docker image
|
|
id: container-scan
|
|
uses: anchore/scan-action@869c549e657a088dc0441b08ce4fc0ecdac2bb65 # v5.3.0
|
|
with:
|
|
image: ${{ steps.image-name.outputs.name }}
|
|
fail-build: false
|
|
output-format: sarif
|
|
|
|
- name: Upload Grype results to GitHub
|
|
uses: github/codeql-action/upload-sarif@d68b2d4edb4189fd2a5366ac14e72027bd4b37dd # v3.28.2
|
|
with:
|
|
sarif_file: ${{ steps.container-scan.outputs.sarif }}
|
|
|
|
- name: Log out of Docker
|
|
run: docker logout
|
|
|
|
crowdin-push:
|
|
name: Crowdin Push
|
|
if: github.event_name != 'pull_request_target' && github.ref == 'refs/heads/main'
|
|
needs:
|
|
- build-artifacts
|
|
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: "308189"
|
|
with:
|
|
config: apps/web/crowdin.yml
|
|
crowdin_branch_name: main
|
|
upload_sources: true
|
|
upload_translations: false
|
|
|
|
trigger-web-vault-deploy:
|
|
name: Trigger web vault deploy
|
|
if: github.event_name != 'pull_request_target' && github.ref == 'refs/heads/main'
|
|
runs-on: ubuntu-22.04
|
|
needs:
|
|
- build-artifacts
|
|
steps:
|
|
- name: Login to Azure - CI Subscription
|
|
uses: Azure/login@e15b166166a8746d1a47596803bd8c1b595455cf # v1.6.0
|
|
with:
|
|
creds: ${{ secrets.AZURE_KV_CI_SERVICE_PRINCIPAL }}
|
|
|
|
- name: Retrieve github PAT secrets
|
|
id: retrieve-secret-pat
|
|
uses: bitwarden/gh-actions/get-keyvault-secrets@main
|
|
with:
|
|
keyvault: "bitwarden-ci"
|
|
secrets: "github-pat-bitwarden-devops-bot-repo-scope"
|
|
|
|
- name: Trigger web vault deploy using GitHub Run ID
|
|
uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1
|
|
with:
|
|
github-token: ${{ steps.retrieve-secret-pat.outputs.github-pat-bitwarden-devops-bot-repo-scope }}
|
|
script: |
|
|
await github.rest.actions.createWorkflowDispatch({
|
|
owner: 'bitwarden',
|
|
repo: 'clients',
|
|
workflow_id: 'deploy-web.yml',
|
|
ref: 'main',
|
|
inputs: {
|
|
'environment': 'USDEV',
|
|
'build-web-run-id': '${{ github.run_id }}'
|
|
}
|
|
})
|
|
|
|
check-failures:
|
|
name: Check for failures
|
|
if: always()
|
|
runs-on: ubuntu-22.04
|
|
needs:
|
|
- setup
|
|
- build-artifacts
|
|
- build-containers
|
|
- crowdin-push
|
|
- trigger-web-vault-deploy
|
|
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-web')
|
|
&& 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 }}
|