-
Notifications
You must be signed in to change notification settings - Fork 73
150 lines (132 loc) · 5.5 KB
/
docs-deploy-fork-pr.yml
File metadata and controls
150 lines (132 loc) · 5.5 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
name: "Docs - Fork PR - Deploy"
# This workflow runs in a TRUSTED context (base repo token with write access).
# It is triggered AFTER "Docs - Deploy" completes for a fork PR.
# The "Docs - Deploy" build job uploads the site artifact; this workflow
# downloads it and deploys to gh-pages/staging/{pr}/, then comments on the PR.
#
# Security: no untrusted code is executed here — we only deploy a pre-built
# artifact produced by our own workflow. The workflow_run trigger always runs
# with the base repository's token, regardless of where the PR originated.
on:
workflow_run:
workflows: [ "Docs - Deploy" ]
types: [ completed ]
# Default to no permissions — each job declares only what it needs.
permissions: {}
# Ensure documentation workflows run sequentially
concurrency:
group: "docs-deployment"
cancel-in-progress: false
jobs:
deploy-fork-pr-staging:
# Only run for successful fork PR builds
if: |
github.event.workflow_run.conclusion == 'success' &&
github.event.workflow_run.event == 'pull_request' &&
github.event.workflow_run.head_repository.full_name != github.repository
runs-on: ubuntu-latest
permissions:
contents: write # push to gh-pages
pull-requests: write # comment on PR
steps:
- name: Find staging artifact for this PR
id: artifact
uses: actions/github-script@v7
env:
WORKFLOW_RUN_ID: ${{ github.event.workflow_run.id }}
with:
script: |
const runId = parseInt(process.env.WORKFLOW_RUN_ID, 10);
const artifacts = await github.rest.actions.listWorkflowRunArtifacts({
owner: context.repo.owner,
repo: context.repo.repo,
run_id: runId
});
const staging = artifacts.data.artifacts.find(a => a.name.startsWith('staging-site-'));
if (!staging) {
core.setFailed('No staging artifact found for this workflow run');
return;
}
// Extract and validate PR number (must be a positive integer)
const prNumberStr = staging.name.replace('staging-site-', '');
const prNumber = parseInt(prNumberStr, 10);
if (!prNumber || prNumber <= 0 || String(prNumber) !== prNumberStr) {
core.setFailed(`Invalid PR number extracted from artifact name: ${staging.name}`);
return;
}
core.setOutput('artifact_name', staging.name);
core.setOutput('pr_number', String(prNumber));
- name: Download staging artifact
uses: actions/download-artifact@v4
with:
run-id: ${{ github.event.workflow_run.id }}
github-token: ${{ secrets.GITHUB_TOKEN }}
name: ${{ steps.artifact.outputs.artifact_name }}
path: /tmp/site-temp
- name: Checkout gh-pages branch
uses: actions/checkout@v4
with:
ref: gh-pages
fetch-depth: 0
- name: Deploy staging content
env:
PR_NUMBER: ${{ steps.artifact.outputs.pr_number }}
run: |
# Validate PR_NUMBER is a positive integer before using in paths
if ! [[ "$PR_NUMBER" =~ ^[1-9][0-9]*$ ]]; then
echo "Invalid PR number: $PR_NUMBER"
exit 1
fi
mkdir -p staging/$PR_NUMBER
rm -rf staging/$PR_NUMBER/*
cp -r /tmp/site-temp/. staging/$PR_NUMBER/
rm -rf /tmp/site-temp
git config --local user.email "action@github.com"
git config --local user.name "GitHub Action"
git add staging/$PR_NUMBER
if ! git diff --cached --quiet; then
git commit -m "Deploy staging docs for PR #$PR_NUMBER"
git push origin gh-pages
else
echo "No changes to commit"
fi
- name: Comment on PR
uses: actions/github-script@v7
env:
PR_NUMBER: ${{ steps.artifact.outputs.pr_number }}
with:
script: |
const prNumber = parseInt(process.env.PR_NUMBER, 10);
if (!prNumber || prNumber <= 0) {
core.setFailed('Invalid PR number');
return;
}
const stagingUrl = `https://mono.github.io/SkiaSharp.Extended/staging/${prNumber}/`;
const sampleUrl = `https://mono.github.io/SkiaSharp.Extended/staging/${prNumber}/sample/`;
// Only comment once; check for an existing bot comment
const comments = await github.rest.issues.listComments({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: prNumber
});
const botComment = comments.data.find(c =>
c.user.type === 'Bot' &&
c.body.includes('Documentation Preview')
);
if (botComment) {
console.log('Bot comment already exists, skipping.');
return;
}
const commentBody = `📖 **Documentation Preview**
The documentation for this PR has been deployed and is available at:
🔗 **[View Staging Documentation](${stagingUrl})**
🔗 **[View Staging Blazor Sample](${sampleUrl})**
This preview will be updated automatically when you push new commits to this PR.
---
*This comment is automatically updated by the documentation staging workflow.*`;
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: prNumber,
body: commentBody
});