Skip to content
This repository was archived by the owner on Aug 6, 2026. It is now read-only.
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
87 changes: 87 additions & 0 deletions .github/workflows/trunk-impacted-targets.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
# Uploads this PR's impacted targets to Trunk so the parallel merge queue can
# schedule it. Trunk needs an impacted-targets upload to place a PR into a lane;
# without one, fork PRs never enter the queue and have to be merged by hand (see
# PR #2819).
#
# The upload authenticates with the org API token (x-api-token) on internal PRs.
# Fork PR workflow runs do NOT receive repo secrets β€” GitHub withholds them from
# `pull_request` runs originating in a fork β€” so for forks we authenticate with
# the workflow run id instead (x-forked-workflow-run-id). Trunk verifies the run
# id belongs to a live fork-PR workflow whose head SHA matches the payload.
# Ref: https://docs.trunk.io/merge-queue/optimizations/parallel-queues/api#handling-forked-pull-requests
#
# SECURITY: this MUST stay on the `pull_request` trigger, never
# `pull_request_target`. `pull_request_target` would hand repo secrets to code
# from untrusted forks ("pwn request"). The fork path deliberately needs no
# secret, so the plain `pull_request` trigger is sufficient and safe.
name: Trunk Impacted Targets

on:
pull_request:
types: [opened, synchronize, reopened, ready_for_review]

concurrency:
# Supersede in-flight uploads when the PR head moves; the last upload per head
# SHA wins on Trunk's side anyway. Key on the PR number, not head_ref: fork
# PRs frequently share a source branch name (many are opened from `main`), and
# keying on head_ref would put two such PRs in one group where one cancels the
# other's upload β€” leaving that head SHA without the upload it needs to enter
# the queue.
group: trunk-impacted-targets-${{ github.event.pull_request.number || github.head_ref || github.ref }}
cancel-in-progress: true

jobs:
upload:
runs-on: ubuntu-latest
# Reads only the event payload and talks out to Trunk β€” no repo write or PR
# API access needed.
permissions:
contents: read
env:
IS_FORK: ${{ github.event.pull_request.head.repo.full_name != github.repository }}
RUN_ID: ${{ github.run_id }}
REPO_OWNER: ${{ github.repository_owner }}
REPO_NAME: ${{ github.event.repository.name }}
PR_NUMBER: ${{ github.event.pull_request.number }}
# Head SHA (not the synthetic merge commit): it matches the workflow run's
# head_sha, which is what Trunk checks when verifying a fork upload.
PR_SHA: ${{ github.event.pull_request.head.sha }}
TARGET_BRANCH: ${{ github.event.pull_request.base.ref }}
TRUNK_API_TOKEN: ${{ secrets.TRUNK_API_TOKEN }}
steps:
- name: Upload impacted targets to Trunk
# Not continue-on-error: a silent failure here is exactly what kept fork
# PRs out of the queue, so surface upload problems loudly. --retry rides
# out transient Trunk/network blips.
run: |
set -euo pipefail

# We report "ALL" β€” every target β€” which is always correct: it can
# never under-report and let the queue merge conflicting PRs in
# parallel. It yields no parallelism benefit, but it gets every PR
# (forks included) into the queue. To actually parallelise, replace
# "ALL" with a computed target-name list (e.g. derived from the
# dorny/paths-filter outputs in test.yml) once the queue's target
# names are defined; see the Trunk bazel-action reference impl.
payload="$(jq -n \
--arg host "github.com" \
--arg owner "$REPO_OWNER" \
--arg name "$REPO_NAME" \
--argjson number "$PR_NUMBER" \
--arg sha "$PR_SHA" \
--arg targetBranch "$TARGET_BRANCH" \
'{repo: {host: $host, owner: $owner, name: $name}, pr: {number: $number, sha: $sha}, targetBranch: $targetBranch, impactedTargets: "ALL"}')"

if [ "$IS_FORK" = "true" ]; then
echo "Fork PR β€” authenticating with x-forked-workflow-run-id ($RUN_ID)"
auth_header="x-forked-workflow-run-id: $RUN_ID"
else
echo "Internal PR β€” authenticating with x-api-token"
auth_header="x-api-token: $TRUNK_API_TOKEN"
fi

curl --fail --silent --show-error --retry 3 --retry-all-errors \
-X POST "https://api.trunk.io/v1/setImpactedTargets" \
-H "Content-Type: application/json" \
-H "$auth_header" \
--data "$payload"