mirror of
https://github.com/element-hq/synapse.git
synced 2026-08-14 09:20:49 +00:00
Add explicit permissions blocks so workflows and jobs no longer rely on GitHub's default GITHUB_TOKEN scopes. Document each granted permission inline with the workflow reason it is needed, so future edits can tell the difference between repository checkout access, package publishing, OIDC authentication, issue creation, and release publishing. Move Docker package and OIDC permissions from the workflow level to the image build and merge jobs that need them. Keep release artifact builds read-only and grant contents: write only to the tag-only release upload job. Grant issues: write only to the scheduled failure issue-creation jobs, pull-requests: read only to the paths-filter job, and disable the token entirely for workflows that do not need the default GITHUB_TOKEN.
233 lines
8.8 KiB
YAML
233 lines
8.8 KiB
YAML
# GitHub actions workflow which builds and publishes the docker images.
|
|
|
|
name: Build docker images
|
|
|
|
on:
|
|
push:
|
|
tags: ["v*"]
|
|
branches: [master, main, develop]
|
|
workflow_dispatch:
|
|
|
|
# No default GITHUB_TOKEN permissions are needed at the workflow level.
|
|
permissions: {}
|
|
|
|
jobs:
|
|
build:
|
|
name: Build and push image for ${{ matrix.platform }}
|
|
runs-on: ${{ matrix.runs_on }}
|
|
permissions:
|
|
# Required to check out the repository.
|
|
contents: read
|
|
# Required to push images to GitHub Container Registry.
|
|
packages: write
|
|
# Required for OIDC authentication while publishing images.
|
|
id-token: write
|
|
strategy:
|
|
matrix:
|
|
include:
|
|
- platform: linux/amd64
|
|
runs_on: ubuntu-24.04
|
|
suffix: linux-amd64
|
|
- platform: linux/arm64
|
|
runs_on: ubuntu-24.04-arm
|
|
suffix: linux-arm64
|
|
steps:
|
|
- name: Set up Docker Buildx
|
|
id: buildx
|
|
uses: docker/setup-buildx-action@d7f5e7f509e45cec5c76c4d5afdd7de93d0b3df5 # v4.1.0
|
|
|
|
- name: Checkout repository
|
|
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
|
|
|
|
- name: Extract version from pyproject.toml
|
|
# Note: explicitly requesting bash will mean bash is invoked with `-eo pipefail`, see
|
|
# https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsshell
|
|
shell: bash
|
|
run: |
|
|
echo "SYNAPSE_VERSION=$(grep "^version" pyproject.toml | sed -E 's/version\s*=\s*["]([^"]*)["]/\1/')" >> $GITHUB_ENV
|
|
|
|
- name: Log in to DockerHub
|
|
uses: docker/login-action@650006c6eb7dba73a995cc03b0b2d7f5ca915bee # v4.2.0
|
|
with:
|
|
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
|
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
|
|
|
- name: Log in to GHCR
|
|
uses: docker/login-action@650006c6eb7dba73a995cc03b0b2d7f5ca915bee # v4.2.0
|
|
with:
|
|
registry: ghcr.io
|
|
username: ${{ github.repository_owner }}
|
|
password: ${{ secrets.GITHUB_TOKEN }}
|
|
|
|
- name: Tailscale
|
|
uses: tailscale/github-action@306e68a486fd2350f2bfc3b19fcd143891a4a2d8 # v4.1.2
|
|
with:
|
|
oauth-client-id: ${{ secrets.TS_OAUTH_CLIENT_ID }}
|
|
audience: ${{ secrets.TS_AUDIENCE }}
|
|
tags: tag:github-actions
|
|
|
|
- name: Compute vault jwt role name
|
|
id: vault-jwt-role
|
|
run: |
|
|
echo "role_name=github_service_management_$( echo "${{ github.repository }}" | sed -r 's|[/-]|_|g')" | tee -a "$GITHUB_OUTPUT"
|
|
|
|
- name: Get team registry token
|
|
id: import-secrets
|
|
uses: hashicorp/vault-action@892a26828f195e65540a40b4768ae4571f51ebfc # v4.0.0
|
|
with:
|
|
url: https://vault.infra.ci.i.element.dev
|
|
role: ${{ steps.vault-jwt-role.outputs.role_name }}
|
|
path: service-management/github-actions
|
|
jwtGithubAudience: https://vault.infra.ci.i.element.dev
|
|
method: jwt
|
|
secrets: |
|
|
services/backend-repositories/secret/data/oci.element.io username | OCI_USERNAME ;
|
|
services/backend-repositories/secret/data/oci.element.io password | OCI_PASSWORD ;
|
|
|
|
- name: Login to Element OCI Registry
|
|
uses: docker/login-action@650006c6eb7dba73a995cc03b0b2d7f5ca915bee # v4.2.0
|
|
with:
|
|
registry: oci-push.vpn.infra.element.io
|
|
username: ${{ steps.import-secrets.outputs.OCI_USERNAME }}
|
|
password: ${{ steps.import-secrets.outputs.OCI_PASSWORD }}
|
|
|
|
- name: Build and push by digest
|
|
id: build
|
|
uses: docker/build-push-action@f9f3042f7e2789586610d6e8b85c8f03e5195baf # v7.2.0
|
|
with:
|
|
push: true
|
|
labels: |
|
|
gitsha1=${{ github.sha }}
|
|
org.opencontainers.image.version=${{ env.SYNAPSE_VERSION }}
|
|
tags: |
|
|
docker.io/matrixdotorg/synapse
|
|
ghcr.io/element-hq/synapse
|
|
oci-push.vpn.infra.element.io/synapse
|
|
file: "docker/Dockerfile"
|
|
platforms: ${{ matrix.platform }}
|
|
outputs: type=image,push-by-digest=true,name-canonical=true,push=true
|
|
|
|
- name: Export digest
|
|
run: |
|
|
mkdir -p ${{ runner.temp }}/digests
|
|
digest="${{ steps.build.outputs.digest }}"
|
|
touch "${{ runner.temp }}/digests/${digest#sha256:}"
|
|
|
|
- name: Upload digest
|
|
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
|
with:
|
|
name: digests-${{ matrix.suffix }}
|
|
path: ${{ runner.temp }}/digests/*
|
|
if-no-files-found: error
|
|
retention-days: 1
|
|
|
|
merge:
|
|
name: Push merged images to ${{ matrix.repository }}
|
|
runs-on: ubuntu-latest
|
|
permissions:
|
|
# Required to push merged images to GitHub Container Registry.
|
|
packages: write
|
|
# Required for OIDC authentication while publishing images.
|
|
id-token: write
|
|
strategy:
|
|
matrix:
|
|
repository:
|
|
- docker.io/matrixdotorg/synapse
|
|
- ghcr.io/element-hq/synapse
|
|
- oci-push.vpn.infra.element.io/synapse
|
|
|
|
needs:
|
|
- build
|
|
steps:
|
|
- name: Download digests
|
|
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
|
|
with:
|
|
path: ${{ runner.temp }}/digests
|
|
pattern: digests-*
|
|
merge-multiple: true
|
|
|
|
- name: Log in to DockerHub
|
|
uses: docker/login-action@650006c6eb7dba73a995cc03b0b2d7f5ca915bee # v4.2.0
|
|
if: ${{ startsWith(matrix.repository, 'docker.io') }}
|
|
with:
|
|
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
|
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
|
|
|
- name: Log in to GHCR
|
|
uses: docker/login-action@650006c6eb7dba73a995cc03b0b2d7f5ca915bee # v4.2.0
|
|
if: ${{ startsWith(matrix.repository, 'ghcr.io') }}
|
|
with:
|
|
registry: ghcr.io
|
|
username: ${{ github.repository_owner }}
|
|
password: ${{ secrets.GITHUB_TOKEN }}
|
|
|
|
- name: Tailscale
|
|
uses: tailscale/github-action@306e68a486fd2350f2bfc3b19fcd143891a4a2d8 # v4.1.2
|
|
with:
|
|
oauth-client-id: ${{ secrets.TS_OAUTH_CLIENT_ID }}
|
|
audience: ${{ secrets.TS_AUDIENCE }}
|
|
tags: tag:github-actions
|
|
|
|
- name: Compute vault jwt role name
|
|
id: vault-jwt-role
|
|
run: |
|
|
echo "role_name=github_service_management_$( echo "${{ github.repository }}" | sed -r 's|[/-]|_|g')" | tee -a "$GITHUB_OUTPUT"
|
|
|
|
- name: Get team registry token
|
|
id: import-secrets
|
|
uses: hashicorp/vault-action@892a26828f195e65540a40b4768ae4571f51ebfc # v4.0.0
|
|
with:
|
|
url: https://vault.infra.ci.i.element.dev
|
|
role: ${{ steps.vault-jwt-role.outputs.role_name }}
|
|
path: service-management/github-actions
|
|
jwtGithubAudience: https://vault.infra.ci.i.element.dev
|
|
method: jwt
|
|
secrets: |
|
|
services/backend-repositories/secret/data/oci.element.io username | OCI_USERNAME ;
|
|
services/backend-repositories/secret/data/oci.element.io password | OCI_PASSWORD ;
|
|
|
|
- name: Login to Element OCI Registry
|
|
uses: docker/login-action@650006c6eb7dba73a995cc03b0b2d7f5ca915bee # v4.2.0
|
|
with:
|
|
registry: oci-push.vpn.infra.element.io
|
|
username: ${{ steps.import-secrets.outputs.OCI_USERNAME }}
|
|
password: ${{ steps.import-secrets.outputs.OCI_PASSWORD }}
|
|
|
|
- name: Set up Docker Buildx
|
|
uses: docker/setup-buildx-action@d7f5e7f509e45cec5c76c4d5afdd7de93d0b3df5 # v4.1.0
|
|
|
|
- name: Install Cosign
|
|
uses: sigstore/cosign-installer@6f9f17788090df1f26f669e9d70d6ae9567deba6 # v4.1.2
|
|
|
|
- name: Calculate docker image tag
|
|
uses: docker/metadata-action@80c7e94dd9b9319bd5eb7a0e0fe9291e23a2a2e9 # v6.1.0
|
|
with:
|
|
images: ${{ matrix.repository }}
|
|
flavor: |
|
|
latest=false
|
|
tags: |
|
|
type=raw,value=develop,enable=${{ github.ref == 'refs/heads/develop' }}
|
|
type=raw,value=latest,enable=${{ github.ref == 'refs/heads/master' }}
|
|
type=raw,value=latest,enable=${{ github.ref == 'refs/heads/main' }}
|
|
type=pep440,pattern={{raw}}
|
|
type=sha
|
|
|
|
- name: Create manifest list and push
|
|
working-directory: ${{ runner.temp }}/digests
|
|
env:
|
|
REPOSITORY: ${{ matrix.repository }}
|
|
run: |
|
|
docker buildx imagetools create $(jq -cr '.tags | map("-t " + .) | join(" ")' <<< "$DOCKER_METADATA_OUTPUT_JSON") \
|
|
$(printf "$REPOSITORY@sha256:%s " *)
|
|
|
|
- name: Sign each manifest
|
|
env:
|
|
REPOSITORY: ${{ matrix.repository }}
|
|
run: |
|
|
DIGESTS=""
|
|
for TAG in $(echo "$DOCKER_METADATA_OUTPUT_JSON" | jq -r '.tags[]'); do
|
|
DIGEST="$(docker buildx imagetools inspect $TAG --format '{{json .Manifest}}' | jq -r '.digest')"
|
|
DIGESTS="$DIGESTS $REPOSITORY@$DIGEST"
|
|
done
|
|
cosign sign --yes $DIGESTS
|