docs-examples-sync #177
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Import versioned docs examples | |
| on: | |
| workflow_dispatch: {} | |
| repository_dispatch: | |
| types: [docs-examples-sync] | |
| permissions: | |
| contents: read | |
| concurrency: | |
| group: import-docs-examples | |
| cancel-in-progress: false | |
| jobs: | |
| prepare: | |
| runs-on: ubuntu-latest | |
| outputs: | |
| matrix: ${{ steps.matrix.outputs.matrix }} | |
| steps: | |
| - id: matrix | |
| name: Build docs branch matrix | |
| env: | |
| EVENT_NAME: ${{ github.event_name }} | |
| DISPATCH_DOCS_BRANCH: ${{ github.event.client_payload.docs_branch }} | |
| run: | | |
| node --input-type=module <<'NODE' | |
| import fs from "node:fs"; | |
| const releaseBranch = (version) => { | |
| const match = typeof version === "string" && version.match(/^(\d+)\.(\d+)\.\d+(?:-[0-9A-Za-z.-]+)?(?:\+[0-9A-Za-z.-]+)?$/); | |
| if (!match) throw new Error(`npm dist-tags.latest must be a concrete semver version; got ${JSON.stringify(version)}`); | |
| return { docs_branch: `prod-docs/${match[1]}.${match[2]}`, bucket: `${match[1]}.${match[2]}` }; | |
| }; | |
| const dispatchBranch = process.env.DISPATCH_DOCS_BRANCH; | |
| let matrix; | |
| if (process.env.EVENT_NAME === "repository_dispatch" && dispatchBranch) { | |
| if (dispatchBranch === "develop") { | |
| matrix = [{ docs_branch: "develop", bucket: "next" }]; | |
| } else { | |
| const match = dispatchBranch.match(/^prod-docs\/(\d+)\.(\d+)$/); | |
| if (!match) throw new Error(`Unsupported repository_dispatch docs_branch: ${JSON.stringify(dispatchBranch)}`); | |
| matrix = [{ docs_branch: dispatchBranch, bucket: `${match[1]}.${match[2]}` }]; | |
| } | |
| } else { | |
| const response = await fetch("https://registry.npmjs.org/handsontable"); | |
| if (!response.ok) throw new Error(`Could not fetch npm dist-tags.latest: registry returned ${response.status}`); | |
| const registry = await response.json(); | |
| matrix = [releaseBranch(registry?.["dist-tags"]?.latest), { docs_branch: "develop", bucket: "next" }]; | |
| } | |
| fs.appendFileSync(process.env.GITHUB_OUTPUT, `matrix=${JSON.stringify(matrix)}\n`); | |
| NODE | |
| import: | |
| needs: prepare | |
| runs-on: ubuntu-latest | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| include: ${{ fromJSON(needs.prepare.outputs.matrix) }} | |
| defaults: | |
| run: | |
| working-directory: runner | |
| steps: | |
| - uses: actions/checkout@v5 | |
| - name: Check out Handsontable docs source | |
| uses: actions/checkout@v5 | |
| with: | |
| repository: handsontable/handsontable | |
| ref: ${{ matrix.docs_branch }} | |
| path: handsontable | |
| token: ${{ secrets.DOCS_REPO_TOKEN || github.token }} | |
| sparse-checkout: | | |
| /docs/content/** | |
| /handsontable/package.json | |
| sparse-checkout-cone-mode: false | |
| - id: import | |
| name: Import ${{ matrix.bucket }} bucket | |
| continue-on-error: true | |
| run: | | |
| set -o pipefail | |
| node pipeline/import-docs.mjs \ | |
| --docs="$GITHUB_WORKSPACE/handsontable/docs" \ | |
| --docs-branch="${{ matrix.docs_branch }}" 2>&1 | tee import-docs.log | |
| - name: Summarize ${{ matrix.bucket }} import | |
| if: always() | |
| working-directory: . | |
| env: | |
| BUCKET: ${{ matrix.bucket }} | |
| DOCS_BRANCH: ${{ matrix.docs_branch }} | |
| IMPORT_OUTCOME: ${{ steps.import.outcome }} | |
| run: | | |
| node --input-type=module <<'NODE' | |
| import fs from "node:fs"; | |
| import path from "node:path"; | |
| const manifestPath = path.join( | |
| "runner", | |
| "apps", | |
| "authoring", | |
| "public", | |
| "docs-examples", | |
| process.env.BUCKET, | |
| "manifest.json", | |
| ); | |
| const lines = [ | |
| `## Docs examples: \`${process.env.BUCKET}\``, | |
| "", | |
| `- Docs branch: \`${process.env.DOCS_BRANCH}\``, | |
| `- Import result: **${process.env.IMPORT_OUTCOME}**`, | |
| ]; | |
| if (fs.existsSync(manifestPath)) { | |
| const manifest = JSON.parse(fs.readFileSync(manifestPath, "utf8")); | |
| const counts = manifest.examples.reduce((result, { framework }) => { | |
| result[framework] = (result[framework] || 0) + 1; | |
| return result; | |
| }, {}); | |
| lines.push(`- Handsontable version: \`${manifest.hotVersion}\``); | |
| lines.push(`- Examples: ${manifest.count}`); | |
| lines.push(`- By framework: ${Object.entries(counts).map(([name, count]) => `${name} (${count})`).join(", ")}`); | |
| } else { | |
| lines.push("- Manifest: not generated"); | |
| } | |
| fs.appendFileSync(process.env.GITHUB_STEP_SUMMARY, `${lines.join("\n")}\n\n`); | |
| NODE | |
| - name: Fail when import failed | |
| if: steps.import.outcome == 'failure' | |
| run: exit 1 | |
| - name: Stage ${{ matrix.bucket }} bucket | |
| run: | | |
| mkdir -p "$RUNNER_TEMP/docs-examples" | |
| cp -R "apps/authoring/public/docs-examples/${{ matrix.bucket }}" "$RUNNER_TEMP/docs-examples/${{ matrix.bucket }}" | |
| - name: Upload ${{ matrix.bucket }} bucket | |
| uses: actions/upload-artifact@v6 | |
| with: | |
| name: docs-examples-${{ matrix.bucket }} | |
| path: ${{ runner.temp }}/docs-examples | |
| retention-days: 7 | |
| publish: | |
| needs: [prepare, import] | |
| if: needs.import.result == 'success' | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: write | |
| pull-requests: write | |
| steps: | |
| - uses: actions/checkout@v5 | |
| - name: Download generated buckets | |
| uses: actions/download-artifact@v7 | |
| with: | |
| pattern: docs-examples-* | |
| merge-multiple: true | |
| path: runner/apps/authoring/public/docs-examples | |
| - name: Regenerate the docs bucket index | |
| working-directory: runner | |
| run: node --input-type=module -e 'import("./pipeline/import-docs.mjs").then(m => m.writeDocsBucketIndex())' | |
| - name: Regenerate the docs taxonomy the API worker bundles | |
| working-directory: runner | |
| run: node --input-type=module -e 'import("./pipeline/import-docs.mjs").then(m => m.writeDocsTaxonomy())' | |
| - name: Create or update generated-content pull request | |
| # SHA-pinned: this job holds contents+PR write permissions, so a retargeted | |
| # upstream tag must not be able to run new code here. | |
| uses: peter-evans/create-pull-request@5f6978faf089d4d20b00c7766989d076bb2fc7f1 # v8.1.1 | |
| with: | |
| branch: chore/docs-example-buckets | |
| base: ${{ github.ref_name }} | |
| commit-message: "chore(docs): update versioned docs examples" | |
| title: "chore(docs): update versioned docs examples" | |
| body: | | |
| Generated by the **Import versioned docs examples** workflow. | |
| The workflow imported the requested Handsontable documentation bucket(s) | |
| with concrete npm dependency versions. | |
| labels: automated | |
| reviewers: ${{ vars.AUTO_PR_REVIEWERS }} |