Skip to content

Commit 2528bef

Browse files
authored
Add support for deleted files to get-changed-files (#54922)
1 parent ea328a6 commit 2528bef

File tree

6 files changed

+153
-69
lines changed

6 files changed

+153
-69
lines changed

Diff for: .github/actions/get-changed-files/action.yml

+8-11
Original file line numberDiff line numberDiff line change
@@ -9,34 +9,31 @@ inputs:
99
head:
1010
description: 'Head ref to check for changes against'
1111
required: false
12-
pr:
13-
description: 'The PR to check for changes against'
14-
required: false
15-
token:
16-
description: 'The token'
17-
required: true
1812
output_file:
1913
description: 'Optional file path to write the changes to'
2014
required: false
2115

2216
outputs:
2317
all_changed_files:
24-
description: 'List of all changed files (unfiltered)'
18+
description: 'List of all changed files (unfiltered), includes removals'
2519
value: ${{ steps.get_changes.outputs.all_changed_files }}
2620
filtered_changed_files:
27-
description: 'List of changed files matching the `files` filter'
21+
description: 'List of changed files matching the `files` filter, does not include removals'
2822
value: ${{ steps.get_changes.outputs.filtered_changed_files }}
23+
filtered_deleted_files:
24+
description: 'List of deleted files matching the `files` filter'
25+
value: ${{ steps.get_changes.outputs.filtered_deleted_files }}
26+
filtered_renamed_files:
27+
description: 'List of renamed files matching the `files` filter'
28+
value: ${{ steps.get_changes.outputs.filtered_renamed_files }}
2929

3030
runs:
3131
using: 'composite'
3232
steps:
3333
- name: Gather changed files
3434
id: get_changes
3535
env:
36-
INPUT_FILES: ${{ inputs.files }}
37-
INPUT_PR: ${{ inputs.pr || github.event.pull_request.number }}
3836
INPUT_HEAD: ${{ inputs.head || github.event.pull_request.head.ref || github.event.merge_group.head_ref || github.ref_name }}
3937
INPUT_OUTPUT_FILE: ${{ inputs.output_file }}
40-
GH_TOKEN: ${{ inputs.token }}
4138
shell: bash
4239
run: ${{ github.action_path }}/get-changed-files.sh

Diff for: .github/actions/get-changed-files/get-changed-files.sh

+140-39
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,8 @@
22

33
# Required environment variables:
44
# $INPUT_FILES: Pattern(s) to filter files by (e.g., "content/** data/**")
5-
# $INPUT_PR: Pull request number (if running in PR context)
65
# $INPUT_HEAD: Current branch or SHA for git diff
76
# $INPUT_OUTPUT_FILE: Optional file to redirect output to.
8-
# $GH_TOKEN: the access token
97

108
# Default value for files parameter if not provided
119
FILTER=${INPUT_FILES:-.}
@@ -14,63 +12,156 @@ FILTER=${INPUT_FILES:-.}
1412
echo "__ using filter: __"
1513
echo "$FILTER"
1614

17-
# Find the file diff in the pull request or merge group
18-
# If its a pull request, use the faster call to the GitHub API
19-
# For push, workflow_dispatch, and merge_group, use git diff
20-
if [ -n "$INPUT_PR" ]
21-
then
22-
echo "__ running gh pr diff __"
23-
DIFF=$(gh pr diff $INPUT_PR --name-only)
24-
if [ -z "$DIFF" ]; then
25-
echo "__ gh pr diff failed, falling back to git diff __"
26-
HEAD=$(gh pr view $INPUT_PR --json headRefName --jq .headRefName)
27-
fi
28-
fi
15+
# Ensure we have the latest from the remote
16+
echo "__ fetching latest changes __"
17+
git fetch --depth=1 origin main
18+
git fetch --depth=1 origin ${INPUT_HEAD:-HEAD}
2919

30-
if [ -z "$DIFF" ]; then
31-
# If HEAD was set from gh pr view but INPUT_HEAD is empty, use HEAD instead
32-
if [ -z "$INPUT_HEAD" ] && [ -n "$HEAD" ]; then
33-
INPUT_HEAD=$HEAD
34-
fi
35-
echo "__ using branch name $INPUT_HEAD __"
36-
git fetch origin $INPUT_HEAD:refs/remotes/origin/$INPUT_HEAD
37-
echo "__ running git diff __"
20+
# Get diff with status information
21+
echo "__ running git diff with status __"
22+
DIFF_OUTPUT=$(git diff --name-status origin/main origin/${INPUT_HEAD:-HEAD})
3823

39-
DIFF=$(git diff --name-only origin/main origin/$INPUT_HEAD)
40-
fi
24+
# Function to extract files by pattern from diff output
25+
extract_files() {
26+
local pattern=$1
27+
local field=$2
28+
echo "$DIFF_OUTPUT" | grep -E "$pattern" | cut -f$field
29+
}
4130

42-
# So we can inspect the output
43-
echo "__ DIFF found __"
44-
echo "$DIFF"
31+
# Extract files by status
32+
echo "__ extracting files by status __"
33+
MODIFIED_FILES=$(extract_files "^[AM]" 2)
34+
DELETED_FILES=$(extract_files "^D" 2)
35+
RENAMED_OLD_FILES=$(extract_files "^R[0-9]+" 2)
36+
RENAMED_NEW_FILES=$(extract_files "^R[0-9]+" 3)
37+
38+
# Create paired renames in format "oldname=>newname"
39+
create_rename_pairs() {
40+
local old_files=$1
41+
local new_files=$2
42+
local pairs=()
4543

46-
# Filter the DIFF to just the directories specified in the input files
47-
if [ "$FILTER" != "." ]; then
48-
echo "__ filtering DIFF to only include $FILTER __"
49-
FILTERED_DIFF=""
5044
IFS=$'\n'
51-
for file in $DIFF; do
45+
for i in $(seq 1 $(echo "$old_files" | wc -l)); do
46+
OLD=$(echo "$old_files" | sed -n "${i}p")
47+
NEW=$(echo "$new_files" | sed -n "${i}p")
48+
pairs+=("$OLD=>$NEW")
49+
done
50+
unset IFS
51+
52+
printf "%s\n" "${pairs[@]}"
53+
}
54+
55+
RENAMED_FILES_WITH_HISTORY=$(create_rename_pairs "$RENAMED_OLD_FILES" "$RENAMED_NEW_FILES")
56+
57+
# Combine files for different outputs
58+
DIFF=$(echo -e "$MODIFIED_FILES\n$RENAMED_NEW_FILES" | sort | uniq)
59+
ALL_DIFF=$(echo -e "$MODIFIED_FILES\n$DELETED_FILES\n$RENAMED_NEW_FILES" | sort | uniq)
60+
61+
# Debug output
62+
echo "__ MODIFIED files found __"
63+
echo "$MODIFIED_FILES"
64+
echo "__ DELETED files found __"
65+
echo "$DELETED_FILES"
66+
echo "__ RENAMED files found (with history) __"
67+
echo "$RENAMED_FILES_WITH_HISTORY"
68+
echo "__ ALL changed files __"
69+
echo "$ALL_DIFF"
70+
71+
# Function to filter files by pattern
72+
filter_files() {
73+
local files=$1
74+
local result=""
75+
76+
IFS=$'\n'
77+
for file in $files; do
5278
while IFS= read -r pattern || [ -n "$pattern" ]; do
5379
clean_pattern=${pattern%/}
5480
if [[ $file == $clean_pattern || $file == $clean_pattern/* ]]; then
55-
FILTERED_DIFF="$FILTERED_DIFF $file"
81+
result="$result $file"
82+
break
83+
fi
84+
done <<< "$FILTER"
85+
done
86+
unset IFS
87+
88+
echo "$result"
89+
}
90+
91+
# Function to filter rename pairs
92+
filter_renames() {
93+
local new_files=$1
94+
local old_files=$2
95+
local result=""
96+
97+
IFS=$'\n'
98+
for i in $(seq 1 $(echo "$new_files" | wc -l)); do
99+
NEW=$(echo "$new_files" | sed -n "${i}p")
100+
OLD=$(echo "$old_files" | sed -n "${i}p")
101+
102+
while IFS= read -r pattern || [ -n "$pattern" ]; do
103+
clean_pattern=${pattern%/}
104+
if [[ $NEW == $clean_pattern || $NEW == $clean_pattern/* ]]; then
105+
result="$result $OLD=>$NEW"
56106
break
57107
fi
58108
done <<< "$FILTER"
59109
done
60110
unset IFS
111+
112+
echo "$result"
113+
}
114+
115+
# Filter the files to just the directories specified in the input files
116+
if [ "$FILTER" != "." ]; then
117+
echo "__ filtering files to only include $FILTER __"
118+
119+
FILTERED_MODIFIED=$(filter_files "$MODIFIED_FILES")
120+
FILTERED_DELETED=$(filter_files "$DELETED_FILES")
121+
FILTERED_RENAMED=$(filter_renames "$RENAMED_NEW_FILES" "$RENAMED_OLD_FILES")
122+
123+
# For filtered_changed_files (non-deleted files)
124+
FILTERED_DIFF="$FILTERED_MODIFIED"
125+
for new_file in $(echo "$FILTERED_RENAMED" | grep -o "=>[^[:space:]]*" | sed 's/=>//g'); do
126+
FILTERED_DIFF="$FILTERED_DIFF $new_file"
127+
done
128+
129+
MODIFIED_FILES=$FILTERED_MODIFIED
130+
DELETED_FILES=$FILTERED_DELETED
131+
RENAMED_FILES_WITH_HISTORY=$FILTERED_RENAMED
61132
DIFF=$FILTERED_DIFF
62-
echo "__ filtered DIFF __"
63-
echo "$DIFF"
133+
134+
echo "__ filtered MODIFIED files __"
135+
echo "$MODIFIED_FILES"
136+
echo "__ filtered DELETED files __"
137+
echo "$DELETED_FILES"
138+
echo "__ filtered RENAMED files (with history) __"
139+
echo "$RENAMED_FILES_WITH_HISTORY"
140+
echo "__ filtered changed files (non-deleted) __"
141+
echo "$FILTERED_DIFF"
64142
fi
65143

144+
# Function to format output (standardize whitespace)
145+
format_output() {
146+
local input=$1
147+
echo "$input" | tr '\n' ' ' | tr -s ' ' | sed 's/^ *//' | sed 's/ *$//'
148+
}
149+
66150
echo "__ formatting output __"
67-
FORMATTED_DIFF=$(echo "$DIFF" | tr '\n' ' ' | tr -s ' ' | sed 's/^ *//' | sed 's/ *$//')
68-
echo "Formatted diff: '$FORMATTED_DIFF'"
151+
FORMATTED_MODIFIED=$(format_output "$MODIFIED_FILES")
152+
FORMATTED_DELETED=$(format_output "$DELETED_FILES")
153+
FORMATTED_DIFF=$(format_output "$DIFF")
154+
FORMATTED_RENAMED=$(format_output "$RENAMED_FILES_WITH_HISTORY")
155+
ALL_FORMATTED=$(format_output "$ALL_DIFF")
156+
157+
echo "Formatted modified: '$FORMATTED_MODIFIED'"
158+
echo "Formatted deleted: '$FORMATTED_DELETED'"
159+
echo "Formatted renamed: '$FORMATTED_RENAMED'"
160+
echo "Formatted non-deleted changes: '$FORMATTED_DIFF'"
69161

70162
# Set the output for GitHub Actions
71-
ALL_FORMATTED=$(echo "$DIFF" | tr '\n' ' ' | tr -s ' ' | sed 's/^ *//' | sed 's/ *$//')
72163
HAS_CHANGES=true
73-
if [[ -z "$ALL_FORMATTED" ]]; then
164+
if [[ -z "$FORMATTED_DIFF" && -z "$FORMATTED_DELETED" ]]; then
74165
echo "No changed files detected"
75166
HAS_CHANGES=false
76167
fi
@@ -83,6 +174,8 @@ set_outputs() {
83174
echo "Setting empty outputs to $target"
84175
echo "all_changed_files=" >> "$target"
85176
echo "filtered_changed_files=" >> "$target"
177+
echo "filtered_deleted_files=" >> "$target"
178+
echo "filtered_renamed_files=" >> "$target"
86179
else
87180
echo "Setting non-empty outputs to $target"
88181
echo "all_changed_files<<EOF" >> "$target"
@@ -92,6 +185,14 @@ set_outputs() {
92185
echo "filtered_changed_files<<EOF" >> "$target"
93186
echo "$FORMATTED_DIFF" >> "$target"
94187
echo "EOF" >> "$target"
188+
189+
echo "filtered_deleted_files<<EOF" >> "$target"
190+
echo "$FORMATTED_DELETED" >> "$target"
191+
echo "EOF" >> "$target"
192+
193+
echo "filtered_renamed_files<<EOF" >> "$target"
194+
echo "$FORMATTED_RENAMED" >> "$target"
195+
echo "EOF" >> "$target"
95196
fi
96197
}
97198

Diff for: .github/workflows/content-lint-markdown.yml

+1-2
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,6 @@ jobs:
3535
files: |
3636
content/**
3737
data/**
38-
token: ${{ secrets.GITHUB_TOKEN }}
3938
4039
- name: Print content linter annotations if changed content/data files
4140
if: steps.changed_files.outputs.filtered_changed_files
@@ -50,7 +49,7 @@ jobs:
5049
run: npm run lint-content -- --print-annotations --paths $CHANGED_FILES
5150

5251
- name: Run content linter if changed content/data files
53-
if: steps.changed_files.outputs.any_changed == 'true'
52+
if: steps.changed_files.outputs.filtered_changed_files
5453
env:
5554
# Make it an environment variable so that its value doesn't need to be escaped.
5655
# See https://docs.github.com/en/actions/security-guides/security-hardening-for-github-actions#using-an-intermediate-environment-variable

Diff for: .github/workflows/reviewers-legal.yml

-1
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,6 @@ jobs:
3939
uses: ./.github/actions/get-changed-files
4040
with:
4141
files: 'content/**'
42-
token: ${{ secrets.GITHUB_TOKEN }}
4342

4443
- name: Set up Node and dependencies
4544
if: steps.changed_files.outputs.filtered_changed_files

Diff for: .github/workflows/test-changed-content.yml

+4-15
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,6 @@ jobs:
2828
# Even if if doesn't do anything
2929
- name: Check out repo
3030
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
31-
with:
32-
# See https://github.com/tj-actions/changed-files#on-pull_request-
33-
fetch-depth: 2
3431

3532
- uses: ./.github/actions/node-npm-setup
3633

@@ -45,21 +42,13 @@ jobs:
4542
run: npm run build
4643

4744
- name: Get changed files
48-
id: changed-files
49-
uses: tj-actions/changed-files@40853de9f8ce2d6cfdc73c1b96f14e22ba44aec4 # v45.0.0
45+
id: changed_files
46+
uses: ./.github/actions/get-changed-files
5047
with:
51-
# No need to escape the file names because we make the output of
52-
# tj-actions/changed-files be set as an environment variable. Not
53-
# as a direct input to the line of bash that uses it.
54-
# See https://docs.github.com/en/actions/security-guides/security-hardening-for-github-actions#using-an-intermediate-environment-variable
55-
safe_output: false
5648
files: 'content/**'
57-
# Necessary so we can know what the old name was when a
58-
# content file was renamed.
59-
output_renamed_files_as_deleted_and_added: true
6049

6150
- name: Run tests
6251
env:
63-
CHANGED_FILES: ${{ steps.changed-files.outputs.modified_files }}
64-
DELETED_FILES: ${{ steps.changed-files.outputs.deleted_files }}
52+
CHANGED_FILES: ${{ steps.changed_files.outputs.filtered_changed_files }}
53+
DELETED_FILES: ${{ steps.changed_files.outputs.filtered_deleted_files }}
6554
run: npm test -- src/content-render/tests/render-changed-and-deleted-files.js

Diff for: .github/workflows/validate-github-github-docs-urls.yml

-1
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,6 @@ jobs:
106106
with:
107107
files: |
108108
content/**
109-
token: ${{ secrets.GITHUB_TOKEN }}
110109
111110
- name: Generate PR comment
112111
if: ${{ github.event_name == 'pull_request' && steps.changed_files.outputs.filtered_changed_files }}

0 commit comments

Comments
 (0)