mirror of
https://github.com/dani-garcia/vaultwarden.git
synced 2026-04-02 15:19:21 -07:00
As according to the docs: https://docs.github.com/en/actions/how-tos/deploy/configure-and-manage-deployments/control-deployments#using-environments-without-deployments This is useful when you want to use environments for: Organizing secrets—group related secrets under an environment name without creating deployment records. Access control—restrict which branches can use certain secrets via environment branch policies, without deployment tracking. CI and testing jobs—reference an environment for its configuration without adding noise to the deployment history.
389 lines
15 KiB
YAML
389 lines
15 KiB
YAML
name: Release
|
|
permissions: {}
|
|
|
|
concurrency:
|
|
# Apply concurrency control only on the upstream repo
|
|
group: ${{ github.repository == 'dani-garcia/vaultwarden' && format('{0}-{1}', github.workflow, github.ref) || github.run_id }}
|
|
# Don't cancel other runs when creating a tag
|
|
cancel-in-progress: ${{ github.ref_type == 'branch' }}
|
|
|
|
on:
|
|
push:
|
|
branches:
|
|
- main
|
|
|
|
tags:
|
|
# https://docs.github.com/en/actions/writing-workflows/workflow-syntax-for-github-actions#filter-pattern-cheat-sheet
|
|
- '[1-2].[0-9]+.[0-9]+'
|
|
|
|
defaults:
|
|
run:
|
|
shell: bash
|
|
|
|
# A "release" environment must be created in the repository settings
|
|
# (Settings > Environments > New environment) with the following
|
|
# variables and secrets configured as needed.
|
|
#
|
|
# Variables (only set the ones for registries you want to push to):
|
|
# DOCKERHUB_REPO: 'index.docker.io/<user>/<repo>'
|
|
# QUAY_REPO: 'quay.io/<user>/<repo>'
|
|
# GHCR_REPO: 'ghcr.io/<user>/<repo>'
|
|
#
|
|
# Secrets (only required when the corresponding *_REPO variable is set):
|
|
# DOCKERHUB_REPO => DOCKERHUB_USERNAME, DOCKERHUB_TOKEN
|
|
# QUAY_REPO => QUAY_USERNAME, QUAY_TOKEN
|
|
# GITHUB_TOKEN is provided automatically
|
|
|
|
jobs:
|
|
docker-build:
|
|
name: Build Vaultwarden containers
|
|
if: ${{ github.repository == 'dani-garcia/vaultwarden' }}
|
|
environment:
|
|
name: release
|
|
deployment: false
|
|
permissions:
|
|
packages: write # Needed to upload packages and artifacts
|
|
contents: read
|
|
attestations: write # Needed to generate an artifact attestation for a build
|
|
id-token: write # Needed to mint the OIDC token necessary to request a Sigstore signing certificate
|
|
runs-on: ${{ contains(matrix.arch, 'arm') && 'ubuntu-24.04-arm' || 'ubuntu-24.04' }}
|
|
timeout-minutes: 120
|
|
env:
|
|
SOURCE_COMMIT: ${{ github.sha }}
|
|
SOURCE_REPOSITORY_URL: "https://github.com/${{ github.repository }}"
|
|
strategy:
|
|
matrix:
|
|
arch: ["amd64", "arm64", "arm/v7", "arm/v6"]
|
|
base_image: ["debian","alpine"]
|
|
|
|
steps:
|
|
- name: Initialize QEMU binfmt support
|
|
uses: docker/setup-qemu-action@ce360397dd3f832beb865e1373c09c0e9f86d70a # v4.0.0
|
|
with:
|
|
platforms: "arm64,arm"
|
|
|
|
# Start Docker Buildx
|
|
- name: Setup Docker Buildx
|
|
uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd # v4.0.0
|
|
# https://github.com/moby/buildkit/issues/3969
|
|
# Also set max parallelism to 2, the default of 4 breaks GitHub Actions and causes OOMKills
|
|
with:
|
|
cache-binary: false
|
|
buildkitd-config-inline: |
|
|
[worker.oci]
|
|
max-parallelism = 2
|
|
driver-opts: |
|
|
network=host
|
|
|
|
# Checkout the repo
|
|
- name: Checkout
|
|
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
|
# We need fetch-depth of 0 so we also get all the tag metadata
|
|
with:
|
|
persist-credentials: false
|
|
fetch-depth: 0
|
|
|
|
# Normalize the architecture string for use in paths and cache keys
|
|
- name: Normalize architecture string
|
|
env:
|
|
MATRIX_ARCH: ${{ matrix.arch }}
|
|
run: |
|
|
# Replace slashes with nothing to create a safe string for paths/cache keys
|
|
NORMALIZED_ARCH="${MATRIX_ARCH//\/}"
|
|
echo "NORMALIZED_ARCH=${NORMALIZED_ARCH}" | tee -a "${GITHUB_ENV}"
|
|
|
|
# Determine Source Version
|
|
- name: Determine Source Version
|
|
run: |
|
|
# Get the Source Version for this release
|
|
GIT_EXACT_TAG="$(git describe --tags --abbrev=0 --exact-match 2>/dev/null || true)"
|
|
if [[ -n "${GIT_EXACT_TAG}" ]]; then
|
|
echo "SOURCE_VERSION=${GIT_EXACT_TAG}" | tee -a "${GITHUB_ENV}"
|
|
else
|
|
GIT_LAST_TAG="$(git describe --tags --abbrev=0)"
|
|
echo "SOURCE_VERSION=${GIT_LAST_TAG}-${SOURCE_COMMIT:0:8}" | tee -a "${GITHUB_ENV}"
|
|
fi
|
|
|
|
# Login to Docker Hub
|
|
- name: Login to Docker Hub
|
|
uses: docker/login-action@b45d80f862d83dbcd57f89517bcf500b2ab88fb2 # v4.0.0
|
|
with:
|
|
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
|
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
|
if: ${{ vars.DOCKERHUB_REPO != '' }}
|
|
|
|
- name: Add registry for DockerHub
|
|
if: ${{ vars.DOCKERHUB_REPO != '' }}
|
|
env:
|
|
DOCKERHUB_REPO: ${{ vars.DOCKERHUB_REPO }}
|
|
run: |
|
|
echo "CONTAINER_REGISTRIES=${DOCKERHUB_REPO}" | tee -a "${GITHUB_ENV}"
|
|
|
|
# Login to GitHub Container Registry
|
|
- name: Login to GitHub Container Registry
|
|
uses: docker/login-action@b45d80f862d83dbcd57f89517bcf500b2ab88fb2 # v4.0.0
|
|
with:
|
|
registry: ghcr.io
|
|
username: ${{ github.repository_owner }}
|
|
password: ${{ secrets.GITHUB_TOKEN }}
|
|
if: ${{ vars.GHCR_REPO != '' }}
|
|
|
|
- name: Add registry for ghcr.io
|
|
if: ${{ vars.GHCR_REPO != '' }}
|
|
env:
|
|
GHCR_REPO: ${{ vars.GHCR_REPO }}
|
|
run: |
|
|
echo "CONTAINER_REGISTRIES=${CONTAINER_REGISTRIES:+${CONTAINER_REGISTRIES},}${GHCR_REPO}" | tee -a "${GITHUB_ENV}"
|
|
|
|
# Login to Quay.io
|
|
- name: Login to Quay.io
|
|
uses: docker/login-action@b45d80f862d83dbcd57f89517bcf500b2ab88fb2 # v4.0.0
|
|
with:
|
|
registry: quay.io
|
|
username: ${{ secrets.QUAY_USERNAME }}
|
|
password: ${{ secrets.QUAY_TOKEN }}
|
|
if: ${{ vars.QUAY_REPO != '' }}
|
|
|
|
- name: Add registry for Quay.io
|
|
if: ${{ vars.QUAY_REPO != '' }}
|
|
env:
|
|
QUAY_REPO: ${{ vars.QUAY_REPO }}
|
|
run: |
|
|
echo "CONTAINER_REGISTRIES=${CONTAINER_REGISTRIES:+${CONTAINER_REGISTRIES},}${QUAY_REPO}" | tee -a "${GITHUB_ENV}"
|
|
|
|
- name: Configure build cache from/to
|
|
env:
|
|
GHCR_REPO: ${{ vars.GHCR_REPO }}
|
|
BASE_IMAGE: ${{ matrix.base_image }}
|
|
NORMALIZED_ARCH: ${{ env.NORMALIZED_ARCH }}
|
|
run: |
|
|
#
|
|
# Check if there is a GitHub Container Registry Login and use it for caching
|
|
if [[ -n "${GHCR_REPO}" ]]; then
|
|
echo "BAKE_CACHE_FROM=type=registry,ref=${GHCR_REPO}-buildcache:${BASE_IMAGE}-${NORMALIZED_ARCH}" | tee -a "${GITHUB_ENV}"
|
|
echo "BAKE_CACHE_TO=type=registry,ref=${GHCR_REPO}-buildcache:${BASE_IMAGE}-${NORMALIZED_ARCH},compression=zstd,mode=max" | tee -a "${GITHUB_ENV}"
|
|
else
|
|
echo "BAKE_CACHE_FROM="
|
|
echo "BAKE_CACHE_TO="
|
|
fi
|
|
#
|
|
|
|
- name: Generate tags
|
|
id: tags
|
|
env:
|
|
CONTAINER_REGISTRIES: "${{ env.CONTAINER_REGISTRIES }}"
|
|
run: |
|
|
# Convert comma-separated list to newline-separated set commands
|
|
TAGS=$(echo "${CONTAINER_REGISTRIES}" | tr ',' '\n' | sed "s|.*|*.tags=&|")
|
|
|
|
# Output for use in next step
|
|
{
|
|
echo "TAGS<<EOF"
|
|
echo "$TAGS"
|
|
echo "EOF"
|
|
} >> "$GITHUB_ENV"
|
|
|
|
- name: Bake ${{ matrix.base_image }} containers
|
|
id: bake_vw
|
|
uses: docker/bake-action@82490499d2e5613fcead7e128237ef0b0ea210f7 # v7.0.0
|
|
env:
|
|
BASE_TAGS: "${{ steps.determine-version.outputs.BASE_TAGS }}"
|
|
SOURCE_COMMIT: "${{ env.SOURCE_COMMIT }}"
|
|
SOURCE_VERSION: "${{ env.SOURCE_VERSION }}"
|
|
SOURCE_REPOSITORY_URL: "${{ env.SOURCE_REPOSITORY_URL }}"
|
|
with:
|
|
pull: true
|
|
source: .
|
|
files: docker/docker-bake.hcl
|
|
targets: "${{ matrix.base_image }}-multi"
|
|
set: |
|
|
*.cache-from=${{ env.BAKE_CACHE_FROM }}
|
|
*.cache-to=${{ env.BAKE_CACHE_TO }}
|
|
*.platform=linux/${{ matrix.arch }}
|
|
${{ env.TAGS }}
|
|
*.output=type=local,dest=./output
|
|
*.output=type=image,push-by-digest=true,name-canonical=true,push=true
|
|
|
|
- name: Extract digest SHA
|
|
env:
|
|
BAKE_METADATA: ${{ steps.bake_vw.outputs.metadata }}
|
|
BASE_IMAGE: ${{ matrix.base_image }}
|
|
run: |
|
|
GET_DIGEST_SHA="$(jq -r --arg base "$BASE_IMAGE" '.[$base + "-multi"]."containerimage.digest"' <<< "${BAKE_METADATA}")"
|
|
echo "DIGEST_SHA=${GET_DIGEST_SHA}" | tee -a "${GITHUB_ENV}"
|
|
|
|
- name: Export digest
|
|
env:
|
|
DIGEST_SHA: ${{ env.DIGEST_SHA }}
|
|
RUNNER_TEMP: ${{ runner.temp }}
|
|
run: |
|
|
mkdir -p "${RUNNER_TEMP}"/digests
|
|
digest="${DIGEST_SHA}"
|
|
touch "${RUNNER_TEMP}/digests/${digest#sha256:}"
|
|
|
|
- name: Upload digest
|
|
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
|
|
with:
|
|
name: digests-${{ env.NORMALIZED_ARCH }}-${{ matrix.base_image }}
|
|
path: ${{ runner.temp }}/digests/*
|
|
if-no-files-found: error
|
|
retention-days: 1
|
|
|
|
- name: Rename binaries to match target platform
|
|
env:
|
|
NORMALIZED_ARCH: ${{ env.NORMALIZED_ARCH }}
|
|
run: |
|
|
mv ./output/vaultwarden vaultwarden-"${NORMALIZED_ARCH}"
|
|
|
|
# Upload artifacts to Github Actions and Attest the binaries
|
|
- name: Attest binaries
|
|
uses: actions/attest@59d89421af93a897026c735860bf21b6eb4f7b26 # v4.1.0
|
|
with:
|
|
subject-path: vaultwarden-${{ env.NORMALIZED_ARCH }}
|
|
|
|
- name: Upload binaries as artifacts
|
|
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
|
|
with:
|
|
name: vaultwarden-${{ env.SOURCE_VERSION }}-linux-${{ env.NORMALIZED_ARCH }}-${{ matrix.base_image }}
|
|
path: vaultwarden-${{ env.NORMALIZED_ARCH }}
|
|
|
|
merge-manifests:
|
|
name: Merge manifests
|
|
runs-on: ubuntu-latest
|
|
needs: docker-build
|
|
environment:
|
|
name: release
|
|
deployment: false
|
|
permissions:
|
|
packages: write # Needed to upload packages and artifacts
|
|
attestations: write # Needed to generate an artifact attestation for a build
|
|
id-token: write # Needed to mint the OIDC token necessary to request a Sigstore signing certificate
|
|
strategy:
|
|
matrix:
|
|
base_image: ["debian","alpine"]
|
|
|
|
steps:
|
|
- name: Download digests
|
|
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
|
|
with:
|
|
path: ${{ runner.temp }}/digests
|
|
pattern: digests-*-${{ matrix.base_image }}
|
|
merge-multiple: true
|
|
|
|
# Login to Docker Hub
|
|
- name: Login to Docker Hub
|
|
uses: docker/login-action@b45d80f862d83dbcd57f89517bcf500b2ab88fb2 # v4.0.0
|
|
with:
|
|
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
|
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
|
if: ${{ vars.DOCKERHUB_REPO != '' }}
|
|
|
|
- name: Add registry for DockerHub
|
|
if: ${{ vars.DOCKERHUB_REPO != '' }}
|
|
env:
|
|
DOCKERHUB_REPO: ${{ vars.DOCKERHUB_REPO }}
|
|
run: |
|
|
echo "CONTAINER_REGISTRIES=${DOCKERHUB_REPO}" | tee -a "${GITHUB_ENV}"
|
|
|
|
# Login to GitHub Container Registry
|
|
- name: Login to GitHub Container Registry
|
|
uses: docker/login-action@b45d80f862d83dbcd57f89517bcf500b2ab88fb2 # v4.0.0
|
|
with:
|
|
registry: ghcr.io
|
|
username: ${{ github.repository_owner }}
|
|
password: ${{ secrets.GITHUB_TOKEN }}
|
|
if: ${{ vars.GHCR_REPO != '' }}
|
|
|
|
- name: Add registry for ghcr.io
|
|
if: ${{ vars.GHCR_REPO != '' }}
|
|
env:
|
|
GHCR_REPO: ${{ vars.GHCR_REPO }}
|
|
run: |
|
|
echo "CONTAINER_REGISTRIES=${CONTAINER_REGISTRIES:+${CONTAINER_REGISTRIES},}${GHCR_REPO}" | tee -a "${GITHUB_ENV}"
|
|
|
|
# Login to Quay.io
|
|
- name: Login to Quay.io
|
|
uses: docker/login-action@b45d80f862d83dbcd57f89517bcf500b2ab88fb2 # v4.0.0
|
|
with:
|
|
registry: quay.io
|
|
username: ${{ secrets.QUAY_USERNAME }}
|
|
password: ${{ secrets.QUAY_TOKEN }}
|
|
if: ${{ vars.QUAY_REPO != '' }}
|
|
|
|
- name: Add registry for Quay.io
|
|
if: ${{ vars.QUAY_REPO != '' }}
|
|
env:
|
|
QUAY_REPO: ${{ vars.QUAY_REPO }}
|
|
run: |
|
|
echo "CONTAINER_REGISTRIES=${CONTAINER_REGISTRIES:+${CONTAINER_REGISTRIES},}${QUAY_REPO}" | tee -a "${GITHUB_ENV}"
|
|
|
|
# Determine Base Tags
|
|
- name: Determine Base Tags
|
|
env:
|
|
BASE_IMAGE_TAG: "${{ matrix.base_image != 'debian' && format('-{0}', matrix.base_image) || '' }}"
|
|
REF_TYPE: ${{ github.ref_type }}
|
|
run: |
|
|
# Check which main tag we are going to build determined by ref_type
|
|
if [[ "${REF_TYPE}" == "tag" ]]; then
|
|
echo "BASE_TAGS=latest${BASE_IMAGE_TAG},${GITHUB_REF#refs/*/}${BASE_IMAGE_TAG}${BASE_IMAGE_TAG//-/,}" | tee -a "${GITHUB_ENV}"
|
|
elif [[ "${REF_TYPE}" == "branch" ]]; then
|
|
echo "BASE_TAGS=testing${BASE_IMAGE_TAG}" | tee -a "${GITHUB_ENV}"
|
|
fi
|
|
|
|
- name: Create manifest list, push it and extract digest SHA
|
|
working-directory: ${{ runner.temp }}/digests
|
|
env:
|
|
BASE_TAGS: "${{ env.BASE_TAGS }}"
|
|
CONTAINER_REGISTRIES: "${{ env.CONTAINER_REGISTRIES }}"
|
|
run: |
|
|
IFS=',' read -ra IMAGES <<< "${CONTAINER_REGISTRIES}"
|
|
IFS=',' read -ra TAGS <<< "${BASE_TAGS}"
|
|
|
|
TAG_ARGS=()
|
|
for img in "${IMAGES[@]}"; do
|
|
for tag in "${TAGS[@]}"; do
|
|
TAG_ARGS+=("-t" "${img}:${tag}")
|
|
done
|
|
done
|
|
|
|
echo "Creating manifest"
|
|
if ! OUTPUT=$(docker buildx imagetools create \
|
|
"${TAG_ARGS[@]}" \
|
|
$(printf "${IMAGES[0]}@sha256:%s " *) 2>&1); then
|
|
echo "Manifest creation failed"
|
|
echo "${OUTPUT}"
|
|
exit 1
|
|
fi
|
|
|
|
echo "Manifest created successfully"
|
|
echo "${OUTPUT}"
|
|
|
|
# Extract digest SHA for subsequent steps
|
|
GET_DIGEST_SHA="$(echo "${OUTPUT}" | grep -oE 'sha256:[a-f0-9]{64}' | tail -1)"
|
|
echo "DIGEST_SHA=${GET_DIGEST_SHA}" | tee -a "${GITHUB_ENV}"
|
|
|
|
# Attest container images
|
|
- name: Attest - docker.io - ${{ matrix.base_image }}
|
|
if: ${{ vars.DOCKERHUB_REPO != '' && env.DIGEST_SHA != ''}}
|
|
uses: actions/attest@59d89421af93a897026c735860bf21b6eb4f7b26 # v4.1.0
|
|
with:
|
|
subject-name: ${{ vars.DOCKERHUB_REPO }}
|
|
subject-digest: ${{ env.DIGEST_SHA }}
|
|
push-to-registry: true
|
|
|
|
- name: Attest - ghcr.io - ${{ matrix.base_image }}
|
|
if: ${{ vars.GHCR_REPO != '' && env.DIGEST_SHA != ''}}
|
|
uses: actions/attest@59d89421af93a897026c735860bf21b6eb4f7b26 # v4.1.0
|
|
with:
|
|
subject-name: ${{ vars.GHCR_REPO }}
|
|
subject-digest: ${{ env.DIGEST_SHA }}
|
|
push-to-registry: true
|
|
|
|
- name: Attest - quay.io - ${{ matrix.base_image }}
|
|
if: ${{ vars.QUAY_REPO != '' && env.DIGEST_SHA != ''}}
|
|
uses: actions/attest@59d89421af93a897026c735860bf21b6eb4f7b26 # v4.1.0
|
|
with:
|
|
subject-name: ${{ vars.QUAY_REPO }}
|
|
subject-digest: ${{ env.DIGEST_SHA }}
|
|
push-to-registry: true
|