-
Notifications
You must be signed in to change notification settings - Fork 449
feat(ci,docs): build and publish a combined HTML and spec doc artifact #2638
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
27 commits
Select commit
Hold shift + click to select a range
f115982
feat(docs): add `docs-build` workflow for parallel doc generation
danceratopz 6610b5b
test(docs): temporarily widen workflow for E2E testing
danceratopz 5392605
feat(ci): add job summary to `check-should-publish`
danceratopz b75c846
chore: trigger CI
danceratopz 2292138
test(docs): add second test branch to allowlist for version selector …
danceratopz 42e4e90
chore(ci): remove test config; ready for merge
danceratopz da9c9b3
fix(ci): use target branch tip SHA in docs metadata and dispatch
danceratopz 636bbe5
chore(docs): remove inert `edit_uri`
danceratopz 8fce2e5
fix(ci): fail loud when docs allowlist is empty or unreadable
danceratopz ea6a989
chore(ci): move lint-md and changelog to docs-build.yaml
danceratopz 5613749
refactor(docs): nest rendered spec reference under /specs/reference/
danceratopz d346c9c
fix(docs): resolve relative links by adding explicit `.md` suffix
danceratopz 6208a3b
test(docs): temporarily widen workflow for E2E testing
danceratopz b10e61e
fix(docs): force reference nav links to open in a new tab
danceratopz 2d76409
chore(ci): remove test config; ready for merge
danceratopz 4eeeb7e
feat(ci): add `ref` and `publish` inputs to docs-build dispatch
danceratopz 3496b74
chore(ci): allowlist `devnets/bal/4` for docs publishing
danceratopz 3f37fa1
refactor(ci): drop `publish` dispatch input and `is_deploy` output
danceratopz 743c621
fix(ci): create `specs/reference/` before staging spec docs
danceratopz 9429469
chore(docs): namespace docs URL under `/docs/execution-specs/`
danceratopz 197daaf
chore(ci): drop unused `default:` from `docs-branches.yaml`
danceratopz 39d2800
fix(ci): use `GITHUB_SHA` directly on push events
danceratopz fce3ef5
docs: drop `gh-pages` mentions and retarget spec links
danceratopz cc7c065
test(docs): temporarily widen workflow for E2E testing
danceratopz a6ad4fc
chore(ci): remove test config; ready for merge
danceratopz b4c4f8d
refactor(ci): narrow `docs-build` `push` trigger to auto-publish set
danceratopz 7c9bf7f
chore(ci): add `mainnet` entry to docs publish allowlist
danceratopz File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,18 @@ | ||
| # Branches whose documentation is built and published to | ||
| # steel.ethereum.foundation/docs/execution-specs/ | ||
| # | ||
| # The `branches[]` list must stay in sync with steel-website's | ||
| # `docs-config.yml`; a branch that publishes here but isn't listed there | ||
| # is dispatched but dropped by the aggregator. | ||
| # | ||
| # Each entry defines: | ||
| # - path: The branch name (must match the Git branch exactly) | ||
| # - label: Human-readable label for the version switcher UI | ||
|
|
||
| branches: | ||
| - path: "mainnet" | ||
| label: "Mainnet (BPO2)" | ||
| - path: "forks/amsterdam" | ||
| label: "Amsterdam" | ||
| - path: "devnets/bal/4" | ||
| label: "bal-devnet-4" | ||
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,356 @@ | ||
| # Build Docs | ||
| # | ||
| # Dual-purpose workflow: | ||
| # - On PRs: Tests that MkDocs and spec docs build successfully | ||
| # - On push to allowlisted branches: Builds, uploads artifacts, and triggers | ||
| # the aggregator workflow in steel-website for deployment | ||
| # | ||
| # Site structure at steel.ethereum.foundation/docs/execution-specs/: | ||
| # /docs/execution-specs/ - Default branch docs (mirrored) | ||
| # /docs/execution-specs/specs/reference/ - Default branch spec reference (mirrored) | ||
| # /docs/execution-specs/<branch>/ - Branch-specific docs | ||
| # /docs/execution-specs/<branch>/specs/reference - Branch-specific spec reference (docc output) | ||
|
|
||
| name: Build Docs | ||
|
|
||
| on: | ||
| push: | ||
| # Branches that auto-publish on push. Other allowlisted branches in | ||
| # .github/configs/docs-branches.yaml publish only via workflow_dispatch | ||
| # (use the `ref:` input to publish a tag/SHA). | ||
| branches: | ||
| - mainnet | ||
| - forks/amsterdam | ||
| paths: &docs_paths | ||
| - "src/ethereum/**" | ||
| - "src/ethereum_spec_tools/docc.py" | ||
| - "src/ethereum_spec_tools/forks.py" | ||
| - "static/**" | ||
| - "docs/**" | ||
| - "packages/testing/**" | ||
| - "*.md" | ||
| - "mkdocs.yml" | ||
| - "uv.lock" | ||
| - "pyproject.toml" | ||
| - ".github/workflows/docs-build.yaml" | ||
| - ".github/configs/docs-branches.yaml" | ||
|
|
||
| pull_request: | ||
| paths: *docs_paths | ||
|
|
||
| workflow_dispatch: | ||
| inputs: | ||
| branch: | ||
| description: "Branch to publish under. Must be in the allowlist (see .github/configs/docs-branches.yaml)." | ||
| required: true | ||
| type: string | ||
| default: forks/amsterdam | ||
| ref: | ||
| description: "Ref to build: branch name, tag (e.g. v1.2.3), or commit SHA. Empty = tip of the branch above." | ||
| required: false | ||
| type: string | ||
| default: "" | ||
|
|
||
| concurrency: | ||
| group: docs-build-${{ github.ref }} | ||
| cancel-in-progress: true | ||
|
|
||
| permissions: | ||
| contents: read | ||
|
|
||
| jobs: | ||
| lint-md: | ||
| name: "Lint Markdown" | ||
| runs-on: ubuntu-latest | ||
| steps: | ||
| - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 | ||
| # TODO: Still on node20 — update when upstream releases a node22+ version | ||
| - uses: DavidAnson/markdownlint-cli2-action@07035fd053f7be764496c0f8d8f9f41f98305101 # v22.0.0 | ||
| with: | ||
| globs: | | ||
| docs/**/*.md | ||
| *.md | ||
|
|
||
| changelog: | ||
| name: "Validate Changelog Entries" | ||
| runs-on: ubuntu-latest | ||
| steps: | ||
| - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 | ||
| - uses: ./.github/actions/setup-uv | ||
| - name: Run changelog validation | ||
| run: just changelog | ||
|
|
||
| check-should-publish: | ||
| name: "Check Should Publish" | ||
| runs-on: ubuntu-latest | ||
| needs: [lint-md, changelog] | ||
| outputs: | ||
| should_publish: ${{ steps.check.outputs.should_publish }} | ||
| branch: ${{ steps.check.outputs.branch }} | ||
| branch_artifact_name: ${{ steps.check.outputs.branch_artifact_name }} | ||
| commit_sha: ${{ steps.check.outputs.commit_sha }} | ||
| steps: | ||
| - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 | ||
| with: | ||
| sparse-checkout: .github/configs/docs-branches.yaml | ||
| sparse-checkout-cone-mode: false | ||
|
|
||
| - name: Resolve publish configuration | ||
| id: check | ||
| env: | ||
| BRANCH_INPUT: ${{ github.event.inputs.branch || github.ref_name }} | ||
| REF_INPUT: ${{ github.event.inputs.ref }} | ||
| EVENT_NAME: ${{ github.event_name }} | ||
| GH_TOKEN: ${{ github.token }} | ||
| run: | | ||
| echo "branch=$BRANCH_INPUT" >> "$GITHUB_OUTPUT" | ||
|
|
||
| # Create artifact-safe name (replace / with -) | ||
| BRANCH_ARTIFACT_NAME="${BRANCH_INPUT//\//-}" | ||
| echo "branch_artifact_name=$BRANCH_ARTIFACT_NAME" >> "$GITHUB_OUTPUT" | ||
|
|
||
| # Extract branch paths from allowlist config | ||
| ALLOWLISTED_BRANCHES=$(yq '.branches[].path' .github/configs/docs-branches.yaml 2>/dev/null || echo "") | ||
|
|
||
| if [ -z "$ALLOWLISTED_BRANCHES" ]; then | ||
| echo "ERROR: Could not read allowlist from .github/configs/docs-branches.yaml" | ||
| exit 1 | ||
| fi | ||
|
|
||
| # Check if branch is in allowlist | ||
| if echo "$ALLOWLISTED_BRANCHES" | grep -qxF "$BRANCH_INPUT"; then | ||
| SHOULD_PUBLISH="true" | ||
| else | ||
| SHOULD_PUBLISH="false" | ||
| fi | ||
| echo "should_publish=$SHOULD_PUBLISH" >> "$GITHUB_OUTPUT" | ||
|
|
||
| # Resolve the concrete SHA we will build, so metadata.json and the | ||
| # aggregator dispatch payload match what the build jobs check out. | ||
| # | ||
| # On push, GITHUB_SHA is the pushed commit; using it avoids a race | ||
| # where another push lands between the event and a `gh api` lookup. | ||
| # On workflow_dispatch, the user may specify any branch/tag/SHA via | ||
| # the `ref` input (empty falls back to the branch tip), and | ||
| # github.sha points at whatever ref the dispatch was launched from | ||
| # (often the default branch), so we resolve via the API. | ||
| if [ "$EVENT_NAME" != "pull_request" ] && [ "$SHOULD_PUBLISH" = "true" ]; then | ||
| if [ "$EVENT_NAME" = "push" ]; then | ||
| COMMIT_SHA="$GITHUB_SHA" | ||
| else | ||
| RESOLVE_REF="${REF_INPUT:-$BRANCH_INPUT}" | ||
| COMMIT_SHA=$(gh api "repos/${GITHUB_REPOSITORY}/commits/${RESOLVE_REF}" --jq .sha 2>/dev/null || true) | ||
| if [ -z "$COMMIT_SHA" ]; then | ||
| echo "ERROR: could not resolve commit SHA for ref '${RESOLVE_REF}'" | ||
| exit 1 | ||
| fi | ||
| fi | ||
| echo "commit_sha=$COMMIT_SHA" >> "$GITHUB_OUTPUT" | ||
| fi | ||
|
|
||
| # Write job summary | ||
| { | ||
| echo "## Check Should Publish" | ||
| echo "" | ||
| echo "| Setting | Value |" | ||
| echo "|---------|-------|" | ||
| echo "| **Branch** | \`$BRANCH_INPUT\` |" | ||
| if [ -n "$REF_INPUT" ]; then | ||
| echo "| **Ref** | \`$REF_INPUT\` |" | ||
| fi | ||
| if [ -n "${COMMIT_SHA:-}" ]; then | ||
| echo "| **Resolved SHA** | \`${COMMIT_SHA:0:7}\` |" | ||
| fi | ||
| echo "| **Event** | \`$EVENT_NAME\` |" | ||
| echo "| **Allowlisted** | $SHOULD_PUBLISH |" | ||
| echo "" | ||
|
|
||
| if [ "$EVENT_NAME" = "pull_request" ]; then | ||
| echo "-> **Build only** -- pull request; artifacts are not published." | ||
| elif [ "$SHOULD_PUBLISH" = "true" ]; then | ||
| echo "-> **Will publish** at <https://steel.ethereum.foundation/docs/execution-specs/${BRANCH_INPUT}/>" | ||
| echo "" | ||
| echo "_Note: the URL only resolves if \`${BRANCH_INPUT}\` is also configured in steel-website's \`BRANCH_CONFIG\` (\`deploy.yml\`). If not, the aggregator will receive the dispatch but drop the artifact._" | ||
| else | ||
| echo "-> **Skipping publish** -- branch is not in the allowlist (\`.github/configs/docs-branches.yaml\`)." | ||
| echo "" | ||
| echo "Allowlisted branches:" | ||
| echo "$ALLOWLISTED_BRANCHES" | while read -r b; do | ||
| echo "- \`$b\`" | ||
| done | ||
| fi | ||
| } >> "$GITHUB_STEP_SUMMARY" | ||
|
|
||
| html-docs: | ||
| name: "Build HTML Docs" | ||
| runs-on: ubuntu-latest | ||
| needs: check-should-publish | ||
| # Always build for PRs (testing); only build for push if allowlisted | ||
| if: github.event_name == 'pull_request' || needs.check-should-publish.outputs.should_publish == 'true' | ||
|
|
||
| steps: | ||
| - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 | ||
| with: | ||
| ref: ${{ github.event_name == 'workflow_dispatch' && needs.check-should-publish.outputs.commit_sha || '' }} | ||
| fetch-depth: 0 | ||
| submodules: recursive | ||
|
|
||
| - uses: ./.github/actions/setup-uv | ||
|
|
||
| - name: Build MkDocs documentation | ||
| env: | ||
| BRANCH: ${{ needs.check-should-publish.outputs.branch }} | ||
| SHOULD_PUBLISH: ${{ needs.check-should-publish.outputs.should_publish }} | ||
| run: | | ||
| if [ "$SHOULD_PUBLISH" = "true" ]; then | ||
| export SITE_URL="https://steel.ethereum.foundation/docs/execution-specs/${BRANCH}/" | ||
| else | ||
| export SITE_URL="https://example.com/docs/${BRANCH}/" | ||
| fi | ||
|
|
||
| echo "Building MkDocs with SITE_URL=$SITE_URL" | ||
| just docs | ||
|
|
||
| - name: Upload HTML docs artifact | ||
| if: needs.check-should-publish.outputs.should_publish == 'true' | ||
| uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0 | ||
| with: | ||
| name: docs-html-${{ needs.check-should-publish.outputs.branch_artifact_name }} | ||
| path: .just/docs/site/ | ||
| retention-days: 1 | ||
| if-no-files-found: error | ||
|
|
||
| spec-docs: | ||
| name: "Build Spec Docs" | ||
| runs-on: ubuntu-latest | ||
| needs: check-should-publish | ||
| if: github.event_name == 'pull_request' || needs.check-should-publish.outputs.should_publish == 'true' | ||
|
|
||
| steps: | ||
| - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 | ||
| with: | ||
| ref: ${{ github.event_name == 'workflow_dispatch' && needs.check-should-publish.outputs.commit_sha || '' }} | ||
| fetch-depth: 0 | ||
| submodules: recursive | ||
|
|
||
| - uses: ./.github/actions/setup-uv | ||
|
|
||
| - name: Build spec documentation | ||
| run: just docs-spec | ||
| env: | ||
| DOCC_SKIP_DIFFS: ${{ case(github.event_name == 'push' && github.ref_name == github.event.repository.default_branch, '', '1') }} | ||
|
|
||
| - name: Upload spec docs artifact | ||
| if: needs.check-should-publish.outputs.should_publish == 'true' | ||
| uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0 | ||
| with: | ||
| name: docs-spec-${{ needs.check-should-publish.outputs.branch_artifact_name }} | ||
| path: .just/docs-spec/ | ||
| retention-days: 1 | ||
| if-no-files-found: error | ||
|
|
||
| combine: | ||
| name: "Combine and Upload" | ||
| runs-on: ubuntu-latest | ||
| needs: [check-should-publish, html-docs, spec-docs] | ||
| if: needs.check-should-publish.outputs.should_publish == 'true' | ||
|
|
||
| steps: | ||
| - name: Download HTML docs artifact | ||
| uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7.0.0 | ||
| with: | ||
| name: docs-html-${{ needs.check-should-publish.outputs.branch_artifact_name }} | ||
| path: html-docs/ | ||
|
|
||
| - name: Download spec docs artifact | ||
| uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7.0.0 | ||
| with: | ||
| name: docs-spec-${{ needs.check-should-publish.outputs.branch_artifact_name }} | ||
| path: spec-docs/ | ||
|
|
||
| - name: Stage combined artifact | ||
| env: | ||
| BRANCH: ${{ needs.check-should-publish.outputs.branch }} | ||
| COMMIT_SHA: ${{ needs.check-should-publish.outputs.commit_sha }} | ||
| run: | | ||
| mkdir -p "stage/${BRANCH}/specs/reference" | ||
|
|
||
| # HTML docs at root of branch directory | ||
| rsync -a html-docs/ "stage/${BRANCH}/" | ||
|
|
||
| # Spec reference (docc output) nested under specs/ to mirror nav hierarchy | ||
| rsync -a spec-docs/ "stage/${BRANCH}/specs/reference/" | ||
|
|
||
| # Build metadata | ||
| cat > "stage/${BRANCH}/metadata.json" <<EOF | ||
| { | ||
| "branch": "${BRANCH}", | ||
| "commit_sha": "${COMMIT_SHA}", | ||
| "commit_sha_short": "${COMMIT_SHA:0:7}", | ||
| "build_timestamp": "$(date -u +%Y-%m-%dT%H:%M:%SZ)", | ||
| "build_url": "${GITHUB_SERVER_URL}/${GITHUB_REPOSITORY}/actions/runs/${GITHUB_RUN_ID}" | ||
| } | ||
| EOF | ||
|
|
||
| touch "stage/.nojekyll" | ||
|
|
||
| - name: Validate staged output | ||
| env: | ||
| BRANCH: ${{ needs.check-should-publish.outputs.branch }} | ||
| run: | | ||
| for f in "stage/${BRANCH}/index.html" "stage/${BRANCH}/specs/reference/index.html" "stage/${BRANCH}/metadata.json"; do | ||
| if [ ! -f "$f" ]; then | ||
| echo "ERROR: Missing $f" | ||
| exit 1 | ||
| fi | ||
| done | ||
|
|
||
| echo "Validation passed" | ||
| echo "" | ||
| echo "=== Staged content summary ===" | ||
| du -sh "stage/${BRANCH}/" | ||
| du -sh "stage/${BRANCH}/specs/reference/" | ||
|
|
||
| - name: Upload combined docs artifact | ||
| uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0 | ||
| with: | ||
| name: docs-${{ needs.check-should-publish.outputs.branch_artifact_name }} | ||
| path: stage/ | ||
| retention-days: 90 | ||
| if-no-files-found: error | ||
|
|
||
| trigger-aggregator: | ||
| name: "Trigger Aggregator" | ||
| runs-on: ubuntu-latest | ||
| needs: [check-should-publish, combine] | ||
| if: needs.check-should-publish.outputs.should_publish == 'true' | ||
|
|
||
| steps: | ||
| - name: Trigger steel-website aggregator workflow | ||
| uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1 | ||
| env: | ||
| BRANCH: ${{ needs.check-should-publish.outputs.branch }} | ||
| SHA: ${{ needs.check-should-publish.outputs.commit_sha }} | ||
| RUN_ID: ${{ github.run_id }} | ||
| with: | ||
| github-token: ${{ secrets.STEEL_WEBSITE_DISPATCH_TOKEN }} | ||
| script: | | ||
| await github.rest.repos.createDispatchEvent({ | ||
| owner: 'ethereum', | ||
| repo: 'steel-website', | ||
| event_type: 'docs-artifact-ready', | ||
| client_payload: { | ||
| branch: process.env.BRANCH, | ||
| sha: process.env.SHA, | ||
| run_id: process.env.RUN_ID | ||
| } | ||
| }); | ||
|
|
||
| - name: Log trigger | ||
| env: | ||
| BRANCH: ${{ needs.check-should-publish.outputs.branch }} | ||
| run: | | ||
| echo "Triggered aggregator workflow in ethereum/steel-website" | ||
| echo " Branch: $BRANCH" | ||
| echo " SHA: ${{ github.sha }}" | ||
| echo " Run ID: ${{ github.run_id }}" |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.