Skip to content

Commit 6e007ad

Browse files
authored
支持为 PR 生成预览构建
1 parent ecac9c9 commit 6e007ad

1 file changed

Lines changed: 329 additions & 0 deletions

File tree

.github/workflows/pr-preview.yml

Lines changed: 329 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,329 @@
1+
name: PR Preview
2+
on:
3+
issue_comment:
4+
types: [created]
5+
pull_request_target:
6+
types: [labeled, closed]
7+
concurrency:
8+
group: pr-preview
9+
cancel-in-progress: false
10+
env:
11+
GITHUB_PR_NUMBER: ${{ github.event_name == 'issue_comment' && github.event.issue.number || github.event.pull_request.number }}
12+
JEKYLL_ENV: production
13+
jobs:
14+
preview-remove:
15+
if: >-
16+
${{
17+
!github.event.repository.fork && (
18+
( github.event_name == 'pull_request_target' && (
19+
github.event.action == 'closed' || (
20+
github.event.action == 'labeled' &&
21+
github.event.label.name == 'preview/remove'
22+
)
23+
)
24+
) || (
25+
github.event_name == 'issue_comment' &&
26+
github.event.issue.pull_request &&
27+
github.event.comment.body == '/preview remove' &&
28+
contains('OWNER,MEMBER', github.event.comment.author_association)
29+
)
30+
)
31+
}}
32+
runs-on: ubuntu-latest
33+
permissions:
34+
actions: write
35+
contents: write
36+
pull-requests: write
37+
steps:
38+
- id: restore-pages
39+
name: Restore Pages
40+
uses: actions/cache/restore@v4
41+
with:
42+
key: pages-${{ github.run_id }}
43+
path: /home/runner/gh-pages
44+
restore-keys: pages-
45+
- name: Prepare Pages
46+
run: |
47+
mkdir -p /home/runner/gh-pages
48+
rm -rf /home/runner/gh-pages/.git
49+
rm -rf /home/runner/gh-pages/PR${{ env.GITHUB_PR_NUMBER }}
50+
echo "[$(date)] Remove Preview PR${{ env.GITHUB_PR_NUMBER }}" > /home/runner/gh-pages/index.html
51+
- name: Save Pages
52+
uses: actions/cache/save@v4
53+
with:
54+
key: pages-${{ github.run_id }}
55+
path: /home/runner/gh-pages
56+
- if: ${{ github.event_name == 'issue_comment' }}
57+
id: comment-message
58+
name: Comment Message (issue_comment)
59+
uses: actions/github-script@v8
60+
with:
61+
script: |
62+
github.rest.issues.updateComment({
63+
owner: context.repo.owner,
64+
repo: context.repo.repo,
65+
comment_id: context.payload.comment.id,
66+
issue_number: context.issue.number,
67+
body: "Remove Preview"
68+
});
69+
- if: ${{ github.event_name == 'pull_request_target' || steps.comment-message.outcome == 'failure' }}
70+
name: Comment Message
71+
uses: actions/github-script@v8
72+
with:
73+
script: |
74+
github.rest.issues.createComment({
75+
owner: context.repo.owner,
76+
repo: context.repo.repo,
77+
issue_number: context.issue.number,
78+
body: "Remove Preview"
79+
});
80+
- if: ${{ steps.restore-pages.outputs.cache-matched-key }}
81+
name: Remove History Cache
82+
uses: actions/github-script@v8
83+
with:
84+
script: |
85+
github.rest.actions.deleteActionsCacheByKey({
86+
owner: context.repo.owner,
87+
repo: context.repo.repo,
88+
key: "${{ steps.restore-pages.outputs.cache-matched-key }}"
89+
});
90+
- if: ${{ github.event_name == 'pull_request_target' }}
91+
name: Remove Label (pull_request_target)
92+
continue-on-error: true
93+
uses: actions/github-script@v8
94+
with:
95+
script: |
96+
github.rest.issues.removeLabel({
97+
owner: context.repo.owner,
98+
repo: context.repo.repo,
99+
issue_number: context.issue.number,
100+
name: "preview/remove"
101+
});
102+
preview-create-init:
103+
if: >-
104+
${{
105+
!github.event.repository.fork && (
106+
( github.event_name == 'pull_request_target' &&
107+
github.event.action == 'labeled' &&
108+
github.event.label.name == 'preview/create'
109+
) || (
110+
github.event_name == 'issue_comment' &&
111+
github.event.issue.pull_request &&
112+
github.event.comment.body == '/preview create' &&
113+
contains('OWNER,MEMBER', github.event.comment.author_association)
114+
)
115+
)
116+
}}
117+
runs-on: ubuntu-latest
118+
permissions:
119+
checks: write
120+
outputs:
121+
sha: ${{ steps.init.outputs.sha }}
122+
domain: ${{ steps.init.outputs.domain }}
123+
pathname: ${{ steps.init.outputs.pathname }}
124+
repository: ${{ steps.init.outputs.repository }}
125+
check-id: ${{ steps.init.outputs.check-id }}
126+
steps:
127+
- id: init
128+
name: Init
129+
uses: actions/github-script@v8
130+
with:
131+
script: |
132+
const { owner, repo } = context.repo;
133+
const pages = (await octokit.rest.repos.getPages({ owner, repo })).data;
134+
core.setOutput('domain', pages.cname || `${owner.toLowerCase()}.github.io`);
135+
core.setOutput('pathname', pages.cname == null ? `/${repo}` : '');
136+
const pr = context.payload.pull_request || (await github.rest.pulls.get({
137+
owner, repo,
138+
pull_number: context.issue.number
139+
})).data;
140+
core.setOutput('sha', pr.head.sha);
141+
core.setOutput('repository', pr.head.repo.full_name);
142+
const { data: check } = await github.rest.checks.create({
143+
owner, repo,
144+
name: "Create preview",
145+
head_sha: pr.head.sha,
146+
status: "in_progress",
147+
started_at: new Date().toISOString(),
148+
details_url: `https://github.com/${context.repo.owner}/${context.repo.repo}/actions/runs/${{ github.run_id }}`,
149+
output: {
150+
title: "Create preview by command",
151+
summary: "Preview is being created..."
152+
}
153+
});
154+
core.setOutput('check-id', check.id);
155+
preview-create-build:
156+
needs: preview-create-init
157+
runs-on: ubuntu-latest
158+
outputs:
159+
artifact-id: ${{ steps.upload-site.outputs.artifact-id }}
160+
steps:
161+
- name: Checkout PR
162+
uses: actions/checkout@v5
163+
with:
164+
ref: ${{ needs.preview-create-init.outputs.sha }}
165+
repository: ${{ needs.preview-create-init.outputs.repository }}
166+
fetch-depth: 1
167+
- name: Setup Ruby
168+
uses: ruby/setup-ruby@v1
169+
with:
170+
ruby-version: "3.4"
171+
bundler-cache: true
172+
- name: Jekyll Build
173+
run: |
174+
echo "url: https://${{ needs.preview-create-init.outputs.domain }}" > _action.yml
175+
echo "baseurl: ${{ needs.preview-create-init.outputs.pathname }}/PR${{ env.GITHUB_PR_NUMBER }}" >> _action.yml
176+
echo "source: ${{ github.workspace }}" >> _action.yml
177+
echo "destination: /home/runner/site" >> _action.yml
178+
bundle exec jekyll build --config _config.yml,_action.yml
179+
- id: upload-site
180+
name: Upload Site
181+
uses: actions/upload-artifact@v4
182+
with:
183+
name: site
184+
path: /home/runner/site
185+
preview-create-deploy:
186+
needs: [preview-create-init, preview-create-build]
187+
runs-on: ubuntu-latest
188+
environment:
189+
name: github-pages
190+
url: https://${{ needs.preview-create-init.outputs.domain }}${{ needs.preview-create-init.outputs.pathname }}/PR${{ env.GITHUB_PR_NUMBER }}
191+
permissions:
192+
actions: write
193+
pages: write
194+
id-token: write
195+
contents: write
196+
steps:
197+
- id: restore-pages
198+
name: Restore Pages
199+
uses: actions/cache/restore@v4
200+
with:
201+
key: pages-${{ github.run_id }}
202+
path: /home/runner/gh-pages
203+
restore-keys: pages-
204+
- name: Prepare Pages
205+
run: |
206+
mkdir -p /home/runner/gh-pages
207+
rm -rf /home/runner/gh-pages/.git
208+
rm -rf /home/runner/gh-pages/PR${{ env.GITHUB_PR_NUMBER }}
209+
echo "[$(date)] Preview PR${{ env.GITHUB_PR_NUMBER }}" > /home/runner/gh-pages/index.html
210+
- name: Merge Site
211+
uses: actions/download-artifact@v5
212+
with:
213+
name: site
214+
path: /home/runner/gh-pages/PR${{ env.GITHUB_PR_NUMBER }}
215+
- id: upload-pages
216+
name: Upload Pages
217+
uses: actions/upload-pages-artifact@v4
218+
with:
219+
name: github-pages
220+
path: /home/runner/gh-pages
221+
- name: Setup Pages
222+
uses: actions/configure-pages@v5
223+
- name: Deploy Pages
224+
uses: actions/deploy-pages@v4
225+
with:
226+
artifact_name: github-pages
227+
- name: Save Pages
228+
uses: actions/cache/save@v4
229+
with:
230+
key: pages-${{ github.run_id }}
231+
path: /home/runner/gh-pages
232+
- if: ${{ steps.restore-pages.outputs.cache-matched-key }}
233+
name: Remove History Cache
234+
uses: actions/github-script@v8
235+
with:
236+
script: |
237+
github.rest.actions.deleteActionsCacheByKey({
238+
owner: context.repo.owner,
239+
repo: context.repo.repo,
240+
key: "${{ steps.restore-pages.outputs.cache-matched-key }}"
241+
});
242+
- if: ${{ steps.upload-pages.outputs.artifact_id }}
243+
name: Remove Pages Artifact
244+
uses: actions/github-script@v8
245+
with:
246+
script: |
247+
github.rest.actions.deleteArtifact({
248+
owner: context.repo.owner,
249+
repo: context.repo.repo,
250+
artifact_id: "${{ steps.upload-pages.outputs.artifact_id }}",
251+
});
252+
- if: ${{ needs.preview-create-build.outputs.artifact-id }}
253+
name: Remove Temp Artifact
254+
uses: actions/github-script@v8
255+
with:
256+
script: |
257+
github.rest.actions.deleteArtifact({
258+
owner: context.repo.owner,
259+
repo: context.repo.repo,
260+
artifact_id: "${{ needs.preview-create-build.outputs.artifact-id }}"
261+
});
262+
preview-create-finally:
263+
if: ${{ always() && needs.preview-create-init.result == 'success' }}
264+
needs: [preview-create-init, preview-create-deploy]
265+
runs-on: ubuntu-latest
266+
permissions:
267+
checks: write
268+
pull-requests: write
269+
steps:
270+
- if: ${{ github.event_name == 'issue_comment' }}
271+
id: comment-message
272+
name: Comment Message (issue_comment)
273+
env:
274+
PREVIEW_URL: https://${{ needs.preview-create-init.outputs.domain }}${{ needs.preview-create-init.outputs.pathname }}/PR${{ env.GITHUB_PR_NUMBER }}
275+
continue-on-error: true
276+
uses: actions/github-script@v8
277+
with:
278+
script: |
279+
github.rest.issues.updateComment({
280+
owner: context.repo.owner,
281+
repo: context.repo.repo,
282+
comment_id: context.payload.comment.id,
283+
issue_number: context.issue.number,
284+
body: "Preview URL: ${{ env.PREVIEW_URL }}"
285+
});
286+
- if: ${{ steps.comment-message.outcome == 'failure' }}
287+
name: Comment Message
288+
env:
289+
PREVIEW_URL: https://${{ needs.preview-create-init.outputs.domain }}${{ needs.preview-create-init.outputs.pathname }}/PR${{ env.GITHUB_PR_NUMBER }}
290+
uses: actions/github-script@v8
291+
with:
292+
script: |
293+
github.rest.issues.createComment({
294+
owner: context.repo.owner,
295+
repo: context.repo.repo,
296+
issue_number: context.issue.number,
297+
body: "Preview URL: ${{ env.PREVIEW_URL }}"
298+
});
299+
- if: ${{ github.event_name == 'pull_request_target' }}
300+
name: Remove Label (pull_request_target)
301+
continue-on-error: true
302+
uses: actions/github-script@v8
303+
with:
304+
script: |
305+
github.rest.issues.removeLabel({
306+
owner: context.repo.owner,
307+
repo: context.repo.repo,
308+
issue_number: context.issue.number,
309+
name: "preview/create"
310+
});
311+
- name: Check Over
312+
env:
313+
PREVIEW_URL: https://${{ needs.preview-create-init.outputs.domain }}${{ needs.preview-create-init.outputs.pathname }}/PR${{ env.GITHUB_PR_NUMBER }}
314+
uses: actions/github-script@v8
315+
with:
316+
script: |
317+
github.rest.checks.update({
318+
owner: context.repo.owner,
319+
repo: context.repo.repo,
320+
check_run_id: ${{ needs.preview-create-init.outputs.check-id }},
321+
status: "completed",
322+
conclusion: "${{ needs.preview-create-deploy.result == 'success' && 'success' || 'failure' }}",
323+
completed_at: new Date().toISOString(),
324+
details_url: `https://github.com/${context.repo.owner}/${context.repo.repo}/runs/${{ github.run_id }}`,
325+
output: {
326+
title: "Create preview ${{ needs.preview-create-deploy.result == 'success' && 'success' || 'failure' }}",
327+
summary: `${{ needs.preview-create-deploy.result == 'success' && 'Preview URL: ${process.env.PREVIEW_URL}' || '' }}`
328+
}
329+
});

0 commit comments

Comments
 (0)