Org.put_policy type not in body anymore (#6514) #587
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Release | |
| permissions: {} | |
| 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]+' | |
| 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' }} | |
| defaults: | |
| run: | |
| shell: bash | |
| env: | |
| # The *_REPO variables need to be configured as repository variables | |
| # Append `/settings/variables/actions` to your repo url | |
| # DOCKERHUB_REPO needs to be 'index.docker.io/<user>/<repo>' | |
| # Check for Docker hub credentials in secrets | |
| HAVE_DOCKERHUB_LOGIN: ${{ vars.DOCKERHUB_REPO != '' && secrets.DOCKERHUB_USERNAME != '' && secrets.DOCKERHUB_TOKEN != '' }} | |
| # GHCR_REPO needs to be 'ghcr.io/<user>/<repo>' | |
| # Check for Github credentials in secrets | |
| HAVE_GHCR_LOGIN: ${{ vars.GHCR_REPO != '' && github.repository_owner != '' && secrets.GITHUB_TOKEN != '' }} | |
| # QUAY_REPO needs to be 'quay.io/<user>/<repo>' | |
| # Check for Quay.io credentials in secrets | |
| HAVE_QUAY_LOGIN: ${{ vars.QUAY_REPO != '' && secrets.QUAY_USERNAME != '' && secrets.QUAY_TOKEN != '' }} | |
| jobs: | |
| docker-build: | |
| name: Build Vaultwarden containers | |
| if: ${{ github.repository == 'dani-garcia/vaultwarden' }} | |
| 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 | |
| # Start a local docker registry to extract the compiled binaries to upload as artifacts and attest them | |
| services: | |
| registry: | |
| image: registry@sha256:1fc7de654f2ac1247f0b67e8a459e273b0993be7d2beda1f3f56fbf1001ed3e7 # v3.0.0 | |
| ports: | |
| - 5000:5000 | |
| 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"] | |
| outputs: | |
| base-tags: ${{ steps.determine-version.outputs.BASE_TAGS }} | |
| steps: | |
| - name: Initialize QEMU binfmt support | |
| uses: docker/setup-qemu-action@c7c53464625b32c7a7e944ae62b3e17d2b600130 # v3.7.0 | |
| with: | |
| platforms: "arm64,arm" | |
| # Start Docker Buildx | |
| - name: Setup Docker Buildx | |
| uses: docker/setup-buildx-action@e468171a9de216ec08956ac3ada2f0791b6bd435 # v3.11.1 | |
| # 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@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 #v6.0.0 | |
| # 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 Base Tags and Source Version | |
| - name: Determine Base Tags and Source Version | |
| id: determine-version | |
| env: | |
| 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,${GITHUB_REF#refs/*/}" | tee -a "${GITHUB_OUTPUT}" | |
| elif [[ "${REF_TYPE}" == "branch" ]]; then | |
| echo "BASE_TAGS=testing" | tee -a "${GITHUB_OUTPUT}" | |
| fi | |
| # 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 | |
| # End Determine Base Tags | |
| # Login to Docker Hub | |
| - name: Login to Docker Hub | |
| uses: docker/login-action@5e57cd118135c172c3672efd75eb46360885c0ef # v3.6.0 | |
| with: | |
| username: ${{ secrets.DOCKERHUB_USERNAME }} | |
| password: ${{ secrets.DOCKERHUB_TOKEN }} | |
| if: ${{ env.HAVE_DOCKERHUB_LOGIN == 'true' }} | |
| - name: Add registry for DockerHub | |
| if: ${{ env.HAVE_DOCKERHUB_LOGIN == 'true' }} | |
| 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@5e57cd118135c172c3672efd75eb46360885c0ef # v3.6.0 | |
| with: | |
| registry: ghcr.io | |
| username: ${{ github.repository_owner }} | |
| password: ${{ secrets.GITHUB_TOKEN }} | |
| if: ${{ env.HAVE_GHCR_LOGIN == 'true' }} | |
| - name: Add registry for ghcr.io | |
| if: ${{ env.HAVE_GHCR_LOGIN == 'true' }} | |
| 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@5e57cd118135c172c3672efd75eb46360885c0ef # v3.6.0 | |
| with: | |
| registry: quay.io | |
| username: ${{ secrets.QUAY_USERNAME }} | |
| password: ${{ secrets.QUAY_TOKEN }} | |
| if: ${{ env.HAVE_QUAY_LOGIN == 'true' }} | |
| - name: Add registry for Quay.io | |
| if: ${{ env.HAVE_QUAY_LOGIN == 'true' }} | |
| 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 "${HAVE_GHCR_LOGIN}" ]]; 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: Add localhost registry | |
| run: | | |
| echo "CONTAINER_REGISTRIES=${CONTAINER_REGISTRIES:+${CONTAINER_REGISTRIES},}localhost:5000/vaultwarden/server" | tee -a "${GITHUB_ENV}" | |
| - 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@5be5f02ff8819ecd3092ea6b2e6261c31774f2b4 # v6.10.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=image,push-by-digest=true,name-canonical=true,push=true,compression=zstd | |
| - 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@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0 | |
| with: | |
| name: digests-${{ env.NORMALIZED_ARCH }}-${{ matrix.base_image }} | |
| path: ${{ runner.temp }}/digests/* | |
| if-no-files-found: error | |
| retention-days: 1 | |
| # Extract the Alpine binaries from the containers | |
| - name: Extract binaries | |
| env: | |
| REF_TYPE: ${{ github.ref_type }} | |
| BASE_IMAGE: ${{ matrix.base_image }} | |
| DIGEST_SHA: ${{ env.DIGEST_SHA }} | |
| NORMALIZED_ARCH: ${{ env.NORMALIZED_ARCH }} | |
| run: | | |
| # Check which main tag we are going to build determined by ref_type | |
| if [[ "${REF_TYPE}" == "tag" ]]; then | |
| EXTRACT_TAG="latest" | |
| elif [[ "${REF_TYPE}" == "branch" ]]; then | |
| EXTRACT_TAG="testing" | |
| fi | |
| # Check which base_image was used and append -alpine if needed | |
| if [[ "${BASE_IMAGE}" == "alpine" ]]; then | |
| EXTRACT_TAG="${EXTRACT_TAG}-alpine" | |
| fi | |
| CONTAINER_ID="$(docker create "localhost:5000/vaultwarden/server:${EXTRACT_TAG}@${DIGEST_SHA}")" | |
| # Copy the binary | |
| docker cp "$CONTAINER_ID":/vaultwarden vaultwarden-"${NORMALIZED_ARCH}" | |
| # Clean up | |
| docker rm "$CONTAINER_ID" | |
| # Upload artifacts to Github Actions and Attest the binaries | |
| - name: Attest binaries | |
| uses: actions/attest-build-provenance@977bb373ede98d70efdf65b84cb5f73e068dcc2a # v3.0.0 | |
| with: | |
| subject-path: vaultwarden-${{ env.NORMALIZED_ARCH }} | |
| - name: Upload binaries as artifacts | |
| uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.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 | |
| env: | |
| BASE_TAGS: ${{ needs.docker-build.outputs.base-tags }} | |
| 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@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6.0.0 | |
| 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@5e57cd118135c172c3672efd75eb46360885c0ef # v3.6.0 | |
| with: | |
| username: ${{ secrets.DOCKERHUB_USERNAME }} | |
| password: ${{ secrets.DOCKERHUB_TOKEN }} | |
| if: ${{ env.HAVE_DOCKERHUB_LOGIN == 'true' }} | |
| - name: Add registry for DockerHub | |
| if: ${{ env.HAVE_DOCKERHUB_LOGIN == 'true' }} | |
| 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@5e57cd118135c172c3672efd75eb46360885c0ef # v3.6.0 | |
| with: | |
| registry: ghcr.io | |
| username: ${{ github.repository_owner }} | |
| password: ${{ secrets.GITHUB_TOKEN }} | |
| if: ${{ env.HAVE_GHCR_LOGIN == 'true' }} | |
| - name: Add registry for ghcr.io | |
| if: ${{ env.HAVE_GHCR_LOGIN == 'true' }} | |
| 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@5e57cd118135c172c3672efd75eb46360885c0ef # v3.6.0 | |
| with: | |
| registry: quay.io | |
| username: ${{ secrets.QUAY_USERNAME }} | |
| password: ${{ secrets.QUAY_TOKEN }} | |
| if: ${{ env.HAVE_QUAY_LOGIN == 'true' }} | |
| - name: Add registry for Quay.io | |
| if: ${{ env.HAVE_QUAY_LOGIN == 'true' }} | |
| env: | |
| QUAY_REPO: ${{ vars.QUAY_REPO }} | |
| run: | | |
| echo "CONTAINER_REGISTRIES=${CONTAINER_REGISTRIES:+${CONTAINER_REGISTRIES},}${QUAY_REPO}" | tee -a "${GITHUB_ENV}" | |
| - name: Create manifest list, push it and extract digest SHA | |
| working-directory: ${{ runner.temp }}/digests | |
| env: | |
| BASE_IMAGE: "${{ matrix.base_image }}" | |
| BASE_TAGS: "${{ env.BASE_TAGS }}" | |
| CONTAINER_REGISTRIES: "${{ env.CONTAINER_REGISTRIES }}" | |
| run: | | |
| set +e | |
| IFS=',' read -ra IMAGES <<< "${CONTAINER_REGISTRIES}" | |
| IFS=',' read -ra TAGS <<< "${BASE_TAGS}" | |
| for img in "${IMAGES[@]}"; do | |
| for tag in "${TAGS[@]}"; do | |
| echo "Creating manifest for $img:$tag-${BASE_IMAGE}" | |
| OUTPUT=$(docker buildx imagetools create \ | |
| -t "$img:$tag-${BASE_IMAGE}" \ | |
| $(printf "$img:$tag-${BASE_IMAGE}@sha256:%s " *) 2>&1) | |
| STATUS=$? | |
| if [ $STATUS -ne 0 ]; then | |
| echo "Manifest creation failed for $img" | |
| echo "$OUTPUT" | |
| exit $STATUS | |
| fi | |
| echo "Manifest created for $img" | |
| echo "$OUTPUT" | |
| done | |
| done | |
| set -e | |
| # 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: ${{ env.HAVE_DOCKERHUB_LOGIN == 'true' && env.DIGEST_SHA != ''}} | |
| uses: actions/attest-build-provenance@977bb373ede98d70efdf65b84cb5f73e068dcc2a # v3.0.0 | |
| with: | |
| subject-name: ${{ vars.DOCKERHUB_REPO }} | |
| subject-digest: ${{ env.DIGEST_SHA }} | |
| push-to-registry: true | |
| - name: Attest - ghcr.io - ${{ matrix.base_image }} | |
| if: ${{ env.HAVE_GHCR_LOGIN == 'true' && env.DIGEST_SHA != ''}} | |
| uses: actions/attest-build-provenance@977bb373ede98d70efdf65b84cb5f73e068dcc2a # v3.0.0 | |
| with: | |
| subject-name: ${{ vars.GHCR_REPO }} | |
| subject-digest: ${{ env.DIGEST_SHA }} | |
| push-to-registry: true | |
| - name: Attest - quay.io - ${{ matrix.base_image }} | |
| if: ${{ env.HAVE_QUAY_LOGIN == 'true' && env.DIGEST_SHA != ''}} | |
| uses: actions/attest-build-provenance@977bb373ede98d70efdf65b84cb5f73e068dcc2a # v3.0.0 | |
| with: | |
| subject-name: ${{ vars.QUAY_REPO }} | |
| subject-digest: ${{ env.DIGEST_SHA }} | |
| push-to-registry: true |