BRE-648 - Add logic to push images to ghcr.io (#351)

This commit is contained in:
Vince Grassia
2025-03-05 14:39:12 -05:00
committed by GitHub
parent 21d9ea0aed
commit c969cd71d8
4 changed files with 155 additions and 93 deletions

View File

@@ -5,11 +5,6 @@ on:
paths:
- "docker-unified/**"
- ".github/workflows/build-unified.yml"
workflow_call:
inputs:
server_branch:
type: string
default: main
workflow_dispatch:
inputs:
server_branch:
@@ -27,20 +22,13 @@ env:
jobs:
build-docker:
name: Build Docker image
runs-on: ubuntu-22.04
runs-on: ubuntu-24.04
permissions:
security-events: write
id-token: write
packages: write
security-events: write
steps:
- name: Checkout Repository - workflow_call
if: ${{ github.event_name == 'workflow_call' }}
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
repository: bitwarden/self-host
ref: main
- name: Checkout Repository - workflow_dispatch
if: ${{ github.event_name != 'workflow_call' }}
- name: Checkout Repository
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- name: Get server branch to checkout
@@ -60,11 +48,7 @@ jobs:
SERVER_BRANCH: ${{ steps.server-branch-name.outputs.server_branch }}
id: publish-branch-check
run: |
if [[ "${{ github.event_name }}" == "workflow_call" ]]; then
REF=main
else
REF=${GITHUB_REF#refs/heads/}
fi
REF=${GITHUB_REF#refs/heads/}
IFS="," read -a publish_branches <<< $PUBLISH_BRANCHES
@@ -90,17 +74,12 @@ jobs:
- name: Login to Azure ACR
run: az acr login -n bitwardenprod
- name: Login to Azure - CI Subscription
uses: Azure/login@e15b166166a8746d1a47596803bd8c1b595455cf # v1.6.0
- name: Login to GitHub Container Registry
uses: docker/login-action@9780b0c442fbb1117ed29e0efdff1e18412f7567 # v3.3.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"
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Setup Docker Trust
if: ${{ env.is_publish_branch == 'true' }}
@@ -131,16 +110,23 @@ jobs:
IS_PUBLISH_BRANCH: ${{ env.is_publish_branch }}
run: |
if [[ ("${IMAGE_TAG}" == "dev" || "${IMAGE_TAG}" == "beta") && "${IS_PUBLISH_BRANCH}" == "true" ]]; then
echo "tags=$_AZ_REGISTRY/self-host:${IMAGE_TAG},bitwarden/self-host:${IMAGE_TAG}" >> $GITHUB_OUTPUT
echo "tags=$_AZ_REGISTRY/self-host:${IMAGE_TAG},bitwarden/self-host:${IMAGE_TAG},ghcr.io/bitwarden/self-host:${IMAGE_TAG}" >> $GITHUB_OUTPUT
else
echo "tags=$_AZ_REGISTRY/self-host:${IMAGE_TAG}" >> $GITHUB_OUTPUT
fi
- name: Generate GH App token
uses: actions/create-github-app-token@c1a285145b9d317df6ced56c09f525b5c2b6f755 # v1.11.1
id: app-token
with:
app-id: ${{ secrets.BW_GHAPP_ID }}
private-key: ${{ secrets.BW_GHAPP_KEY }}
- name: Checkout server repo
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
repository: bitwarden/server
token: ${{ steps.retrieve-secret-pat.outputs.github-pat-bitwarden-devops-bot-repo-scope }}
token: ${{ steps.app-token.outputs.token }}
ref: ${{ steps.server-branch-name.outputs.server_branch }}
path: "server"
@@ -156,8 +142,6 @@ jobs:
linux/arm64/v8
push: true
tags: ${{ steps.tag-list.outputs.tags }}
secrets: |
"GH_PAT=${{ steps.retrieve-secret-pat.outputs.github-pat-bitwarden-devops-bot-repo-scope }}"
- name: Install Cosign
if: env.is_publish_branch == 'true'
@@ -165,6 +149,7 @@ jobs:
- name: Sign image with Cosign
if: env.is_publish_branch == 'true'
id: sign
env:
DIGEST: ${{ steps.build-docker.outputs.digest }}
TAGS: ${{ steps.tag-list.outputs.tags }}
@@ -175,6 +160,15 @@ jobs:
images+="${tag}@${DIGEST} "
done
cosign sign --yes ${images}
echo "images=${images}" >> $GITHUB_OUTPUT
- name: Verify the signed image(s) with Cosign
if: env.is_publish_branch == 'true'
run: |
cosign verify
--certificate-identity "${{ github.server_url }}/${{ github.workflow_ref }}" \
--certificate-oidc-issuer "https://token.actions.githubusercontent.com" \
${{ steps.sign.outputs.images }}
- name: Scan Docker image
id: container-scan
@@ -195,10 +189,11 @@ jobs:
docker logout
echo "DOCKER_CONTENT_TRUST=0" >> $GITHUB_ENV
check-failures:
name: Check for failures
if: always()
runs-on: ubuntu-22.04
runs-on: ubuntu-24.04
needs: build-docker
steps:
- name: Check if any job failed

View File

@@ -1,5 +1,5 @@
name: Release
run-name: Release ${{ github.event.inputs.release_type }} v${{ github.event.inputs.release_version }}
run-name: Release ${{ inputs.release_type }} v${{ inputs.release_version }}
on:
workflow_dispatch:
@@ -22,7 +22,7 @@ env:
jobs:
setup:
name: Setup
runs-on: ubuntu-22.04
runs-on: ubuntu-24.04
outputs:
_WEB_RELEASE_TAG: ${{ steps.set-tags.outputs.WEB_RELEASE_TAG }}
_CORE_RELEASE_TAG: ${{ steps.set-tags.outputs.CORE_RELEASE_TAG }}
@@ -30,7 +30,7 @@ jobs:
_LATEST_SELF_HOST_VERSION: ${{ steps.get-self-host.outputs.version }}
steps:
- name: Branch check
if: ${{ github.event.inputs.release_type != 'Dry Run' }}
if: ${{ inputs.release_type != 'Dry Run' }}
run: |
if [[ "$GITHUB_REF" != "refs/heads/main" ]]; then
echo "==================================="
@@ -50,7 +50,7 @@ jobs:
- name: Check Release Version
env:
RELEASE_VERSION: ${{ github.event.inputs.release_version }}
RELEASE_VERSION: ${{ inputs.release_version }}
PREVIOUS_RELEASE_VERSION: ${{ steps.get-self-host.outputs.version }}
run: |
if [ "$RELEASE_VERSION" == "$PREVIOUS_RELEASE_VERSION" ]; then
@@ -71,7 +71,7 @@ jobs:
release:
name: Create GitHub Release
runs-on: ubuntu-22.04
runs-on: ubuntu-24.04
needs: setup
steps:
- name: Checkout repo
@@ -128,7 +128,7 @@ jobs:
) >> $GITHUB_OUTPUT
- name: Create release
if: ${{ github.event.inputs.release_type != 'Dry Run' }}
if: ${{ inputs.release_type != 'Dry Run' }}
uses: ncipollo/release-action@cdcc88a9acf3ca41c16c37bb7d21b9ad48560d87 # v1.15.0
with:
artifacts: 'bitwarden.sh,
@@ -137,15 +137,16 @@ jobs:
run.ps1,
version.json'
commit: ${{ github.sha }}
tag: "v${{ github.event.inputs.release_version }}"
name: "Version ${{ github.event.inputs.release_version }}"
tag: "v${{ inputs.release_version }}"
name: "Version ${{ 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
runs-on: ubuntu-24.04
needs:
- setup
- release
@@ -170,7 +171,7 @@ jobs:
aws-selfhost-version-bucket-name"
- name: Upload version.json to S3 bucket
if: ${{ github.event.inputs.release_type != 'Dry Run' }}
if: ${{ 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 }}
@@ -181,15 +182,19 @@ jobs:
--acl "public-read" \
--quiet
tag-docker-latest:
name: Tag Docker Hub images with release version and latest
runs-on: ubuntu-22.04
name: Tag ${{ matrix.project_name }} image with release version and latest
runs-on: ubuntu-24.04
needs:
- setup
- release
env:
_CORE_RELEASE_TAG: ${{ needs.setup.outputs._CORE_RELEASE_TAG }}
_BRANCH_NAME: main
permissions:
id-token: write
packages: write
strategy:
fail-fast: false
matrix:
@@ -211,18 +216,14 @@ jobs:
- 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: Install Cosign
uses: sigstore/cosign-installer@d7d6bc7722e3daa8354c50bcb52f4837da5e9b6a # v3.8.1
- name: Login to Azure - Prod Subscription
uses: Azure/login@e15b166166a8746d1a47596803bd8c1b595455cf # v1.6.0
with:
@@ -262,8 +263,8 @@ jobs:
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' }}
- name: Push release version and latest image to DockerHub
if: ${{ inputs.release_type != 'Dry Run' }}
env:
DOCKER_CONTENT_TRUST: 1
DOCKER_CONTENT_TRUST_REPOSITORY_PASSPHRASE: ${{ steps.setup-dct.outputs.dct-delegate-repo-passphrase }}
@@ -271,19 +272,53 @@ jobs:
docker push bitwarden/$_PROJECT_NAME:$_RELEASE_TAG
docker push bitwarden/$_PROJECT_NAME:latest
- name: Log out of Docker and disable Docker Notary
### ghcr.io section
- name: Login to GitHub Container Registry
uses: docker/login-action@9780b0c442fbb1117ed29e0efdff1e18412f7567 # v3.3.0
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Tag release version and latest image
run: |
docker tag $_AZ_REGISTRY/$_PROJECT_NAME:$_RELEASE_TAG ghcr.io/bitwarden/$_PROJECT_NAME:$_RELEASE_TAG
docker tag $_AZ_REGISTRY/$_PROJECT_NAME:$_RELEASE_TAG ghcr.io/bitwarden/$_PROJECT_NAME:latest
- name: Push release version and latest image
if: ${{ inputs.release_type != 'Dry Run' }}
run: |
docker push ghcr.io/bitwarden/$_PROJECT_NAME:$_RELEASE_TAG
docker push ghcr.io/bitwarden/$_PROJECT_NAME:latest
- name: Sign image with Cosign
run: |
cosign sign --yes ghcr.io/bitwarden/$_PROJECT_NAME:$_RELEASE_TAG
cosign sign --yes ghcr.io/bitwarden/$_PROJECT_NAME:latest
- name: Verify the signed image with Cosign
run: |
cosign verify --certificate-identity "${{ github.server_url }}/${{ github.workflow_ref }}" --certificate-oidc-issuer "https://token.actions.githubusercontent.com" ghcr.io/bitwarden/$_PROJECT_NAME:$_RELEASE_TAG
cosign verify --certificate-identity "${{ github.server_url }}/${{ github.workflow_ref }}" --certificate-oidc-issuer "https://token.actions.githubusercontent.com" ghcr.io/bitwarden/$_PROJECT_NAME:latest
- name: Log out of Docker
run: |
docker logout
echo "DOCKER_CONTENT_TRUST=0" >> $GITHUB_ENV
docker logout ghcr.io
docker logout $_AZ_REGISTRY
release-unified:
name: Release Self-host unified
runs-on: ubuntu-22.04
runs-on: ubuntu-24.04
needs:
- setup
- release
env:
_RELEASE_VERSION: ${{ github.event.inputs.release_version }}-beta # TODO: remove `-beta` after GA
_RELEASE_VERSION: ${{ inputs.release_version }}-beta # TODO: remove `-beta` after GA
permissions:
id-token: write
packages: write
steps:
########## DockerHub ##########
- name: Setup DCT
@@ -293,34 +328,27 @@ jobs:
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' }}
if: ${{ 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
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
skopeo logout --all
########## ACR PROD ##########
- name: Login to Azure ACR
@@ -328,7 +356,7 @@ jobs:
- name: Pull latest project image
run: |
if [[ "${{ github.event.inputs.release_type }}" == "Dry Run" ]]; then
if [[ "${{ inputs.release_type }}" == "Dry Run" ]]; then
docker pull $_AZ_REGISTRY/self-host:dev
else
docker pull $_AZ_REGISTRY/self-host:beta
@@ -336,7 +364,7 @@ jobs:
- name: Tag version and latest
run: |
if [[ "${{ github.event.inputs.release_type }}" == "Dry Run" ]]; then
if [[ "${{ 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
@@ -344,37 +372,65 @@ jobs:
fi
- name: Push version and latest image
if: ${{ github.event.inputs.release_type != 'Dry Run' }}
if: ${{ 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
run: docker logout $_AZ_REGISTRY
########## ghcr.io ##########
- name: Login to GitHub Container Registry
uses: docker/login-action@9780b0c442fbb1117ed29e0efdff1e18412f7567 # v3.3.0
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Tag release version and latest image
run: |
docker tag $_AZ_REGISTRY/self-host:$_RELEASE_TAG ghcr.io/bitwarden/self-host:$_RELEASE_TAG
docker tag $_AZ_REGISTRY/self-host:$_RELEASE_TAG ghcr.io/bitwarden/self-host:latest
- name: Push release version and latest image
if: ${{ inputs.release_type != 'Dry Run' }}
run: |
docker push ghcr.io/bitwarden/self-host:$_RELEASE_TAG
docker push ghcr.io/bitwarden/self-host:latest
- name: Sign image with Cosign
run: |
cosign sign --yes ghcr.io/bitwarden/self-host:$_RELEASE_TAG
cosign sign --yes ghcr.io/bitwarden/self-host:latest
- name: Verify the signed image with Cosign
run: |
cosign verify --certificate-identity "${{ github.server_url }}/${{ github.workflow_ref }}" --certificate-oidc-issuer "https://token.actions.githubusercontent.com" ghcr.io/bitwarden/self-host:$_RELEASE_TAG
cosign verify --certificate-identity "${{ github.server_url }}/${{ github.workflow_ref }}" --certificate-oidc-issuer "https://token.actions.githubusercontent.com" ghcr.io/bitwarden/self-host:latest
- name: Log out of Docker
run: docker logout ghcr.io
trigger-workflows:
name: Trigger workflows
runs-on: ubuntu-22.04
runs-on: ubuntu-24.04
needs:
- setup
- release
steps:
- name: Log in to Azure - CI subscription
uses: Azure/login@e15b166166a8746d1a47596803bd8c1b595455cf # v1.6.0
- name: Generate GH App token
uses: actions/create-github-app-token@c1a285145b9d317df6ced56c09f525b5c2b6f755 # v1.11.1
id: app-token
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"
app-id: ${{ secrets.BW_GHAPP_ID }}
private-key: ${{ secrets.BW_GHAPP_KEY }}
- 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 }}
github-token: ${{ steps.app-token.outputs.token }}
script: |
await github.rest.actions.createWorkflowDispatch({
owner: 'bitwarden',

View File

@@ -190,6 +190,7 @@ jobs:
- name: Create versions PR
if: ${{ steps.version-changed.outputs.changes_to_commit == 'TRUE' }}
id: create-pr
env:
GH_TOKEN: ${{ steps.app-token.outputs.token }}
PR_BRANCH: ${{ steps.create-branch.outputs.name }}

View File

@@ -1,9 +1,19 @@
# Self-Host Release Repository
Bitwarden's dedicated self-hosted release repository. This holds the installation scripts for our self-host project.
Bitwarden's dedicated self-hosted release repository. This holds the installation scripts and container images for our self-host project.
For any issues regarding a specific client application, please visit [bitwarden/clients](https://github.com/bitwarden/clients)
---
## Container Images
Bitwarden provides OCI-Compliant container images in our ghcr.io [repository](https://github.com/orgs/bitwarden/packages?repo_name=self-host).
All images published to ghcr.io are
signed by using Cosign's [keyless signing](https://docs.sigstore.dev/cosign/signing/overview/). The images can be
verified with the following command (where `$IMAGE_NAME` is set to an image in our repository):
```sh
$ cosign verify ghcr.io/bitwarden/$IMAGE_NAME:latest --certificate-identity-regexp="https://github\.com/bitwarden/self-host/\.github/workflows/release\.yml@.*" --certificate-oidc-issuer="https://token.actions.githubusercontent.com"
```
## Quick Deploy
[![Deploy to DO](https://www.deploytodo.com/do-btn-blue.svg)](https://marketplace.digitalocean.com/apps/bitwarden?action=deploy)
[Deploy to Kubernetes with Helm](https://github.com/bitwarden/helm-charts/blob/main/charts/self-host/README.md)