-
Notifications
You must be signed in to change notification settings - Fork 60
191 lines (160 loc) · 7.57 KB
/
generate_pdfs.yml
File metadata and controls
191 lines (160 loc) · 7.57 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
name: Generate PDFs
# Triggered by:
# - push to master that changes lecture markdown files
# - manual dispatch (regenerates PDFs for ALL lecture files)
on:
push:
branches:
- master
paths:
- '[0-9][0-9]_*.md'
workflow_dispatch:
concurrency:
group: pdf-generation
cancel-in-progress: false
permissions:
contents: write
jobs:
# -------------------------------------------------------------------------
# Job 1 – build PDFs and publish GitHub Releases
# -------------------------------------------------------------------------
generate_pdfs:
name: Generate PDFs and create releases
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 2
token: ${{ secrets.GITHUB_TOKEN }}
- name: Detect changed lecture files (push) or select all (dispatch)
id: changes
run: |
if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
# Regenerate PDFs for every numbered lecture file
files=$(ls [0-9][0-9]_*.md 2>/dev/null | tr '\n' ' ')
else
files=$(git diff --name-only HEAD^ HEAD \
| grep -E '^[0-9]{2}_.*\.md$' || true)
files="${files//$'\n'/ }"
fi
echo "changed_files=${files}" >> "$GITHUB_OUTPUT"
echo "Files to process: ${files}"
# -----------------------------------------------------------------------
# Validate that every changed file has a version tag and auto-increment
# the patch component when the corresponding release tag already exists.
#
# Logic:
# 1. Extract version from the <!-- ... --> frontmatter.
# → Fail hard if the tag is absent.
# 2. Compute the release tag (same algorithm as the PDF step below).
# → If the release tag already exists on GitHub, the user forgot to
# bump the version. We increment the patch component in the file.
# 3. Commit & push any modified files with "[skip ci]" so the PDF step
# reads the correct (bumped) version from the working tree.
# -----------------------------------------------------------------------
- name: Check versions and auto-increment patch if tag already exists
if: steps.changes.outputs.changed_files != ''
run: |
set -euo pipefail
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
bumped_files=""
error_files=""
for file in ${{ steps.changes.outputs.changed_files }}; do
[ -f "$file" ] || continue
filename=$(basename "$file" .md)
# ── 1. Require a version tag ───────────────────────────────────
version=$(grep -oP '(?m)^version:\s*\K[\d.]+' "$file" | head -1 || true)
if [ -z "$version" ]; then
echo "ERROR: $file has no 'version:' tag in its frontmatter." >&2
error_files="$error_files $file"
continue
fi
# ── 2. Compute safe release tag ───────────────────────────────
safe_tag=$(echo "$filename" \
| tr '[:upper:]' '[:lower:]' \
| sed -e 's/ä/ae/g' -e 's/ö/oe/g' -e 's/ü/ue/g' -e 's/ß/ss/g' \
-e 's/Ä/ae/g' -e 's/Ö/oe/g' -e 's/Ü/ue/g' \
-e 's/[^a-z0-9_-]//g')
release_tag="${safe_tag}_v${version}"
# ── 3. Auto-increment patch if release tag already exists ─────
if gh release view "$release_tag" > /dev/null 2>&1; then
echo "Tag '$release_tag' already exists for $file – auto-incrementing patch."
# Increment last numeric component: e.g. 1.0.10 → 1.0.11
new_version=$(echo "$version" | awk -F. '{$NF = $NF + 1; print}' OFS='.')
# Replace the version line inside the HTML comment frontmatter.
# The sed pattern handles optional spaces around the colon.
sed -i -E "s/^(version:[[:space:]]*)[0-9]+(\.[0-9]+)*/\1${new_version}/" "$file"
echo " $file: $version → $new_version"
bumped_files="$bumped_files $file"
else
echo "Tag '$release_tag' is new – no version bump needed for $file."
fi
done
# ── Fail if any file was missing a version tag ───────────────────
if [ -n "$error_files" ]; then
echo ""
echo "The following files are missing a 'version:' tag:" >&2
for f in $error_files; do echo " $f" >&2; done
echo "Please add 'version: X.Y.Z' to the HTML comment frontmatter." >&2
exit 1
fi
# ── Commit & push version bumps ───────────────────────────────────
if [ -n "$bumped_files" ]; then
git add $bumped_files
git commit -m "ci: auto-increment patch version for changed courses [skip ci]"
git pull --rebase origin master || true
git push
echo "Version bumps pushed to master."
fi
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Set up Node.js
if: steps.changes.outputs.changed_files != ''
uses: actions/setup-node@v4
with:
node-version: '22'
- name: Install LiaScript exporter
if: steps.changes.outputs.changed_files != ''
run: npm install -g @liascript/exporter
- name: Generate PDFs and publish GitHub Releases
if: steps.changes.outputs.changed_files != ''
run: |
set -euo pipefail
mkdir -p /tmp/pdf_build
for file in ${{ steps.changes.outputs.changed_files }}; do
[ -f "$file" ] || continue
filename=$(basename "$file" .md)
# Safe tag: lowercase, transliterate umlauts, remove non-ASCII
safe_tag=$(echo "$filename" \
| tr '[:upper:]' '[:lower:]' \
| sed -e 's/ä/ae/g' -e 's/ö/oe/g' -e 's/ü/ue/g' -e 's/ß/ss/g' \
-e 's/Ä/ae/g' -e 's/Ö/oe/g' -e 's/Ü/ue/g' \
-e 's/[^a-z0-9_-]//g')
# Re-read version from the file (may have been bumped in the
# previous step; the version tag is guaranteed to exist by now).
version=$(grep -oP '(?m)^version:\s*\K[\d.]+' "$file" | head -1)
asset_name="${filename}_v${version}_Documentation"
release_tag="${safe_tag}_v${version}"
echo "==> $file (tag: $release_tag)"
# Generate PDF
liaex \
--input "$file" \
--format pdf \
--output "/tmp/pdf_build/${asset_name}" \
--pdf-timeout 60000
pdf_path="/tmp/pdf_build/${asset_name}.pdf"
if [ ! -f "$pdf_path" ]; then
echo "ERROR: PDF not created for $file" >&2
exit 1
fi
# The version-check step guarantees the tag is new at this point.
gh release create "$release_tag" \
--title "PDF – ${filename} (v${version})" \
--notes "Automated PDF export for \`${file}\` – version ${version}" \
"$pdf_path"
done
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}