From 80efec5a264e3db2c1a53f9dc1bf2c5814f7f7c9 Mon Sep 17 00:00:00 2001 From: Vlada Dusek Date: Wed, 15 Apr 2026 09:51:07 +0200 Subject: [PATCH 01/14] ci: Extract docs versioning into reusable `manual_version_docs.yaml` workflow Extract the inline `version_docs` job from `manual_release_stable.yaml` into a standalone workflow that can be triggered manually or called from the release pipeline. Key improvements: - Fix `api:version` ENOENT bug by running docusaurus commands through `uv run` - Clean up ALL versions for the same major (not just exact major.minor match) - Remove non-docs artifacts (pyproject.toml, .gitignore, caches) from snapshots Co-Authored-By: Claude Opus 4.6 (1M context) --- .github/workflows/manual_release_stable.yaml | 64 +-------- .github/workflows/manual_version_docs.yaml | 142 +++++++++++++++++++ 2 files changed, 146 insertions(+), 60 deletions(-) create mode 100644 .github/workflows/manual_version_docs.yaml diff --git a/.github/workflows/manual_release_stable.yaml b/.github/workflows/manual_release_stable.yaml index fb35202b..ed44b1a9 100644 --- a/.github/workflows/manual_release_stable.yaml +++ b/.github/workflows/manual_release_stable.yaml @@ -105,68 +105,12 @@ jobs: version_docs: name: Version docs needs: [release_prepare, changelog_update, pypi_publish] - runs-on: ubuntu-latest - outputs: - version_docs_commitish: ${{ steps.commit_versioned_docs.outputs.commit_long_sha }} permissions: contents: write - env: - NODE_VERSION: 22 - PYTHON_VERSION: 3.14 - - steps: - - name: Checkout repository - uses: actions/checkout@v6 - with: - token: ${{ secrets.APIFY_SERVICE_ACCOUNT_GITHUB_TOKEN }} - ref: ${{ needs.changelog_update.outputs.changelog_commitish }} - - - name: Set up Node - uses: actions/setup-node@v6 - with: - node-version: ${{ env.NODE_VERSION }} - - - name: Set up Python - uses: actions/setup-python@v6 - with: - python-version: ${{ env.PYTHON_VERSION }} - - - name: Set up uv package manager - uses: astral-sh/setup-uv@v7 - with: - python-version: ${{ env.PYTHON_VERSION }} - - - name: Install Python dependencies - run: uv run poe install-dev - - - name: Install website dependencies - run: | - cd website - corepack enable - yarn install - - - name: Snapshot the current version - run: | - cd website - VERSION="$(python -c "import tomllib, pathlib; print(tomllib.loads(pathlib.Path('../pyproject.toml').read_text())['project']['version'])")" - MAJOR_MINOR="$(echo "$VERSION" | cut -d. -f1-2)" - export MAJOR_MINOR - # Remove existing version if present (patch releases override) - rm -rf "versioned_docs/version-${MAJOR_MINOR}" - rm -rf "versioned_sidebars/version-${MAJOR_MINOR}-sidebars.json" - jq 'map(select(. != env.MAJOR_MINOR))' versions.json > tmp.json && mv tmp.json versions.json - # Build API reference and create version snapshots - bash build_api_reference.sh - npx docusaurus docs:version "$MAJOR_MINOR" - npx docusaurus api:version "$MAJOR_MINOR" - - - name: Commit and push versioned docs - id: commit_versioned_docs - uses: EndBug/add-and-commit@v10 - with: - add: "website/versioned_docs website/versioned_sidebars website/versions.json" - message: "docs: version ${{ needs.release_prepare.outputs.version_number }} docs [skip ci]" - default_author: github_actions + uses: ./.github/workflows/manual_version_docs.yaml + with: + ref: ${{ needs.changelog_update.outputs.changelog_commitish }} + secrets: inherit doc_release: name: Doc release diff --git a/.github/workflows/manual_version_docs.yaml b/.github/workflows/manual_version_docs.yaml new file mode 100644 index 00000000..09a067c6 --- /dev/null +++ b/.github/workflows/manual_version_docs.yaml @@ -0,0 +1,142 @@ +name: Version docs + +on: + # Runs when manually triggered from the GitHub UI. + workflow_dispatch: + inputs: + ref: + description: "Git ref to checkout (branch, tag, or SHA). Defaults to the default branch." + required: false + type: string + default: "" + + # Runs when invoked by another workflow. + workflow_call: + inputs: + ref: + description: "Git ref to checkout (branch, tag, or SHA)" + required: true + type: string + outputs: + version_docs_commitish: + description: "The commit SHA of the versioned docs commit" + value: ${{ jobs.version_docs.outputs.version_docs_commitish }} + +concurrency: + group: version-docs + cancel-in-progress: false + +permissions: + contents: read + +jobs: + version_docs: + name: Version docs + runs-on: ubuntu-latest + outputs: + version_docs_commitish: ${{ steps.resolve_commitish.outputs.commitish }} + permissions: + contents: write + env: + NODE_VERSION: 22 + PYTHON_VERSION: "3.14" + + steps: + - name: Determine checkout ref + id: resolve_ref + run: | + REF="${{ inputs.ref }}" + if [ -z "$REF" ]; then + REF="${{ github.event.repository.default_branch }}" + fi + echo "ref=$REF" >> "$GITHUB_OUTPUT" + + - name: Checkout repository + uses: actions/checkout@v6 + with: + token: ${{ secrets.APIFY_SERVICE_ACCOUNT_GITHUB_TOKEN }} + ref: ${{ steps.resolve_ref.outputs.ref }} + + - name: Set up Node + uses: actions/setup-node@v6 + with: + node-version: ${{ env.NODE_VERSION }} + + - name: Set up Python + uses: actions/setup-python@v6 + with: + python-version: ${{ env.PYTHON_VERSION }} + + - name: Set up uv package manager + uses: astral-sh/setup-uv@v7 + with: + python-version: ${{ env.PYTHON_VERSION }} + + - name: Install Python dependencies + run: uv run poe install-dev + + - name: Install website dependencies + run: | + cd website + corepack enable + yarn install + + - name: Snapshot the current version + run: | + cd website + + # Extract version from pyproject.toml. + VERSION="$(python -c "import tomllib, pathlib; print(tomllib.loads(pathlib.Path('../pyproject.toml').read_text())['project']['version'])")" + MAJOR_MINOR="$(echo "$VERSION" | cut -d. -f1-2)" + MAJOR="$(echo "$VERSION" | cut -d. -f1)" + echo "Version: $VERSION, Major.Minor: $MAJOR_MINOR, Major: $MAJOR" + + # Remove ALL existing versions for this major (not just exact major.minor match). + for dir in versioned_docs/version-${MAJOR}.*; do + if [ -d "$dir" ]; then + echo "Removing $dir" + rm -rf "$dir" + fi + done + for file in versioned_sidebars/version-${MAJOR}.*-sidebars.json; do + if [ -f "$file" ]; then + echo "Removing $file" + rm -f "$file" + fi + done + + # Update versions.json to remove entries for this major version. + if [ -f versions.json ]; then + jq --arg major "$MAJOR" '[.[] | select((split(".")[0]) != $major)]' versions.json > tmp.json && mv tmp.json versions.json + else + echo "[]" > versions.json + fi + + # Build API reference and create Docusaurus version snapshots. + bash build_api_reference.sh + uv run npx docusaurus docs:version "$MAJOR_MINOR" + uv run npx docusaurus api:version "$MAJOR_MINOR" + + # Clean up non-docs artifacts from the snapshot. + rm -f "versioned_docs/version-${MAJOR_MINOR}/changelog.md" + rm -f "versioned_docs/version-${MAJOR_MINOR}/pyproject.toml" + rm -f "versioned_docs/version-${MAJOR_MINOR}/.gitignore" + rm -rf "versioned_docs/version-${MAJOR_MINOR}/.ruff_cache" + rm -rf "versioned_docs/version-${MAJOR_MINOR}/.ty_cache" + + - name: Commit and push versioned docs + id: commit_versioned_docs + uses: EndBug/add-and-commit@v10 + with: + add: "website/versioned_docs website/versioned_sidebars website/versions.json" + message: "docs: version docs [skip ci]" + default_author: github_actions + + - name: Resolve output commitish + id: resolve_commitish + run: | + SHA="${{ steps.commit_versioned_docs.outputs.commit_long_sha }}" + if [ -z "$SHA" ]; then + SHA="$(git rev-parse HEAD)" + fi + echo "commitish=$SHA" >> "$GITHUB_OUTPUT" From 35424c75f1a6520dbe3badd9f15aa88d6f115bd9 Mon Sep 17 00:00:00 2001 From: Vlada Dusek Date: Wed, 15 Apr 2026 09:57:13 +0200 Subject: [PATCH 02/14] fix: Quote variable expansions in for loop globs to satisfy shellcheck Co-Authored-By: Claude Opus 4.6 (1M context) --- .github/workflows/manual_version_docs.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/manual_version_docs.yaml b/.github/workflows/manual_version_docs.yaml index 09a067c6..eea60b60 100644 --- a/.github/workflows/manual_version_docs.yaml +++ b/.github/workflows/manual_version_docs.yaml @@ -92,13 +92,13 @@ jobs: echo "Version: $VERSION, Major.Minor: $MAJOR_MINOR, Major: $MAJOR" # Remove ALL existing versions for this major (not just exact major.minor match). - for dir in versioned_docs/version-${MAJOR}.*; do + for dir in "versioned_docs/version-${MAJOR}."*; do if [ -d "$dir" ]; then echo "Removing $dir" rm -rf "$dir" fi done - for file in versioned_sidebars/version-${MAJOR}.*-sidebars.json; do + for file in "versioned_sidebars/version-${MAJOR}."*-sidebars.json; do if [ -f "$file" ]; then echo "Removing $file" rm -f "$file" From d832d6819f43bf3f2c7b69befc6b06d3ecaef140 Mon Sep 17 00:00:00 2001 From: Vlada Dusek Date: Wed, 15 Apr 2026 10:08:33 +0200 Subject: [PATCH 03/14] refactor: Merge website deps install into snapshot step Co-Authored-By: Claude Opus 4.6 (1M context) --- .github/workflows/manual_version_docs.yaml | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/.github/workflows/manual_version_docs.yaml b/.github/workflows/manual_version_docs.yaml index eea60b60..5c723870 100644 --- a/.github/workflows/manual_version_docs.yaml +++ b/.github/workflows/manual_version_docs.yaml @@ -75,16 +75,12 @@ jobs: - name: Install Python dependencies run: uv run poe install-dev - - name: Install website dependencies + - name: Snapshot the current version run: | cd website corepack enable yarn install - - name: Snapshot the current version - run: | - cd website - # Extract version from pyproject.toml. VERSION="$(python -c "import tomllib, pathlib; print(tomllib.loads(pathlib.Path('../pyproject.toml').read_text())['project']['version'])")" MAJOR_MINOR="$(echo "$VERSION" | cut -d. -f1-2)" From 4cb04e08bebfdf93a30fb3ac107c431e861ff3ce Mon Sep 17 00:00:00 2001 From: Vlada Dusek Date: Wed, 15 Apr 2026 10:10:16 +0200 Subject: [PATCH 04/14] refactor: Use `[[` instead of `[` for bash conditionals Co-Authored-By: Claude Opus 4.6 (1M context) --- .github/workflows/manual_version_docs.yaml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/manual_version_docs.yaml b/.github/workflows/manual_version_docs.yaml index 5c723870..47ec7f2b 100644 --- a/.github/workflows/manual_version_docs.yaml +++ b/.github/workflows/manual_version_docs.yaml @@ -46,7 +46,7 @@ jobs: id: resolve_ref run: | REF="${{ inputs.ref }}" - if [ -z "$REF" ]; then + if [[ -z "$REF" ]]; then REF="${{ github.event.repository.default_branch }}" fi echo "ref=$REF" >> "$GITHUB_OUTPUT" @@ -89,20 +89,20 @@ jobs: # Remove ALL existing versions for this major (not just exact major.minor match). for dir in "versioned_docs/version-${MAJOR}."*; do - if [ -d "$dir" ]; then + if [[ -d "$dir" ]]; then echo "Removing $dir" rm -rf "$dir" fi done for file in "versioned_sidebars/version-${MAJOR}."*-sidebars.json; do - if [ -f "$file" ]; then + if [[ -f "$file" ]]; then echo "Removing $file" rm -f "$file" fi done # Update versions.json to remove entries for this major version. - if [ -f versions.json ]; then + if [[ -f versions.json ]]; then jq --arg major "$MAJOR" '[.[] | select((split(".")[0]) != $major)]' versions.json > tmp.json && mv tmp.json versions.json else echo "[]" > versions.json @@ -132,7 +132,7 @@ jobs: id: resolve_commitish run: | SHA="${{ steps.commit_versioned_docs.outputs.commit_long_sha }}" - if [ -z "$SHA" ]; then + if [[ -z "$SHA" ]]; then SHA="$(git rev-parse HEAD)" fi echo "commitish=$SHA" >> "$GITHUB_OUTPUT" From 5b0bca0a6cd778b1bb60a2fef5ff9ff66714dca5 Mon Sep 17 00:00:00 2001 From: Vlada Dusek Date: Wed, 15 Apr 2026 10:24:29 +0200 Subject: [PATCH 05/14] refactor: Use defensive version lookup instead of glob-based deletion Query versions.json for the specific existing version for a given major instead of aggressively globbing version-${MAJOR}.*. This means: - Major release (e.g. 3.0.0): nothing is deleted (new major, no prior minor) - Minor release (e.g. 3.1.0): only the exact old minor (3.0) is removed - Patch release (e.g. 3.1.1): only the exact current minor (3.1) is removed and recreated Co-Authored-By: Claude Opus 4.6 (1M context) --- .github/workflows/manual_version_docs.yaml | 29 ++++++++++------------ 1 file changed, 13 insertions(+), 16 deletions(-) diff --git a/.github/workflows/manual_version_docs.yaml b/.github/workflows/manual_version_docs.yaml index 47ec7f2b..0f45aaa3 100644 --- a/.github/workflows/manual_version_docs.yaml +++ b/.github/workflows/manual_version_docs.yaml @@ -87,27 +87,24 @@ jobs: MAJOR="$(echo "$VERSION" | cut -d. -f1)" echo "Version: $VERSION, Major.Minor: $MAJOR_MINOR, Major: $MAJOR" - # Remove ALL existing versions for this major (not just exact major.minor match). - for dir in "versioned_docs/version-${MAJOR}."*; do - if [[ -d "$dir" ]]; then - echo "Removing $dir" - rm -rf "$dir" - fi - done - for file in "versioned_sidebars/version-${MAJOR}."*-sidebars.json; do - if [[ -f "$file" ]]; then - echo "Removing $file" - rm -f "$file" - fi - done - - # Update versions.json to remove entries for this major version. + # Find the existing version for this major in versions.json (if any). if [[ -f versions.json ]]; then - jq --arg major "$MAJOR" '[.[] | select((split(".")[0]) != $major)]' versions.json > tmp.json && mv tmp.json versions.json + OLD_VERSION="$(jq -r --arg major "$MAJOR" '.[] | select(startswith($major + "."))' versions.json | head -1)" else + OLD_VERSION="" echo "[]" > versions.json fi + # Remove only the specific old version for this major (if found). + if [[ -n "$OLD_VERSION" ]]; then + echo "Removing old version $OLD_VERSION for major $MAJOR" + rm -rf "versioned_docs/version-${OLD_VERSION}" + rm -f "versioned_sidebars/version-${OLD_VERSION}-sidebars.json" + jq --arg old "$OLD_VERSION" '[.[] | select(. != $old)]' versions.json > tmp.json && mv tmp.json versions.json + else + echo "No existing version found for major $MAJOR, nothing to remove" + fi + # Build API reference and create Docusaurus version snapshots. bash build_api_reference.sh uv run npx docusaurus docs:version "$MAJOR_MINOR" From 6232541394dc9a253d5afd695d8a500a87662fd8 Mon Sep 17 00:00:00 2001 From: Vlada Dusek Date: Wed, 15 Apr 2026 10:31:44 +0200 Subject: [PATCH 06/14] refactor: Include version number in docs versioning commit message --- .github/workflows/manual_version_docs.yaml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/manual_version_docs.yaml b/.github/workflows/manual_version_docs.yaml index 0f45aaa3..90744258 100644 --- a/.github/workflows/manual_version_docs.yaml +++ b/.github/workflows/manual_version_docs.yaml @@ -76,6 +76,7 @@ jobs: run: uv run poe install-dev - name: Snapshot the current version + id: snapshot run: | cd website corepack enable @@ -85,6 +86,7 @@ jobs: VERSION="$(python -c "import tomllib, pathlib; print(tomllib.loads(pathlib.Path('../pyproject.toml').read_text())['project']['version'])")" MAJOR_MINOR="$(echo "$VERSION" | cut -d. -f1-2)" MAJOR="$(echo "$VERSION" | cut -d. -f1)" + echo "version=$VERSION" >> "$GITHUB_OUTPUT" echo "Version: $VERSION, Major.Minor: $MAJOR_MINOR, Major: $MAJOR" # Find the existing version for this major in versions.json (if any). @@ -122,7 +124,7 @@ jobs: uses: EndBug/add-and-commit@v10 with: add: "website/versioned_docs website/versioned_sidebars website/versions.json" - message: "docs: version docs [skip ci]" + message: "docs: Version docs for v${{ steps.snapshot.outputs.version }} [skip ci]" default_author: github_actions - name: Resolve output commitish From f2ed9e4d20c51f507c61393c929a9b18bf0e2150 Mon Sep 17 00:00:00 2001 From: Vlada Dusek Date: Wed, 15 Apr 2026 10:39:41 +0200 Subject: [PATCH 07/14] refactor: Use .gitignore instead of explicit cleanup for versioned docs artifacts Add gitignore patterns for pyproject.toml and .gitignore inside website/versioned_docs/ so git add never stages them. This replaces the explicit rm commands in the workflow since changelog.md, .ruff_cache, and .ty_cache are already covered by existing patterns. Co-Authored-By: Claude Opus 4.6 (1M context) --- .github/workflows/manual_version_docs.yaml | 7 ------- .gitignore | 2 ++ 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/.github/workflows/manual_version_docs.yaml b/.github/workflows/manual_version_docs.yaml index 90744258..e3b2bdb4 100644 --- a/.github/workflows/manual_version_docs.yaml +++ b/.github/workflows/manual_version_docs.yaml @@ -112,13 +112,6 @@ jobs: uv run npx docusaurus docs:version "$MAJOR_MINOR" uv run npx docusaurus api:version "$MAJOR_MINOR" - # Clean up non-docs artifacts from the snapshot. - rm -f "versioned_docs/version-${MAJOR_MINOR}/changelog.md" - rm -f "versioned_docs/version-${MAJOR_MINOR}/pyproject.toml" - rm -f "versioned_docs/version-${MAJOR_MINOR}/.gitignore" - rm -rf "versioned_docs/version-${MAJOR_MINOR}/.ruff_cache" - rm -rf "versioned_docs/version-${MAJOR_MINOR}/.ty_cache" - - name: Commit and push versioned docs id: commit_versioned_docs uses: EndBug/add-and-commit@v10 diff --git a/.gitignore b/.gitignore index 77add859..60947301 100644 --- a/.gitignore +++ b/.gitignore @@ -64,6 +64,8 @@ Session.vim # Docs docs/changelog.md website/versioned_docs/*/changelog.md +website/versioned_docs/*/pyproject.toml +website/versioned_docs/*/.gitignore # Website build artifacts, node dependencies website/build From 2cbc62d994f43cffbc00d1b75c26187955845041 Mon Sep 17 00:00:00 2001 From: Vlada Dusek Date: Wed, 15 Apr 2026 10:44:20 +0200 Subject: [PATCH 08/14] refactor: Remove unnecessary quotes and move env to workflow level Co-Authored-By: Claude Opus 4.6 (1M context) --- .github/workflows/manual_version_docs.yaml | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/.github/workflows/manual_version_docs.yaml b/.github/workflows/manual_version_docs.yaml index e3b2bdb4..b0cf4437 100644 --- a/.github/workflows/manual_version_docs.yaml +++ b/.github/workflows/manual_version_docs.yaml @@ -5,7 +5,7 @@ on: workflow_dispatch: inputs: ref: - description: "Git ref to checkout (branch, tag, or SHA). Defaults to the default branch." + description: Git ref to checkout (branch, tag, or SHA). Defaults to the default branch. required: false type: string default: "" @@ -14,12 +14,12 @@ on: workflow_call: inputs: ref: - description: "Git ref to checkout (branch, tag, or SHA)" + description: Git ref to checkout (branch, tag, or SHA) required: true type: string outputs: version_docs_commitish: - description: "The commit SHA of the versioned docs commit" + description: The commit SHA of the versioned docs commit value: ${{ jobs.version_docs.outputs.version_docs_commitish }} concurrency: @@ -29,6 +29,10 @@ concurrency: permissions: contents: read +env: + NODE_VERSION: 22 + PYTHON_VERSION: "3.14" + jobs: version_docs: name: Version docs @@ -37,9 +41,6 @@ jobs: version_docs_commitish: ${{ steps.resolve_commitish.outputs.commitish }} permissions: contents: write - env: - NODE_VERSION: 22 - PYTHON_VERSION: "3.14" steps: - name: Determine checkout ref @@ -116,7 +117,7 @@ jobs: id: commit_versioned_docs uses: EndBug/add-and-commit@v10 with: - add: "website/versioned_docs website/versioned_sidebars website/versions.json" + add: website/versioned_docs website/versioned_sidebars website/versions.json message: "docs: Version docs for v${{ steps.snapshot.outputs.version }} [skip ci]" default_author: github_actions From d94ab9550776235fcccf0c70f001e5110dfcb7d8 Mon Sep 17 00:00:00 2001 From: Vlada Dusek Date: Wed, 15 Apr 2026 10:45:24 +0200 Subject: [PATCH 09/14] refactor: Use uv version --short to extract project version Co-Authored-By: Claude Opus 4.6 (1M context) --- .github/workflows/manual_version_docs.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/manual_version_docs.yaml b/.github/workflows/manual_version_docs.yaml index b0cf4437..f7674607 100644 --- a/.github/workflows/manual_version_docs.yaml +++ b/.github/workflows/manual_version_docs.yaml @@ -84,7 +84,7 @@ jobs: yarn install # Extract version from pyproject.toml. - VERSION="$(python -c "import tomllib, pathlib; print(tomllib.loads(pathlib.Path('../pyproject.toml').read_text())['project']['version'])")" + VERSION="$(uv version --short)" MAJOR_MINOR="$(echo "$VERSION" | cut -d. -f1-2)" MAJOR="$(echo "$VERSION" | cut -d. -f1)" echo "version=$VERSION" >> "$GITHUB_OUTPUT" From 4859af28f3c76892ae80f4d98801c12be7836832 Mon Sep 17 00:00:00 2001 From: Vlada Dusek Date: Wed, 15 Apr 2026 10:46:31 +0200 Subject: [PATCH 10/14] refactor: Use more precise variable names for version identifiers Co-Authored-By: Claude Opus 4.6 (1M context) --- .github/workflows/manual_version_docs.yaml | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/.github/workflows/manual_version_docs.yaml b/.github/workflows/manual_version_docs.yaml index f7674607..1dfadafd 100644 --- a/.github/workflows/manual_version_docs.yaml +++ b/.github/workflows/manual_version_docs.yaml @@ -84,15 +84,15 @@ jobs: yarn install # Extract version from pyproject.toml. - VERSION="$(uv version --short)" - MAJOR_MINOR="$(echo "$VERSION" | cut -d. -f1-2)" - MAJOR="$(echo "$VERSION" | cut -d. -f1)" - echo "version=$VERSION" >> "$GITHUB_OUTPUT" - echo "Version: $VERSION, Major.Minor: $MAJOR_MINOR, Major: $MAJOR" + FULL_VERSION="$(uv version --short)" + MAJOR_MINOR_VERSION="$(echo "$FULL_VERSION" | cut -d. -f1-2)" + MAJOR_VERSION="$(echo "$FULL_VERSION" | cut -d. -f1)" + echo "version=$FULL_VERSION" >> "$GITHUB_OUTPUT" + echo "Version: $FULL_VERSION, Major.Minor: $MAJOR_MINOR_VERSION, Major: $MAJOR_VERSION" # Find the existing version for this major in versions.json (if any). if [[ -f versions.json ]]; then - OLD_VERSION="$(jq -r --arg major "$MAJOR" '.[] | select(startswith($major + "."))' versions.json | head -1)" + OLD_VERSION="$(jq -r --arg major "$MAJOR_VERSION" '.[] | select(startswith($major + "."))' versions.json | head -1)" else OLD_VERSION="" echo "[]" > versions.json @@ -100,18 +100,18 @@ jobs: # Remove only the specific old version for this major (if found). if [[ -n "$OLD_VERSION" ]]; then - echo "Removing old version $OLD_VERSION for major $MAJOR" + echo "Removing old version $OLD_VERSION for major $MAJOR_VERSION" rm -rf "versioned_docs/version-${OLD_VERSION}" rm -f "versioned_sidebars/version-${OLD_VERSION}-sidebars.json" jq --arg old "$OLD_VERSION" '[.[] | select(. != $old)]' versions.json > tmp.json && mv tmp.json versions.json else - echo "No existing version found for major $MAJOR, nothing to remove" + echo "No existing version found for major $MAJOR_VERSION, nothing to remove" fi # Build API reference and create Docusaurus version snapshots. bash build_api_reference.sh - uv run npx docusaurus docs:version "$MAJOR_MINOR" - uv run npx docusaurus api:version "$MAJOR_MINOR" + uv run npx docusaurus docs:version "$MAJOR_MINOR_VERSION" + uv run npx docusaurus api:version "$MAJOR_MINOR_VERSION" - name: Commit and push versioned docs id: commit_versioned_docs From beee4dad87f3565b06fde60094c9ebe9015dcc0f Mon Sep 17 00:00:00 2001 From: Vlada Dusek Date: Wed, 15 Apr 2026 10:49:00 +0200 Subject: [PATCH 11/14] refactor: Remove unnecessary .gitignore pattern from versioned docs Co-Authored-By: Claude Opus 4.6 (1M context) --- .gitignore | 1 - 1 file changed, 1 deletion(-) diff --git a/.gitignore b/.gitignore index 60947301..81c18518 100644 --- a/.gitignore +++ b/.gitignore @@ -65,7 +65,6 @@ Session.vim docs/changelog.md website/versioned_docs/*/changelog.md website/versioned_docs/*/pyproject.toml -website/versioned_docs/*/.gitignore # Website build artifacts, node dependencies website/build From 9037b075470a81819abc94a869b263ab3e52e469 Mon Sep 17 00:00:00 2001 From: Vlada Dusek Date: Wed, 15 Apr 2026 12:39:50 +0200 Subject: [PATCH 12/14] refactor: Quote NODE_VERSION env value for consistency Co-Authored-By: Claude Opus 4.6 (1M context) --- .github/workflows/manual_version_docs.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/manual_version_docs.yaml b/.github/workflows/manual_version_docs.yaml index 1dfadafd..f752b349 100644 --- a/.github/workflows/manual_version_docs.yaml +++ b/.github/workflows/manual_version_docs.yaml @@ -30,7 +30,7 @@ permissions: contents: read env: - NODE_VERSION: 22 + NODE_VERSION: "22" PYTHON_VERSION: "3.14" jobs: From d944121b83559d0cfd9e28e107c8f46407c6e9af Mon Sep 17 00:00:00 2001 From: Vlada Dusek Date: Wed, 15 Apr 2026 12:43:02 +0200 Subject: [PATCH 13/14] fix: Remove all old versions for same major, not just the first match Co-Authored-By: Claude Opus 4.6 (1M context) --- .github/workflows/manual_version_docs.yaml | 23 ++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/.github/workflows/manual_version_docs.yaml b/.github/workflows/manual_version_docs.yaml index f752b349..8f473726 100644 --- a/.github/workflows/manual_version_docs.yaml +++ b/.github/workflows/manual_version_docs.yaml @@ -90,22 +90,25 @@ jobs: echo "version=$FULL_VERSION" >> "$GITHUB_OUTPUT" echo "Version: $FULL_VERSION, Major.Minor: $MAJOR_MINOR_VERSION, Major: $MAJOR_VERSION" - # Find the existing version for this major in versions.json (if any). + # Find the existing versions for this major in versions.json (if any). if [[ -f versions.json ]]; then - OLD_VERSION="$(jq -r --arg major "$MAJOR_VERSION" '.[] | select(startswith($major + "."))' versions.json | head -1)" + OLD_VERSIONS="$(jq -r --arg major "$MAJOR_VERSION" '.[] | select(startswith($major + "."))' versions.json)" else - OLD_VERSION="" + OLD_VERSIONS="" echo "[]" > versions.json fi - # Remove only the specific old version for this major (if found). - if [[ -n "$OLD_VERSION" ]]; then - echo "Removing old version $OLD_VERSION for major $MAJOR_VERSION" - rm -rf "versioned_docs/version-${OLD_VERSION}" - rm -f "versioned_sidebars/version-${OLD_VERSION}-sidebars.json" - jq --arg old "$OLD_VERSION" '[.[] | select(. != $old)]' versions.json > tmp.json && mv tmp.json versions.json + # Remove all old versions for this major (if found). + if [[ -n "$OLD_VERSIONS" ]]; then + while IFS= read -r OLD_VERSION; do + [[ -z "$OLD_VERSION" ]] && continue + echo "Removing old version $OLD_VERSION for major $MAJOR_VERSION" + rm -rf "versioned_docs/version-${OLD_VERSION}" + rm -f "versioned_sidebars/version-${OLD_VERSION}-sidebars.json" + done <<< "$OLD_VERSIONS" + jq --arg major "$MAJOR_VERSION" 'map(select(startswith($major + ".") | not))' versions.json > tmp.json && mv tmp.json versions.json else - echo "No existing version found for major $MAJOR_VERSION, nothing to remove" + echo "No existing versions found for major $MAJOR_VERSION, nothing to remove" fi # Build API reference and create Docusaurus version snapshots. From cee276496e6ff9dda9387d308bf098228ac14be9 Mon Sep 17 00:00:00 2001 From: Vlada Dusek Date: Wed, 15 Apr 2026 12:50:26 +0200 Subject: [PATCH 14/14] fix: Prevent script injection in workflow run blocks Pass inputs.ref, github.event.repository.default_branch, and steps outputs through env variables instead of direct ${{ }} interpolation in run: blocks. Co-Authored-By: Claude Opus 4.6 (1M context) --- .github/workflows/manual_version_docs.yaml | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/.github/workflows/manual_version_docs.yaml b/.github/workflows/manual_version_docs.yaml index 8f473726..b9f99886 100644 --- a/.github/workflows/manual_version_docs.yaml +++ b/.github/workflows/manual_version_docs.yaml @@ -45,11 +45,11 @@ jobs: steps: - name: Determine checkout ref id: resolve_ref + env: + INPUT_REF: ${{ inputs.ref }} + DEFAULT_BRANCH: ${{ github.event.repository.default_branch }} run: | - REF="${{ inputs.ref }}" - if [[ -z "$REF" ]]; then - REF="${{ github.event.repository.default_branch }}" - fi + REF="${INPUT_REF:-$DEFAULT_BRANCH}" echo "ref=$REF" >> "$GITHUB_OUTPUT" - name: Checkout repository @@ -126,9 +126,7 @@ jobs: - name: Resolve output commitish id: resolve_commitish + env: + COMMIT_SHA: ${{ steps.commit_versioned_docs.outputs.commit_long_sha }} run: | - SHA="${{ steps.commit_versioned_docs.outputs.commit_long_sha }}" - if [[ -z "$SHA" ]]; then - SHA="$(git rev-parse HEAD)" - fi - echo "commitish=$SHA" >> "$GITHUB_OUTPUT" + echo "commitish=${COMMIT_SHA:-$(git rev-parse HEAD)}" >> "$GITHUB_OUTPUT"