Files
synapse/.github/workflows/schema_diff.yml
T
Mohammed Sufiyan AhmedandOlivier 'reivilibre 1e69b49255 Fix Schema Diff CI failing to post comment on PRs from forks (#20207)
Fixes: #20167

The `Schema Diff` workflow posts a PR comment showing the effective
schema diff. For PRs from forks, `GITHUB_TOKEN` is downgraded to
read-only, so the comment-posting step was silently failing.

### Changes
- `schema_diff.yml`: only post the comment directly when the PR is from
the same repository. For forked PRs, upload the diff (and PR number) as
a short-lived artifact instead of trying to comment.
- `schema_diff_comment.yml` (new): triggered by `workflow_run` after
`Schema Diff` completes, with `pull-requests: write` permission (granted
because this workflow always runs in the context of the base
repository). It downloads the artifact, if present, and posts the
comment on behalf of the forked PR.

This avoids `pull_request_target`, per the security concerns raised in
the issue (zizmor flags it as dangerous). The new workflow only ever
treats the downloaded artifact as inert comment text -- it is never
executed.

---------

Co-authored-by: Olivier 'reivilibre <oliverw@element.io>
2026-09-11 12:55:13 +01:00

129 lines
4.9 KiB
YAML

name: Schema Diff # If this is changed, need to update `schema_diff_comment.yml` as well
on:
pull_request:
paths:
- synapse/storage/schema/*/delta/**
- synapse/storage/schema/*/full_schemas/**
- .github/workflows/schema_diff.yml
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
permissions:
contents: read
jobs:
# Posts a GitHub PR comment that shows what the effective change to the schema is.
# Provides an excuse to run the `make_full_schema.sh` script in CI (so we keep it working)
# and can act as a review aid for schema changes, letting you easily see the diff of the
# end result, even when background updates or complex schema deltas are present.
show-schema-diff:
name: Show schema diff
runs-on: ubuntu-latest
permissions:
pull-requests: write
steps:
- name: Start postgres with a faked clock
background: true
id: postgres
# Use faketime here for schema deltas that are wall-clock sensitive under Postgres
# For SQLite, faketime is used when invoking `make_full_schema.sh` within the script
run: |
# Build a docker image with faketime
mkdir /tmp/postgres-faketime
cat > /tmp/postgres-faketime/Dockerfile <<'EOF'
FROM postgres:14-alpine
RUN apk add --no-cache libfaketime
# It seems like it could be harmful to fake the monotonic timer
# as it might prevent deadlock detection, etc.
# But not sure, just doing out of precaution.
ENV FAKETIME_DONT_FAKE_MONOTONIC=1
ENTRYPOINT ["faketime", "-f", "2001-05-25 12:42:42", "docker-entrypoint.sh"]
CMD ["postgres"]
EOF
docker build -t localhost/postgres-faketime /tmp/postgres-faketime
# Run it in the background
docker run -d --name postgres -p 5432:5432 \
-e POSTGRES_PASSWORD=postgres \
-e POSTGRES_INITDB_ARGS="--lc-collate C --lc-ctype C --encoding UTF8" \
--health-cmd pg_isready --health-interval 10s \
--health-timeout 5s --health-retries 5 \
localhost/postgres-faketime
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
fetch-depth: 0
- name: Install PostgreSQL client and faketime
run: sudo apt-get -qq install postgresql-client faketime
- uses: matrix-org/setup-python-poetry@5bbf6603c5c930615ec8a29f1b5d7d258d905aa4 # v2.0.0
with:
poetry-version: "2.4.1"
extras: "postgres"
python-version: "3.x"
- name: Wait for Postgres to be up
run: |
until [ "$(docker inspect -f '{{.State.Health.Status}}' postgres)" = healthy ]; do sleep 2; done
- name: Generate schema diff
id: schema_diff
env:
PGHOST: localhost
PGUSER: postgres
PGPASSWORD: postgres
run: |
poetry run python .ci/scripts/schema_diff.py \
--base origin/develop \
> "${{ runner.temp }}/schema_diff.md"
- name: Stop postgres
cancel: postgres
# If the generation step failed, write an error message so the sticky
# comment step still has a file to read.
- name: Ensure output file exists on failure
if: always() && steps.schema_diff.outcome == 'failure'
run: |
echo "⚠️ Schema diff generation failed. See job logs for details." \
> "${{ runner.temp }}/schema_diff.md"
# Post a comment.
#
# For same-repo PRs, we can do this directly and we are done.
- name: Post sticky PR comment
uses: marocchino/sticky-pull-request-comment@3d7b8546315c63df45a03981d50a43ec19237f80 # v3
# Only run for same-repo PRs
if: always() && github.event.pull_request.head.repo.full_name == github.repository
with:
header: schema-diff
path: ${{ runner.temp }}/schema_diff.md
# For PRs from forks, we only have a read-only `GITHUB_TOKEN` here and need to work around
# by triggering a `workflow_run` onto the main repo.
#
# We upload an artifact and the `schema_diff_comment.yml` workflow will be triggered
# on the main repo by this workflow exiting.
- name: Save PR number for forked PRs
# Only run for fork PRs
if: always() && github.event.pull_request.head.repo.full_name != github.repository
run: echo "${{ github.event.pull_request.number }}" > "${{ runner.temp }}/pr_number"
- name: Upload schema diff artifact for forked PRs
# Only run for fork PRs
if: always() && github.event.pull_request.head.repo.full_name != github.repository
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: schema-diff
path: |
${{ runner.temp }}/schema_diff.md
${{ runner.temp }}/pr_number
retention-days: 1