@@ -13,9 +13,17 @@ concurrency:
1313 group : preview-${{ github.event.pull_request.number || github.run_id }}
1414 cancel-in-progress : true
1515
16+ defaults :
17+ run :
18+ shell : bash
19+
1620jobs :
1721 preview :
1822 runs-on : ubuntu-latest
23+ outputs :
24+ removed_prs_json : ${{ steps.prune-previews.outputs.removed_prs_json }}
25+ env :
26+ PREVIEW_RETENTION_LIMIT : 6
1927
2028 steps :
2129
6775 action : auto
6876 comment : false
6977
78+ - name : Checkout gh-pages for preview retention
79+ if : github.event.action != 'closed'
80+ uses : actions/checkout@v4
81+ with :
82+ ref : gh-pages
83+ fetch-depth : 0
84+ path : gh-pages-maintenance
85+
86+ - name : Prune old PR previews
87+ id : prune-previews
88+ if : github.event.action != 'closed'
89+ run : |
90+ cd gh-pages-maintenance
91+ mkdir -p pr-preview
92+ removed_prs=()
93+
94+ mapfile -t previews < <(
95+ while IFS= read -r preview; do
96+ timestamp="$(git log -1 --format=%ct -- "pr-preview/$preview" 2>/dev/null || echo 0)"
97+ printf '%s %s\n' "$timestamp" "$preview"
98+ done < <(find pr-preview -mindepth 1 -maxdepth 1 -type d -name 'pr-*' -printf '%f\n') \
99+ | sort -nr \
100+ | awk '{print $2}'
101+ )
102+
103+ if (( ${#previews[@]} <= PREVIEW_RETENTION_LIMIT )); then
104+ echo "removed_prs_json=[]" >> "$GITHUB_OUTPUT"
105+ exit 0
106+ fi
107+
108+ for preview in "${previews[@]:PREVIEW_RETENTION_LIMIT}"; do
109+ rm -rf "pr-preview/$preview"
110+ removed_prs+=("${preview#pr-}")
111+ done
112+
113+ if git diff --quiet -- pr-preview; then
114+ echo "removed_prs=" >> "$GITHUB_OUTPUT"
115+ echo "removed_prs_json=[]" >> "$GITHUB_OUTPUT"
116+ exit 0
117+ fi
118+
119+ git config user.name "github-actions[bot]"
120+ git config user.email "github-actions[bot]@users.noreply.github.com"
121+ git add pr-preview
122+ git commit -m "Prune old PR previews"
123+ git push
124+
125+ echo "removed_prs=$(IFS=,; echo "${removed_prs[*]}")" >> "$GITHUB_OUTPUT"
126+ echo "removed_prs_json=$(printf '%s\n' "${removed_prs[@]}" | jq -R . | jq -sc .)" >> "$GITHUB_OUTPUT"
127+
70128 - name : Comment PR with Preview URL
71129 if : github.event.action != 'closed'
72130 uses : marocchino/sticky-pull-request-comment@v2
@@ -75,7 +133,57 @@ jobs:
75133 message : |
76134 🚀 Preview deployment: https://${{ github.repository_owner }}.github.io/${{ github.event.repository.name }}/pr-preview/pr-${{ github.event.pull_request.number }}/
77135
78- - name : Cleanup PR preview
136+ - name : Comment on pruned previews
137+ if : github.event.action != 'closed' && steps.prune-previews.outputs.removed_prs_json != '[]'
138+ uses : actions/github-script@v7
139+ env :
140+ REMOVED_PRS_JSON : ${{ steps.prune-previews.outputs.removed_prs_json }}
141+ PREVIEW_RETENTION_LIMIT : ${{ env.PREVIEW_RETENTION_LIMIT }}
142+ with :
143+ script : |
144+ const removedPrs = JSON.parse(process.env.REMOVED_PRS_JSON);
145+ const retentionLimit = process.env.PREVIEW_RETENTION_LIMIT;
146+ const header = "pr-preview";
147+ const marker = `<!-- Sticky Pull Request Comment${header} -->`;
148+
149+ for (const prNumber of removedPrs) {
150+ const body =
151+ `Preview deployment for PR #${prNumber} removed.\n\n` +
152+ `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` +
153+ `If needed, push a new commit to this PR to generate a fresh preview.\n` +
154+ `${marker}`;
155+
156+ const { data: comments } = await github.rest.issues.listComments({
157+ owner: context.repo.owner,
158+ repo: context.repo.repo,
159+ issue_number: Number(prNumber),
160+ per_page: 100,
161+ });
162+
163+ const existingComment = [...comments].reverse().find((comment) =>
164+ comment.user?.login === "github-actions[bot]" &&
165+ comment.body?.includes(marker)
166+ );
167+
168+ if (existingComment) {
169+ await github.rest.issues.updateComment({
170+ owner: context.repo.owner,
171+ repo: context.repo.repo,
172+ comment_id: existingComment.id,
173+ body,
174+ });
175+ continue;
176+ }
177+
178+ await github.rest.issues.createComment({
179+ owner: context.repo.owner,
180+ repo: context.repo.repo,
181+ issue_number: Number(prNumber),
182+ body,
183+ });
184+ }
185+
186+ - name : Cleanup PR preview on close
79187 if : github.event.action == 'closed'
80188 uses : rossjrw/pr-preview-action@v1.6.3
81189 with :
0 commit comments