name: Release run-name: Release ${{ github.event.inputs.release_type }} v${{ github.event.inputs.release_version }} on: workflow_dispatch: inputs: release_version: description: "Release Version" required: true release_type: description: "Release Options" required: true default: "Release" type: choice options: - Release - Dry Run env: _AZ_REGISTRY: bitwardenprod.azurecr.io jobs: setup: name: Setup runs-on: ubuntu-22.04 outputs: _WEB_RELEASE_TAG: ${{ steps.set-tags.outputs.WEB_RELEASE_TAG }} _CORE_RELEASE_TAG: ${{ steps.set-tags.outputs.CORE_RELEASE_TAG }} _KEY_CONNECTOR_RELEASE_TAG: ${{ steps.set-tags.outputs.KEY_CONNECTOR_RELEASE_TAG }} _LATEST_SELF_HOST_VERSION: ${{ steps.get-self-host.outputs.version }} steps: - name: Branch check if: ${{ github.event.inputs.release_type != 'Dry Run' }} run: | if [[ "$GITHUB_REF" != "refs/heads/main" ]]; then echo "===================================" echo "[!] Can only release from the 'main' branch" echo "===================================" exit 1 fi - name: Checkout repo uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - name: Get Latest Self-Host Version id: get-self-host uses: bitwarden/gh-actions/get-release-version@main with: repository: bitwarden/self-host - name: Check Release Version env: RELEASE_VERSION: ${{ github.event.inputs.release_version }} PREVIOUS_RELEASE_VERSION: ${{ steps.get-self-host.outputs.version }} run: | if [ "$RELEASE_VERSION" == "$PREVIOUS_RELEASE_VERSION" ]; then echo "[!] Already released v$RELEASE_VERSION. Please bump version to continue" exit 1 fi - name: Set Release Tags id: set-tags run: | WEB=$(jq -r '.versions.webVersion' < version.json) CORE=$(jq -r '.versions.coreVersion' < version.json) KEY_CONNECTOR=$(jq -r '.versions.keyConnectorVersion' < version.json) echo "WEB_RELEASE_TAG=$WEB" >> $GITHUB_OUTPUT echo "CORE_RELEASE_TAG=$CORE" >> $GITHUB_OUTPUT echo "KEY_CONNECTOR_RELEASE_TAG=$KEY_CONNECTOR" >> $GITHUB_OUTPUT release: name: Create GitHub Release runs-on: ubuntu-22.04 needs: setup steps: - name: Checkout repo uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: fetch-depth: 0 - name: Get projects that changed versions id: changed-projects env: _LATEST_SELF_HOST_VERSION: ${{ needs.setup.outputs._LATEST_SELF_HOST_VERSION }} run: | git diff --unified=0 $_LATEST_SELF_HOST_VERSION main -- version.json >> diff.txt if grep -q "webVersion" diff.txt; then echo "WEB_VERSION_CHANGED=true" >> $GITHUB_OUTPUT fi if grep -q "coreVersion" diff.txt; then echo "CORE_VERSION_CHANGED=true" >> $GITHUB_OUTPUT fi if grep -q "keyConnectorVersion" diff.txt; then echo "KEY_CONNECTOR_VERSION_CHANGED=true" >> $GITHUB_OUTPUT fi - name: Prepare release notes id: prepare-release-notes run: | RELEASE_NOTES="" if [ -n "${{ steps.changed-projects.outputs.CORE_VERSION_CHANGED }}" ]; then RELEASE_NOTES+="Update Core version to [v${{ needs.setup.outputs._CORE_RELEASE_TAG }}](https://github.com/bitwarden/server/releases/tag/v${{ needs.setup.outputs._CORE_RELEASE_TAG }})" fi if [ -n "${{ steps.changed-projects.outputs.WEB_VERSION_CHANGED }}" ]; then if [ -n "$RELEASE_NOTES" ]; then RELEASE_NOTES+=$'\n' fi RELEASE_NOTES+="Update Web version to [v${{ needs.setup.outputs._WEB_RELEASE_TAG }}](https://github.com/bitwarden/clients/releases/tag/web-v${{ needs.setup.outputs._WEB_RELEASE_TAG }})" fi if [ -n "${{ steps.changed-projects.outputs.KEY_CONNECTOR_VERSION_CHANGED }}" ]; then if [ -n "$RELEASE_NOTES" ]; then RELEASE_NOTES+=$'\n' fi RELEASE_NOTES+="Update Key Connector version to [v${{ needs.setup.outputs._KEY_CONNECTOR_RELEASE_TAG }}](https://github.com/bitwarden/key-connector/releases/tag/v${{ needs.setup.outputs._KEY_CONNECTOR_RELEASE_TAG }})" fi echo "RELEASE_NOTES=$RELEASE_NOTES" >> $GITHUB_OUTPUT - name: Create release if: ${{ github.event.inputs.release_type != 'Dry Run' }} uses: ncipollo/release-action@2c591bcc8ecdcd2db72b97d6147f871fcd833ba5 # v1.14.0 with: artifacts: 'bitwarden.sh, run.sh, bitwarden.ps1, run.ps1, version.json' commit: ${{ github.sha }} tag: "v${{ github.event.inputs.release_version }}" name: "Version ${{ github.event.inputs.release_version }}" body: ${{ steps.prepare-release-notes.outputs.RELEASE_NOTES }} token: ${{ secrets.GITHUB_TOKEN }} draft: false release-version: name: Upload version.json runs-on: ubuntu-22.04 needs: - setup - release steps: - name: Checkout repo uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: ref: main - name: Login to Azure - CI Subscription uses: Azure/login@e15b166166a8746d1a47596803bd8c1b595455cf # v1.6.0 with: creds: ${{ secrets.AZURE_KV_CI_SERVICE_PRINCIPAL }} - name: Retrieve secrets id: retrieve-secrets uses: bitwarden/gh-actions/get-keyvault-secrets@main with: keyvault: "bitwarden-ci" secrets: "aws-selfhost-version-access-id, aws-selfhost-version-access-key, aws-selfhost-version-bucket-name" - name: Upload version.json to S3 bucket if: ${{ github.event.inputs.release_type != 'Dry Run' }} env: AWS_ACCESS_KEY_ID: ${{ steps.retrieve-secrets.outputs.aws-selfhost-version-access-id }} AWS_SECRET_ACCESS_KEY: ${{ steps.retrieve-secrets.outputs.aws-selfhost-version-access-key }} AWS_DEFAULT_REGION: 'us-east-1' AWS_S3_BUCKET_NAME: ${{ steps.retrieve-secrets.outputs.aws-selfhost-version-bucket-name }} run: | aws s3 cp version.json $AWS_S3_BUCKET_NAME \ --acl "public-read" \ --quiet tag-docker-latest: name: Tag Docker Hub images with release version and latest runs-on: ubuntu-22.04 needs: - setup - release env: _CORE_RELEASE_TAG: ${{ needs.setup.outputs._CORE_RELEASE_TAG }} _BRANCH_NAME: main strategy: fail-fast: false matrix: include: - project_name: Admin - project_name: Api - project_name: Attachments - project_name: Events - project_name: Icons - project_name: Identity - project_name: MsSql - project_name: MsSqlMigratorUtility - project_name: Nginx - project_name: Notifications - project_name: Scim - project_name: Server - project_name: Setup - project_name: Sso - project_name: Web release_tag: ${{ needs.setup.outputs._WEB_RELEASE_TAG }} steps: - name: Print environment run: | whoami docker --version echo "GitHub ref: $GITHUB_REF" echo "GitHub event: $GITHUB_EVENT" - name: Checkout repo uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: ref: main - name: Login to Azure - Prod Subscription uses: Azure/login@e15b166166a8746d1a47596803bd8c1b595455cf # v1.6.0 with: creds: ${{ secrets.AZURE_PROD_KV_CREDENTIALS }} - name: Login to Azure ACR run: az acr login -n ${_AZ_REGISTRY%.azurecr.io} - name: Setup project name and release tag 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_ENV if [ -z "${{ matrix.release_tag }}" ]; then # Use core release tag by default. echo "_RELEASE_TAG=$_CORE_RELEASE_TAG" >> $GITHUB_ENV else echo "_RELEASE_TAG=${{ matrix.release_tag }}" >> $GITHUB_ENV fi ########## DockerHub ########## - name: Setup DCT id: setup-dct uses: bitwarden/gh-actions/setup-docker-trust@main with: azure-creds: ${{ secrets.AZURE_KV_CI_SERVICE_PRINCIPAL }} azure-keyvault-name: "bitwarden-ci" - name: Pull versioned image run: docker pull $_AZ_REGISTRY/$_PROJECT_NAME:$_RELEASE_TAG - name: Tag release version and latest image run: | docker tag $_AZ_REGISTRY/$_PROJECT_NAME:$_RELEASE_TAG bitwarden/$_PROJECT_NAME:$_RELEASE_TAG docker tag $_AZ_REGISTRY/$_PROJECT_NAME:$_RELEASE_TAG bitwarden/$_PROJECT_NAME:latest - name: Push release version and latest image if: ${{ github.event.inputs.release_type != 'Dry Run' }} env: DOCKER_CONTENT_TRUST: 1 DOCKER_CONTENT_TRUST_REPOSITORY_PASSPHRASE: ${{ steps.setup-dct.outputs.dct-delegate-repo-passphrase }} run: | docker push bitwarden/$_PROJECT_NAME:$_RELEASE_TAG docker push bitwarden/$_PROJECT_NAME:latest - name: Log out of Docker and disable Docker Notary run: | docker logout echo "DOCKER_CONTENT_TRUST=0" >> $GITHUB_ENV release-unified: name: Release Self-host unified runs-on: ubuntu-22.04 needs: - setup - release env: _RELEASE_VERSION: ${{ github.event.inputs.release_version }}-beta # TODO: remove `-beta` after GA steps: ########## DockerHub ########## - name: Setup DCT id: setup-dct uses: bitwarden/gh-actions/setup-docker-trust@main with: azure-creds: ${{ secrets.AZURE_KV_CI_SERVICE_PRINCIPAL }} azure-keyvault-name: "bitwarden-ci" - name: Install Skopeo run: | wget https://github.com/lework/skopeo-binary/releases/download/v1.13.3/skopeo-linux-amd64 mv skopeo-linux-amd64 skopeo chmod +x skopeo - name: Login to Azure - PROD Subscription uses: Azure/login@e15b166166a8746d1a47596803bd8c1b595455cf # v1.6.0 with: creds: ${{ secrets.AZURE_PROD_KV_CREDENTIALS }} - name: Push version and latest image if: ${{ github.event.inputs.release_type != 'Dry Run' }} env: DOCKER_CONTENT_TRUST: 1 DOCKER_CONTENT_TRUST_REPOSITORY_PASSPHRASE: ${{ steps.setup-dct.outputs.dct-delegate-repo-passphrase }} run: | ./skopeo --version ./skopeo login $_AZ_REGISTRY -u 00000000-0000-0000-0000-000000000000 -p $(az acr login --expose-token --name ${_AZ_REGISTRY%.azurecr.io} | jq -r .accessToken) ./skopeo copy --all docker://$_AZ_REGISTRY/self-host:beta docker://docker.io/bitwarden/self-host:$_RELEASE_VERSION ./skopeo copy --all docker://$_AZ_REGISTRY/self-host:beta docker://docker.io/bitwarden/self-host:beta # TODO: Delete after GA # ./skopeo copy --all docker://$_AZ_REGISTRY/self-host:beta docker://docker.io/bitwarden/self-host:latest # TODO: uncomment after GA - name: Log out of Docker, skopeo and disable Docker Notary run: | docker logout ./skopeo logout --all echo "DOCKER_CONTENT_TRUST=0" >> $GITHUB_ENV ########## ACR PROD ########## - name: Login to Azure ACR run: az acr login -n ${_AZ_REGISTRY%.azurecr.io} - name: Pull latest project image run: | if [[ "${{ github.event.inputs.release_type }}" == "Dry Run" ]]; then docker pull $_AZ_REGISTRY/self-host:dev else docker pull $_AZ_REGISTRY/self-host:beta fi - name: Tag version and latest run: | if [[ "${{ github.event.inputs.release_type }}" == "Dry Run" ]]; then docker tag $_AZ_REGISTRY/self-host:dev $_AZ_REGISTRY/self-host:dryrun else docker tag $_AZ_REGISTRY/self-host:beta $_AZ_REGISTRY/self-host:$_RELEASE_VERSION docker tag $_AZ_REGISTRY/self-host:beta $_AZ_REGISTRY/self-host:latest fi - name: Push version and latest image if: ${{ github.event.inputs.release_type != 'Dry Run' }} run: | docker push $_AZ_REGISTRY/self-host:$_RELEASE_VERSION docker push $_AZ_REGISTRY/self-host:latest - name: Log out of Docker run: docker logout trigger-workflows: name: Trigger workflows runs-on: ubuntu-22.04 needs: - setup - release 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 release-digital-ocean workflow 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: 'release-digital-ocean.yml', ref: 'main', inputs: {} });