-
Notifications
You must be signed in to change notification settings - Fork 403
237 lines (212 loc) · 9.89 KB
/
Copy pathdocs-pr-preview.yml
File metadata and controls
237 lines (212 loc) · 9.89 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
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
# Create a documentation preview in the pull request
# --------------------------------------------------
# This GitHub Actions workflow triggers by commenting '/docs-preview' on a PR.
# It creates a new Read the Docs version for the PR branch and triggers a build.
#
# Key Steps:
# 1. Use the script (.github/scripts/pr_detect_changed_subtrees.py) to detect changed project
# 2. Get the PR branch name and derive the RTD version slug
# 3. Activate the branch as a new version on Read the Docs (key difference from update-docs.yml)
# 4. Trigger a build for that version
# 5. Comment the preview URL back on the PR
#
# Note: if multiple projects are changed in one PR, only the first detected project is previewed.
name: Docs Preview
on:
issue_comment:
types: [created, edited]
permissions:
contents: read
pull-requests: write
jobs:
build:
runs-on: ubuntu-latest
# Only run when '/docs-preview' is commented on a PR by a member or owner
if: >-
github.event.issue.pull_request != null &&
contains(github.event.comment.body, '/docs-preview') &&
(github.event.comment.author_association == 'MEMBER' ||
github.event.comment.author_association == 'OWNER')
steps:
- name: Generate a token
id: generate-token
uses: actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 # v3.2.0
with:
app-id: ${{ secrets.APP_ID }}
private-key: ${{ secrets.APP_PRIVATE_KEY }}
owner: ${{ github.repository_owner }}
- name: Checkout config files only
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
sparse-checkout: .github
sparse-checkout-cone-mode: true
token: ${{ steps.generate-token.outputs.token }}
- name: Set up Python
uses: actions/setup-python@e797f83bcb11b83ae66e0230d6156d7c80228e7c # v6.0.0
with:
python-version: '3.10'
- name: Install python dependencies
run: |
python -m pip install --upgrade pip
pip install pydantic requests
- name: Set up Git user
run: |
git config user.name "assistant-librarian[bot]"
git config user.email "assistant-librarian[bot]@users.noreply.github.com"
- name: Detect changed subtrees from PR
id: detect
env:
GH_TOKEN: ${{ steps.generate-token.outputs.token }}
run: |
python .github/scripts/pr_detect_changed_subtrees.py \
--repo "${{ github.repository }}" \
--pr "${{ github.event.issue.number }}" \
--config ".github/repos-config.json" \
- name: Extract first project
id: extract
env:
SUBTREES: ${{ steps.detect.outputs.subtrees }}
run: |
# pr_detect_changed_subtrees.py returns a string of project names
# separated by "\n", i.e. "projects/rocprim\nprojects/hipblaslt\nshared/tensile"
# head -n1: extracts the first project, i.e. "projects/rocprim"
# cut -d'/' -f2: cuts the "projects/" prefix, leaving "rocprim" for project_name
project=$(echo "$SUBTREES" | head -n1)
echo "project=$project" >> $GITHUB_OUTPUT
echo "project_name=$(echo "$project" | cut -d'/' -f2)" >> $GITHUB_OUTPUT
- name: Get PR branch
if: steps.extract.outputs.project
id: pr
env:
GH_TOKEN: ${{ steps.generate-token.outputs.token }}
run: |
PR_DATA=$(gh api repos/${{ github.repository }}/pulls/${{ github.event.issue.number }})
# Previews are only supported for branches in the upstream repo.
# Fork PRs are not supported (see the PR Docs Preview runbook).
head_repo=$(echo "$PR_DATA" | jq -r .head.repo.full_name)
base_repo=$(echo "$PR_DATA" | jq -r .base.repo.full_name)
if [ "$head_repo" != "$base_repo" ]; then
echo "PR is from a fork ($head_repo); docs preview is only supported for branches in $base_repo. Refusing to run." >&2
exit 1
fi
echo "branch=$(echo "$PR_DATA" | jq -r .head.ref)" >> $GITHUB_OUTPUT
- name: Derive RTD slugs and verify project exists
if: steps.extract.outputs.project
id: rtd
env:
RTD_TOKEN: ${{ secrets.RTD_TOKEN }}
FOLDER_NAME: ${{ steps.extract.outputs.project_name }}
BRANCH_NAME: ${{ steps.pr.outputs.branch }}
run: |
branch_name="$BRANCH_NAME"
# Generate slug like 'user-me-my_test_branch' from 'user/me/my_test_branch'
version_slug="${branch_name//\//-}"
# Load the map and look up the rtd_slug by rtd_alias
project_slug=$(jq -r --arg folder_name "$FOLDER_NAME" \
'.projects[] | select(.folder == $folder_name) | .rtd_slug' \
.github/docs-config.json)
echo "version_slug=$version_slug" >> $GITHUB_OUTPUT
echo "project_slug=$project_slug" >> $GITHUB_OUTPUT
# The API call returns upto 300 projects information from RTD
# jq extracts the project slug from the list
project_list=$(curl \
--connect-timeout 180 \
--header "Authorization: Token $RTD_TOKEN" \
"https://app.readthedocs.com/api/v3/projects/?expand=advanced-micro-devices&limit=300" \
| jq -r '.results[].slug')
if echo "$project_list" | grep -Fxq "$project_slug"; then
echo "exists=true" >> $GITHUB_OUTPUT
# Fetch documentation URL
doc_url=$(curl \
--connect-timeout 180 \
--silent \
--header "Authorization: Token $RTD_TOKEN" \
"https://app.readthedocs.com/api/v3/projects/$project_slug/" \
| jq --raw-output '.urls.documentation')
# Strip trailing version segment (e.g. "latest/") to get the base url
doc_base=$(echo "$doc_url" | sed 's|/[^/]\+/\?$||')
echo "doc_base=$doc_base" >> $GITHUB_OUTPUT
else
echo "$FOLDER_NAME does not exist on Read the Docs, skipping."
echo "exists=false" >> $GITHUB_OUTPUT
fi
- name: Sync RTD versions to discover PR branch
# Without a GitHub webhook configured on the repo, RTD is unaware of new branches.
# Triggering a sync forces RTD to re-scan the repository and register the PR branch
# as a version before we attempt to activate it in the next step.
if: steps.rtd.outputs.exists == 'true'
env:
RTD_TOKEN: ${{ secrets.RTD_TOKEN }}
PROJECT_SLUG: ${{ steps.rtd.outputs.project_slug }}
run: |
curl \
--connect-timeout 180 \
--fail \
--request POST \
--header "Authorization: Token $RTD_TOKEN" \
"https://app.readthedocs.com/api/v3/projects/${PROJECT_SLUG}/sync-versions/"
- name: Wait for RTD to register PR branch version
if: steps.rtd.outputs.exists == 'true'
env:
RTD_TOKEN: ${{ secrets.RTD_TOKEN }}
PROJECT_SLUG: ${{ steps.rtd.outputs.project_slug }}
VERSION_SLUG: ${{ steps.rtd.outputs.version_slug }}
run: |
declare version_url="https://app.readthedocs.com/api/v3/projects/${PROJECT_SLUG}/versions/${VERSION_SLUG}/"
declare -i MAXIMUM_NUMBER_OF_POLLS=20
declare -i SLEEP_BETWEEN_POLLS_SECONDS=15
echo "Polling for version to appear: $version_url"
for i in $(seq 1 ${MAXIMUM_NUMBER_OF_POLLS}); do
status=$(curl --silent --output /dev/null --write-out "%{http_code}" \
--header "Authorization: Token $RTD_TOKEN" \
"$version_url")
if [ "$status" = "200" ]; then
echo "Version found after $i attempt(s)."
exit 0
fi
echo "Attempt $i: version not yet registered (HTTP $status), waiting 15s..."
sleep ${SLEEP_BETWEEN_POLLS_SECONDS}
done
echo "Timed out waiting for RTD to register version."
exit 1
- name: Activate PR branch as a new RTD version
if: steps.rtd.outputs.exists == 'true'
env:
RTD_TOKEN: ${{ secrets.RTD_TOKEN }}
PROJECT_SLUG: ${{ steps.rtd.outputs.project_slug }}
VERSION_SLUG: ${{ steps.rtd.outputs.version_slug }}
run: |
curl \
--connect-timeout 180 \
--fail \
--request PATCH \
--header "Authorization: Token $RTD_TOKEN" \
--header "Content-Type: application/json" \
--data '{"active": true, "hidden": true, "privacy_level": "private"}' \
"https://app.readthedocs.com/api/v3/projects/${PROJECT_SLUG}/versions/${VERSION_SLUG}/"
- name: Trigger RTD build for PR branch
if: steps.rtd.outputs.exists == 'true'
env:
RTD_TOKEN: ${{ secrets.RTD_TOKEN }}
PROJECT_SLUG: ${{ steps.rtd.outputs.project_slug }}
VERSION_SLUG: ${{ steps.rtd.outputs.version_slug }}
run: |
curl \
--fail \
--silent \
--request POST \
--header "Authorization: Token $RTD_TOKEN" \
"https://app.readthedocs.com/api/v3/projects/${PROJECT_SLUG}/versions/${VERSION_SLUG}/builds/"
- name: Comment RTD preview URL on PR
if: steps.rtd.outputs.exists == 'true'
env:
GH_TOKEN: ${{ steps.generate-token.outputs.token }}
DOC_BASE: ${{ steps.rtd.outputs.doc_base }}
VERSION_SLUG: ${{ steps.rtd.outputs.version_slug }}
FOLDER_NAME: ${{ steps.extract.outputs.project_name }}
run: |
preview_url="${DOC_BASE}/${VERSION_SLUG}/"
gh pr comment ${{ github.event.issue.number }} \
--repo ${{ github.repository }} \
--body "Docs preview for **$FOLDER_NAME** is building on Read the Docs: $preview_url \
(Note: If a pull request includes multiple projects, only the preview for the first project will be built.)"