From a16129985557ed4e9f7b7868eab72fc108bd3908 Mon Sep 17 00:00:00 2001 From: Amy Galles <9685081+AmyLGalles@users.noreply.github.com> Date: Thu, 9 Jan 2025 14:23:34 -0800 Subject: [PATCH 01/10] Example file for Scan workflow --- .github/templates/workflow-templates/scan.yml | 110 ++++++++++++++++++ 1 file changed, 110 insertions(+) create mode 100644 .github/templates/workflow-templates/scan.yml diff --git a/.github/templates/workflow-templates/scan.yml b/.github/templates/workflow-templates/scan.yml new file mode 100644 index 00000000..d59b8a3a --- /dev/null +++ b/.github/templates/workflow-templates/scan.yml @@ -0,0 +1,110 @@ +# Workflow templates are based on starter workflows provided by github at +# https://github.com/actions/starter-workflows/tree/main and customized to +# represent common practices used on Bitwarden repositories. + +# The Scan Workflow enables you to trigger SAST and quality scans directly +# From the GitHub workflow. + +name: Scan + +on: + +# Controls when the workflow will run + workflow_dispatch: # When triggered manually + + push: # On push to the following branches. Temporarily add a development branch to prompt workflow runs for troubleshooting + branches: + - "main" + - "rc" + - "hotfix-rc" + pull_request_target: # When a pull request event occurs. Default is opened or reopened unless otherwise specified, as below: + types: [opened, synchronize] + +# A workflow run is made up of one or more jobs that can run sequentially or in parallel +jobs: + # This workflow contains the jobs "check-run", "sast", and "quality" + # This job is relatively simple and just imports a previously written action to be used in this workflow + check-run: # You set this value with the name of the job you're describing + name: Check PR run # Human readable descriptor + uses: bitwarden/gh-actions/.github/workflows/check-run.yml@main # location and branch of bitwarden-owned action being used + + sast: + # A more complex job that has multiple actions as steps described below + name: SAST scan + runs-on: ubuntu-22.04 + needs: check-run # This job will wait until check-run completes + permissions: + contents: read # For actions/checkout to fetch code + pull-requests: write # For github actions to uplaod feedback to PR + security-events: write # For github/codeql-action/upload-sarif to upload SARIF results + + # Steps represent a sequence of tasks that will be executed as part of the job + steps: + - name: Check out repo + # Always pin a public action version to a full git SHA. Version pins are insecure and can introduce vulnerabilities into workflows. + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + with: # Parameters specific to this action that need to be defined in order for the step to be completed + ref: ${{ github.event.pull_request.head.sha }} + + - name: Scan with Checkmarx + uses: checkmarx/ast-github-action@f0869bd1a37fddc06499a096101e6c900e815d81 # 2.0.36 + env: # Environment variables set for this step but not accessible by all workflows, steps or jobs. + INCREMENTAL: "${{ contains(github.event_name, 'pull_request') && '--sast-incremental' || '' }}" + with: + project_name: ${{ github.repository }} + cx_tenant: ${{ secrets.CHECKMARX_TENANT }} + base_uri: https://ast.checkmarx.net/ + cx_client_id: ${{ secrets.CHECKMARX_CLIENT_ID }} + cx_client_secret: ${{ secrets.CHECKMARX_SECRET }} + additional_params: | + --report-format sarif \ + --filter "state=TO_VERIFY;PROPOSED_NOT_EXPLOITABLE;CONFIRMED;URGENT" \ + --output-path . ${{ env.INCREMENTAL }} + + - name: Upload Checkmarx results to GitHub + uses: github/codeql-action/upload-sarif@662472033e021d55d94146f66f6058822b0b39fd # v3.27.0 + with: + sarif_file: cx_result.sarif + + quality: + name: Quality scan + # The type of runner that the job will run on + runs-on: ubuntu-22.04 + needs: check-run + permissions: + contents: read + pull-requests: write + + steps: + # Set up whatever resources your environment will need to run workflows on your code + - name: Set up JDK 17 + uses: actions/setup-java@8df1039502a15bceb9433410b1a100fbe190c53b # v4.5.0 + with: + java-version: 17 + distribution: "zulu" + # This step checks out a copy of your repository. + - name: Check out repo + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + with: + fetch-depth: 0 # Full git history for actions that rely on whether a change has occurred + ref: ${{ github.event.pull_request.head.sha }} + + - name: Set up .NET + uses: actions/setup-dotnet@3e891b0cb619bf60e2c25674b222b8940e2c1c25 # v4.1.0 + # Install a tool without a Github Action + - name: Install SonarCloud scanner + run: dotnet tool install dotnet-sonarscanner -g + + - name: Scan with SonarCloud + env: + SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + # Additional scripts to run outside of a Github Action + run: | + dotnet-sonarscanner begin /k:"${{ github.repository_owner }}_${{ github.event.repository.name }}" \ + /d:sonar.test.inclusions=test/,bitwarden_license/test/ \ + /d:sonar.exclusions=test/,bitwarden_license/test/ \ + /o:"${{ github.repository_owner }}" /d:sonar.token="${{ secrets.SONAR_TOKEN }}" \ + /d:sonar.host.url="https://sonarcloud.io" + dotnet build + dotnet-sonarscanner end /d:sonar.token="${{ secrets.SONAR_TOKEN }}" \ No newline at end of file From 0c3618ed1bed50b17976608738c55b582f74c9eb Mon Sep 17 00:00:00 2001 From: Amy Galles <9685081+AmyLGalles@users.noreply.github.com> Date: Mon, 13 Jan 2025 10:12:26 -0800 Subject: [PATCH 02/10] adding second example workflow --- .../templates/workflow-templates/build.yml | 728 ++++++++++++++++++ .github/templates/workflow-templates/scan.yml | 4 +- 2 files changed, 729 insertions(+), 3 deletions(-) create mode 100644 .github/templates/workflow-templates/build.yml diff --git a/.github/templates/workflow-templates/build.yml b/.github/templates/workflow-templates/build.yml new file mode 100644 index 00000000..f0b016e4 --- /dev/null +++ b/.github/templates/workflow-templates/build.yml @@ -0,0 +1,728 @@ +# Workflow templates are based on starter workflows provided by github at +# https://github.com/actions/starter-workflows/tree/main and customized to +# represent common practices used on Bitwarden repositories. + +# The Build Workflow Lints code, builds and signs Node project, Docker images, +# related artifacts and uploads image to ACR, runs DB Migrator utility, deploys +# to Kubernetes, updates Ephemeral Environments, self-host builds, +# checks for failure and posts status to Slack. +# From the GitHub workflow. + +name: Build + +on: +# Controls when the workflow will run + workflow_dispatch: # When triggered manually + push: # On push to the following branches. Temporarily add a development branch to prompt workflow runs for troubleshooting + branches: + - "main" + - "rc" + - "hotfix-rc" + pull_request_target: # When a pull request event occurs. Default is opened or reopened unless otherwise specified, as below: + types: [opened, synchronize] + +env: # Environment variables set for this step but not accessible by all workflows, steps or jobs. + _AZ_REGISTRY: "bitwardenprod.azurecr.io" + +# A workflow run is made up of one or more jobs that can run sequentially or in parallel +jobs: #This workflow contains the jobs "check-run", "lint", "build-artifacts", "build-docker", "upload", "buildmsqlmigratorutility", +# "self-host-build", "trigger-k8s-deploy", "trigger-ee-updates", "trigger-ephemeral-environment-sync" and "check-failures" + + # This job is relatively simple and just imports a previously written action to be used in this workflow + check-run: # You set this value with the name of the job you're describing + name: Check PR run # Human readable descriptor + uses: bitwarden/gh-actions/.github/workflows/check-run.yml@main # location and branch of bitwarden-owned action being used + + lint: + name: Lint + runs-on: ubuntu-22.04 + needs: + - check-run # This job will wait until check-run completes + steps: + - name: Check out repo + + # Always pin a public action version to a full git SHA. Version pins are insecure and can introduce vulnerabilities into workflows. + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + with: # Parameters specific to this action that need to be defined in order for the step to be completed + ref: ${{ github.event.pull_request.head.sha }} + + - name: Set up .NET # Set up whatever resources your environment will need to run workflows on your code + uses: actions/setup-dotnet@87b7050bc53ea08284295505d98d2aa94301e852 # v4.2.0 + + - name: Verify format # Additional scripts to run outside of a Github Action + run: dotnet format --verify-no-changes + + build-artifacts: + name: Build artifacts + runs-on: ubuntu-22.04 + needs: + - lint + strategy: + fail-fast: false + matrix: + include: + - project_name: Admin + base_path: ./src + node: true + - project_name: Api + base_path: ./src + - project_name: Billing + base_path: ./src + - project_name: Events + base_path: ./src + - project_name: EventsProcessor + base_path: ./src + - project_name: Icons + base_path: ./src + - project_name: Identity + base_path: ./src + - project_name: MsSqlMigratorUtility + base_path: ./util + dotnet: true + - project_name: Notifications + base_path: ./src + - project_name: Scim + base_path: ./bitwarden_license/src + dotnet: true + - project_name: Server + base_path: ./util + - project_name: Setup + base_path: ./util + - project_name: Sso + base_path: ./bitwarden_license/src + node: true + steps: + - name: Check out repo + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + with: + ref: ${{ github.event.pull_request.head.sha }} + + - name: Set up .NET + uses: actions/setup-dotnet@87b7050bc53ea08284295505d98d2aa94301e852 # v4.2.0 + + - 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 }} + 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@6f51ac03b9356f520e9adb1b1b7802705f340c2b # v4.5.0 + with: + name: ${{ matrix.project_name }}.zip + path: ${{ matrix.base_path }}/${{ matrix.project_name }}/${{ matrix.project_name }}.zip + if-no-files-found: error + + build-docker: + name: Build Docker images + runs-on: ubuntu-22.04 + permissions: + security-events: write + id-token: write + needs: + - build-artifacts + strategy: + fail-fast: false + matrix: + include: + - project_name: Admin + base_path: ./src + dotnet: 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: Server + base_path: ./util + dotnet: true + - project_name: Setup + base_path: ./util + dotnet: true + - project_name: Sso + base_path: ./bitwarden_license/src + dotnet: true + 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" + 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: Log in to Azure - production subscription + uses: Azure/login@e15b166166a8746d1a47596803bd8c1b595455cf # v1.6.0 + with: + creds: ${{ secrets.AZURE_PROD_KV_CREDENTIALS }} + + - name: Log in to ACR - production subscription + run: az acr login -n bitwardenprod + + - 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_target" ]]; then + IMAGE_TAG=$(echo "${GITHUB_HEAD_REF}" | sed "s#/#-#g") + else + IMAGE_TAG=$(echo "${GITHUB_REF:11}" | sed "s#/#-#g") + fi + + if [[ "$IMAGE_TAG" == "main" ]]; then + IMAGE_TAG=dev + fi + + echo "image_tag=$IMAGE_TAG" >> $GITHUB_OUTPUT + echo "### :mega: Docker Image Tag: $IMAGE_TAG" >> $GITHUB_STEP_SUMMARY + + - name: Set up project name + id: setup + run: | + PROJECT_NAME=$(echo "${{ matrix.project_name }}" | awk '{print tolower($0)}') + echo "Matrix name: ${{ matrix.project_name }}" + echo "PROJECT_NAME: $PROJECT_NAME" + echo "project_name=$PROJECT_NAME" >> $GITHUB_OUTPUT + + - name: Generate image tags(s) + id: image-tags + env: + IMAGE_TAG: ${{ steps.tag.outputs.image_tag }} + PROJECT_NAME: ${{ steps.setup.outputs.project_name }} + SHA: ${{ github.sha }} + run: | + TAGS="${_AZ_REGISTRY}/${PROJECT_NAME}:${IMAGE_TAG}" + echo "primary_tag=$TAGS" >> $GITHUB_OUTPUT + if [[ "${IMAGE_TAG}" == "dev" ]]; then + SHORT_SHA=$(git rev-parse --short ${SHA}) + TAGS=$TAGS",${_AZ_REGISTRY}/${PROJECT_NAME}:dev-${SHORT_SHA}" + fi + echo "tags=$TAGS" >> $GITHUB_OUTPUT + + - name: Get build artifact + if: ${{ matrix.dotnet }} + uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8 + with: + name: ${{ matrix.project_name }}.zip + + - name: Set up build artifact + if: ${{ matrix.dotnet }} + run: | + mkdir -p ${{ matrix.base_path}}/${{ matrix.project_name }}/obj/build-output/publish + unzip ${{ matrix.project_name }}.zip \ + -d ${{ matrix.base_path }}/${{ matrix.project_name }}/obj/build-output/publish + + - name: Build Docker image + id: build-docker + uses: docker/build-push-action@b32b51a8eda65d6793cd0494a773d4f6bcef32dc # v6.11.0 + with: + context: ${{ matrix.base_path }}/${{ matrix.project_name }} + file: ${{ matrix.base_path }}/${{ matrix.project_name }}/Dockerfile + platforms: linux/amd64 + 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_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-tags.outputs.tags }} + 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@abae793926ec39a78ab18002bc7fc45bbbd94342 # v6.0.0 + with: + image: ${{ steps.image-tags.outputs.primary_tag }} + fail-build: false + output-format: sarif + + - name: Upload Grype results to GitHub + uses: github/codeql-action/upload-sarif@48ab28a6f5dbc2a99bf1e0131198dd8f1df78169 # v3.28.0 + with: + sarif_file: ${{ steps.container-scan.outputs.sarif }} + + upload: + name: Upload + runs-on: ubuntu-22.04 + needs: build-docker + steps: + - name: Check out repo + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + with: + ref: ${{ github.event.pull_request.head.sha }} + + - name: Set up .NET + uses: actions/setup-dotnet@87b7050bc53ea08284295505d98d2aa94301e852 # v4.2.0 + + - name: Log in to Azure - production subscription + uses: Azure/login@e15b166166a8746d1a47596803bd8c1b595455cf # v1.6.0 + with: + creds: ${{ secrets.AZURE_PROD_KV_CREDENTIALS }} + + - name: Log in to ACR - production subscription + run: az acr login -n $_AZ_REGISTRY --only-show-errors + + - name: Make Docker stubs + if: | + github.event_name != 'pull_request_target' + && (github.ref == 'refs/heads/main' || github.ref == 'refs/heads/rc' || github.ref == 'refs/heads/hotfix-rc') + run: | + # Set proper setup image based on branch + case "$GITHUB_REF" in + "refs/heads/main") + SETUP_IMAGE="$_AZ_REGISTRY/setup:dev" + ;; + "refs/heads/rc") + SETUP_IMAGE="$_AZ_REGISTRY/setup:rc" + ;; + "refs/heads/hotfix-rc") + SETUP_IMAGE="$_AZ_REGISTRY/setup:hotfix-rc" + ;; + esac + + STUB_OUTPUT=$(pwd)/docker-stub + + # Run setup + docker run -i --rm --name setup -v $STUB_OUTPUT/US:/bitwarden $SETUP_IMAGE \ + dotnet Setup.dll -stub 1 -install 1 -domain bitwarden.example.com -os lin -cloud-region US + docker run -i --rm --name setup -v $STUB_OUTPUT/EU:/bitwarden $SETUP_IMAGE \ + dotnet Setup.dll -stub 1 -install 1 -domain bitwarden.example.com -os lin -cloud-region EU + + sudo chown -R $(whoami):$(whoami) $STUB_OUTPUT + + # Remove extra directories and files + rm -rf $STUB_OUTPUT/US/letsencrypt + rm -rf $STUB_OUTPUT/EU/letsencrypt + rm $STUB_OUTPUT/US/env/uid.env $STUB_OUTPUT/US/config.yml + rm $STUB_OUTPUT/EU/env/uid.env $STUB_OUTPUT/EU/config.yml + + # Create uid environment files + touch $STUB_OUTPUT/US/env/uid.env + touch $STUB_OUTPUT/EU/env/uid.env + + # Zip up the Docker stub files + cd docker-stub/US; zip -r ../../docker-stub-US.zip *; cd ../.. + cd docker-stub/EU; zip -r ../../docker-stub-EU.zip *; cd ../.. + + - name: Make Docker stub checksums + if: | + github.event_name != 'pull_request_target' + && (github.ref == 'refs/heads/main' || github.ref == 'refs/heads/rc' || github.ref == 'refs/heads/hotfix-rc') + run: | + sha256sum docker-stub-US.zip > docker-stub-US-sha256.txt + sha256sum docker-stub-EU.zip > docker-stub-EU-sha256.txt + + - name: Upload Docker stub US artifact + if: | + github.event_name != 'pull_request_target' + && (github.ref == 'refs/heads/main' || github.ref == 'refs/heads/rc' || github.ref == 'refs/heads/hotfix-rc') + uses: actions/upload-artifact@6f51ac03b9356f520e9adb1b1b7802705f340c2b # v4.5.0 + with: + name: docker-stub-US.zip + path: docker-stub-US.zip + if-no-files-found: error + + - name: Upload Docker stub EU artifact + if: | + github.event_name != 'pull_request_target' + && (github.ref == 'refs/heads/main' || github.ref == 'refs/heads/rc' || github.ref == 'refs/heads/hotfix-rc') + uses: actions/upload-artifact@6f51ac03b9356f520e9adb1b1b7802705f340c2b # v4.5.0 + with: + name: docker-stub-EU.zip + path: docker-stub-EU.zip + if-no-files-found: error + + - name: Upload Docker stub US checksum artifact + if: | + github.event_name != 'pull_request_target' + && (github.ref == 'refs/heads/main' || github.ref == 'refs/heads/rc' || github.ref == 'refs/heads/hotfix-rc') + uses: actions/upload-artifact@6f51ac03b9356f520e9adb1b1b7802705f340c2b # v4.5.0 + with: + name: docker-stub-US-sha256.txt + path: docker-stub-US-sha256.txt + if-no-files-found: error + + - name: Upload Docker stub EU checksum artifact + if: | + github.event_name != 'pull_request_target' + && (github.ref == 'refs/heads/main' || github.ref == 'refs/heads/rc' || github.ref == 'refs/heads/hotfix-rc') + uses: actions/upload-artifact@6f51ac03b9356f520e9adb1b1b7802705f340c2b # v4.5.0 + with: + name: docker-stub-EU-sha256.txt + path: docker-stub-EU-sha256.txt + if-no-files-found: error + + - name: Build Public API Swagger + run: | + cd ./src/Api + echo "Restore tools" + dotnet tool restore + echo "Publish" + dotnet publish -c "Release" -o obj/build-output/publish + + dotnet swagger tofile --output ../../swagger.json --host https://api.bitwarden.com \ + ./obj/build-output/publish/Api.dll public + cd ../.. + env: + ASPNETCORE_ENVIRONMENT: Production + swaggerGen: "True" + DOTNET_ROLL_FORWARD_ON_NO_CANDIDATE_FX: 2 + GLOBALSETTINGS__SQLSERVER__CONNECTIONSTRING: "placeholder" + + - name: Upload Public API Swagger artifact + uses: actions/upload-artifact@6f51ac03b9356f520e9adb1b1b7802705f340c2b # v4.5.0 + with: + name: swagger.json + path: swagger.json + if-no-files-found: error + + - name: Build Internal API Swagger + run: | + cd ./src/Api + echo "Restore API tools" + dotnet tool restore + echo "Publish API" + dotnet publish -c "Release" -o obj/build-output/publish + + dotnet swagger tofile --output ../../internal.json --host https://api.bitwarden.com \ + ./obj/build-output/publish/Api.dll internal + + cd ../Identity + + echo "Restore Identity tools" + dotnet tool restore + echo "Publish Identity" + dotnet publish -c "Release" -o obj/build-output/publish + + dotnet swagger tofile --output ../../identity.json --host https://identity.bitwarden.com \ + ./obj/build-output/publish/Identity.dll v1 + cd ../.. + env: + ASPNETCORE_ENVIRONMENT: Development + swaggerGen: "True" + DOTNET_ROLL_FORWARD_ON_NO_CANDIDATE_FX: 2 + GLOBALSETTINGS__SQLSERVER__CONNECTIONSTRING: "placeholder" + + - name: Upload Internal API Swagger artifact + uses: actions/upload-artifact@6f51ac03b9356f520e9adb1b1b7802705f340c2b # v4.5.0 + with: + name: internal.json + path: internal.json + if-no-files-found: error + + - name: Upload Identity Swagger artifact + uses: actions/upload-artifact@6f51ac03b9356f520e9adb1b1b7802705f340c2b # v4.5.0 + with: + name: identity.json + path: identity.json + if-no-files-found: error + + build-mssqlmigratorutility: + name: Build MSSQL migrator utility + runs-on: ubuntu-22.04 + needs: + - lint + defaults: + run: + shell: bash + working-directory: "util/MsSqlMigratorUtility" + strategy: + fail-fast: false + matrix: + target: + - osx-x64 + - linux-x64 + - win-x64 + steps: + - name: Check out repo + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + with: + ref: ${{ github.event.pull_request.head.sha }} + + - name: Set up .NET + uses: actions/setup-dotnet@87b7050bc53ea08284295505d98d2aa94301e852 # v4.2.0 + + - name: Print environment + run: | + whoami + dotnet --info + echo "GitHub ref: $GITHUB_REF" + echo "GitHub event: $GITHUB_EVENT" + + - name: Publish project + run: | + dotnet publish -c "Release" -o obj/build-output/publish -r ${{ matrix.target }} -p:PublishSingleFile=true \ + -p:IncludeNativeLibrariesForSelfExtract=true --self-contained true + + - name: Upload project artifact for Windows + if: ${{ contains(matrix.target, 'win') == true }} + uses: actions/upload-artifact@6f51ac03b9356f520e9adb1b1b7802705f340c2b # v4.5.0 + with: + name: MsSqlMigratorUtility-${{ matrix.target }} + path: util/MsSqlMigratorUtility/obj/build-output/publish/MsSqlMigratorUtility.exe + if-no-files-found: error + + - name: Upload project artifact + if: ${{ contains(matrix.target, 'win') == false }} + uses: actions/upload-artifact@6f51ac03b9356f520e9adb1b1b7802705f340c2b # v4.5.0 + with: + name: MsSqlMigratorUtility-${{ matrix.target }} + path: util/MsSqlMigratorUtility/obj/build-output/publish/MsSqlMigratorUtility + if-no-files-found: error + + self-host-build: + name: Trigger self-host build + if: | + github.event_name != 'pull_request_target' + && (github.ref == 'refs/heads/main' || github.ref == 'refs/heads/rc' || github.ref == 'refs/heads/hotfix-rc') + runs-on: ubuntu-22.04 + needs: + - build-docker + 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 self-host build + 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: 'self-host', + workflow_id: 'build-unified.yml', + ref: 'main', + inputs: { + server_branch: process.env.GITHUB_REF + } + }); + + trigger-k8s-deploy: + name: Trigger k8s deploy + if: github.event_name != 'pull_request_target' && github.ref == 'refs/heads/main' + runs-on: ubuntu-22.04 + needs: + - build-docker + 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 k8s deploy + 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: 'deploy-k8s.yml', + ref: 'main', + inputs: { + environment: 'US-DEV Cloud', + tag: 'main' + } + }) + + trigger-ee-updates: + name: Trigger Ephemeral Environment updates + if: | + github.event_name == 'pull_request_target' + && contains(github.event.pull_request.labels.*.name, 'ephemeral-environment') + runs-on: ubuntu-24.04 + needs: + - build-docker + 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 + needs: trigger-ee-updates + if: | + github.event_name == 'pull_request_target' + && contains(github.event.pull_request.labels.*.name, 'ephemeral-environment') + uses: bitwarden/gh-actions/.github/workflows/_ephemeral_environment_manager.yml@main + with: + ephemeral_env_branch: process.env.GITHUB_HEAD_REF + project: server + sync_environment: true + pull_request_number: ${{ github.event.number }} + secrets: inherit + + check-failures: + name: Check for failures + if: always() + runs-on: ubuntu-22.04 + needs: + - lint + - build-artifacts + - build-docker + - upload + - build-mssqlmigratorutility + - self-host-build + - trigger-k8s-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') + && contains(needs.*.result, 'failure') + run: exit 1 + + - name: Log in to Azure - CI subscription + uses: Azure/login@e15b166166a8746d1a47596803bd8c1b595455cf # v1.6.0 + if: failure() + with: + creds: ${{ secrets.AZURE_KV_CI_SERVICE_PRINCIPAL }} + + - name: Retrieve secrets + id: retrieve-secrets + uses: bitwarden/gh-actions/get-keyvault-secrets@main + if: failure() + 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 }} \ No newline at end of file diff --git a/.github/templates/workflow-templates/scan.yml b/.github/templates/workflow-templates/scan.yml index d59b8a3a..a05a0384 100644 --- a/.github/templates/workflow-templates/scan.yml +++ b/.github/templates/workflow-templates/scan.yml @@ -8,7 +8,6 @@ name: Scan on: - # Controls when the workflow will run workflow_dispatch: # When triggered manually @@ -31,7 +30,7 @@ jobs: sast: # A more complex job that has multiple actions as steps described below name: SAST scan - runs-on: ubuntu-22.04 + runs-on: ubuntu-22.04 # The type of runner that the job will run on needs: check-run # This job will wait until check-run completes permissions: contents: read # For actions/checkout to fetch code @@ -68,7 +67,6 @@ jobs: quality: name: Quality scan - # The type of runner that the job will run on runs-on: ubuntu-22.04 needs: check-run permissions: From 22c364d6082d3635aa3206a0bcfbfdaa234ec419 Mon Sep 17 00:00:00 2001 From: Amy Galles <9685081+AmyLGalles@users.noreply.github.com> Date: Mon, 13 Jan 2025 10:16:39 -0800 Subject: [PATCH 03/10] documenting some options not used in this workflow --- .github/templates/workflow-templates/scan.yml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.github/templates/workflow-templates/scan.yml b/.github/templates/workflow-templates/scan.yml index a05a0384..1c6710f7 100644 --- a/.github/templates/workflow-templates/scan.yml +++ b/.github/templates/workflow-templates/scan.yml @@ -9,6 +9,9 @@ name: Scan on: # Controls when the workflow will run + +# Can use other triggers such as multiple events, activity types and fiters: +# https://docs.github.com/en/actions/writing-workflows/workflow-syntax-for-github-actions#on workflow_dispatch: # When triggered manually push: # On push to the following branches. Temporarily add a development branch to prompt workflow runs for troubleshooting @@ -17,7 +20,7 @@ on: - "rc" - "hotfix-rc" pull_request_target: # When a pull request event occurs. Default is opened or reopened unless otherwise specified, as below: - types: [opened, synchronize] + types: [opened, synchronize] # Other options include labeled, unlabeled, reopened # A workflow run is made up of one or more jobs that can run sequentially or in parallel jobs: From a1da0286787d14fc74acfe491f0672f18cbba935 Mon Sep 17 00:00:00 2001 From: Amy Galles <9685081+AmyLGalles@users.noreply.github.com> Date: Mon, 13 Jan 2025 10:31:15 -0800 Subject: [PATCH 04/10] adding example of not running on draft PRs --- .github/templates/workflow-templates/build.yml | 7 ++++--- .github/templates/workflow-templates/scan.yml | 3 ++- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/.github/templates/workflow-templates/build.yml b/.github/templates/workflow-templates/build.yml index f0b016e4..b158bb44 100644 --- a/.github/templates/workflow-templates/build.yml +++ b/.github/templates/workflow-templates/build.yml @@ -35,6 +35,7 @@ jobs: #This workflow contains the jobs "check-run", "lint", "build-artifacts", " lint: name: Lint + if: github.event.pull_request.draft == false # prevent part of a job from running on a draft PR runs-on: ubuntu-22.04 needs: - check-run # This job will wait until check-run completes @@ -57,9 +58,9 @@ jobs: #This workflow contains the jobs "check-run", "lint", "build-artifacts", " runs-on: ubuntu-22.04 needs: - lint - strategy: - fail-fast: false - matrix: + strategy: # Create multiple job runs for each of a set of variables + fail-fast: false # If true, cancel entire run if any job in the matrix fails + matrix: # Matrix of variables used to define multiple job runs include: - project_name: Admin base_path: ./src diff --git a/.github/templates/workflow-templates/scan.yml b/.github/templates/workflow-templates/scan.yml index 1c6710f7..4ee4f9b6 100644 --- a/.github/templates/workflow-templates/scan.yml +++ b/.github/templates/workflow-templates/scan.yml @@ -44,11 +44,12 @@ jobs: steps: - name: Check out repo # Always pin a public action version to a full git SHA. Version pins are insecure and can introduce vulnerabilities into workflows. - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: # Parameters specific to this action that need to be defined in order for the step to be completed ref: ${{ github.event.pull_request.head.sha }} - name: Scan with Checkmarx + if: github.event.pull_request.draft == false # prevent part of a job from running on a draft PR uses: checkmarx/ast-github-action@f0869bd1a37fddc06499a096101e6c900e815d81 # 2.0.36 env: # Environment variables set for this step but not accessible by all workflows, steps or jobs. INCREMENTAL: "${{ contains(github.event_name, 'pull_request') && '--sast-incremental' || '' }}" From f218de4f66e7c1d8b6e8c166d6d08950f3360639 Mon Sep 17 00:00:00 2001 From: Amy Galles <9685081+AmyLGalles@users.noreply.github.com> Date: Wed, 15 Jan 2025 12:57:59 -0800 Subject: [PATCH 05/10] removing some potentially harmful default features and documenting why --- .../templates/workflow-templates/build.yml | 43 ++++++------------- .github/templates/workflow-templates/scan.yml | 20 +++++---- 2 files changed, 26 insertions(+), 37 deletions(-) diff --git a/.github/templates/workflow-templates/build.yml b/.github/templates/workflow-templates/build.yml index b158bb44..021615a4 100644 --- a/.github/templates/workflow-templates/build.yml +++ b/.github/templates/workflow-templates/build.yml @@ -2,7 +2,7 @@ # https://github.com/actions/starter-workflows/tree/main and customized to # represent common practices used on Bitwarden repositories. -# The Build Workflow Lints code, builds and signs Node project, Docker images, +# The Build Workflow Lints code, builds Node project, Docker images, # related artifacts and uploads image to ACR, runs DB Migrator utility, deploys # to Kubernetes, updates Ephemeral Environments, self-host builds, # checks for failure and posts status to Slack. @@ -18,27 +18,29 @@ on: - "main" - "rc" - "hotfix-rc" - pull_request_target: # When a pull request event occurs. Default is opened or reopened unless otherwise specified, as below: - types: [opened, synchronize] + # pull_request_target: #We strongly discourage using this unless absolutely necessary as it requires access to certain Github secrets + # More info at https://github.blog/news-insights/product-news/github-actions-improvements-for-fork-and-pull-request-workflows/#improvements-for-public-repository-forks + pull_request: # When a pull request event occurs + branches: ["main"] # Branches where a pull request will trigger the workflow + paths-ignore: # Updates to these directories or files will not trigger a workflow run + - ".github/workflows/**" + push: + branches: ["main"] + paths-ignore: + - ".github/workflows/**" env: # Environment variables set for this step but not accessible by all workflows, steps or jobs. _AZ_REGISTRY: "bitwardenprod.azurecr.io" # A workflow run is made up of one or more jobs that can run sequentially or in parallel -jobs: #This workflow contains the jobs "check-run", "lint", "build-artifacts", "build-docker", "upload", "buildmsqlmigratorutility", +jobs: #This workflow contains the jobs "lint", "build-artifacts", "build-docker", "upload", "buildmsqlmigratorutility", # "self-host-build", "trigger-k8s-deploy", "trigger-ee-updates", "trigger-ephemeral-environment-sync" and "check-failures" # This job is relatively simple and just imports a previously written action to be used in this workflow - check-run: # You set this value with the name of the job you're describing - name: Check PR run # Human readable descriptor - uses: bitwarden/gh-actions/.github/workflows/check-run.yml@main # location and branch of bitwarden-owned action being used - - lint: + lint: name: Lint if: github.event.pull_request.draft == false # prevent part of a job from running on a draft PR runs-on: ubuntu-22.04 - needs: - - check-run # This job will wait until check-run completes steps: - name: Check out repo @@ -57,7 +59,7 @@ jobs: #This workflow contains the jobs "check-run", "lint", "build-artifacts", " name: Build artifacts runs-on: ubuntu-22.04 needs: - - lint + - lint # This job will wait until lint completes strategy: # Create multiple job runs for each of a set of variables fail-fast: false # If true, cancel entire run if any job in the matrix fails matrix: # Matrix of variables used to define multiple job runs @@ -306,23 +308,6 @@ jobs: #This workflow contains the jobs "check-run", "lint", "build-artifacts", " 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-tags.outputs.tags }} - 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@abae793926ec39a78ab18002bc7fc45bbbd94342 # v6.0.0 diff --git a/.github/templates/workflow-templates/scan.yml b/.github/templates/workflow-templates/scan.yml index 4ee4f9b6..046fb3da 100644 --- a/.github/templates/workflow-templates/scan.yml +++ b/.github/templates/workflow-templates/scan.yml @@ -19,22 +19,26 @@ on: - "main" - "rc" - "hotfix-rc" - pull_request_target: # When a pull request event occurs. Default is opened or reopened unless otherwise specified, as below: - types: [opened, synchronize] # Other options include labeled, unlabeled, reopened + # pull_request_target: #We strongly discourage using this unless absolutely necessary as it requires access to certain Github secrets + # More info at https://github.blog/news-insights/product-news/github-actions-improvements-for-fork-and-pull-request-workflows/#improvements-for-public-repository-forks + pull_request: # When a pull request event occurs + branches: ["main"] # Branches where a pull request will trigger the workflow + paths-ignore: # Updates to these directories or files will not trigger a workflow run + - ".github/workflows/**" + push: + branches: ["main"] + paths-ignore: + - ".github/workflows/**" # A workflow run is made up of one or more jobs that can run sequentially or in parallel jobs: - # This workflow contains the jobs "check-run", "sast", and "quality" + # This workflow contains the jobs "sast", and "quality" # This job is relatively simple and just imports a previously written action to be used in this workflow - check-run: # You set this value with the name of the job you're describing - name: Check PR run # Human readable descriptor - uses: bitwarden/gh-actions/.github/workflows/check-run.yml@main # location and branch of bitwarden-owned action being used sast: # A more complex job that has multiple actions as steps described below name: SAST scan runs-on: ubuntu-22.04 # The type of runner that the job will run on - needs: check-run # This job will wait until check-run completes permissions: contents: read # For actions/checkout to fetch code pull-requests: write # For github actions to uplaod feedback to PR @@ -72,7 +76,7 @@ jobs: quality: name: Quality scan runs-on: ubuntu-22.04 - needs: check-run +# needs: use this if you want this step to wait for another to finish before running permissions: contents: read pull-requests: write From 742ae04ff237945c4971c3b4a70f668e04e00702 Mon Sep 17 00:00:00 2001 From: Amy Galles <9685081+AmyLGalles@users.noreply.github.com> Date: Thu, 23 Jan 2025 14:34:59 -0800 Subject: [PATCH 06/10] adding a more concise example for ci runs --- .github/templates/workflow-templates/ci.yaml | 52 ++++++++++++++++++++ 1 file changed, 52 insertions(+) create mode 100644 .github/templates/workflow-templates/ci.yaml diff --git a/.github/templates/workflow-templates/ci.yaml b/.github/templates/workflow-templates/ci.yaml new file mode 100644 index 00000000..daaceae1 --- /dev/null +++ b/.github/templates/workflow-templates/ci.yaml @@ -0,0 +1,52 @@ +# Workflow templates are based on starter workflows provided by github at +# https://github.com/actions/starter-workflows/tree/main and customized to +# represent common practices used on Bitwarden repositories. + +name: CI + +on: + workflow_dispatch: # Allows you to run this workflow manually from the Actions tab + pull_request: # When a pull request event occurs + +permissions: # Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages + checks: write + contents: read + id-token: write + pull-requests: write + +jobs: + version: + name: Calculate version + uses: ./.github/workflows/_version.yml #path to a pre-written + + test: + name: Run test + uses: ./.github/workflows/_test.yml + with: + project-name: Billing.Test + project-path: ./test/Billing.Test + + build: + name: Run build + needs: + - test + - version + uses: ./.github/workflows/_build.yml + with: + project-name: Billing + project-path: ./src/Billing + version: ${{ needs.version.outputs.version }} + + build-push-docker: + name: Build Docker image + needs: + - test + - version + - build + uses: ./.github/workflows/_docker.yml + with: + project-name: Billing + project-path: ./src/Billing + version: ${{ needs.version.outputs.version }} + image-name: billing-relay + push-docker-image: false \ No newline at end of file From 2adc0f31de53715573d269662975bddb19ea1be8 Mon Sep 17 00:00:00 2001 From: Amy Galles <9685081+AmyLGalles@users.noreply.github.com> Date: Thu, 23 Jan 2025 17:03:14 -0800 Subject: [PATCH 07/10] included glossary-style workflow example and removed bad build example --- .../templates/workflow-templates/build.yml | 714 ------------------ .github/templates/workflow-templates/ci.yaml | 16 +- .../templates/workflow-templates/example.yml | 107 +++ .github/templates/workflow-templates/scan.yml | 8 +- 4 files changed, 121 insertions(+), 724 deletions(-) delete mode 100644 .github/templates/workflow-templates/build.yml create mode 100644 .github/templates/workflow-templates/example.yml diff --git a/.github/templates/workflow-templates/build.yml b/.github/templates/workflow-templates/build.yml deleted file mode 100644 index 021615a4..00000000 --- a/.github/templates/workflow-templates/build.yml +++ /dev/null @@ -1,714 +0,0 @@ -# Workflow templates are based on starter workflows provided by github at -# https://github.com/actions/starter-workflows/tree/main and customized to -# represent common practices used on Bitwarden repositories. - -# The Build Workflow Lints code, builds Node project, Docker images, -# related artifacts and uploads image to ACR, runs DB Migrator utility, deploys -# to Kubernetes, updates Ephemeral Environments, self-host builds, -# checks for failure and posts status to Slack. -# From the GitHub workflow. - -name: Build - -on: -# Controls when the workflow will run - workflow_dispatch: # When triggered manually - push: # On push to the following branches. Temporarily add a development branch to prompt workflow runs for troubleshooting - branches: - - "main" - - "rc" - - "hotfix-rc" - # pull_request_target: #We strongly discourage using this unless absolutely necessary as it requires access to certain Github secrets - # More info at https://github.blog/news-insights/product-news/github-actions-improvements-for-fork-and-pull-request-workflows/#improvements-for-public-repository-forks - pull_request: # When a pull request event occurs - branches: ["main"] # Branches where a pull request will trigger the workflow - paths-ignore: # Updates to these directories or files will not trigger a workflow run - - ".github/workflows/**" - push: - branches: ["main"] - paths-ignore: - - ".github/workflows/**" - -env: # Environment variables set for this step but not accessible by all workflows, steps or jobs. - _AZ_REGISTRY: "bitwardenprod.azurecr.io" - -# A workflow run is made up of one or more jobs that can run sequentially or in parallel -jobs: #This workflow contains the jobs "lint", "build-artifacts", "build-docker", "upload", "buildmsqlmigratorutility", -# "self-host-build", "trigger-k8s-deploy", "trigger-ee-updates", "trigger-ephemeral-environment-sync" and "check-failures" - - # This job is relatively simple and just imports a previously written action to be used in this workflow - lint: - name: Lint - if: github.event.pull_request.draft == false # prevent part of a job from running on a draft PR - runs-on: ubuntu-22.04 - steps: - - name: Check out repo - - # Always pin a public action version to a full git SHA. Version pins are insecure and can introduce vulnerabilities into workflows. - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - with: # Parameters specific to this action that need to be defined in order for the step to be completed - ref: ${{ github.event.pull_request.head.sha }} - - - name: Set up .NET # Set up whatever resources your environment will need to run workflows on your code - uses: actions/setup-dotnet@87b7050bc53ea08284295505d98d2aa94301e852 # v4.2.0 - - - name: Verify format # Additional scripts to run outside of a Github Action - run: dotnet format --verify-no-changes - - build-artifacts: - name: Build artifacts - runs-on: ubuntu-22.04 - needs: - - lint # This job will wait until lint completes - strategy: # Create multiple job runs for each of a set of variables - fail-fast: false # If true, cancel entire run if any job in the matrix fails - matrix: # Matrix of variables used to define multiple job runs - include: - - project_name: Admin - base_path: ./src - node: true - - project_name: Api - base_path: ./src - - project_name: Billing - base_path: ./src - - project_name: Events - base_path: ./src - - project_name: EventsProcessor - base_path: ./src - - project_name: Icons - base_path: ./src - - project_name: Identity - base_path: ./src - - project_name: MsSqlMigratorUtility - base_path: ./util - dotnet: true - - project_name: Notifications - base_path: ./src - - project_name: Scim - base_path: ./bitwarden_license/src - dotnet: true - - project_name: Server - base_path: ./util - - project_name: Setup - base_path: ./util - - project_name: Sso - base_path: ./bitwarden_license/src - node: true - steps: - - name: Check out repo - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - with: - ref: ${{ github.event.pull_request.head.sha }} - - - name: Set up .NET - uses: actions/setup-dotnet@87b7050bc53ea08284295505d98d2aa94301e852 # v4.2.0 - - - 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 }} - 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@6f51ac03b9356f520e9adb1b1b7802705f340c2b # v4.5.0 - with: - name: ${{ matrix.project_name }}.zip - path: ${{ matrix.base_path }}/${{ matrix.project_name }}/${{ matrix.project_name }}.zip - if-no-files-found: error - - build-docker: - name: Build Docker images - runs-on: ubuntu-22.04 - permissions: - security-events: write - id-token: write - needs: - - build-artifacts - strategy: - fail-fast: false - matrix: - include: - - project_name: Admin - base_path: ./src - dotnet: 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: Server - base_path: ./util - dotnet: true - - project_name: Setup - base_path: ./util - dotnet: true - - project_name: Sso - base_path: ./bitwarden_license/src - dotnet: true - 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" - 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: Log in to Azure - production subscription - uses: Azure/login@e15b166166a8746d1a47596803bd8c1b595455cf # v1.6.0 - with: - creds: ${{ secrets.AZURE_PROD_KV_CREDENTIALS }} - - - name: Log in to ACR - production subscription - run: az acr login -n bitwardenprod - - - 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_target" ]]; then - IMAGE_TAG=$(echo "${GITHUB_HEAD_REF}" | sed "s#/#-#g") - else - IMAGE_TAG=$(echo "${GITHUB_REF:11}" | sed "s#/#-#g") - fi - - if [[ "$IMAGE_TAG" == "main" ]]; then - IMAGE_TAG=dev - fi - - echo "image_tag=$IMAGE_TAG" >> $GITHUB_OUTPUT - echo "### :mega: Docker Image Tag: $IMAGE_TAG" >> $GITHUB_STEP_SUMMARY - - - name: Set up project name - id: setup - run: | - PROJECT_NAME=$(echo "${{ matrix.project_name }}" | awk '{print tolower($0)}') - echo "Matrix name: ${{ matrix.project_name }}" - echo "PROJECT_NAME: $PROJECT_NAME" - echo "project_name=$PROJECT_NAME" >> $GITHUB_OUTPUT - - - name: Generate image tags(s) - id: image-tags - env: - IMAGE_TAG: ${{ steps.tag.outputs.image_tag }} - PROJECT_NAME: ${{ steps.setup.outputs.project_name }} - SHA: ${{ github.sha }} - run: | - TAGS="${_AZ_REGISTRY}/${PROJECT_NAME}:${IMAGE_TAG}" - echo "primary_tag=$TAGS" >> $GITHUB_OUTPUT - if [[ "${IMAGE_TAG}" == "dev" ]]; then - SHORT_SHA=$(git rev-parse --short ${SHA}) - TAGS=$TAGS",${_AZ_REGISTRY}/${PROJECT_NAME}:dev-${SHORT_SHA}" - fi - echo "tags=$TAGS" >> $GITHUB_OUTPUT - - - name: Get build artifact - if: ${{ matrix.dotnet }} - uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8 - with: - name: ${{ matrix.project_name }}.zip - - - name: Set up build artifact - if: ${{ matrix.dotnet }} - run: | - mkdir -p ${{ matrix.base_path}}/${{ matrix.project_name }}/obj/build-output/publish - unzip ${{ matrix.project_name }}.zip \ - -d ${{ matrix.base_path }}/${{ matrix.project_name }}/obj/build-output/publish - - - name: Build Docker image - id: build-docker - uses: docker/build-push-action@b32b51a8eda65d6793cd0494a773d4f6bcef32dc # v6.11.0 - with: - context: ${{ matrix.base_path }}/${{ matrix.project_name }} - file: ${{ matrix.base_path }}/${{ matrix.project_name }}/Dockerfile - platforms: linux/amd64 - push: true - tags: ${{ steps.image-tags.outputs.tags }} - secrets: | - "GH_PAT=${{ steps.retrieve-secret-pat.outputs.github-pat-bitwarden-devops-bot-repo-scope }}" - - - name: Scan Docker image - id: container-scan - uses: anchore/scan-action@abae793926ec39a78ab18002bc7fc45bbbd94342 # v6.0.0 - with: - image: ${{ steps.image-tags.outputs.primary_tag }} - fail-build: false - output-format: sarif - - - name: Upload Grype results to GitHub - uses: github/codeql-action/upload-sarif@48ab28a6f5dbc2a99bf1e0131198dd8f1df78169 # v3.28.0 - with: - sarif_file: ${{ steps.container-scan.outputs.sarif }} - - upload: - name: Upload - runs-on: ubuntu-22.04 - needs: build-docker - steps: - - name: Check out repo - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - with: - ref: ${{ github.event.pull_request.head.sha }} - - - name: Set up .NET - uses: actions/setup-dotnet@87b7050bc53ea08284295505d98d2aa94301e852 # v4.2.0 - - - name: Log in to Azure - production subscription - uses: Azure/login@e15b166166a8746d1a47596803bd8c1b595455cf # v1.6.0 - with: - creds: ${{ secrets.AZURE_PROD_KV_CREDENTIALS }} - - - name: Log in to ACR - production subscription - run: az acr login -n $_AZ_REGISTRY --only-show-errors - - - name: Make Docker stubs - if: | - github.event_name != 'pull_request_target' - && (github.ref == 'refs/heads/main' || github.ref == 'refs/heads/rc' || github.ref == 'refs/heads/hotfix-rc') - run: | - # Set proper setup image based on branch - case "$GITHUB_REF" in - "refs/heads/main") - SETUP_IMAGE="$_AZ_REGISTRY/setup:dev" - ;; - "refs/heads/rc") - SETUP_IMAGE="$_AZ_REGISTRY/setup:rc" - ;; - "refs/heads/hotfix-rc") - SETUP_IMAGE="$_AZ_REGISTRY/setup:hotfix-rc" - ;; - esac - - STUB_OUTPUT=$(pwd)/docker-stub - - # Run setup - docker run -i --rm --name setup -v $STUB_OUTPUT/US:/bitwarden $SETUP_IMAGE \ - dotnet Setup.dll -stub 1 -install 1 -domain bitwarden.example.com -os lin -cloud-region US - docker run -i --rm --name setup -v $STUB_OUTPUT/EU:/bitwarden $SETUP_IMAGE \ - dotnet Setup.dll -stub 1 -install 1 -domain bitwarden.example.com -os lin -cloud-region EU - - sudo chown -R $(whoami):$(whoami) $STUB_OUTPUT - - # Remove extra directories and files - rm -rf $STUB_OUTPUT/US/letsencrypt - rm -rf $STUB_OUTPUT/EU/letsencrypt - rm $STUB_OUTPUT/US/env/uid.env $STUB_OUTPUT/US/config.yml - rm $STUB_OUTPUT/EU/env/uid.env $STUB_OUTPUT/EU/config.yml - - # Create uid environment files - touch $STUB_OUTPUT/US/env/uid.env - touch $STUB_OUTPUT/EU/env/uid.env - - # Zip up the Docker stub files - cd docker-stub/US; zip -r ../../docker-stub-US.zip *; cd ../.. - cd docker-stub/EU; zip -r ../../docker-stub-EU.zip *; cd ../.. - - - name: Make Docker stub checksums - if: | - github.event_name != 'pull_request_target' - && (github.ref == 'refs/heads/main' || github.ref == 'refs/heads/rc' || github.ref == 'refs/heads/hotfix-rc') - run: | - sha256sum docker-stub-US.zip > docker-stub-US-sha256.txt - sha256sum docker-stub-EU.zip > docker-stub-EU-sha256.txt - - - name: Upload Docker stub US artifact - if: | - github.event_name != 'pull_request_target' - && (github.ref == 'refs/heads/main' || github.ref == 'refs/heads/rc' || github.ref == 'refs/heads/hotfix-rc') - uses: actions/upload-artifact@6f51ac03b9356f520e9adb1b1b7802705f340c2b # v4.5.0 - with: - name: docker-stub-US.zip - path: docker-stub-US.zip - if-no-files-found: error - - - name: Upload Docker stub EU artifact - if: | - github.event_name != 'pull_request_target' - && (github.ref == 'refs/heads/main' || github.ref == 'refs/heads/rc' || github.ref == 'refs/heads/hotfix-rc') - uses: actions/upload-artifact@6f51ac03b9356f520e9adb1b1b7802705f340c2b # v4.5.0 - with: - name: docker-stub-EU.zip - path: docker-stub-EU.zip - if-no-files-found: error - - - name: Upload Docker stub US checksum artifact - if: | - github.event_name != 'pull_request_target' - && (github.ref == 'refs/heads/main' || github.ref == 'refs/heads/rc' || github.ref == 'refs/heads/hotfix-rc') - uses: actions/upload-artifact@6f51ac03b9356f520e9adb1b1b7802705f340c2b # v4.5.0 - with: - name: docker-stub-US-sha256.txt - path: docker-stub-US-sha256.txt - if-no-files-found: error - - - name: Upload Docker stub EU checksum artifact - if: | - github.event_name != 'pull_request_target' - && (github.ref == 'refs/heads/main' || github.ref == 'refs/heads/rc' || github.ref == 'refs/heads/hotfix-rc') - uses: actions/upload-artifact@6f51ac03b9356f520e9adb1b1b7802705f340c2b # v4.5.0 - with: - name: docker-stub-EU-sha256.txt - path: docker-stub-EU-sha256.txt - if-no-files-found: error - - - name: Build Public API Swagger - run: | - cd ./src/Api - echo "Restore tools" - dotnet tool restore - echo "Publish" - dotnet publish -c "Release" -o obj/build-output/publish - - dotnet swagger tofile --output ../../swagger.json --host https://api.bitwarden.com \ - ./obj/build-output/publish/Api.dll public - cd ../.. - env: - ASPNETCORE_ENVIRONMENT: Production - swaggerGen: "True" - DOTNET_ROLL_FORWARD_ON_NO_CANDIDATE_FX: 2 - GLOBALSETTINGS__SQLSERVER__CONNECTIONSTRING: "placeholder" - - - name: Upload Public API Swagger artifact - uses: actions/upload-artifact@6f51ac03b9356f520e9adb1b1b7802705f340c2b # v4.5.0 - with: - name: swagger.json - path: swagger.json - if-no-files-found: error - - - name: Build Internal API Swagger - run: | - cd ./src/Api - echo "Restore API tools" - dotnet tool restore - echo "Publish API" - dotnet publish -c "Release" -o obj/build-output/publish - - dotnet swagger tofile --output ../../internal.json --host https://api.bitwarden.com \ - ./obj/build-output/publish/Api.dll internal - - cd ../Identity - - echo "Restore Identity tools" - dotnet tool restore - echo "Publish Identity" - dotnet publish -c "Release" -o obj/build-output/publish - - dotnet swagger tofile --output ../../identity.json --host https://identity.bitwarden.com \ - ./obj/build-output/publish/Identity.dll v1 - cd ../.. - env: - ASPNETCORE_ENVIRONMENT: Development - swaggerGen: "True" - DOTNET_ROLL_FORWARD_ON_NO_CANDIDATE_FX: 2 - GLOBALSETTINGS__SQLSERVER__CONNECTIONSTRING: "placeholder" - - - name: Upload Internal API Swagger artifact - uses: actions/upload-artifact@6f51ac03b9356f520e9adb1b1b7802705f340c2b # v4.5.0 - with: - name: internal.json - path: internal.json - if-no-files-found: error - - - name: Upload Identity Swagger artifact - uses: actions/upload-artifact@6f51ac03b9356f520e9adb1b1b7802705f340c2b # v4.5.0 - with: - name: identity.json - path: identity.json - if-no-files-found: error - - build-mssqlmigratorutility: - name: Build MSSQL migrator utility - runs-on: ubuntu-22.04 - needs: - - lint - defaults: - run: - shell: bash - working-directory: "util/MsSqlMigratorUtility" - strategy: - fail-fast: false - matrix: - target: - - osx-x64 - - linux-x64 - - win-x64 - steps: - - name: Check out repo - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - with: - ref: ${{ github.event.pull_request.head.sha }} - - - name: Set up .NET - uses: actions/setup-dotnet@87b7050bc53ea08284295505d98d2aa94301e852 # v4.2.0 - - - name: Print environment - run: | - whoami - dotnet --info - echo "GitHub ref: $GITHUB_REF" - echo "GitHub event: $GITHUB_EVENT" - - - name: Publish project - run: | - dotnet publish -c "Release" -o obj/build-output/publish -r ${{ matrix.target }} -p:PublishSingleFile=true \ - -p:IncludeNativeLibrariesForSelfExtract=true --self-contained true - - - name: Upload project artifact for Windows - if: ${{ contains(matrix.target, 'win') == true }} - uses: actions/upload-artifact@6f51ac03b9356f520e9adb1b1b7802705f340c2b # v4.5.0 - with: - name: MsSqlMigratorUtility-${{ matrix.target }} - path: util/MsSqlMigratorUtility/obj/build-output/publish/MsSqlMigratorUtility.exe - if-no-files-found: error - - - name: Upload project artifact - if: ${{ contains(matrix.target, 'win') == false }} - uses: actions/upload-artifact@6f51ac03b9356f520e9adb1b1b7802705f340c2b # v4.5.0 - with: - name: MsSqlMigratorUtility-${{ matrix.target }} - path: util/MsSqlMigratorUtility/obj/build-output/publish/MsSqlMigratorUtility - if-no-files-found: error - - self-host-build: - name: Trigger self-host build - if: | - github.event_name != 'pull_request_target' - && (github.ref == 'refs/heads/main' || github.ref == 'refs/heads/rc' || github.ref == 'refs/heads/hotfix-rc') - runs-on: ubuntu-22.04 - needs: - - build-docker - 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 self-host build - 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: 'self-host', - workflow_id: 'build-unified.yml', - ref: 'main', - inputs: { - server_branch: process.env.GITHUB_REF - } - }); - - trigger-k8s-deploy: - name: Trigger k8s deploy - if: github.event_name != 'pull_request_target' && github.ref == 'refs/heads/main' - runs-on: ubuntu-22.04 - needs: - - build-docker - 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 k8s deploy - 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: 'deploy-k8s.yml', - ref: 'main', - inputs: { - environment: 'US-DEV Cloud', - tag: 'main' - } - }) - - trigger-ee-updates: - name: Trigger Ephemeral Environment updates - if: | - github.event_name == 'pull_request_target' - && contains(github.event.pull_request.labels.*.name, 'ephemeral-environment') - runs-on: ubuntu-24.04 - needs: - - build-docker - 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 - needs: trigger-ee-updates - if: | - github.event_name == 'pull_request_target' - && contains(github.event.pull_request.labels.*.name, 'ephemeral-environment') - uses: bitwarden/gh-actions/.github/workflows/_ephemeral_environment_manager.yml@main - with: - ephemeral_env_branch: process.env.GITHUB_HEAD_REF - project: server - sync_environment: true - pull_request_number: ${{ github.event.number }} - secrets: inherit - - check-failures: - name: Check for failures - if: always() - runs-on: ubuntu-22.04 - needs: - - lint - - build-artifacts - - build-docker - - upload - - build-mssqlmigratorutility - - self-host-build - - trigger-k8s-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') - && contains(needs.*.result, 'failure') - run: exit 1 - - - name: Log in to Azure - CI subscription - uses: Azure/login@e15b166166a8746d1a47596803bd8c1b595455cf # v1.6.0 - if: failure() - with: - creds: ${{ secrets.AZURE_KV_CI_SERVICE_PRINCIPAL }} - - - name: Retrieve secrets - id: retrieve-secrets - uses: bitwarden/gh-actions/get-keyvault-secrets@main - if: failure() - 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 }} \ No newline at end of file diff --git a/.github/templates/workflow-templates/ci.yaml b/.github/templates/workflow-templates/ci.yaml index daaceae1..c6fbe501 100644 --- a/.github/templates/workflow-templates/ci.yaml +++ b/.github/templates/workflow-templates/ci.yaml @@ -8,27 +8,27 @@ on: workflow_dispatch: # Allows you to run this workflow manually from the Actions tab pull_request: # When a pull request event occurs -permissions: # Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages - checks: write - contents: read - id-token: write - pull-requests: write +permissions: # Sets permissions of the GITHUB_TOKEN + checks: write # permits an action to create a check run + contents: read # for actions to fetch code and list commits + id-token: write # required to fetch an OpenID Connect (OIDC) token + pull-requests: write # permits an action to add a label to a pull request jobs: version: name: Calculate version - uses: ./.github/workflows/_version.yml #path to a pre-written + uses: ./.github/workflows/_version.yml #path to an existing github action test: name: Run test uses: ./.github/workflows/_test.yml - with: + with: # Parameters specific to this action that need to be defined in order for the step to be completed project-name: Billing.Test project-path: ./test/Billing.Test build: name: Run build - needs: + needs: # This job will not run until test and version jobs are complete - test - version uses: ./.github/workflows/_build.yml diff --git a/.github/templates/workflow-templates/example.yml b/.github/templates/workflow-templates/example.yml new file mode 100644 index 00000000..c12f8d14 --- /dev/null +++ b/.github/templates/workflow-templates/example.yml @@ -0,0 +1,107 @@ +# Workflow templates are based on starter workflows provided by github at +# https://github.com/actions/starter-workflows/tree/main and customized to +# represent common practices used on ACME repositories. + +# This imaginary workflow runs two steps and illustrates a number of options that we use throughout workflows in the Bitwarden repositories + +name: Build + +on: # describes when to run the workflow + # https://docs.github.com/en/actions/writing-workflows/choosing-when-your-workflow-runs/events-that-trigger-workflows + + workflow_dispatch: # When triggered manually + + push: # On push to the following branches. Temporarily add a development branch to prompt workflow runs for troubleshooting + branches: ["main", "rc", "hotfix-rc"] + paths-ignore: # Updates to these directories or files will not trigger a workflow run + - ".github/workflows/**" + + # pull_request_target: #We strongly discourage using this unless absolutely necessary as it requires access to certain Github secrets. + # If using this, include the .github/workflows/check-run.yml job as + # More info at https://github.blog/news-insights/product-news/github-actions-improvements-for-fork-and-pull-request-workflows/#improvements-for-public-repository-forks + + pull_request: # When a pull request event occurs + types: [opened, synchronize, unlabeled, labeled, unlabeled, reopened, edited] + branches: ["main"] # Branches where a pull request will trigger the workflow + - ".github/workflows/**" + + release: # Runs your workflow when release activity in your repository occurs + types: + - [published, created] + + merge_group: # Runs required status checks on merge groups created by merge queue + types: [checks_requested] + + repository_dispatch: # Runs when a webook event triggers a workflow from outside of github + types: [contentful-publish] # Optional, limit repository dispatch events to those in a specified list + + workflow_call: # Workflow can be called by another workflow + +env: # Environment variables set for this step but not accessible by all workflows, steps or jobs. + _AZ_REGISTRY: "ACMEprod.azurecr.io" + INCREMENTAL: "${{ contains(github.event_name, 'pull_request') && '--sast-incremental' || '' }}" + VERSION: ${{ inputs.version }} + +jobs: # A workflow run is made up of one or more jobs that can run sequentially or in parallel + + first-job: + name: First Job Name + if: github.event.pull_request.draft == false # prevent part of a job from running on a draft PR + runs-on: ubuntu-22.04 # The type of runner that the job will run on + strategy: # Create multiple job runs for each of a set of variables + fail-fast: false # If true, cancel entire run if any job in the matrix fails + matrix: # Matrix of variables used to define multiple job runs + include: + - project_name: Admin + base_path: ./src + node: true # enables steps with if: ${{ matrix.node }} + + # https://docs.github.com/en/actions/writing-workflows/choosing-what-your-workflow-does/controlling-permissions-for-github_token + permissions: # Sets permissions of the GITHUB_TOKEN + security-events: write # Allow actions to upload results to Github + id-token: write # Required to fetch an OpenID Connect (OIDC) token + contents: read # For actions/checkout to fetch code + deployments: write # Permits an action to create a new deployment. + issues: write # Permits an action to create a new issue. + checks: write # Permits an action to create a check run. + actions: write # Permits an action to cancel a workflow run. + packages: read # Permits an action to access packages on GitHub Packages + pull-requests: write # Permits an action to add a label to a pull request + + https://docs.github.com/en/actions/writing-workflows/choosing-what-your-workflow-does/setting-a-default-shell-and-working-directory + defaults: + run: # Set the default shell and working directory + shell: bash + working-directory: "home/WorkingDirectory" + secrets: inherit # When called by another workflow, pass all the calling workflow's secrets to the called workflow + + steps: + - name: Descriptive step name + # NOT RECOMMENDED if: always() # run even if previous steps failed or the workflow is canceled, this can cause a workflow run to hang indefinitely + # if: failure() # run when any previous step of a job fails + # if: '!cancelled()' # run even if previous steps failed + + # Always pin a public action version to a full git SHA, followed by the version number in a comment. Version pins are insecure and can introduce vulnerabilities into workflows. + uses: actions/checkout@11bd71901bbsdflakceea73d27597364c9af683 # v4.2.2 + with: # Parameters specific to this action that need to be defined in order for the step to be completed + fetch-depth: 0 # Full git history for actions that rely on whether a change has occurred + ref: ${{ github.event.pull_request.head.sha }} + creds: ${{ secrets.SECRETS_OR_CREDENTIALS }} + - name: Another descriptive step name + if: ${{ matrix.node }} + # run a script instead of an existing github action + run: | + whoami + dotnet --info + node --version + npm --version + echo "GitHub ref: $GITHUB_REF" + echo "GitHub event: $GITHUB_EVENT" + + # This job is relatively simple and just imports a previously written action to be used in this workflow + second-job: + name: Second Job Name + runs-on: ubuntu-22.04 + uses: bitwarden/gh-actions/.github/workflows/action-name.yml@main # location and branch of bitwarden-owned action being used + needs: + - first-job # This job will wait until first-job completes \ No newline at end of file diff --git a/.github/templates/workflow-templates/scan.yml b/.github/templates/workflow-templates/scan.yml index 046fb3da..b25a48e0 100644 --- a/.github/templates/workflow-templates/scan.yml +++ b/.github/templates/workflow-templates/scan.yml @@ -32,13 +32,17 @@ on: # A workflow run is made up of one or more jobs that can run sequentially or in parallel jobs: - # This workflow contains the jobs "sast", and "quality" + # This workflow contains the jobs "check-run", "sast", and "quality" # This job is relatively simple and just imports a previously written action to be used in this workflow + check-run: # You set this value with the name of the job you're describing + name: Check PR run # Human readable descriptor + uses: bitwarden/gh-actions/.github/workflows/check-run.yml@main # location and branch of bitwarden-owned action being used sast: # A more complex job that has multiple actions as steps described below name: SAST scan runs-on: ubuntu-22.04 # The type of runner that the job will run on + needs: check-run # This job will wait until check-run completes permissions: contents: read # For actions/checkout to fetch code pull-requests: write # For github actions to uplaod feedback to PR @@ -76,7 +80,7 @@ jobs: quality: name: Quality scan runs-on: ubuntu-22.04 -# needs: use this if you want this step to wait for another to finish before running + needs: check-run permissions: contents: read pull-requests: write From 4586d2e2e514e4cc729beb22840f4fdcc8109261 Mon Sep 17 00:00:00 2001 From: Amy Galles <9685081+AmyLGalles@users.noreply.github.com> Date: Thu, 23 Jan 2025 17:04:37 -0800 Subject: [PATCH 08/10] add newline --- .github/templates/workflow-templates/example.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/templates/workflow-templates/example.yml b/.github/templates/workflow-templates/example.yml index c12f8d14..8c6cd5bb 100644 --- a/.github/templates/workflow-templates/example.yml +++ b/.github/templates/workflow-templates/example.yml @@ -104,4 +104,4 @@ jobs: # A workflow run is made up of one or more jobs that can run sequentially runs-on: ubuntu-22.04 uses: bitwarden/gh-actions/.github/workflows/action-name.yml@main # location and branch of bitwarden-owned action being used needs: - - first-job # This job will wait until first-job completes \ No newline at end of file + - first-job # This job will wait until first-job completes From 3f29ca173907a46f16d6505e5a3be518b22a4e30 Mon Sep 17 00:00:00 2001 From: Amy Galles <9685081+AmyLGalles@users.noreply.github.com> Date: Thu, 23 Jan 2025 17:05:20 -0800 Subject: [PATCH 09/10] add newline --- .github/templates/workflow-templates/ci.yaml | 2 +- .github/templates/workflow-templates/scan.yml | 18 +++++------------- 2 files changed, 6 insertions(+), 14 deletions(-) diff --git a/.github/templates/workflow-templates/ci.yaml b/.github/templates/workflow-templates/ci.yaml index c6fbe501..6d446c07 100644 --- a/.github/templates/workflow-templates/ci.yaml +++ b/.github/templates/workflow-templates/ci.yaml @@ -49,4 +49,4 @@ jobs: project-path: ./src/Billing version: ${{ needs.version.outputs.version }} image-name: billing-relay - push-docker-image: false \ No newline at end of file + push-docker-image: false diff --git a/.github/templates/workflow-templates/scan.yml b/.github/templates/workflow-templates/scan.yml index b25a48e0..be638017 100644 --- a/.github/templates/workflow-templates/scan.yml +++ b/.github/templates/workflow-templates/scan.yml @@ -19,16 +19,8 @@ on: - "main" - "rc" - "hotfix-rc" - # pull_request_target: #We strongly discourage using this unless absolutely necessary as it requires access to certain Github secrets - # More info at https://github.blog/news-insights/product-news/github-actions-improvements-for-fork-and-pull-request-workflows/#improvements-for-public-repository-forks - pull_request: # When a pull request event occurs - branches: ["main"] # Branches where a pull request will trigger the workflow - paths-ignore: # Updates to these directories or files will not trigger a workflow run - - ".github/workflows/**" - push: - branches: ["main"] - paths-ignore: - - ".github/workflows/**" + pull_request_target: # When a pull request event occurs. Default is opened or reopened unless otherwise specified, as below: + types: [opened, synchronize] # Other options include labeled, unlabeled, reopened # A workflow run is made up of one or more jobs that can run sequentially or in parallel jobs: @@ -43,9 +35,9 @@ jobs: name: SAST scan runs-on: ubuntu-22.04 # The type of runner that the job will run on needs: check-run # This job will wait until check-run completes - permissions: + permissions: # Sets permissions of the GITHUB_TOKEN contents: read # For actions/checkout to fetch code - pull-requests: write # For github actions to uplaod feedback to PR + pull-requests: write # For github actions to upload feedback to PR security-events: write # For github/codeql-action/upload-sarif to upload SARIF results # Steps represent a sequence of tasks that will be executed as part of the job @@ -117,4 +109,4 @@ jobs: /o:"${{ github.repository_owner }}" /d:sonar.token="${{ secrets.SONAR_TOKEN }}" \ /d:sonar.host.url="https://sonarcloud.io" dotnet build - dotnet-sonarscanner end /d:sonar.token="${{ secrets.SONAR_TOKEN }}" \ No newline at end of file + dotnet-sonarscanner end /d:sonar.token="${{ secrets.SONAR_TOKEN }}" From 7d73a0d5bf3a4e966fb1ecb755f6f338b3fea587 Mon Sep 17 00:00:00 2001 From: Amy Galles <9685081+AmyLGalles@users.noreply.github.com> Date: Thu, 23 Jan 2025 21:51:31 -0800 Subject: [PATCH 10/10] making annotations more consistent across template files --- .github/templates/workflow-templates/ci.yaml | 10 +++++----- .../templates/workflow-templates/example.yml | 20 +++++++++---------- .github/templates/workflow-templates/scan.yml | 6 +++--- 3 files changed, 18 insertions(+), 18 deletions(-) diff --git a/.github/templates/workflow-templates/ci.yaml b/.github/templates/workflow-templates/ci.yaml index 6d446c07..beaa901b 100644 --- a/.github/templates/workflow-templates/ci.yaml +++ b/.github/templates/workflow-templates/ci.yaml @@ -9,15 +9,15 @@ on: pull_request: # When a pull request event occurs permissions: # Sets permissions of the GITHUB_TOKEN - checks: write # permits an action to create a check run - contents: read # for actions to fetch code and list commits - id-token: write # required to fetch an OpenID Connect (OIDC) token - pull-requests: write # permits an action to add a label to a pull request + checks: write # Permits an action to create a check run + contents: read # For actions to fetch code and list commits + id-token: write # Required to fetch an OpenID Connect (OIDC) token + pull-requests: write # Permits an action to add a label to a pull request jobs: version: name: Calculate version - uses: ./.github/workflows/_version.yml #path to an existing github action + uses: ./.github/workflows/_version.yml # Path to an existing github action test: name: Run test diff --git a/.github/templates/workflow-templates/example.yml b/.github/templates/workflow-templates/example.yml index 8c6cd5bb..73a7bdae 100644 --- a/.github/templates/workflow-templates/example.yml +++ b/.github/templates/workflow-templates/example.yml @@ -6,17 +6,17 @@ name: Build -on: # describes when to run the workflow +on: # Describes when to run the workflow # https://docs.github.com/en/actions/writing-workflows/choosing-when-your-workflow-runs/events-that-trigger-workflows workflow_dispatch: # When triggered manually - push: # On push to the following branches. Temporarily add a development branch to prompt workflow runs for troubleshooting + push: # On push to the following branches. Temporarily add a development branch to prompt workflow runs for troubleshooting branches: ["main", "rc", "hotfix-rc"] paths-ignore: # Updates to these directories or files will not trigger a workflow run - ".github/workflows/**" - # pull_request_target: #We strongly discourage using this unless absolutely necessary as it requires access to certain Github secrets. + # Pull_request_target: #We strongly discourage using this unless absolutely necessary as it requires access to certain Github secrets. # If using this, include the .github/workflows/check-run.yml job as # More info at https://github.blog/news-insights/product-news/github-actions-improvements-for-fork-and-pull-request-workflows/#improvements-for-public-repository-forks @@ -54,17 +54,17 @@ jobs: # A workflow run is made up of one or more jobs that can run sequentially include: - project_name: Admin base_path: ./src - node: true # enables steps with if: ${{ matrix.node }} + node: true # Enables steps with if: ${{ matrix.node }} # https://docs.github.com/en/actions/writing-workflows/choosing-what-your-workflow-does/controlling-permissions-for-github_token permissions: # Sets permissions of the GITHUB_TOKEN security-events: write # Allow actions to upload results to Github id-token: write # Required to fetch an OpenID Connect (OIDC) token contents: read # For actions/checkout to fetch code - deployments: write # Permits an action to create a new deployment. - issues: write # Permits an action to create a new issue. - checks: write # Permits an action to create a check run. - actions: write # Permits an action to cancel a workflow run. + deployments: write # Permits an action to create a new deployment + issues: write # Permits an action to create a new issue + checks: write # Permits an action to create a check run + actions: write # Permits an action to cancel a workflow run packages: read # Permits an action to access packages on GitHub Packages pull-requests: write # Permits an action to add a label to a pull request @@ -89,7 +89,7 @@ jobs: # A workflow run is made up of one or more jobs that can run sequentially creds: ${{ secrets.SECRETS_OR_CREDENTIALS }} - name: Another descriptive step name if: ${{ matrix.node }} - # run a script instead of an existing github action + # Run a script instead of an existing github action run: | whoami dotnet --info @@ -102,6 +102,6 @@ jobs: # A workflow run is made up of one or more jobs that can run sequentially second-job: name: Second Job Name runs-on: ubuntu-22.04 - uses: bitwarden/gh-actions/.github/workflows/action-name.yml@main # location and branch of bitwarden-owned action being used + uses: bitwarden/gh-actions/.github/workflows/action-name.yml@main # Location and branch of bitwarden-owned action being used needs: - first-job # This job will wait until first-job completes diff --git a/.github/templates/workflow-templates/scan.yml b/.github/templates/workflow-templates/scan.yml index be638017..765dc3e1 100644 --- a/.github/templates/workflow-templates/scan.yml +++ b/.github/templates/workflow-templates/scan.yml @@ -49,9 +49,9 @@ jobs: ref: ${{ github.event.pull_request.head.sha }} - name: Scan with Checkmarx - if: github.event.pull_request.draft == false # prevent part of a job from running on a draft PR + if: github.event.pull_request.draft == false # Prevent part of a job from running on a draft PR uses: checkmarx/ast-github-action@f0869bd1a37fddc06499a096101e6c900e815d81 # 2.0.36 - env: # Environment variables set for this step but not accessible by all workflows, steps or jobs. + env: # Environment variables set for this step but not accessible by all workflows, steps or jobs INCREMENTAL: "${{ contains(github.event_name, 'pull_request') && '--sast-incremental' || '' }}" with: project_name: ${{ github.repository }} @@ -84,7 +84,7 @@ jobs: with: java-version: 17 distribution: "zulu" - # This step checks out a copy of your repository. + # This step checks out a copy of your repository - name: Check out repo uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: