diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index fd2949492f6..2209cb98d5d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -77,6 +77,8 @@ jobs: run: scripts/test-release-ref-contract.sh - name: Relay image eligibility contract run: scripts/test-relay-image-eligibility-workflow.sh + - name: PR image URL event contract + run: scripts/test-pr-image-url-event.sh - name: Desktop release candidate contract run: scripts/test-desktop-release-candidate.sh - name: OSS desktop promotion contract diff --git a/.github/workflows/pr-image-urls.yml b/.github/workflows/pr-image-urls.yml new file mode 100644 index 00000000000..2124361d334 --- /dev/null +++ b/.github/workflows/pr-image-urls.yml @@ -0,0 +1,23 @@ +name: PR Image URLs + +on: + pull_request_target: + types: [opened, edited, reopened] + +permissions: + contents: read + +jobs: + check: + name: Check PR image URLs + runs-on: ubuntu-latest + timeout-minutes: 2 + steps: + # pull_request_target has a privileged context. Check out only the trusted + # base commit and never execute code from the pull request branch. + - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 + with: + ref: ${{ github.event.pull_request.base.sha }} + persist-credentials: false + - name: Check pull request body + run: scripts/check-pr-image-urls-event.sh diff --git a/scripts/check-pr-image-urls-event.sh b/scripts/check-pr-image-urls-event.sh new file mode 100755 index 00000000000..424645254bb --- /dev/null +++ b/scripts/check-pr-image-urls-event.sh @@ -0,0 +1,29 @@ +#!/usr/bin/env bash +set -euo pipefail + +if [[ -z "${GITHUB_EVENT_PATH:-}" ]]; then + echo "error: GITHUB_EVENT_PATH is required" >&2 + exit 1 +fi + +script_dir=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd) +markdown_file=$(mktemp) +trap 'rm -f "$markdown_file"' EXIT + +if ! jq -e '(.pull_request | type) == "object"' "$GITHUB_EVENT_PATH" \ + >/dev/null 2>&1; then + echo "error: event does not contain a pull_request object" >&2 + exit 1 +fi + +jq -er ' + if .pull_request.body == null then + "" + elif (.pull_request.body | type) == "string" then + .pull_request.body + else + error("pull_request.body must be a string or null") + end +' "$GITHUB_EVENT_PATH" >"$markdown_file" + +"$script_dir/check-pr-image-urls.sh" "$markdown_file" diff --git a/scripts/test-pr-image-url-event.sh b/scripts/test-pr-image-url-event.sh new file mode 100755 index 00000000000..64470724c55 --- /dev/null +++ b/scripts/test-pr-image-url-event.sh @@ -0,0 +1,42 @@ +#!/usr/bin/env bash +set -euo pipefail + +repo_root=$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd) +checker="$repo_root/scripts/check-pr-image-urls-event.sh" +test_tmp=$(mktemp -d) +trap 'rm -rf "$test_tmp"' EXIT + +bad_url="https://buzz.example.com/media/$(printf 'a%.0s' {1..64}).png" +bad_body="Screenshot: ![broken]($bad_url)"$'\n'"\$(touch \"$test_tmp/injected\")" +jq -n --arg body "$bad_body" \ + '{pull_request: {body: $body}}' >"$test_tmp/bad-event.json" + +if GITHUB_EVENT_PATH="$test_tmp/bad-event.json" "$checker" \ + >"$test_tmp/bad-output" 2>&1; then + echo "PR event checker accepted a relay media URL" >&2 + exit 1 +fi +grep -Fq "$bad_url" "$test_tmp/bad-output" +grep -Fq "scripts/post-screenshots.sh" "$test_tmp/bad-output" +[[ ! -e "$test_tmp/injected" ]] + +jq -n --arg body 'Screenshot: ![safe](https://github.com/user-attachments/assets/example)' \ + '{pull_request: {body: $body}}' >"$test_tmp/good-event.json" +GITHUB_EVENT_PATH="$test_tmp/good-event.json" "$checker" + +jq -n '{pull_request: {body: null}}' >"$test_tmp/empty-event.json" +GITHUB_EVENT_PATH="$test_tmp/empty-event.json" "$checker" + +jq -n '{workflow_dispatch: {}}' >"$test_tmp/non-pr-event.json" +if GITHUB_EVENT_PATH="$test_tmp/non-pr-event.json" "$checker" \ + >"$test_tmp/non-pr-output" 2>&1; then + echo "PR event checker accepted an event without a pull_request object" >&2 + exit 1 +fi +expected_non_pr_error="error: event does not contain a pull_request object" +if [[ "$(<"$test_tmp/non-pr-output")" != "$expected_non_pr_error" ]]; then + echo "PR event checker did not emit the expected non-PR event error" >&2 + exit 1 +fi + +echo "PR image URL event test passed"