@@ -26,8 +26,14 @@ defaults:
2626
2727jobs :
2828 build-and-deploy-preview :
29+ outputs :
30+ removed_prs_json : ${{ steps.prune-previews.outputs.removed_prs_json }}
31+
2932 runs-on : ubuntu-24.04
3033
34+ env :
35+ PREVIEW_RETENTION_LIMIT : 6
36+
3137 steps :
3238 - name : Checkout PR code
3339 if : github.event.action != 'closed'
7480 action : auto
7581 comment : false
7682
83+ - name : Checkout gh-pages for preview retention
84+ if : github.event.action != 'closed'
85+ uses : actions/checkout@v6
86+ with :
87+ ref : gh-pages
88+ fetch-depth : 0
89+ persist-credentials : true
90+ filter : blob:none
91+ sparse-checkout : |
92+ pr-preview
93+ path : gh-pages-maintenance
94+
95+
96+ - name : Prune old PR previews
97+ id : prune-previews
98+ if : github.event.action != 'closed'
99+ run : |
100+ cd gh-pages-maintenance
101+ mkdir -p pr-preview
102+ removed_prs=()
103+
104+ mapfile -t previews < <(
105+ while IFS= read -r preview; do
106+ timestamp="$(git log -1 --format=%ct -- "pr-preview/$preview" 2>/dev/null || echo 0)"
107+ printf '%s %s\n' "$timestamp" "$preview"
108+ done < <(find pr-preview -mindepth 1 -maxdepth 1 -type d -name 'pr-*' -printf '%f\n') \
109+ | sort -nr \
110+ | awk '{print $2}'
111+ )
112+
113+ if (( ${#previews[@]} <= $PREVIEW_RETENTION_LIMIT )); then
114+ echo "removed_prs_json=[]" >> "$GITHUB_OUTPUT"
115+ exit 0
116+ fi
117+
118+ for preview in "${previews[@]:$PREVIEW_RETENTION_LIMIT}"; do
119+ rm -rf "pr-preview/$preview"
120+ removed_prs+=("${preview#pr-}")
121+ done
122+
123+ git add pr-preview
124+
125+ if git diff --cached --quiet; then
126+ echo "removed_prs_json=[]" >> "$GITHUB_OUTPUT"
127+ exit 0
128+ fi
129+
130+ git config user.name "github-actions[bot]"
131+ git config user.email "github-actions[bot]@users.noreply.github.com"
132+
133+ git add pr-preview
134+ git commit -m "Prune old PR previews" || true
135+ git push || true
136+
137+ echo "removed_prs_json=$(printf '%s\n' "${removed_prs[@]}" | jq -R . | jq -sc .)" >> "$GITHUB_OUTPUT"
77138 - name : Comment PR with Preview URL
78139 if : github.event.action != 'closed'
79140 uses : marocchino/sticky-pull-request-comment@v2
@@ -83,7 +144,56 @@ jobs:
83144 🚀 Preview deployment: https://${{ github.repository_owner }}.github.io/${{ github.event.repository.name }}/pr-preview/pr-${{ github.event.pull_request.number }}/
84145 > *Note: Preview may take a moment (GitHub Pages deployment in progress). Please wait and refresh. Track deployment [here](https://github.com/${{ github.repository }}/actions/workflows/pages/pages-build-deployment)*
85146
147+ - name : Comment on pruned previews
148+ if : github.event.action != 'closed' && steps.prune-previews.outputs.removed_prs_json != '[]'
149+ uses : actions/github-script@v7
150+ env :
151+ REMOVED_PRS_JSON : ${{ steps.prune-previews.outputs.removed_prs_json }}
152+ PREVIEW_RETENTION_LIMIT : ${{ env.PREVIEW_RETENTION_LIMIT }}
153+ with :
154+ script : |
155+ const removedPrs = JSON.parse(process.env.REMOVED_PRS_JSON);
156+ const retentionLimit = process.env.PREVIEW_RETENTION_LIMIT;
157+ const header = "pr-preview";
158+ const marker = `<!-- Sticky Pull Request Comment${header} -->`;
159+
160+ for (const prNumber of removedPrs) {
161+ const body =
162+ `Preview deployment for PR #${prNumber} removed.\n\n` +
163+ `This PR preview was automatically pruned because we keep only the ${retentionLimit} most recently updated previews on GitHub Pages to stay within deployment size limits.\n\n` +
164+ `If needed, push a new commit to this PR to generate a fresh preview.\n` +
165+ `${marker}`;
166+
167+ const { data: comments } = await github.rest.issues.listComments({
168+ owner: context.repo.owner,
169+ repo: context.repo.repo,
170+ issue_number: Number(prNumber),
171+ per_page: 100,
172+ });
173+
174+ const existingComment = [...comments].reverse().find((comment) =>
175+ comment.user?.login === "github-actions[bot]" &&
176+ comment.body?.includes(marker)
177+ );
178+
179+ if (existingComment) {
180+ await github.rest.issues.updateComment({
181+ owner: context.repo.owner,
182+ repo: context.repo.repo,
183+ comment_id: existingComment.id,
184+ body,
185+ });
186+ continue;
187+ }
86188
189+ await github.rest.issues.createComment({
190+ owner: context.repo.owner,
191+ repo: context.repo.repo,
192+ issue_number: Number(prNumber),
193+ body,
194+ });
195+ }
196+
87197 - name : Cleanup PR preview on close
88198 if : github.event.action == 'closed'
89199 uses : rossjrw/pr-preview-action@v1.6.3
0 commit comments