4646 echo "changed_files=${files}" >> "$GITHUB_OUTPUT"
4747 echo "Files to process: ${files}"
4848
49+ # -----------------------------------------------------------------------
50+ # Validate that every changed file has a version tag and auto-increment
51+ # the patch component when the corresponding release tag already exists.
52+ #
53+ # Logic:
54+ # 1. Extract version from the <!-- ... --> frontmatter.
55+ # → Fail hard if the tag is absent.
56+ # 2. Compute the release tag (same algorithm as the PDF step below).
57+ # → If the release tag already exists on GitHub, the user forgot to
58+ # bump the version. We increment the patch component in the file.
59+ # 3. Commit & push any modified files with "[skip ci]" so the PDF step
60+ # reads the correct (bumped) version from the working tree.
61+ # -----------------------------------------------------------------------
62+ - name : Check versions and auto-increment patch if tag already exists
63+ if : steps.changes.outputs.changed_files != ''
64+ run : |
65+ set -euo pipefail
66+
67+ git config user.name "github-actions[bot]"
68+ git config user.email "github-actions[bot]@users.noreply.github.com"
69+
70+ bumped_files=""
71+ error_files=""
72+
73+ for file in ${{ steps.changes.outputs.changed_files }}; do
74+ [ -f "$file" ] || continue
75+
76+ filename=$(basename "$file" .md)
77+
78+ # ── 1. Require a version tag ───────────────────────────────────
79+ version=$(grep -oP '(?m)^version:\s*\K[\d.]+' "$file" | head -1 || true)
80+ if [ -z "$version" ]; then
81+ echo "ERROR: $file has no 'version:' tag in its frontmatter." >&2
82+ error_files="$error_files $file"
83+ continue
84+ fi
85+
86+ # ── 2. Compute safe release tag ───────────────────────────────
87+ safe_tag=$(echo "$filename" \
88+ | tr '[:upper:]' '[:lower:]' \
89+ | sed -e 's/ä/ae/g' -e 's/ö/oe/g' -e 's/ü/ue/g' -e 's/ß/ss/g' \
90+ -e 's/Ä/ae/g' -e 's/Ö/oe/g' -e 's/Ü/ue/g' \
91+ -e 's/[^a-z0-9_-]//g')
92+ release_tag="${safe_tag}_v${version}"
93+
94+ # ── 3. Auto-increment patch if release tag already exists ─────
95+ if gh release view "$release_tag" > /dev/null 2>&1; then
96+ echo "Tag '$release_tag' already exists for $file – auto-incrementing patch."
97+
98+ # Increment last numeric component: e.g. 1.0.10 → 1.0.11
99+ new_version=$(echo "$version" | awk -F. '{$NF = $NF + 1; print}' OFS='.')
100+
101+ # Replace the version line inside the HTML comment frontmatter.
102+ # The sed pattern handles optional spaces around the colon.
103+ sed -i -E "s/^(version:[[:space:]]*)[0-9]+(\.[0-9]+)*/\1${new_version}/" "$file"
104+
105+ echo " $file: $version → $new_version"
106+ bumped_files="$bumped_files $file"
107+ else
108+ echo "Tag '$release_tag' is new – no version bump needed for $file."
109+ fi
110+ done
111+
112+ # ── Fail if any file was missing a version tag ───────────────────
113+ if [ -n "$error_files" ]; then
114+ echo ""
115+ echo "The following files are missing a 'version:' tag:" >&2
116+ for f in $error_files; do echo " $f" >&2; done
117+ echo "Please add 'version: X.Y.Z' to the HTML comment frontmatter." >&2
118+ exit 1
119+ fi
120+
121+ # ── Commit & push version bumps ───────────────────────────────────
122+ if [ -n "$bumped_files" ]; then
123+ git add $bumped_files
124+ git commit -m "ci: auto-increment patch version for changed courses [skip ci]"
125+ git pull --rebase origin master || true
126+ git push
127+ echo "Version bumps pushed to master."
128+ fi
129+ env :
130+ GH_TOKEN : ${{ secrets.GITHUB_TOKEN }}
131+
49132 - name : Set up Node.js
50133 if : steps.changes.outputs.changed_files != ''
51134 uses : actions/setup-node@v4
74157 -e 's/Ä/ae/g' -e 's/Ö/oe/g' -e 's/Ü/ue/g' \
75158 -e 's/[^a-z0-9_-]//g')
76159
77- # Extract version from frontmatter (e.g. "version: 1.0.10")
78- version=$(grep -oP 'version:\s*\K[\d.]+' "$file" | head -1 || echo "unknown")
160+ # Re-read version from the file (may have been bumped in the
161+ # previous step; the version tag is guaranteed to exist by now).
162+ version=$(grep -oP '(?m)^version:\s*\K[\d.]+' "$file" | head -1)
79163
80164 asset_name="${filename}_v${version}_Documentation"
81165 release_tag="${safe_tag}_v${version}"
@@ -92,20 +176,15 @@ jobs:
92176 pdf_path="/tmp/pdf_build/${asset_name}.pdf"
93177
94178 if [ ! -f "$pdf_path" ]; then
95- echo "WARNING : PDF not created for $file – skipping release."
96- continue
179+ echo "ERROR : PDF not created for $file" >&2
180+ exit 1
97181 fi
98182
99- # Create or update the GitHub Release
100- if gh release view "$release_tag" > /dev/null 2>&1; then
101- echo "Release $release_tag already exists – uploading updated asset."
102- gh release upload "$release_tag" "$pdf_path" --clobber
103- else
104- gh release create "$release_tag" \
105- --title "PDF – ${filename} (v${version})" \
106- --notes "Automated PDF export for \`${file}\` – version ${version}" \
107- "$pdf_path"
108- fi
183+ # The version-check step guarantees the tag is new at this point.
184+ gh release create "$release_tag" \
185+ --title "PDF – ${filename} (v${version})" \
186+ --notes "Automated PDF export for \`${file}\` – version ${version}" \
187+ "$pdf_path"
109188 done
110189 env :
111190 GITHUB_TOKEN : ${{ secrets.GITHUB_TOKEN }}
@@ -124,6 +203,11 @@ jobs:
124203 with :
125204 token : ${{ secrets.GITHUB_TOKEN }}
126205
206+ # Pull any version-bump commits pushed by the generate_pdfs job so that
207+ # liaex fetches up-to-date metadata from raw.githubusercontent.com.
208+ - name : Pull latest commits (including any version bumps)
209+ run : git pull --ff-only origin master || git pull origin master
210+
127211 - name : Set up Node.js
128212 uses : actions/setup-node@v4
129213 with :
0 commit comments