-
Notifications
You must be signed in to change notification settings - Fork 0
149 lines (137 loc) · 5.43 KB
/
Copy pathrelease-content.yml
File metadata and controls
149 lines (137 loc) · 5.43 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: Release book content
# Content editions are independent of tooling/framework pins. Existing complete
# releases are no-ops. Missing assets are built from their existing tag, never
# from a newer checkout that happens to have the same content/VERSION.
on:
push:
branches: [main]
paths:
- "content/**"
- "examples/**"
- "scripts/**"
- ".github/workflows/release-content.yml"
- ".github/workflows/validate-book.yml"
workflow_dispatch:
permissions:
contents: read
concurrency:
group: release-content
cancel-in-progress: false
jobs:
plan:
runs-on: ubuntu-latest
outputs:
action: ${{ steps.plan.outputs.action }}
version: ${{ steps.plan.outputs.version }}
tag: ${{ steps.plan.outputs.tag }}
asset: ${{ steps.plan.outputs.asset }}
source_sha: ${{ steps.plan.outputs.source_sha }}
framework_version: ${{ steps.plan.outputs.framework_version }}
comparison_base: ${{ steps.plan.outputs.comparison_base }}
tag_exists: ${{ steps.plan.outputs.tag_exists }}
steps:
- name: Checkout the triggering source and all edition tags
uses: actions/checkout@v4
with:
fetch-depth: 0
persist-credentials: false
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: "3.12"
- name: Select create, exact-tag repair, or idempotent skip
id: plan
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
python scripts/release_content.py release-plan --repo "$GITHUB_REPOSITORY" > release-plan.json
cat release-plan.json
python - <<'PY'
import json, os
from pathlib import Path
data = json.loads(Path("release-plan.json").read_text())
with open(os.environ["GITHUB_OUTPUT"], "a") as output:
for key, value in data.items():
if isinstance(value, bool):
value = str(value).lower()
output.write(f"{key}={value}\n")
PY
validate:
needs: plan
if: needs.plan.outputs.action != 'skip'
uses: ./.github/workflows/validate-book.yml
with:
source-ref: ${{ needs.plan.outputs.source_sha }}
comparison-base: ${{ needs.plan.outputs.comparison_base }}
artifact-name: validated-release
release:
needs: [plan, validate]
runs-on: ubuntu-latest
permissions:
contents: write
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
ACTION: ${{ needs.plan.outputs.action }}
TAG: ${{ needs.plan.outputs.tag }}
VERSION: ${{ needs.plan.outputs.version }}
ASSET: ${{ needs.plan.outputs.asset }}
SOURCE_SHA: ${{ needs.plan.outputs.source_sha }}
FRAMEWORK_VERSION: ${{ needs.plan.outputs.framework_version }}
TAG_EXISTS: ${{ needs.plan.outputs.tag_exists }}
steps:
- name: Download the gated artifact, without rebuilding
uses: actions/download-artifact@v4
with:
name: validated-release
path: artifact
- name: Check artifact identity and prepare release notes
run: |
python - <<'PY'
import json, os
from pathlib import Path
data = json.loads(Path("artifact/validation.json").read_text())
for key, env in (("version", "VERSION"), ("tag", "TAG"), ("source_sha", "SOURCE_SHA"),
("framework_version", "FRAMEWORK_VERSION")):
if data.get(key) != os.environ[env]:
raise SystemExit(f"Validated artifact mismatch: {key}")
if data.get("status") != "PASS":
raise SystemExit("The artifact did not pass validation.")
PY
cp artifact/site/gh-aw-book.pdf "$ASSET"
{
echo "## GitHub Agentic Workflows — content $TAG"
echo
cat artifact/release-notes.md
echo
echo "---"
echo
echo "📖 Read online: https://aw.isainative.dev/ · [Version history](https://aw.isainative.dev/versions.html)"
echo
echo "📄 The single-file PDF for this version is attached below."
} > release-notes.md
- name: Create or verify the tag without overwriting another source
run: |
if [[ "$TAG_EXISTS" != "true" ]]; then
# Atomic creation fails if another publisher created the ref meanwhile.
gh api --method POST "repos/$GITHUB_REPOSITORY/git/refs" \
-f ref="refs/tags/$TAG" -f sha="$SOURCE_SHA" --silent
fi
ACTUAL_SHA="$(gh api "repos/$GITHUB_REPOSITORY/commits/$TAG" --jq .sha)"
if [[ "$ACTUAL_SHA" != "$SOURCE_SHA" ]]; then
echo "::error::Tag $TAG no longer points to the validated source; refusing to publish."
exit 1
fi
- name: Create the content release
if: env.ACTION == 'create'
run: |
gh release create "$TAG" \
"$ASSET#GitHub Agentic Workflows — v$VERSION (PDF)" \
--repo "$GITHUB_REPOSITORY" --verify-tag \
--title "Content v$VERSION" --notes-file release-notes.md
- name: Repair the missing PDF using only the exact-tag artifact
if: env.ACTION == 'upload'
run: |
# Do not clobber an asset uploaded concurrently by another publisher.
gh release upload "$TAG" \
"$ASSET#GitHub Agentic Workflows — v$VERSION (PDF)" \
--repo "$GITHUB_REPOSITORY"