Skip to content

Commit 8449852

Browse files
authored
Merge pull request #3910 from github/henrymercer/repo-size-diff-check
Action size: Add a PR check that comments on significant repo size changes
2 parents c5297a2 + 72ac23c commit 8449852

6 files changed

Lines changed: 608 additions & 41 deletions

File tree

.github/workflows/pr-checks.yml

Lines changed: 112 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,10 @@ jobs:
3333
runs-on: ${{ matrix.os }}
3434
timeout-minutes: 45
3535

36+
concurrency:
37+
cancel-in-progress: ${{ github.event_name == 'pull_request' || false }}
38+
group: pr-checks-unit-tests-${{ github.ref }}-${{ github.event_name }}-${{ matrix.os }}-node${{ matrix['node-version'] }}
39+
3640
steps:
3741
- name: Prepare git (Windows)
3842
if: runner.os == 'Windows'
@@ -71,22 +75,21 @@ jobs:
7175
sarif_file: eslint.sarif
7276
category: eslint
7377

74-
# Verifying the PR checks are up-to-date requires Node 24. The PR checks are not dependent
75-
# on the main codebase and therefore do not need to be run as part of the same matrix that
76-
# we use for the `unit-tests` job.
77-
verify-pr-checks:
78-
name: Verify PR checks
78+
# These checks do not need to be run as part of the same matrix that we use for the `unit-tests`
79+
# job.
80+
other-checks:
81+
name: Other checks
7982
if: github.triggering_actor != 'dependabot[bot]'
8083
permissions:
8184
contents: read
82-
runs-on: ubuntu-slim
85+
runs-on: ubuntu-latest
8386
timeout-minutes: 10
8487

85-
steps:
86-
- name: Prepare git (Windows)
87-
if: runner.os == 'Windows'
88-
run: git config --global core.autocrlf false
88+
concurrency:
89+
cancel-in-progress: ${{ github.event_name == 'pull_request' || false }}
90+
group: pr-checks-pr-checks-${{ github.ref }}-${{ github.event_name }}
8991

92+
steps:
9093
- name: Checkout repository
9194
uses: actions/checkout@v6
9295

@@ -97,57 +100,134 @@ jobs:
97100
cache: 'npm'
98101

99102
- name: Install dependencies
103+
id: install-deps
100104
run: npm ci
101105

102106
- name: Verify PR checks up to date
103-
if: always()
107+
if: ${{ !cancelled() && steps.install-deps.outcome == 'success' }}
104108
run: .github/workflows/script/verify-pr-checks.sh
105109

106110
- name: Run pr-checks tests
107-
if: always()
111+
if: ${{ !cancelled() && steps.install-deps.outcome == 'success' }}
108112
working-directory: pr-checks
109113
run: npx tsx --test
110114

111-
check-node-version:
112-
if: github.triggering_actor != 'dependabot[bot]'
113-
name: Check Action Node versions
114-
runs-on: ubuntu-latest
115-
timeout-minutes: 45
116-
env:
117-
BASE_REF: ${{ github.base_ref }}
118-
119-
permissions:
120-
contents: read
121-
122-
steps:
123-
- uses: actions/checkout@v6
124-
- id: head-version
125-
name: Verify all Actions use the same Node version
115+
- name: Verify all Actions use the same Node version
116+
id: head-version
126117
run: |
127-
NODE_VERSION=$(find . -name "action.yml" -exec yq -e '.runs.using' {} \; | grep node | sort | uniq)
118+
NODE_VERSION=$(find . -path "*/node_modules" -prune -o -name "action.yml" -exec yq -o=json '.runs.using' {} \; | jq -rs '[.[] | select(. != null and startswith("node"))] | unique | .[]')
128119
echo "NODE_VERSION: ${NODE_VERSION}"
129120
if [[ $(echo "$NODE_VERSION" | wc -l) -gt 1 ]]; then
130121
echo "::error::More than one node version used in 'action.yml' files."
131122
exit 1
132123
fi
133124
echo "node_version=${NODE_VERSION}" >> $GITHUB_OUTPUT
134125
135-
- id: checkout-base
136-
name: 'Backport: Check out base ref'
126+
- name: Fetch base commit
127+
id: fetch-base
128+
# Forks and Dependabot PRs don't have permission to write comments, so skip the repo size
129+
# check in those cases.
130+
if: >-
131+
github.event_name == 'pull_request' &&
132+
github.event.pull_request.head.repo.full_name == github.repository &&
133+
github.event.pull_request.user.login != 'dependabot[bot]'
134+
env:
135+
BASE_SHA: ${{ github.event.pull_request.base.sha }}
136+
HEAD_SHA: ${{ github.event.pull_request.head.sha }}
137+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
138+
run: |
139+
# Compare against the merge base so the size delta reflects only the commits actually
140+
# added by this PR, ignoring any changes that have landed on the base branch since the
141+
# PR branched off.
142+
merge_base=$(gh api "repos/$GITHUB_REPOSITORY/compare/$BASE_SHA...$HEAD_SHA" --jq '.merge_base_commit.sha')
143+
echo "merge_base=$merge_base" >> "$GITHUB_OUTPUT"
144+
git fetch --no-tags --depth=1 origin "$merge_base" "$HEAD_SHA"
145+
146+
- name: Check repo size
147+
if: steps.fetch-base.outcome == 'success'
148+
working-directory: pr-checks
149+
env:
150+
BASE_REF: ${{ github.event.pull_request.base.ref }}
151+
BASE_SHA: ${{ steps.fetch-base.outputs.merge_base }}
152+
HEAD_SHA: ${{ github.event.pull_request.head.sha }}
153+
RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
154+
run: npx tsx check-repo-size.ts --output-dir "$RUNNER_TEMP/repo-size"
155+
156+
- name: Upload repo size comment
157+
if: steps.fetch-base.outcome == 'success'
158+
uses: actions/upload-artifact@v7
159+
with:
160+
name: repo-size-comment
161+
path: ${{ runner.temp }}/repo-size/
162+
if-no-files-found: error
163+
164+
- name: 'Backport: Check out base ref'
165+
id: checkout-base
137166
if: ${{ startsWith(github.head_ref, 'backport-') }}
138167
uses: actions/checkout@v6
139168
with:
140-
ref: ${{ env.BASE_REF }}
169+
ref: ${{ github.base_ref }}
141170

142171
- name: 'Backport: Verify Node versions unchanged'
143172
if: steps.checkout-base.outcome == 'success'
144173
env:
145174
HEAD_VERSION: ${{ steps.head-version.outputs.node_version }}
146175
run: |
147-
BASE_VERSION=$(find . -name "action.yml" -exec yq -e '.runs.using' {} \; | grep node | sort | uniq)
176+
BASE_VERSION=$(find . -path "*/node_modules" -prune -o -name "action.yml" -exec yq -o=json '.runs.using' {} \; | jq -rs '[.[] | select(. != null and startswith("node"))] | unique | .[]')
148177
echo "HEAD_VERSION: ${HEAD_VERSION}"
149178
echo "BASE_VERSION: ${BASE_VERSION}"
150179
if [[ "$BASE_VERSION" != "$HEAD_VERSION" ]]; then
151180
echo "::error::Cannot change the Node version of an Action in a backport PR."
152181
exit 1
153182
fi
183+
184+
post-repo-size-comment:
185+
name: Post repo size comment
186+
needs: other-checks
187+
# Keep write permissions isolated from the job that checks out and tests PR code. This job only
188+
# posts the candidate comment body produced by the read-only `pr-checks` job.
189+
if: >-
190+
github.event_name == 'pull_request' &&
191+
github.event.pull_request.head.repo.full_name == github.repository &&
192+
github.event.pull_request.user.login != 'dependabot[bot]' &&
193+
needs.other-checks.result == 'success'
194+
permissions:
195+
contents: read
196+
pull-requests: write
197+
runs-on: ubuntu-slim
198+
timeout-minutes: 10
199+
200+
concurrency:
201+
cancel-in-progress: true
202+
group: check-repo-size-${{ github.event.pull_request.number }}
203+
204+
steps:
205+
- name: Download repo size comment
206+
uses: actions/download-artifact@v8
207+
with:
208+
name: repo-size-comment
209+
path: repo-size-comment
210+
211+
- name: Post repo size comment
212+
env:
213+
COMMENT_MARKER: "<!-- repo-size-diff-bot -->"
214+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
215+
PR_NUMBER: ${{ github.event.pull_request.number }}
216+
run: |
217+
significant=$(jq -r '.significant' repo-size-comment/metadata.json)
218+
comment_id=$(
219+
gh api "repos/$GITHUB_REPOSITORY/issues/$PR_NUMBER/comments" \
220+
--paginate \
221+
--jq ".[] | select(.body | contains(\"$COMMENT_MARKER\")) | .id" \
222+
| head -n 1
223+
)
224+
225+
if [[ -n "$comment_id" ]]; then
226+
echo "Updating existing comment $comment_id."
227+
gh api --method PATCH "repos/$GITHUB_REPOSITORY/issues/comments/$comment_id" --field body=@repo-size-comment/body.md
228+
elif [[ "$significant" == "true" ]]; then
229+
echo "Creating new repo size comment."
230+
gh api --method POST "repos/$GITHUB_REPOSITORY/issues/$PR_NUMBER/comments" --field body=@repo-size-comment/body.md
231+
else
232+
echo "Skipping repo size comment because the delta is below the threshold and no sticky comment exists."
233+
fi

0 commit comments

Comments
 (0)