diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index ade6a6cfd1..1843015d2c 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -14,6 +14,7 @@ on: env: _AZ_REGISTRY: "bitwardenprod.azurecr.io" + _GITHUB_PR_REPO_NAME: ${{ github.event.pull_request.head.repo.full_name }} jobs: lint: @@ -31,48 +32,63 @@ jobs: - name: Verify format run: dotnet format --verify-no-changes - build-container: - name: Build container images + build-artifacts: + name: Build Docker images runs-on: ubuntu-24.04 - permissions: - id-token: write - security-events: write + needs: + - lint outputs: has_secrets: ${{ steps.check-secrets.outputs.has_secrets }} + permissions: + security-events: write + id-token: write strategy: fail-fast: false matrix: include: - project_name: Admin base_path: ./src + dotnet: true + node: true - project_name: Api base_path: ./src + dotnet: true - project_name: Attachments base_path: ./util - project_name: Billing base_path: ./src + dotnet: true - project_name: Events base_path: ./src + dotnet: true - project_name: EventsProcessor base_path: ./src + dotnet: true - project_name: Icons base_path: ./src + dotnet: true - project_name: Identity base_path: ./src + dotnet: true - project_name: MsSql base_path: ./util - project_name: MsSqlMigratorUtility base_path: ./util + dotnet: true - project_name: Nginx base_path: ./util - project_name: Notifications base_path: ./src + dotnet: true - project_name: Scim base_path: ./bitwarden_license/src + dotnet: true - project_name: Setup base_path: ./util + dotnet: true - project_name: Sso base_path: ./bitwarden_license/src + dotnet: true steps: - name: Check secrets id: check-secrets @@ -87,18 +103,53 @@ jobs: with: ref: ${{ github.event.pull_request.head.sha }} - - name: Check branch to publish - env: - PUBLISH_BRANCHES: "main,rc,hotfix-rc" - id: publish-branch-check - run: | - IFS="," read -a publish_branches <<< $PUBLISH_BRANCHES + - name: Set up .NET + uses: actions/setup-dotnet@87b7050bc53ea08284295505d98d2aa94301e852 # v4.2.0 - if [[ " ${publish_branches[*]} " =~ " ${GITHUB_REF:11} " ]]; then - echo "is_publish_branch=true" >> $GITHUB_ENV - else - echo "is_publish_branch=false" >> $GITHUB_ENV - fi + - name: Set up Node + uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0 + with: + cache: "npm" + cache-dependency-path: "**/package-lock.json" + node-version: "16" + + - name: Print environment + run: | + whoami + dotnet --info + node --version + npm --version + echo "GitHub ref: $GITHUB_REF" + echo "GitHub event: $GITHUB_EVENT" + + - name: Build node + if: ${{ matrix.node }} + working-directory: ${{ matrix.base_path }}/${{ matrix.project_name }} + run: | + npm ci + npm run build + + - name: Publish project + working-directory: ${{ matrix.base_path }}/${{ matrix.project_name }} + if: ${{ matrix.dotnet }} + run: | + echo "Publish" + dotnet publish -c "Release" -o obj/build-output/publish + + cd obj/build-output/publish + zip -r ${{ matrix.project_name }}.zip . + mv ${{ matrix.project_name }}.zip ../../../ + + pwd + ls -atlh ../../../ + + - name: Upload project artifact + uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0 + if: ${{ matrix.dotnet }} + with: + name: ${{ matrix.project_name }}.zip + path: ${{ matrix.base_path }}/${{ matrix.project_name }}/${{ matrix.project_name }}.zip + if-no-files-found: error ########## Set up Docker ########## - name: Set up QEMU emulators @@ -116,22 +167,40 @@ jobs: - name: Log in to ACR - production subscription run: az acr login -n bitwardenprod - ########## Generate image tag and build container image ########## - - name: Generate container image tag + - name: Log in 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" + + ########## Generate image tag and build Docker image ########## + - name: Generate Docker image tag id: tag run: | - if [[ "${GITHUB_EVENT_NAME}" == "pull_request" ]]; then - IMAGE_TAG=$(echo "${GITHUB_HEAD_REF}" | sed "s#/#-#g") + if [[ "${GITHUB_EVENT_NAME}" == "pull_request" || "${GITHUB_EVENT_NAME}" == "pull_request_target" ]]; then + IMAGE_TAG=$(echo "${GITHUB_HEAD_REF}" | sed "s/[^a-zA-Z0-9]/-/g") # Sanitize branch name to alphanumeric only else IMAGE_TAG=$(echo "${GITHUB_REF:11}" | sed "s#/#-#g") fi + if [[ "${{ github.event.pull_request.head.repo.fork }}" == "true" ]]; then + SANITIZED_REPO_NAME=$(echo "$_GITHUB_PR_REPO_NAME" | sed "s/[^a-zA-Z0-9]/-/g") # Sanitize repo name to alphanumeric only + IMAGE_TAG=$SANITIZED_REPO_NAME-$IMAGE_TAG # Add repo name to the tag + IMAGE_TAG=${IMAGE_TAG:0:128} # Limit to 128 characters, as that's the max length for Docker image tags + fi + if [[ "$IMAGE_TAG" == "main" ]]; then IMAGE_TAG=dev fi echo "image_tag=$IMAGE_TAG" >> $GITHUB_OUTPUT - echo "### :mega: Container Image Tag: $IMAGE_TAG" >> $GITHUB_STEP_SUMMARY + echo "### :mega: Docker Image Tag: $IMAGE_TAG" >> $GITHUB_STEP_SUMMARY - name: Set up project name id: setup @@ -162,8 +231,8 @@ jobs: PROJECT_NAME: ${{ steps.setup.outputs.project_name }} run: echo "name=${_AZ_REGISTRY}/${PROJECT_NAME}:buildcache" >> $GITHUB_OUTPUT - - name: Build Container image - id: build-container + - name: Build Docker image + id: build-artifacts uses: docker/build-push-action@67a2d409c0a876cbe6b11854e3e25193efe4e62d # v6.12.0 with: cache-from: type=registry,ref=${{ steps.cache-name.outputs.name }} @@ -176,6 +245,8 @@ jobs: linux/arm64 push: true tags: ${{ steps.image-tags.outputs.tags }} + secrets: | + "GH_PAT=${{ steps.retrieve-secret-pat.outputs.github-pat-bitwarden-devops-bot-repo-scope }}" - name: Install Cosign if: github.event_name != 'pull_request' && github.ref == 'refs/heads/main' @@ -184,7 +255,7 @@ jobs: - name: Sign image with Cosign if: github.event_name != 'pull_request' && github.ref == 'refs/heads/main' env: - DIGEST: ${{ steps.build-container.outputs.digest }} + DIGEST: ${{ steps.build-artifacts.outputs.digest }} TAGS: ${{ steps.image-tags.outputs.tags }} run: | IFS="," read -a tags <<< "${TAGS}" @@ -194,7 +265,7 @@ jobs: done cosign sign --yes ${images} - - name: Scan container image + - name: Scan Docker image id: container-scan uses: anchore/scan-action@abae793926ec39a78ab18002bc7fc45bbbd94342 # v6.0.0 with: @@ -209,10 +280,10 @@ jobs: 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 }} - build-stub-swagger: - name: Build Docker-Stub/Swagger + upload: + name: Upload runs-on: ubuntu-24.04 - needs: build-container + needs: build-artifacts steps: - name: Check out repo uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 @@ -227,11 +298,8 @@ jobs: with: creds: ${{ secrets.AZURE_PROD_KV_CREDENTIALS }} - - name: Login to PROD ACR - run: az acr login -n ${_AZ_REGISTRY%.azurecr.io} - - - name: Restore - run: dotnet tool restore + - name: Log in to ACR - production subscription + run: az acr login -n $_AZ_REGISTRY --only-show-errors - name: Make Docker stubs if: | @@ -326,10 +394,8 @@ jobs: - name: Build Public API Swagger run: | cd ./src/Api - echo "Restore" - dotnet restore --locked-mode - echo "Clean" - dotnet clean -c "Release" -o obj/build-output/publish + echo "Restore tools" + dotnet tool restore echo "Publish" dotnet publish -c "Release" -o obj/build-output/publish @@ -393,6 +459,8 @@ jobs: build-mssqlmigratorutility: name: Build MSSQL migrator utility runs-on: ubuntu-24.04 + needs: + - lint defaults: run: shell: bash @@ -420,11 +488,6 @@ jobs: echo "GitHub ref: $GITHUB_REF" echo "GitHub event: $GITHUB_EVENT" - - name: Restore project - run: | - echo "Restore" - dotnet restore --locked-mode - - name: Publish project run: | dotnet publish -c "Release" -o obj/build-output/publish -r ${{ matrix.target }} -p:PublishSingleFile=true \ @@ -452,7 +515,8 @@ jobs: github.event_name != 'pull_request' && (github.ref == 'refs/heads/main' || github.ref == 'refs/heads/rc' || github.ref == 'refs/heads/hotfix-rc') runs-on: ubuntu-24.04 - needs: build-container + needs: + - build-artifacts steps: - name: Log in to Azure - CI subscription uses: Azure/login@e15b166166a8746d1a47596803bd8c1b595455cf # v1.6.0 @@ -484,8 +548,9 @@ jobs: trigger-k8s-deploy: name: Trigger k8s deploy if: github.event_name != 'pull_request' && github.ref == 'refs/heads/main' - runs-on: ubuntu-24.04 - needs: build-container + runs-on: ubuntu-22.04 + needs: + - build-artifacts steps: - name: Log in to Azure - CI subscription uses: Azure/login@e15b166166a8746d1a47596803bd8c1b595455cf # v1.6.0 @@ -515,49 +580,12 @@ jobs: } }) - trigger-ee-updates: - name: Trigger Ephemeral Environment updates - if: | - needs.build-container.outputs.has_secrets == 'true' - && github.event_name == 'pull_request' - && contains(github.event.pull_request.labels.*.name, 'ephemeral-environment') - runs-on: ubuntu-24.04 - needs: build-container - steps: - - name: Log in 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 Ephemeral Environment update - 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: 'devops', - workflow_id: '_update_ephemeral_tags.yml', - ref: 'main', - inputs: { - ephemeral_env_branch: process.env.GITHUB_HEAD_REF - } - }) - - trigger-ephemeral-environment-sync: - name: Trigger Ephemeral Environment Sync + setup-ephemeral-environment: + name: Setup Ephemeral Environment needs: - - build-container - - trigger-ee-updates + - build-artifacts if: | - needs.build-container.outputs.has_secrets == 'true' + needs.build-artifacts.outputs.has_secrets == 'true' && github.event_name == 'pull_request' && contains(github.event.pull_request.labels.*.name, 'ephemeral-environment') uses: bitwarden/gh-actions/.github/workflows/_ephemeral_environment_manager.yml@main @@ -569,16 +597,14 @@ jobs: check-failures: name: Check for failures if: always() - runs-on: ubuntu-24.04 + runs-on: ubuntu-22.04 needs: - lint - - build-container - - build-stub-swagger + - build-artifacts + - upload - build-mssqlmigratorutility - self-host-build - trigger-k8s-deploy - - trigger-ee-updates - - trigger-ephemeral-environment-sync steps: - name: Check if any job failed if: |