Build Bitwarden lite workflow_dispatch #1179
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Build Bitwarden lite | |
| run-name: Build Bitwarden lite ${{ github.event_name }} | |
| on: | |
| push: | |
| paths: | |
| - "bitwarden-lite/**" | |
| - ".github/workflows/build-bitwarden-lite.yml" | |
| branches: | |
| - main | |
| repository_dispatch: | |
| types: | |
| - build-bitwarden-lite | |
| workflow_dispatch: | |
| inputs: | |
| self_host_repo_ref: | |
| description: "Self-host ref to use for checkout (Default: current ref)" | |
| type: string | |
| required: false | |
| server_branch: | |
| description: "Server branch name (examples: 'main', 'rc', 'feature/sm')" | |
| type: string | |
| default: main | |
| web_branch: | |
| description: "Web client branch name (examples: 'main', 'rc', 'feature/sm')" | |
| type: string | |
| default: main | |
| use_latest_core_version: | |
| description: "Use the latest core version from version.json instead of branch" | |
| type: boolean | |
| default: false | |
| use_latest_web_version: | |
| description: "Use the latest web version from version.json instead of branch" | |
| type: boolean | |
| default: false | |
| workflow_call: | |
| inputs: | |
| self_host_repo_ref: | |
| description: "Self-host ref to use for checkout (Default: current ref)" | |
| type: string | |
| required: false | |
| server_branch: | |
| description: "Server branch name (examples: 'main', 'rc', 'feature/sm')" | |
| type: string | |
| default: main | |
| web_branch: | |
| description: "Web client branch name (examples: 'main', 'rc', 'feature/sm')" | |
| type: string | |
| default: main | |
| use_latest_core_version: | |
| description: "Use the latest core version from version.json instead of branch" | |
| type: boolean | |
| default: false | |
| use_latest_web_version: | |
| description: "Use the latest web version from version.json instead of branch" | |
| type: boolean | |
| default: false | |
| secrets: | |
| AZURE_CLIENT_ID: | |
| description: "Azure client ID for ACR/Cosign auth" | |
| required: false | |
| AZURE_SUBSCRIPTION_ID: | |
| description: "Azure subscription ID" | |
| required: false | |
| AZURE_TENANT_ID: | |
| description: "Azure tenant ID" | |
| required: false | |
| pull_request: | |
| types: [opened, synchronize] | |
| branches: | |
| - main | |
| paths: | |
| - "bitwarden-lite/**" | |
| - ".github/workflows/build-bitwarden-lite.yml" | |
| concurrency: | |
| group: ${{ github.workflow }}-${{ github.ref }} | |
| cancel-in-progress: true | |
| jobs: | |
| check-event-source: | |
| name: Check event and source | |
| runs-on: ubuntu-24.04 | |
| permissions: | |
| contents: read | |
| if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository | |
| steps: | |
| - name: Check PR event and source | |
| run: echo "Internal PR, push, dispatch, or workflow_call — proceeding" | |
| setup: | |
| name: Setup | |
| runs-on: ubuntu-24.04 | |
| needs: check-event-source | |
| permissions: | |
| contents: read | |
| outputs: | |
| server_ref: ${{ steps.set-server-variables.outputs.server_ref }} | |
| web_ref: ${{ steps.set-web-variables.outputs.web_ref }} | |
| push_to_ghcr: ${{ steps.set-server-variables.outputs.push_to_ghcr }} | |
| steps: | |
| - name: Checkout Repository | |
| uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 | |
| with: | |
| ref: ${{ inputs.self_host_repo_ref || github.event.client_payload.self_host_repo_ref || github.ref }} | |
| persist-credentials: false | |
| - name: Set Server variables | |
| id: set-server-variables | |
| env: | |
| SERVER_BRANCH: ${{ inputs.server_branch || github.event.client_payload.server_branch }} | |
| USE_LATEST_CORE_VERSION: ${{ github.event_name == 'repository_dispatch' && github.event.client_payload.use_latest_core_version || inputs.use_latest_core_version }} | |
| run: | | |
| if [[ "$USE_LATEST_CORE_VERSION" == "true" ]]; then | |
| CORE_VERSION=$(jq -r '.versions.coreVersion' version.json) | |
| echo "Server version from version.json: $CORE_VERSION" | |
| SERVER_REF="refs/tags/v$CORE_VERSION" | |
| elif [[ -z "${SERVER_BRANCH}" ]]; then | |
| SERVER_REF="refs/heads/main" | |
| else | |
| SERVER_REF="refs/heads/${SERVER_BRANCH#refs/heads/}" | |
| fi | |
| echo "server_ref=$SERVER_REF" >> "$GITHUB_OUTPUT" | |
| # Always push to ACR. Additionally push to GHCR for rc, hotfix-rc, and version tags. | |
| BRANCH_NAME="${SERVER_REF#refs/heads/}" | |
| if [[ "$SERVER_REF" =~ ^refs/tags/ ]] || [[ "$BRANCH_NAME" == "rc" ]] || [[ "$BRANCH_NAME" == "hotfix-rc" ]]; then | |
| echo "push_to_ghcr=true" >> "$GITHUB_OUTPUT" | |
| else | |
| echo "push_to_ghcr=false" >> "$GITHUB_OUTPUT" | |
| fi | |
| - name: Set Web variables | |
| id: set-web-variables | |
| env: | |
| WEB_BRANCH: ${{ inputs.web_branch || github.event.client_payload.web_branch }} | |
| USE_LATEST_WEB_VERSION: ${{ github.event_name == 'repository_dispatch' && github.event.client_payload.use_latest_web_version || inputs.use_latest_web_version }} | |
| run: | | |
| if [[ "$USE_LATEST_WEB_VERSION" == "true" ]]; then | |
| # Extract webVersion from version.json | |
| WEB_VERSION=$(jq -r '.versions.webVersion' version.json) | |
| echo "Web version from version.json: $WEB_VERSION" | |
| echo "web_ref=refs/tags/web-v$WEB_VERSION" >> "$GITHUB_OUTPUT" | |
| elif [[ -z "${WEB_BRANCH}" ]]; then | |
| echo "web_ref=refs/heads/main" >> "$GITHUB_OUTPUT" | |
| else | |
| echo "web_ref=refs/heads/${WEB_BRANCH#refs/heads/}" >> "$GITHUB_OUTPUT" | |
| fi | |
| build-docker: | |
| name: Build Docker image | |
| runs-on: ubuntu-24.04 | |
| timeout-minutes: 60 | |
| needs: setup | |
| permissions: | |
| contents: read | |
| id-token: write | |
| packages: write | |
| security-events: write | |
| steps: | |
| - name: Checkout Repository | |
| uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 | |
| with: | |
| ref: ${{ inputs.self_host_repo_ref || github.event.client_payload.self_host_repo_ref || github.ref }} | |
| persist-credentials: false | |
| - name: Check secrets | |
| id: check-secrets | |
| env: | |
| AZURE_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID }} | |
| run: | | |
| if [[ -n "$AZURE_CLIENT_ID" ]]; then | |
| echo "has_secrets=true" >> "$GITHUB_OUTPUT" | |
| else | |
| echo "has_secrets=false" >> "$GITHUB_OUTPUT" | |
| fi | |
| - name: Set up QEMU emulators | |
| uses: docker/setup-qemu-action@ce360397dd3f832beb865e1373c09c0e9f86d70a # v4.0.0 | |
| - name: Set up Docker Buildx | |
| uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd # v4.0.0 | |
| - name: Log in to Azure | |
| if: steps.check-secrets.outputs.has_secrets == 'true' | |
| 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: Log in to ACR | |
| if: steps.check-secrets.outputs.has_secrets == 'true' | |
| run: az acr login -n bitwardenprod | |
| - name: Login to GitHub Container Registry | |
| if: steps.check-secrets.outputs.has_secrets == 'true' && needs.setup.outputs.push_to_ghcr == 'true' | |
| uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 # v4.1.0 | |
| with: | |
| registry: ghcr.io | |
| username: ${{ github.actor }} | |
| password: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Generate Docker image tag | |
| id: tag | |
| env: | |
| SERVER_REF: ${{ needs.setup.outputs.server_ref }} | |
| run: | | |
| if [[ $SERVER_REF =~ ^refs/tags/v(.+)$ ]]; then | |
| IMAGE_TAG="${BASH_REMATCH[1]}" | |
| SERVER_TAG="${BASH_REMATCH[1]}" | |
| else | |
| IMAGE_TAG=$(echo "${SERVER_REF#refs/heads/}" | \ | |
| tr '[:upper:]' '[:lower:]' | \ | |
| sed -E 's/[^a-z0-9._-]+/-/g; s/-+/-/g; s/^-+|-+$//g' | \ | |
| cut -c1-128 | \ | |
| sed -E 's/[.-]$//') | |
| SERVER_TAG=$(echo "${SERVER_REF#refs/heads/}" | sed 's|/|-|g' | cut -c1-128) | |
| fi | |
| if [[ "$IMAGE_TAG" == "main" ]]; then | |
| IMAGE_TAG=dev | |
| SERVER_TAG=dev | |
| fi | |
| if [[ -z "$IMAGE_TAG" ]]; then | |
| echo "ERROR: Failed to generate valid IMAGE_TAG from SERVER_REF: $SERVER_REF" | |
| exit 1 | |
| fi | |
| echo "Using lite tag $IMAGE_TAG, server tag $SERVER_TAG" | |
| echo "image_tag=${IMAGE_TAG}" >> "$GITHUB_OUTPUT" | |
| echo "server_tag=${SERVER_TAG}" >> "$GITHUB_OUTPUT" | |
| - name: Generate web image tag | |
| id: web-tag | |
| env: | |
| WEB_REF: ${{ needs.setup.outputs.web_ref }} | |
| run: | | |
| if [[ $WEB_REF =~ ^refs/tags/web-v(.+)$ ]]; then | |
| WEB_TAG="${BASH_REMATCH[1]}" | |
| WEB_IMAGE="ghcr.io/bitwarden/web" | |
| else | |
| WEB_TAG=$(echo "${WEB_REF#refs/heads/}" | \ | |
| tr '[:upper:]' '[:lower:]' | \ | |
| sed -E 's/[^a-z0-9._-]+/-/g; s/-+/-/g; s/^-+|-+$//g' | \ | |
| cut -c1-128 | \ | |
| sed -E 's/[.-]$//') | |
| [[ "$WEB_TAG" == "main" ]] && WEB_TAG=dev | |
| WEB_IMAGE="ghcr.io/bitwarden/web-dev" | |
| fi | |
| echo "web_tag=${WEB_TAG}" >> "$GITHUB_OUTPUT" | |
| echo "web_image=${WEB_IMAGE}" >> "$GITHUB_OUTPUT" | |
| - name: Determine image tags | |
| id: image-ref | |
| env: | |
| PUSH_TO_GHCR: ${{ needs.setup.outputs.push_to_ghcr }} | |
| IMAGE_TAG: ${{ steps.tag.outputs.image_tag }} | |
| run: | | |
| TAGS="bitwardenprod.azurecr.io/lite:${IMAGE_TAG}" | |
| if [[ "$PUSH_TO_GHCR" == "true" ]]; then | |
| TAGS="${TAGS},ghcr.io/bitwarden/lite:${IMAGE_TAG}" | |
| fi | |
| echo "tags=${TAGS}" >> "$GITHUB_OUTPUT" | |
| echo "acr_image=bitwardenprod.azurecr.io/lite:${IMAGE_TAG}" >> "$GITHUB_OUTPUT" | |
| - name: Log build configuration | |
| env: | |
| IMAGE_TAGS: ${{ steps.image-ref.outputs.tags }} | |
| SERVER_REGISTRY: ${{ needs.setup.outputs.push_to_ghcr == 'true' && 'ghcr.io/bitwarden' || 'bitwardenprod.azurecr.io' }} | |
| SERVER_TAG: ${{ steps.tag.outputs.server_tag }} | |
| WEB_IMAGE: ${{ steps.web-tag.outputs.web_image }} | |
| WEB_TAG: ${{ steps.web-tag.outputs.web_tag }} | |
| run: | | |
| echo "### Build Configuration" >> $GITHUB_STEP_SUMMARY | |
| echo "- Lite: ${IMAGE_TAGS}" >> $GITHUB_STEP_SUMMARY | |
| echo "- Server: ${SERVER_REGISTRY}/*:${SERVER_TAG}" >> $GITHUB_STEP_SUMMARY | |
| echo "- Web: ${WEB_IMAGE}:${WEB_TAG}" >> $GITHUB_STEP_SUMMARY | |
| - name: Build and push Docker image | |
| id: build-docker | |
| uses: docker/build-push-action@bcafcacb16a39f128d818304e6c9c0c18556b85f # v7.1.0 | |
| with: | |
| context: . | |
| file: bitwarden-lite/Dockerfile | |
| platforms: | | |
| linux/amd64, | |
| linux/arm/v7, | |
| linux/arm64/v8 | |
| push: ${{ steps.check-secrets.outputs.has_secrets == 'true' }} | |
| tags: ${{ steps.image-ref.outputs.tags }} | |
| build-args: | | |
| SERVER_TAG=${{ steps.tag.outputs.server_tag }} | |
| SERVER_REGISTRY=${{ needs.setup.outputs.push_to_ghcr == 'true' && 'ghcr.io/bitwarden' || 'bitwardenprod.azurecr.io' }} | |
| WEB_IMAGE=${{ steps.web-tag.outputs.web_image }} | |
| WEB_TAG=${{ steps.web-tag.outputs.web_tag }} | |
| - name: Install Cosign | |
| if: steps.check-secrets.outputs.has_secrets == 'true' | |
| uses: sigstore/cosign-installer@6f9f17788090df1f26f669e9d70d6ae9567deba6 # v4.1.2 | |
| - name: Sign image with Cosign | |
| if: steps.check-secrets.outputs.has_secrets == 'true' | |
| env: | |
| DIGEST: ${{ steps.build-docker.outputs.digest }} | |
| PUSH_TO_GHCR: ${{ needs.setup.outputs.push_to_ghcr }} | |
| ACR_IMAGE: ${{ steps.image-ref.outputs.acr_image }} | |
| GHCR_IMAGE: ghcr.io/bitwarden/lite:${{ steps.tag.outputs.image_tag }} | |
| run: | | |
| cosign sign --yes "${ACR_IMAGE}@${DIGEST}" | |
| if [[ "$PUSH_TO_GHCR" == "true" ]]; then | |
| cosign sign --yes "${GHCR_IMAGE}@${DIGEST}" | |
| fi | |
| - name: Scan Docker image | |
| if: steps.check-secrets.outputs.has_secrets == 'true' | |
| id: container-scan | |
| uses: anchore/scan-action@e1165082ffb1fe366ebaf02d8526e7c4989ea9d2 # v7.4.0 | |
| with: | |
| image: ${{ steps.image-ref.outputs.acr_image }} | |
| fail-build: false | |
| output-format: sarif | |
| - name: Upload Grype results to GitHub | |
| if: steps.check-secrets.outputs.has_secrets == 'true' | |
| uses: github/codeql-action/upload-sarif@9e0d7b8d25671d64c341c19c0152d693099fb5ba # v4.35.5 | |
| with: | |
| sarif_file: ${{ steps.container-scan.outputs.sarif }} | |
| sha: ${{ contains(github.event_name, 'pull_request') && github.event.pull_request.head.sha || github.sha }} | |
| ref: ${{ contains(github.event_name, 'pull_request') && format('refs/pull/{0}/head', github.event.pull_request.number) || github.ref }} | |
| - name: Log out of registries | |
| if: always() | |
| run: | | |
| docker logout ghcr.io || true | |
| az acr logout -n bitwardenprod || true |