Repository navigation
223 lines (217 loc) · 9.32 KB
/
Copy pathdocs.yml
File metadata and controls
223 lines (217 loc) · 9.32 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
name: Python developer portal
on:
push:
branches: [main]
paths:
- 'src/**'
- 'docs/**'
- 'overrides/**'
- 'mkdocs.yml'
- 'pyproject.toml'
- 'requirements-docs.txt'
- 'scripts/check-docs-analytics.py'
- 'scripts/check-docs-layout.py'
- 'scripts/prepare_portal.py'
- 'scripts/docstring_cross_references.py'
- '.github/workflows/docs.yml'
workflow_dispatch:
inputs:
stable_tag:
description: 'Published stable SDK tag to deploy, or empty for current main'
type: string
required: false
permissions:
contents: read
concurrency:
group: python-developer-portal
cancel-in-progress: false
jobs:
build:
runs-on: ubuntu-latest
timeout-minutes: 15
outputs:
stable: ${{ steps.release-channel.outputs.stable }}
steps:
- name: Validate the selected stable tag
if: inputs.stable_tag != ''
env:
STABLE_TAG: ${{ inputs.stable_tag }}
run: |
if [[ ! "$STABLE_TAG" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
echo 'stable_tag must name an exact stable SDK version' >&2
exit 1
fi
- uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6
with:
ref: ${{ github.sha }}
fetch-depth: 0
persist-credentials: false
- uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6
with:
python-version: "3.12"
- name: Bootstrap patched pip trust
uses: durable-workflow/.github/.github/actions/bootstrap-patched-pip@75587fc33ff40c34f32ef777293dad56bb6f48c7 # clean-trust
with:
clients: pip,python
- name: Check out the selected published SDK source
if: inputs.stable_tag != ''
uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6
with:
ref: ${{ format('refs/tags/{0}', inputs.stable_tag) }}
path: .docs-sdk
persist-credentials: false
- name: Resolve the public documentation release channel
id: release-channel
env:
STABLE_TAG: ${{ inputs.stable_tag }}
GH_TOKEN: ${{ github.token }}
run: |
docs_revision=$(git rev-parse HEAD)
test "$docs_revision" = "$GITHUB_SHA"
sdk_revision=$docs_revision
project=pyproject.toml
if [ -n "$STABLE_TAG" ]; then
project=.docs-sdk/pyproject.toml
fi
version=$(python - "$project" <<'PY'
import sys
import tomllib
print(tomllib.load(open(sys.argv[1], "rb"))["project"]["version"])
PY
)
if [ -n "$STABLE_TAG" ]; then
test "$GITHUB_EVENT_NAME" = workflow_dispatch
test "$GITHUB_REF" = refs/heads/main
test "$version" = "$STABLE_TAG"
released=$(gh release view "$STABLE_TAG" --repo "$GITHUB_REPOSITORY" --json isDraft,isPrerelease --jq '(.isDraft == false and .isPrerelease == false)')
test "$released" = true
sdk_revision=$(git -C .docs-sdk rev-parse HEAD)
tag_revision=$(git rev-parse "refs/tags/$STABLE_TAG^{commit}")
test "$sdk_revision" = "$tag_revision"
python - "$version" <<'PY'
import json
import re
import sys
import urllib.request
from urllib.parse import urlsplit
from pathlib import Path
import os
version = sys.argv[1]
with urllib.request.urlopen(
f"https://pypi.org/pypi/durable-workflow/{version}/json", timeout=15,
) as response:
payload = response.read(1_048_577)
if len(payload) > 1_048_576:
raise SystemExit("PyPI metadata exceeds size bound")
package = json.loads(payload)
if package.get("info", {}).get("name") != "durable-workflow" or package["info"].get("version") != version:
raise SystemExit("PyPI package identity differs from selected tag")
kinds = set()
wheel = None
for artifact in package.get("urls", []):
if artifact.get("yanked") is not False:
continue
if not re.fullmatch(r"[0-9a-f]{64}", artifact.get("digests", {}).get("sha256", "")):
raise SystemExit("PyPI artifact digest is missing or invalid")
filename = artifact.get("filename", "")
if not filename.startswith(f"durable_workflow-{version}-") and filename != f"durable_workflow-{version}.tar.gz":
raise SystemExit("PyPI artifact filename differs from selected package")
kinds.add(artifact.get("packagetype"))
if filename == f"durable_workflow-{version}-py3-none-any.whl":
if wheel is not None:
raise SystemExit("Selected package has duplicate universal wheels")
wheel = artifact
if not {"bdist_wheel", "sdist"} <= kinds:
raise SystemExit("Selected stable package has no unyanked wheel and sdist")
if wheel is None:
raise SystemExit("Selected package has no universal Python wheel")
url = urlsplit(wheel.get("url", ""))
if (url.geturl() != wheel["url"] or url.scheme != "https" or url.netloc != "files.pythonhosted.org"
or url.query or url.fragment or not url.path.startswith("/packages/")
or not url.path.endswith("/" + wheel["filename"])
or not re.fullmatch(r"[A-Za-z0-9/_.-]+", url.path)):
raise SystemExit("Published wheel URL is outside the package authority")
with Path(os.environ["GITHUB_OUTPUT"]).open("a") as output:
output.write(f"wheel_url={wheel['url']}\nwheel_sha256={wheel['digests']['sha256']}\n")
PY
echo stable=true >> "$GITHUB_OUTPUT"
else
echo stable=false >> "$GITHUB_OUTPUT"
fi
echo "version=$version" >> "$GITHUB_OUTPUT"
echo "docs_revision=$docs_revision" >> "$GITHUB_OUTPUT"
echo "sdk_revision=$sdk_revision" >> "$GITHUB_OUTPUT"
- name: Install package and documentation dependencies
env:
STABLE_TAG: ${{ inputs.stable_tag }}
PUBLISHED_WHEEL_URL: ${{ steps.release-channel.outputs.wheel_url }}
PUBLISHED_WHEEL_SHA256: ${{ steps.release-channel.outputs.wheel_sha256 }}
run: |
pip install --require-hashes --only-binary=:all: -r requirements-docs.txt
if [ -n "$STABLE_TAG" ]; then
python - <<'PY'
import os
from pathlib import Path
requirement = f"durable-workflow @ {os.environ['PUBLISHED_WHEEL_URL']} --hash=sha256:{os.environ['PUBLISHED_WHEEL_SHA256']}\n"
Path(".docs-published-wheel.txt").write_text(requirement)
PY
pip install --require-hashes --no-deps --only-binary=:all: -r .docs-published-wheel.txt
fi
- name: Install Chromium
env:
NODE_OPTIONS: --use-openssl-ca
NODE_EXTRA_CA_CERTS: ''
NODE_USE_SYSTEM_CA: '0'
NODE_TLS_REJECT_UNAUTHORIZED: '1'
run: python -m playwright install chromium
- name: Build and check the portal
env:
CLOUDFLARE_WEB_ANALYTICS_TOKEN: ${{ vars.CLOUDFLARE_WEB_ANALYTICS_TOKEN }}
STABLE_TAG: ${{ inputs.stable_tag }}
DOCS_WHEEL_SHA256: ${{ steps.release-channel.outputs.wheel_sha256 }}
PYTHONDONTWRITEBYTECODE: '1'
run: |
if ! printf '%s' "$CLOUDFLARE_WEB_ANALYTICS_TOKEN" | grep -Eq '^[a-f0-9]{32}$'; then
echo 'CLOUDFLARE_WEB_ANALYTICS_TOKEN must be the canonical 32-character site token' >&2
exit 1
fi
sed -i "s/__CLOUDFLARE_WEB_ANALYTICS_TOKEN__/$CLOUDFLARE_WEB_ANALYTICS_TOKEN/" \
docs/javascripts/analytics.js
python scripts/prepare_portal.py
mkdocs build --strict --config-file .docs-build.yml
python scripts/docstring_cross_references.py --site site
python scripts/check-docs-analytics.py site --require-token
python scripts/check-docs-layout.py site --screenshots docs-review
test -s site/index.html
test "$(cat site/CNAME)" = "python.durable-workflow.com"
- name: Bind the artifact to both documentation and SDK sources
run: |
cp .docs-provenance.json site/deployment-audit.json
cp .docs-api-inventory.json site/api-source-inventory.json
- name: Retain rendered review screenshots
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
with:
name: python-portal-review-${{ github.sha }}
path: docs-review
retention-days: 7
- uses: actions/upload-pages-artifact@fc324d3547104276b827a68afc52ff2a11cc49c9 # v5
if: github.server_url == 'https://github.com'
with:
path: site
deploy:
if: >-
github.server_url == 'https://github.com' &&
github.ref == 'refs/heads/main' &&
needs.build.outputs.stable == 'true'
needs: build
runs-on: ubuntu-latest
permissions:
contents: read
id-token: write
pages: write
environment:
name: github-pages
url: https://python.durable-workflow.com/
steps:
- id: deployment
uses: actions/deploy-pages@cd2ce8fcbc39b97be8ca5fce6e763baed58fa128 # v5