From a9244d7940198806fd476a75caff477c2e4696ba Mon Sep 17 00:00:00 2001 From: skjnldsv Date: Thu, 2 Jul 2026 15:19:17 +0200 Subject: [PATCH 1/6] ci: restrict scheduled deploy matrix to supported branches The consolidated deploy matrix iterated every stable* branch on the remote, including long out-of-support ones (stable9..stable29). In a single run this also blows past the 256-jobs-per-run limit and wastes CI on branches that no longer build. - prepare now builds master + only the stable branches within the support window, reusing build/detect-versions.php for the lowest..highest range. - workflow_dispatch gains an optional "branch" input to build & deploy a single branch on demand (empty = master + all supported stables). Assisted-by: ClaudeCode:claude-opus-4-8 Signed-off-by: skjnldsv --- .github/workflows/deploy-docs.yml | 53 +++++++++++++++++++++++++++---- 1 file changed, 46 insertions(+), 7 deletions(-) diff --git a/.github/workflows/deploy-docs.yml b/.github/workflows/deploy-docs.yml index e50bafda54f..09bb5ecf609 100644 --- a/.github/workflows/deploy-docs.yml +++ b/.github/workflows/deploy-docs.yml @@ -15,6 +15,12 @@ on: schedule: - cron: '0 2 * * *' # 02:00 UTC daily workflow_dispatch: + inputs: + branch: + description: "Build & deploy a single branch (e.g. master or stable34). Leave empty to build master + all supported stable branches." + required: false + type: string + default: "" permissions: contents: read @@ -30,15 +36,46 @@ jobs: outputs: branches: ${{ steps.set.outputs.branches }} steps: - - name: Collect master and stable branches + - name: Checkout repository + uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + + - name: Setup PHP + uses: shivammathur/setup-php@f3e473d116dcccaddc5834248c87452386958240 # v2.37.2 + with: + php-version: '8.3' + + - name: Compute branch matrix id: set env: - GH_TOKEN: ${{ github.token }} + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + INPUT_BRANCH: ${{ inputs.branch }} run: | - stable_branches=$(gh api "repos/${{ github.repository }}/branches" --paginate \ - --jq '.[].name | select(startswith("stable"))' | sort -Vr) - # Build a JSON array: ["master", "stable34", "stable33", ...] - branches_json=$(printf '%s\n' master ${stable_branches} | jq -R . | jq -cs .) + # Manual single-branch dispatch: build only the requested branch. + if [ -n "${INPUT_BRANCH}" ]; then + branches_json=$(printf '%s' "${INPUT_BRANCH}" | jq -R . | jq -cs .) + echo "Single-branch dispatch: ${branches_json}" + echo "branches=${branches_json}" >> $GITHUB_OUTPUT + exit 0 + fi + + # Scheduled / plain dispatch: master + every stable branch that is still + # within the support window. Ancient branches (e.g. stable10) are on the + # remote but out of support and would blow past the 256-jobs-per-run cap. + nums=$(git ls-remote --heads origin "heads/stable[0-9][0-9]" \ + | sed -n 's?.*refs/heads/stable\([0-9]\{2\}\)$?\1?p' | sort -n) + + # Reuse the shared helper to get the supported range (lowest..highest). + eval $(php build/detect-versions.php ${nums}) + echo "Supported stable range: ${lowest_stable}..${highest_stable}" + + selected="master" + for n in ${nums}; do + if [ "$n" -ge "$lowest_stable" ] && [ "$n" -le "$highest_stable" ]; then + selected="${selected} stable${n}" + fi + done + + branches_json=$(printf '%s\n' ${selected} | jq -R . | jq -cs .) echo "Matrix branches: ${branches_json}" echo "branches=${branches_json}" >> $GITHUB_OUTPUT @@ -182,7 +219,9 @@ jobs: if: steps.apply.outputs.has_changes == 'true' run: | default_branch="${{ github.event.repository.default_branch }}" - git fetch origin "${default_branch}" + # gh-pages is checked out single-branch, so there is no origin/ + # tracking ref. Fetch with an explicit refspec to create it. + git fetch origin "${default_branch}:refs/remotes/origin/${default_branch}" git checkout "origin/${default_branch}" -- go.php/index.html user_manual/index.html for d in server/*/; do From aa1096c66683e71703faf72f40b43e6ba376c0d3 Mon Sep 17 00:00:00 2001 From: skjnldsv Date: Thu, 2 Jul 2026 15:40:37 +0200 Subject: [PATCH 2/6] ci: build each version with its own Python via .python-version The deploy resolves build-docs.yml from master for every matrix leg, so a hardcoded python-version would build all branches with master's Python. Read the version from the checked-out branch (.python-version) instead, falling back to 3.13 when the file is absent, so each version can pin its own Python even under the shared workflow. requirements.txt only pins packages and cannot carry the interpreter version. Assisted-by: ClaudeCode:claude-opus-4-8 Signed-off-by: skjnldsv --- .github/workflows/build-docs.yml | 35 +++++++++++++++++++++++++++++--- .python-version | 1 + 2 files changed, 33 insertions(+), 3 deletions(-) create mode 100644 .python-version diff --git a/.github/workflows/build-docs.yml b/.github/workflows/build-docs.yml index 939ae096a7f..6c403b8578d 100644 --- a/.github/workflows/build-docs.yml +++ b/.github/workflows/build-docs.yml @@ -125,10 +125,21 @@ jobs: fi exit $err + - name: Resolve Python version + id: pyver + run: | + # Read the version from the checked-out branch (ref input) so each + # version builds with its own Python; fall back to 3.13 if absent. + if [ -f .python-version ]; then + echo "version=$(tr -d '[:space:]' < .python-version)" >> "$GITHUB_OUTPUT" + else + echo "version=3.13" >> "$GITHUB_OUTPUT" + fi + - name: Set up Python uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 with: - python-version: "3.13" + python-version: ${{ steps.pyver.outputs.version }} cache: "pip" - name: Install pip dependencies @@ -176,10 +187,19 @@ jobs: with: ref: ${{ inputs.ref }} + - name: Resolve Python version + id: pyver + run: | + if [ -f .python-version ]; then + echo "version=$(tr -d '[:space:]' < .python-version)" >> "$GITHUB_OUTPUT" + else + echo "version=3.13" >> "$GITHUB_OUTPUT" + fi + - name: Set up Python uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 with: - python-version: "3.13" + python-version: ${{ steps.pyver.outputs.version }} cache: "pip" - name: Install pip dependencies @@ -282,10 +302,19 @@ jobs: with: ref: ${{ inputs.ref }} + - name: Resolve Python version + id: pyver + run: | + if [ -f .python-version ]; then + echo "version=$(tr -d '[:space:]' < .python-version)" >> "$GITHUB_OUTPUT" + else + echo "version=3.13" >> "$GITHUB_OUTPUT" + fi + - name: Set up Python uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 with: - python-version: "3.13" + python-version: ${{ steps.pyver.outputs.version }} # pip cache is not compatible with the Docker container # cache: "pip" diff --git a/.python-version b/.python-version new file mode 100644 index 00000000000..24ee5b1be99 --- /dev/null +++ b/.python-version @@ -0,0 +1 @@ +3.13 From 2845d942e30fc923cde4467e0655d5358e29868e Mon Sep 17 00:00:00 2001 From: skjnldsv Date: Thu, 2 Jul 2026 15:52:43 +0200 Subject: [PATCH 3/6] ci: only add redirects to folders deployed this run The redirect step iterated every server/*/ folder on gh-pages, including ancient versions (server/12) whose legacy layout has go.php as a file, so mkdir -p failed. Track the folders applied this run in the apply step and restrict the redirect loop to those, and remove any stale go.php path first. Assisted-by: ClaudeCode:claude-opus-4-8 Signed-off-by: skjnldsv --- .github/workflows/deploy-docs.yml | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/.github/workflows/deploy-docs.yml b/.github/workflows/deploy-docs.yml index 09bb5ecf609..973f2c9b035 100644 --- a/.github/workflows/deploy-docs.yml +++ b/.github/workflows/deploy-docs.yml @@ -146,10 +146,12 @@ jobs: id: apply if: steps.staged.outputs.has_stage == 'true' run: | + deployed="" for d in stage/*/; do [ -d "$d" ] || continue branch="$(basename "$d")" echo "Applying version folder: ${branch}" + deployed="${deployed} ${branch}" mkdir -p "server/${branch}" for artifact in "stage/${branch}"/*; do @@ -169,6 +171,10 @@ jobs: done done + # Record which folders we deployed this run, so later steps only touch + # those (not the ancient version folders already present on gh-pages). + echo "folders=$(echo ${deployed} | xargs)" >> $GITHUB_OUTPUT + # Cleanup empty directories find . -type d -empty -delete @@ -224,9 +230,10 @@ jobs: git fetch origin "${default_branch}:refs/remotes/origin/${default_branch}" git checkout "origin/${default_branch}" -- go.php/index.html user_manual/index.html - for d in server/*/; do - [ -d "$d" ] || continue - branch="$(basename "$d")" + # Only the folders deployed this run — not every historical version + # already on gh-pages (some old ones have an incompatible layout). + for branch in ${{ steps.apply.outputs.folders }}; do + rm -rf "server/${branch}/go.php" mkdir -p "server/${branch}/go.php" "server/${branch}/user_manual" cp go.php/index.html "server/${branch}/go.php/index.html" cp user_manual/index.html "server/${branch}/user_manual/index.html" From d7c34bb3ff8c485f3ca83e684f8206c97afb2a86 Mon Sep 17 00:00:00 2001 From: skjnldsv Date: Thu, 2 Jul 2026 16:10:43 +0200 Subject: [PATCH 4/6] ci: fix stable version display in consolidated deploy builds Stable branches conf.py derive the display version from GITHUB_BASE_REF / GITHUB_REF, which in the single-run deploy reflect the workflow branch, not the matrix leg. Every stable build was therefore mislabelled as the dev version (e.g. stable32 rendered as "35 / latest"). Expose the built branch via GITHUB_BASE_REF in the build jobs so each stable conf.py resolves correctly; master conf.py is unaffected (it uses DOCS_DISPLAY_VERSION). Assisted-by: ClaudeCode:claude-opus-4-8 Signed-off-by: skjnldsv --- .github/workflows/build-docs.yml | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/.github/workflows/build-docs.yml b/.github/workflows/build-docs.yml index 6c403b8578d..de9181566dd 100644 --- a/.github/workflows/build-docs.yml +++ b/.github/workflows/build-docs.yml @@ -44,6 +44,13 @@ jobs: name: Building ${{ matrix.manual.name }} HTML runs-on: ubuntu-latest + env: + # The single-run deploy builds each version via a checked-out `ref`, but + # GITHUB_REF stays the workflow's own branch. Stable branches' conf.py read + # GITHUB_BASE_REF to derive their display version, so expose the branch being + # built; otherwise every stable build is mislabelled as the dev version. + GITHUB_BASE_REF: ${{ inputs.branch }} + strategy: fail-fast: false matrix: @@ -165,6 +172,9 @@ jobs: name: Building ${{ matrix.manual.name }} ePub runs-on: ubuntu-latest + env: + GITHUB_BASE_REF: ${{ inputs.branch }} + strategy: fail-fast: false matrix: @@ -284,6 +294,9 @@ jobs: needs: prepare-pdf-image container: ${{ needs.prepare-pdf-image.outputs.image }} + env: + GITHUB_BASE_REF: ${{ inputs.branch }} + strategy: fail-fast: false matrix: From 8e61e21dd0e92cf51b6a11ee8aad05409d5b56fa Mon Sep 17 00:00:00 2001 From: skjnldsv Date: Thu, 2 Jul 2026 16:10:43 +0200 Subject: [PATCH 5/6] ci: list per-version change counts in deploy PR body Add a small table to the deploy PR body showing how many files changed per version folder, so reviewers can see at a glance what actually got updated. Assisted-by: ClaudeCode:claude-opus-4-8 Signed-off-by: skjnldsv --- .github/workflows/deploy-docs.yml | 34 ++++++++++++++++++++++++++++--- 1 file changed, 31 insertions(+), 3 deletions(-) diff --git a/.github/workflows/deploy-docs.yml b/.github/workflows/deploy-docs.yml index 973f2c9b035..b64cdf9a212 100644 --- a/.github/workflows/deploy-docs.yml +++ b/.github/workflows/deploy-docs.yml @@ -239,6 +239,36 @@ jobs: cp user_manual/index.html "server/${branch}/user_manual/index.html" done + # ======================================================================== + # COMPOSE PR BODY — per-version change counts + # ======================================================================== + - name: Compose PR body + id: body + if: steps.apply.outputs.has_changes == 'true' + run: | + # Stage everything so new files count too (create-pull-request commits this). + git add -A + { + echo "text<> "$GITHUB_OUTPUT" + - name: Create Pull Request for documentation deployment uses: peter-evans/create-pull-request@5f6978faf089d4d20b00c7766989d076bb2fc7f1 # v8.1.1 id: cpr @@ -252,9 +282,7 @@ jobs: branch: "automated/deploy/documentation" base: gh-pages title: "Documentation update" - body: | - This PR was automatically generated by the scheduled deploy workflow - and includes the latest documentation for all built versions. + body: ${{ steps.body.outputs.text }} delete-branch: true labels: "automated, 3. to review" From d43db37f3a8b6587d9cc001669e7dded859befdf Mon Sep 17 00:00:00 2001 From: skjnldsv Date: Thu, 2 Jul 2026 16:28:59 +0200 Subject: [PATCH 6/6] ci: drop ineffective GITHUB_BASE_REF override, use DOCS_DISPLAY_VERSION Overriding the reserved GITHUB_BASE_REF via job env does not reach the build process (the runner ignores it), so stable builds were still mislabelled. Instead rely on DOCS_DISPLAY_VERSION, which build-html already exports via detect-versions and which the epub job now sets too (PDF is covered by DOCS_RELEASE). Stable branches conf.py must read DOCS_DISPLAY_VERSION for this to take effect (backported separately). Assisted-by: ClaudeCode:claude-opus-4-8 Signed-off-by: skjnldsv --- .github/workflows/build-docs.yml | 18 +++++------------- 1 file changed, 5 insertions(+), 13 deletions(-) diff --git a/.github/workflows/build-docs.yml b/.github/workflows/build-docs.yml index de9181566dd..20cd2cdd547 100644 --- a/.github/workflows/build-docs.yml +++ b/.github/workflows/build-docs.yml @@ -44,13 +44,6 @@ jobs: name: Building ${{ matrix.manual.name }} HTML runs-on: ubuntu-latest - env: - # The single-run deploy builds each version via a checked-out `ref`, but - # GITHUB_REF stays the workflow's own branch. Stable branches' conf.py read - # GITHUB_BASE_REF to derive their display version, so expose the branch being - # built; otherwise every stable build is mislabelled as the dev version. - GITHUB_BASE_REF: ${{ inputs.branch }} - strategy: fail-fast: false matrix: @@ -172,9 +165,6 @@ jobs: name: Building ${{ matrix.manual.name }} ePub runs-on: ubuntu-latest - env: - GITHUB_BASE_REF: ${{ inputs.branch }} - strategy: fail-fast: false matrix: @@ -218,6 +208,11 @@ jobs: - name: Build epub documentation run: | set -e + # HTML sets DOCS_DISPLAY_VERSION via detect-versions and PDF via DOCS_RELEASE; + # the epub job needs it too so stable branches render their real version. + if [[ "${{ inputs.branch }}" =~ ^stable([0-9]+)$ ]]; then + export DOCS_DISPLAY_VERSION="${BASH_REMATCH[1]}" + fi cd ${{ matrix.manual.directory }} make epub ls -la ${{ matrix.manual.build_epub_path }} @@ -294,9 +289,6 @@ jobs: needs: prepare-pdf-image container: ${{ needs.prepare-pdf-image.outputs.image }} - env: - GITHUB_BASE_REF: ${{ inputs.branch }} - strategy: fail-fast: false matrix: