Skip to content

Commit 964dc8a

Browse files
committed
up
1 parent c5f6fb3 commit 964dc8a

4 files changed

Lines changed: 93 additions & 21 deletions

File tree

.github/workflows/_get-changed-files.yml

Lines changed: 64 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,24 @@ name: Get Changed Files
22

33
on:
44
workflow_call:
5+
inputs:
6+
include-push-diff:
7+
description: |
8+
When true, on push events the output is the diff between
9+
`github.event.before` and `github.sha` (computed via the
10+
GitHub Compare API). Default is false: push events emit '*',
11+
matching the historical behavior.
12+
type: boolean
13+
required: false
14+
default: false
515
outputs:
616
changed-files:
7-
description: "List of changed files (space-separated) or '*' if not in a PR"
17+
description: "Space-separated list of changed files for PR events (and push events when include-push-diff=true); '*' otherwise."
818
value: ${{ jobs.get-changed-files.outputs.changed-files }}
919

20+
permissions:
21+
contents: read
22+
1023
jobs:
1124
get-changed-files:
1225
runs-on: ubuntu-latest
@@ -18,26 +31,65 @@ jobs:
1831
id: get-files
1932
env:
2033
GH_TOKEN: ${{ github.token }}
34+
INCLUDE_PUSH_DIFF: ${{ inputs.include-push-diff }}
2135
run: |
22-
# Check if we're in a pull request context
23-
if [ "${{ github.event_name }}" = "pull_request" ] || [ "${{ github.event_name }}" = "pull_request_target" ]; then
24-
echo "Running in PR context"
36+
set -eu
2537
26-
# Get the PR number from the github context
27-
PR_NUMBER="${{ github.event.number }}"
38+
EVENT_NAME="${{ github.event_name }}"
39+
REPO="${{ github.repository }}"
2840
29-
# Use gh CLI to get changed files in the PR with explicit repo
30-
CHANGED_FILES=$(gh api repos/${{ github.repository }}/pulls/$PR_NUMBER/files --paginate --jq '.[] | select(.status != "removed") | .filename' | tr '\n' ' ' | sed 's/ $//')
41+
# PR context: list files modified by the PR.
42+
if [ "$EVENT_NAME" = "pull_request" ] || [ "$EVENT_NAME" = "pull_request_target" ]; then
43+
echo "Running in PR context"
44+
PR_NUMBER="${{ github.event.number }}"
45+
CHANGED_FILES=$(gh api "repos/$REPO/pulls/$PR_NUMBER/files" --paginate \
46+
--jq '.[] | select(.status != "removed") | .filename' | tr '\n' ' ' | sed 's/ $//')
3147
3248
if [ -z "$CHANGED_FILES" ]; then
3349
echo "No changed files found, setting to '*'"
3450
CHANGED_FILES="*"
3551
fi
36-
3752
echo "Changed files: $CHANGED_FILES"
3853
echo "changed-files=$CHANGED_FILES" >> "$GITHUB_OUTPUT"
54+
exit 0
55+
fi
3956
40-
else
41-
echo "Not in PR context, setting changed files to '*'"
42-
echo "changed-files=*" >> "$GITHUB_OUTPUT"
57+
# Push context with opt-in: diff between previous tip and new
58+
# tip via the GitHub Compare API. This is what lets path-
59+
# filtered jobs skip on push commits that don't touch their
60+
# relevant paths. Callers must explicitly request this with
61+
# `include-push-diff: true` because some workflows (e.g.
62+
# lint.yml) historically rely on the '*' value to take a
63+
# broader code path.
64+
if [ "$EVENT_NAME" = "push" ] && [ "$INCLUDE_PUSH_DIFF" = "true" ]; then
65+
BEFORE="${{ github.event.before }}"
66+
AFTER="${{ github.sha }}"
67+
ZERO_SHA="0000000000000000000000000000000000000000"
68+
69+
if [ -z "$BEFORE" ] || [ "$BEFORE" = "$ZERO_SHA" ]; then
70+
echo "No 'before' SHA on push event (tag/branch creation or initial push); setting changed files to '*'"
71+
echo "changed-files=*" >> "$GITHUB_OUTPUT"
72+
exit 0
73+
fi
74+
75+
echo "Running in push context: comparing $BEFORE..$AFTER"
76+
CHANGED_FILES=$(gh api "repos/$REPO/compare/$BEFORE...$AFTER" --paginate \
77+
--jq '.files[]? | select(.status != "removed") | .filename' 2>/dev/null \
78+
| tr '\n' ' ' | sed 's/ $//' || echo "")
79+
80+
if [ -z "$CHANGED_FILES" ]; then
81+
echo "Compare returned empty; setting changed files to '*'"
82+
echo "changed-files=*" >> "$GITHUB_OUTPUT"
83+
exit 0
84+
fi
85+
86+
echo "Changed files: $CHANGED_FILES"
87+
echo "changed-files=$CHANGED_FILES" >> "$GITHUB_OUTPUT"
88+
exit 0
4389
fi
90+
91+
# Default for non-PR events (push without opt-in,
92+
# workflow_dispatch, schedule, etc.): no diff. Emit '*' to
93+
# preserve the historical behavior.
94+
echo "Event '$EVENT_NAME' (or include-push-diff=false): emitting '*'"
95+
echo "changed-files=*" >> "$GITHUB_OUTPUT"

.github/workflows/promote-to-viable-strict.yml

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,13 @@ jobs:
7272
# rewritten branches, etc.) that aren't part of the official
7373
# main/release history.
7474
REACHABLE=false
75-
for branch in main $(git branch -r | grep -E 'origin/release/' | sed 's|origin/||'); do
75+
# `git for-each-ref` produces clean refnames (no leading
76+
# whitespace, no `origin/HEAD ->` lines), unlike `git branch -r`.
77+
BRANCHES="main"
78+
while IFS= read -r RELEASE_BRANCH; do
79+
BRANCHES="$BRANCHES $RELEASE_BRANCH"
80+
done < <(git for-each-ref --format='%(refname:lstrip=3)' refs/remotes/origin/release/)
81+
for branch in $BRANCHES; do
7682
if git merge-base --is-ancestor "$SHA" "origin/$branch" 2>/dev/null; then
7783
echo "SHA is reachable from origin/$branch"
7884
REACHABLE=true

.github/workflows/pull.yml

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,20 @@ concurrency:
1515
cancel-in-progress: true
1616

1717
jobs:
18-
# Emits PR diff file list; non-PR events emit '*' (every contains()
19-
# check returns true). Gated jobs combine this with run-decision's
20-
# is-full-run output: on push, jobs run only if a path matches OR
21-
# the commit is a sampled full-run.
18+
# Emits the list of changed files for the current PR or push commit.
19+
# On PR: PR diff. On push: diff against `github.event.before`.
20+
# On events without a diff base (workflow_dispatch, tag creation,
21+
# initial push), emits '*' — note that `contains('*', 'path')` is
22+
# false (literal substring match, not glob), so path-filtered jobs
23+
# rely on run-decision's is-full-run output for those events.
2224
changed-files:
2325
name: Get changed files
2426
uses: ./.github/workflows/_get-changed-files.yml
27+
with:
28+
# Opt in to push-event diff so path-filtered jobs can skip pushes
29+
# that don't touch their relevant paths. Without this, push events
30+
# emit '*' and `contains('*', 'path')` is always false.
31+
include-push-diff: true
2532

2633
run-decision:
2734
name: CI run decision

.github/workflows/trunk.yml

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,20 @@ concurrency:
1919
cancel-in-progress: true
2020

2121
jobs:
22-
# Emits PR diff file list; non-PR events emit '*' (every contains()
23-
# check returns true). Gated jobs combine this with run-decision's
24-
# is-full-run output: on push, jobs run only if a path matches OR
25-
# the commit is a sampled full-run.
22+
# Emits the list of changed files for the current PR or push commit.
23+
# On PR: PR diff. On push: diff against `github.event.before`.
24+
# On events without a diff base (workflow_dispatch, tag creation,
25+
# initial push), emits '*' — note that `contains('*', 'path')` is
26+
# false (literal substring match, not glob), so path-filtered jobs
27+
# rely on run-decision's is-full-run output for those events.
2628
changed-files:
2729
name: Get changed files
2830
uses: ./.github/workflows/_get-changed-files.yml
31+
with:
32+
# Opt in to push-event diff so path-filtered jobs can skip pushes
33+
# that don't touch their relevant paths. Without this, push events
34+
# emit '*' and `contains('*', 'path')` is always false.
35+
include-push-diff: true
2936

3037
run-decision:
3138
name: CI run decision

0 commit comments

Comments
 (0)