@@ -2,7 +2,7 @@ name: 🚀 Deploy Static Next.js to GitHub Pages
22
33on :
44 push :
5- branches : ['** '] # Triggers on push to any branch
5+ branches : ['main '] # Only trigger push on main; PR branches use pull_request event
66 pull_request :
77 types : [opened, synchronize, reopened]
88 workflow_dispatch : # Allows manual triggering
2323 steps :
2424 - name : 🔍 Checkout repository
2525 uses : actions/checkout@v4
26+ with :
27+ token : ${{ secrets.GITHUB_TOKEN }}
2628
2729 - name : 🔧 Set deployment variables
2830 id : vars
@@ -92,10 +94,24 @@ jobs:
9294 node-version : ' 24'
9395 cache : ${{ steps.detect-pm.outputs.manager }}
9496
97+ - name : 📦 Cache Next.js build
98+ uses : actions/cache@v4
99+ with :
100+ path : |
101+ ${{ github.workspace }}/.next/cache
102+ key : ${{ runner.os }}-nextjs-${{ hashFiles('**/pnpm-lock.yaml') }}-${{ hashFiles('**/*.js', '**/*.jsx', '**/*.ts', '**/*.tsx') }}
103+ restore-keys : |
104+ ${{ runner.os }}-nextjs-${{ hashFiles('**/pnpm-lock.yaml') }}-
105+
95106 - name : 🚫 Ephemerally delete server/api files
107+ env :
108+ STATIC_BUILD_REMOVE_PATHS : ${{ vars.STATIC_BUILD_REMOVE_PATHS }}
96109 run : |
97- echo "Deleting src/app/api, src/server, src/proxy.ts, and src/app/jobs/[id] for static build..."
98- rm -rf src/app/api src/server src/proxy.ts src/app/jobs/[id] src/app/[...not-found] prisma.config.ts
110+ DEFAULT_PATHS="'src/app/blog/[slug]' 'src/app/invoice/[id]' src/app/api src/server src/proxy.ts 'src/app/jobs/[id]' 'src/app/[...not-found]' prisma.config.ts"
111+ PATHS="${STATIC_BUILD_REMOVE_PATHS:-$DEFAULT_PATHS}"
112+ echo "Deleting server/api files for static build..."
113+ echo "Paths: $PATHS"
114+ eval rm -rf $PATHS
99115
100116 - name : 📥 Install dependencies
101117 run : ${{ steps.detect-pm.outputs.manager }} ${{ steps.detect-pm.outputs.command }}
@@ -147,7 +163,7 @@ jobs:
147163 script : |
148164 const url = '${{ steps.vars.outputs.preview_url }}';
149165 const sha = context.sha.substring(0, 7);
150- const body = `🚀 **Preview deployment ready!**\n\n📎 **Preview URL:** ${url}\n\n_Deployed from commit \`${sha}\`_ `;
166+ const body = `🚀 **Preview deployment ready!**\n\n🌐 **Preview URL:** [ ${url}](${url})\n<sub>Deployed from commit \`${sha}\`</sub> `;
151167
152168 const { data: comments } = await github.rest.issues.listComments({
153169 owner: context.repo.owner,
@@ -172,3 +188,54 @@ jobs:
172188 body,
173189 });
174190 }
191+
192+ - name : Update PR description with preview URL
193+ uses : actions/github-script@v7
194+ with :
195+ script : |
196+ const owner = context.repo.owner;
197+ const repo = context.repo.repo;
198+ const branch = '${{ steps.vars.outputs.branch }}';
199+ const previewUrl = '${{ steps.vars.outputs.preview_url }}';
200+ const sha = context.sha.substring(0, 7);
201+
202+ // Find open PR for this branch
203+ const { data: prs } = await github.rest.pulls.list({
204+ owner, repo, head: `${owner}:${branch}`, state: 'open',
205+ });
206+
207+ if (prs.length === 0) {
208+ console.log(`No open PR found for branch ${branch}, skipping.`);
209+ return;
210+ }
211+
212+ const pr = prs[0];
213+ const body = pr.body || '';
214+
215+ const marker = {
216+ start: '<!-- GH-PAGES-PREVIEW:START -->',
217+ end: '<!-- GH-PAGES-PREVIEW:END -->',
218+ };
219+
220+ const section = [
221+ marker.start,
222+ `🌐 **Preview:** [${previewUrl}](${previewUrl})`,
223+ `<sub>Deployed from \`${sha}\`</sub>`,
224+ marker.end,
225+ ].join('\n');
226+
227+ let updated;
228+ if (body.includes(marker.start)) {
229+ const re = new RegExp(`${marker.start}[\\s\\S]*?${marker.end}`);
230+ updated = body.replace(re, section);
231+ } else {
232+ // Prepend to top of PR description
233+ updated = section + '\n\n' + body;
234+ }
235+
236+ if (updated !== body) {
237+ await github.rest.pulls.update({
238+ owner, repo, pull_number: pr.number, body: updated,
239+ });
240+ console.log(`PR #${pr.number} description updated with preview URL: ${previewUrl}`);
241+ }
0 commit comments