Bitwarden's self-hosted release repository
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

592 lines
21 KiB

name: Release
run-name: Release v${{ inputs.release_version }}
on:
workflow_dispatch:
inputs:
release_version:
description: "Release Version (example: '2025.2.1')"
required: true
env:
_AZ_REGISTRY: bitwardenprod.azurecr.io
concurrency:
group: ${{ github.workflow }}
cancel-in-progress: false
permissions:
contents: read
jobs:
self-host-version-check:
name: Check Self-Host Version Input
if: github.ref_name == 'main'
runs-on: ubuntu-24.04
outputs:
latest_version: ${{ steps.get-self-host.outputs.version }}
steps:
- name: Checkout repo
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
with:
persist-credentials: false
- 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: ${{ 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
update-versions:
name: "Update versions"
runs-on: ubuntu-24.04
needs: self-host-version-check
permissions:
contents: write
id-token: write
outputs:
core_release_tag: ${{ steps.update-core-version.outputs.tag }}
core_version_changed: ${{ steps.update-core-version.outputs.changed }}
web_release_tag: ${{ steps.update-web-version.outputs.tag }}
web_version_changed: ${{ steps.update-web-version.outputs.changed }}
key_connector_release_tag: ${{ steps.update-key-connector-version.outputs.tag }}
key_connector_version_changed: ${{ steps.update-key-connector-version.outputs.changed }}
updated_version_commit_hash: ${{ steps.push-changes.outputs.commit_hash }}
steps:
- name: Log in to Azure
uses: bitwarden/gh-actions/azure-login@main
with:
subscription_id: ${{ secrets.AZURE_SUBSCRIPTION_ID }}
tenant_id: ${{ secrets.AZURE_TENANT_ID }}
client_id: ${{ secrets.AZURE_CLIENT_ID }}
- name: Get Azure Key Vault secrets
id: get-kv-secrets
uses: bitwarden/gh-actions/get-keyvault-secrets@main
with:
keyvault: gh-org-bitwarden
secrets: "BW-GHAPP-ID,BW-GHAPP-KEY"
- name: Log out from Azure
uses: bitwarden/gh-actions/azure-logout@main
- name: Generate GH App token
uses: actions/create-github-app-token@0f859bf9e69e887678d5bbfbee594437cb440ffe # v2.1.0
id: app-token
with:
app-id: ${{ steps.get-kv-secrets.outputs.BW-GHAPP-ID }}
private-key: ${{ steps.get-kv-secrets.outputs.BW-GHAPP-KEY }}
permission-contents: write # for pushing commits
- name: Checkout Branch
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
with:
ref: main
token: ${{ steps.app-token.outputs.token }}
persist-credentials: true
- name: Get Latest Core Version
id: get-core
uses: bitwarden/gh-actions/get-release-version@main
with:
repository: bitwarden/server
trim: true
- name: Update Core version
id: update-core-version
env:
NEW_VERSION: ${{ steps.get-core.outputs.version }}
run: |
OLD_VERSION=$(jq -r '.versions.coreVersion' version.json)
sed -i -e "/^\s*COREVERSION\s*=\s*/s/[0-9]\+.[0-9]\+.[0-9]\+/$NEW_VERSION/" bitwarden.sh
sed -i -e "/^\s*\$coreVersion\s*=\s*/s/[0-9]\+.[0-9]\+.[0-9]\+/$NEW_VERSION/" bitwarden.ps1
sed -i -e '/"coreVersion":/ s/"coreVersion":[^,]*/"coreVersion":"'$NEW_VERSION'"/' version.json
if [[ "$OLD_VERSION" != "$NEW_VERSION" ]]; then
echo "Core version changed from '$OLD_VERSION' to '$NEW_VERSION'" >> "$GITHUB_STEP_SUMMARY"
echo "changed=true" >> "$GITHUB_OUTPUT"
fi
echo "tag=$NEW_VERSION" >> "$GITHUB_OUTPUT"
- name: Get Latest Web Version
id: get-web
uses: bitwarden/gh-actions/get-release-version@main
with:
repository: bitwarden/clients
monorepo: true
monorepo-project: web
trim: true
- name: Update Web version
id: update-web-version
env:
NEW_VERSION: ${{ steps.get-web.outputs.version }}
run: |
OLD_VERSION=$(jq -r '.versions.webVersion' version.json)
sed -i -e "/^\s*WEBVERSION\s*=\s*/s/[0-9]\+.[0-9]\+.[0-9]\+/$NEW_VERSION/" bitwarden.sh
sed -i -e "/^\s*\$webVersion\s*=\s*/s/[0-9]\+.[0-9]\+.[0-9]\+/$NEW_VERSION/" bitwarden.ps1
sed -i -e '/"webVersion":/ s/"webVersion":[^,]*/"webVersion":"'$NEW_VERSION'"/' version.json
if [[ "$OLD_VERSION" != "$NEW_VERSION" ]]; then
echo "Web version changed from '$OLD_VERSION' to '$NEW_VERSION'" >> "$GITHUB_STEP_SUMMARY"
echo "changed=true" >> "$GITHUB_OUTPUT"
fi
echo "tag=$NEW_VERSION" >> "$GITHUB_OUTPUT"
- name: Get Latest Key Connector Version
id: get-key-connector
uses: bitwarden/gh-actions/get-release-version@main
with:
repository: bitwarden/key-connector
trim: true
- name: Update Key Connector version
id: update-key-connector-version
env:
NEW_VERSION: ${{ steps.get-key-connector.outputs.version }}
run: |
OLD_VERSION=$(jq -r '.versions.keyConnectorVersion' version.json)
sed -i -e "/^\s*KEYCONNECTORVERSION\s*=\s*/s/[0-9]\+.[0-9]\+.[0-9]\+/$NEW_VERSION/" bitwarden.sh
sed -i -e "/^\s*\$keyConnectorVersion\s*=\s*/s/[0-9]\+.[0-9]\+.[0-9]\+/$NEW_VERSION/" bitwarden.ps1
sed -i -e '/"keyConnectorVersion":/ s/"keyConnectorVersion":[^,]*/"keyConnectorVersion":"'$NEW_VERSION'"/' version.json
if [[ "$OLD_VERSION" != "$NEW_VERSION" ]]; then
echo "Key Connector version changed from '$OLD_VERSION' to '$NEW_VERSION'" >> "$GITHUB_STEP_SUMMARY"
echo "changed=true" >> "$GITHUB_OUTPUT"
fi
echo "tag=$NEW_VERSION" >> "$GITHUB_OUTPUT"
- name: Update docker-compose.yml with new version
env:
_CORE_VERSION: ${{ steps.update-core-version.outputs.tag }}
run: |
sed -i -e "s|lite:\${TAG:-[^}]*}|lite:\${TAG:-$_CORE_VERSION}|" bitwarden-lite/docker-compose.yml
echo ":pencil: Updated docker-compose.yml TAG to $_CORE_VERSION" >> "$GITHUB_STEP_SUMMARY"
- name: Check if version changed
id: version-changed
run: |
if [ -n "$(git status --porcelain)" ]; then
echo "changes_to_commit=true" >> "$GITHUB_OUTPUT"
else
echo "changes_to_commit=FALSE" >> "$GITHUB_OUTPUT"
echo "No changes to commit!";
fi
- name: Configure Git
if: ${{ steps.version-changed.outputs.changes_to_commit == 'true' }}
run: |
git config --local user.email "178206702+bw-ghapp[bot]@users.noreply.github.com"
git config --local user.name "bw-ghapp[bot]"
- name: Commit files
if: ${{ steps.version-changed.outputs.changes_to_commit == 'true' }}
run: git commit -m "Updated core, web, and key-connector versions" -a
- name: Push changes
id: push-changes
if: ${{ steps.version-changed.outputs.changes_to_commit == 'true' }}
run: |
git push
echo "commit_hash=$(git log -1 --format='%H')" >> "$GITHUB_OUTPUT"
release-github:
name: Create GitHub Release
runs-on: ubuntu-24.04
needs:
- self-host-version-check
- update-versions
permissions:
contents: write
steps:
- name: Checkout repo
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
with:
fetch-depth: 0
persist-credentials: false
ref: main
- name: Prepare release notes
id: prepare-release-notes
env:
CORE_RELEASE_TAG: ${{ needs.update-versions.outputs.core_release_tag }}
CORE_VERSION_CHANGED: ${{ needs.update-versions.outputs.core_version_changed }}
WEB_RELEASE_TAG: ${{ needs.update-versions.outputs.web_release_tag }}
WEB_VERSION_CHANGED: ${{ needs.update-versions.outputs.web_version_changed }}
KEY_CONNECTOR_RELEASE_TAG: ${{ needs.update-versions.outputs.key_connector_release_tag }}
KEY_CONNECTOR_VERSION_CHANGED: ${{ needs.update-versions.outputs.key_connector_version_changed }}
run: |
RELEASE_NOTES=""
if [ -n "${CORE_VERSION_CHANGED}" ]; then
RELEASE_NOTES+="Update Core version to [v${CORE_RELEASE_TAG}](https://github.com/bitwarden/server/releases/tag/v${CORE_RELEASE_TAG})"
fi
if [ -n "${WEB_VERSION_CHANGED}" ]; then
if [ -n "$RELEASE_NOTES" ]; then
RELEASE_NOTES+=$'\n'
fi
RELEASE_NOTES+="Update Web version to [v${WEB_RELEASE_TAG}](https://github.com/bitwarden/clients/releases/tag/web-v${WEB_RELEASE_TAG})"
fi
if [ -n "${KEY_CONNECTOR_VERSION_CHANGED}" ]; then
if [ -n "$RELEASE_NOTES" ]; then
RELEASE_NOTES+=$'\n'
fi
RELEASE_NOTES+="Update Key Connector version to [v${KEY_CONNECTOR_RELEASE_TAG}](https://github.com/bitwarden/key-connector/releases/tag/v${KEY_CONNECTOR_RELEASE_TAG})"
fi
(
echo 'RELEASE_NOTES<<EOF'
echo "$RELEASE_NOTES"
echo EOF
) >> "$GITHUB_OUTPUT"
- name: Create GitHub release
uses: ncipollo/release-action@bcfe5470707e8832e12347755757cec0eb3c22af # v1.18.0
with:
artifacts: 'bitwarden.sh,
run.sh,
bitwarden.ps1,
run.ps1,
version.json'
tag: "v${{ inputs.release_version }}"
name: "Version ${{ inputs.release_version }}"
body: ${{ steps.prepare-release-notes.outputs.RELEASE_NOTES }}
token: ${{ secrets.GITHUB_TOKEN }}
commit: ${{ needs.self-host-version-check.outputs.latest_version }}
draft: false
release-s3:
name: Upload version.json
runs-on: ubuntu-24.04
needs:
- update-versions
- release-github
permissions:
contents: read
id-token: write
steps:
- name: Checkout repo
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
with:
persist-credentials: false
ref: ${{ needs.update-versions.outputs.updated_version_commit_hash }}
- name: Log in to Azure
uses: bitwarden/gh-actions/azure-login@main
with:
subscription_id: ${{ secrets.AZURE_SUBSCRIPTION_ID }}
tenant_id: ${{ secrets.AZURE_TENANT_ID }}
client_id: ${{ secrets.AZURE_CLIENT_ID }}
- name: 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: Log out from Azure
uses: bitwarden/gh-actions/azure-logout@main
- name: Upload version.json to S3 bucket
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-push-latest-images:
name: Release ${{ matrix.project_name }} image
runs-on: ubuntu-24.04
timeout-minutes: 45
needs:
- update-versions
- release-github
permissions:
id-token: write
packages: write
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
steps:
- name: Checkout repo
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
with:
persist-credentials: false
- name: Install Cosign
uses: sigstore/cosign-installer@faadad0cce49287aee09b3a48701e75088a2c6ad # v4.0.0
- name: Log in to Azure
uses: bitwarden/gh-actions/azure-login@main
with:
subscription_id: ${{ secrets.AZURE_SUBSCRIPTION_ID }}
tenant_id: ${{ secrets.AZURE_TENANT_ID }}
client_id: ${{ secrets.AZURE_CLIENT_ID }}
- name: Setup project name and release tag
id: image-setup
env:
CORE_RELEASE_TAG: ${{ needs.update-versions.outputs.core_release_tag }}
WEB_RELEASE_TAG: ${{ needs.update-versions.outputs.web_release_tag }}
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"
if [[ "$PROJECT_NAME" == "web" ]]; then
echo "release_tag=$WEB_RELEASE_TAG" >> "$GITHUB_OUTPUT"
else
echo "release_tag=$CORE_RELEASE_TAG" >> "$GITHUB_OUTPUT"
fi
### ghcr.io section
- name: Login to GitHub Container Registry
uses: docker/login-action@184bdaa0721073962dff0199f1fb9940f07167d1 # v3.5.0
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Push version and latest image
id: push-image
env:
PROJECT_NAME: ${{ steps.image-setup.outputs.project_name }}
RELEASE_TAG: ${{ steps.image-setup.outputs.release_tag }}
run: |
az acr login --name "${_AZ_REGISTRY%.azurecr.io}"
skopeo copy --all "docker://$_AZ_REGISTRY/$PROJECT_NAME:$RELEASE_TAG" "docker://ghcr.io/bitwarden/$PROJECT_NAME:$RELEASE_TAG"
skopeo copy --all "docker://$_AZ_REGISTRY/$PROJECT_NAME:latest" "docker://ghcr.io/bitwarden/$PROJECT_NAME:latest"
# Get digests for signing
RELEASE_DIGEST=$(skopeo inspect "docker://ghcr.io/bitwarden/$PROJECT_NAME:$RELEASE_TAG" --format '{{.Digest}}')
LATEST_DIGEST=$(skopeo inspect "docker://ghcr.io/bitwarden/$PROJECT_NAME:latest" --format '{{.Digest}}')
echo "release_digest=$RELEASE_DIGEST" >> "$GITHUB_OUTPUT"
echo "latest_digest=$LATEST_DIGEST" >> "$GITHUB_OUTPUT"
- name: Sign image with Cosign
env:
PROJECT_NAME: ${{ steps.image-setup.outputs.project_name }}
RELEASE_DIGEST: ${{ steps.push-image.outputs.release_digest }}
LATEST_DIGEST: ${{ steps.push-image.outputs.latest_digest }}
run: |
cosign sign --yes "ghcr.io/bitwarden/$PROJECT_NAME@$RELEASE_DIGEST"
cosign sign --yes "ghcr.io/bitwarden/$PROJECT_NAME@$LATEST_DIGEST"
- name: Log out of Docker
run: |
docker logout ghcr.io
docker logout "$_AZ_REGISTRY"
- name: Log out from Azure
uses: bitwarden/gh-actions/azure-logout@main
build-lite-image:
name: Build Bitwarden lite image
uses: ./.github/workflows/build-bitwarden-lite.yml
needs: update-versions
permissions:
contents: read
id-token: write
packages: write
security-events: write
with:
self_host_repo_ref: ${{ needs.update-versions.outputs.updated_version_commit_hash }}
use_latest_core_version: true
use_latest_web_version: true
secrets: inherit
release-bitwarden-lite:
name: Release Bitwarden lite
runs-on: ubuntu-24.04
timeout-minutes: 30
needs:
- update-versions
- build-lite-image
env:
_CORE_VERSION: ${{ needs.update-versions.outputs.core_release_tag }}
permissions:
contents: write
id-token: write
packages: write
steps:
- name: Log in to Azure
uses: bitwarden/gh-actions/azure-login@main
with:
subscription_id: ${{ secrets.AZURE_SUBSCRIPTION_ID }}
tenant_id: ${{ secrets.AZURE_TENANT_ID }}
client_id: ${{ secrets.AZURE_CLIENT_ID }}
- name: Get Azure Key Vault secrets
id: get-kv-secrets
uses: bitwarden/gh-actions/get-keyvault-secrets@main
with:
keyvault: gh-org-bitwarden
secrets: "BW-GHAPP-ID,BW-GHAPP-KEY"
- name: Log out from Azure
uses: bitwarden/gh-actions/azure-logout@main
- name: Generate GH App token
uses: actions/create-github-app-token@0f859bf9e69e887678d5bbfbee594437cb440ffe # v2.1.0
id: app-token
with:
app-id: ${{ steps.get-kv-secrets.outputs.BW-GHAPP-ID }}
private-key: ${{ steps.get-kv-secrets.outputs.BW-GHAPP-KEY }}
permission-contents: write
- name: Checkout repo
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
with:
ref: main
token: ${{ steps.app-token.outputs.token }}
persist-credentials: true
- name: Login to GitHub Container Registry
uses: docker/login-action@184bdaa0721073962dff0199f1fb9940f07167d1 # v3.5.0
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Install Cosign
uses: sigstore/cosign-installer@faadad0cce49287aee09b3a48701e75088a2c6ad # v4.0.0
- name: Copy version tag to latest
id: copy-lite-image
run: |
skopeo copy --all "docker://ghcr.io/bitwarden/lite:$_CORE_VERSION" "docker://ghcr.io/bitwarden/lite:latest"
echo ":white_check_mark: Promoted Bitwarden lite $_CORE_VERSION to latest" >> "$GITHUB_STEP_SUMMARY"
# Get digest for signing
LATEST_DIGEST=$(skopeo inspect "docker://ghcr.io/bitwarden/lite:latest" --format '{{.Digest}}')
echo "latest_digest=$LATEST_DIGEST" >> "$GITHUB_OUTPUT"
- name: Sign latest image with Cosign
env:
LATEST_DIGEST: ${{ steps.copy-lite-image.outputs.latest_digest }}
run: cosign sign --yes "ghcr.io/bitwarden/lite@$LATEST_DIGEST"
- name: Log out of ghcr.io
run: docker logout ghcr.io
- name: Check if version changed
id: version-changed
run: |
if [ -n "$(git status --porcelain)" ]; then
echo "changes_to_commit=true" >> "$GITHUB_OUTPUT"
else
echo "changes_to_commit=false" >> "$GITHUB_OUTPUT"
echo "No changes to commit"
fi
- name: Configure Git
if: ${{ steps.version-changed.outputs.changes_to_commit == 'true' }}
run: |
git config --local user.email "178206702+bw-ghapp[bot]@users.noreply.github.com"
git config --local user.name "bw-ghapp[bot]"
- name: Commit files
if: ${{ steps.version-changed.outputs.changes_to_commit == 'true' }}
run: git commit -m "Update Bitwarden lite docker-compose.yml to $_CORE_VERSION" -a
- name: Push changes
if: ${{ steps.version-changed.outputs.changes_to_commit == 'true' }}
run: git push
trigger-workflows:
name: Trigger workflows
runs-on: ubuntu-24.04
needs:
- tag-push-latest-images
- release-bitwarden-lite
permissions:
id-token: write
steps:
- name: Log in to Azure
uses: bitwarden/gh-actions/azure-login@main
with:
subscription_id: ${{ secrets.AZURE_SUBSCRIPTION_ID }}
tenant_id: ${{ secrets.AZURE_TENANT_ID }}
client_id: ${{ secrets.AZURE_CLIENT_ID }}
- name: Get Azure Key Vault secrets
id: get-kv-secrets
uses: bitwarden/gh-actions/get-keyvault-secrets@main
with:
keyvault: gh-org-bitwarden
secrets: "BW-GHAPP-ID,BW-GHAPP-KEY"
- name: Log out from Azure
uses: bitwarden/gh-actions/azure-logout@main
- name: Generate GH App token
uses: actions/create-github-app-token@0f859bf9e69e887678d5bbfbee594437cb440ffe # v2.1.0
id: app-token
with:
app-id: ${{ steps.get-kv-secrets.outputs.BW-GHAPP-ID }}
private-key: ${{ steps.get-kv-secrets.outputs.BW-GHAPP-KEY }}
permission-actions: write
- name: Trigger release-digital-ocean workflow
uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0
env:
RELEASE_TAG: v${{ inputs.release_version }}
with:
github-token: ${{ steps.app-token.outputs.token }}
script: |
await github.rest.actions.createWorkflowDispatch({
owner: 'bitwarden',
repo: 'self-host',
workflow_id: 'release-digital-ocean.yml',
ref: process.env.RELEASE_TAG,
inputs: {}
});