name: Docs Deployment on: # Deploy after integration tests complete on master # zizmor: ignore[dangerous-triggers] - runs in base-branch context after a trusted upstream workflow; scoped to master workflow_run: workflows: ["Python-Integration"] types: [completed] branches: [master] # Also allow manual trigger and direct pushes to docs push: paths: - "docs/**" - "README.md" branches: - "master" workflow_dispatch: {} permissions: contents: read actions: read jobs: config: runs-on: ubuntu-26.04 outputs: has-secrets: ${{ steps.check.outputs.has-secrets }} steps: - name: "Check for secrets" id: check shell: bash run: | if [ -n "${SUPERSET_SITE_BUILD}" ]; then echo "has-secrets=1" >> "$GITHUB_OUTPUT" fi env: SUPERSET_SITE_BUILD: ${{ (secrets.SUPERSET_SITE_BUILD != '' && secrets.SUPERSET_SITE_BUILD != '') || '' }} # Master gets frequent, sometimes bursty pushes, and each one can trigger a # deploy attempt. Rather than let every superseded attempt get force-killed # by the build-deploy concurrency group below (which shows up as a # `cancelled` — i.e. red/failing-looking — check on that commit), have each # run check up front whether it's still building master's current tip and, # if not, skip cleanly. Deliberately outside the docs-deploy-asf-site # concurrency group so it runs immediately for every trigger without # blocking or being blocked by anything. check-freshness: runs-on: ubuntu-26.04 outputs: is-current: ${{ steps.check.outputs.is-current }} steps: # Sparse checkout: this job's only job is to be fast, so it fetches # nothing but the freshness-check script itself. - name: Checkout freshness-check script uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: persist-credentials: false sparse-checkout: | .github/workflows/scripts sparse-checkout-cone-mode: false - name: "Check whether this is still master's current commit" id: check env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} BUILD_SHA: ${{ github.event.workflow_run.head_sha || github.sha }} EVENT_NAME: ${{ github.event_name }} REPO: ${{ github.repository }} OUTPUT_NAME: is-current run: .github/workflows/scripts/check-docs-deploy-freshness.sh build-deploy: needs: [config, check-freshness] # Only the run for master's current tip proceeds; anything superseded # already skipped at check-freshness above instead of landing here. # For workflow_run triggers, only deploy when the triggering run originated # from this repository (not a fork), ensuring the checked-out code and any # local actions executed with deploy credentials are trusted. if: >- needs.config.outputs.has-secrets && needs.check-freshness.outputs.is-current == 'true' && (github.event_name != 'workflow_run' || github.event.workflow_run.head_repository.full_name == github.repository) name: Build & Deploy runs-on: ubuntu-26.04 # Serialize deploys: the action pushes to apache/superset-site without # rebasing, so concurrent runs race on the final push and the loser fails # with `! [rejected] asf-site -> asf-site (fetch first)`. Queue instead of # canceling: a run that already passed check-freshness can still be # sitting in the queue for a runner when a newer run starts and finishes # first. cancel-in-progress would let that stale, queued run kill the # newer run's in-progress deploy the moment it's finally scheduled, and # then skip itself at the re-check below — losing the deploy entirely. # Queuing means the stale run just waits its turn and then no-ops at the # re-check, so the fresher content that already deployed is never # clobbered or lost. The check-freshness gate above means it should be # rare for more than one run to reach this point, so the queue stays # short in practice. concurrency: group: docs-deploy-asf-site cancel-in-progress: false steps: - uses: Kesin11/actions-timeline@57fc93f20c6da7fbc14063c6d24a2a5627c799ad # v3.2.0 with: expand-composite-actions: true - name: "Checkout ${{ github.event.workflow_run.head_sha || github.sha }}" uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: ref: ${{ github.event.workflow_run.head_sha || github.sha }} persist-credentials: false submodules: recursive - name: Set up Node.js uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 with: node-version-file: "./docs/.nvmrc" - name: Setup Python uses: ./.github/actions/setup-backend/ - uses: actions/setup-java@b6effb05e454b25005698d916606bdc6ffcbf961 # v5.7.0 with: distribution: "zulu" java-version: "21" - name: Install Graphviz uses: awalsh128/cache-apt-pkgs-action@553a35bb8ebd9fcabcb1c9451aa4c98e1b4ca8a9 # v1.6.3 with: packages: graphviz version: 1.0 execute_install_scripts: true - name: Compute Entity Relationship diagram (ERD) env: SUPERSET_SECRET_KEY: not-a-secret run: | python scripts/erd/erd.py curl -L http://sourceforge.net/projects/plantuml/files/1.2023.7/plantuml.1.2023.7.jar/download > ~/plantuml.jar java -jar ~/plantuml.jar -v -tsvg -r -o "${{ github.workspace }}/docs/static/img/" "${{ github.workspace }}/scripts/erd/erd.puml" - name: yarn install working-directory: docs run: | yarn install --check-cache - name: Download database diagnostics (if triggered by integration tests) if: github.event_name == 'workflow_run' && github.event.workflow_run.conclusion == 'success' uses: dawidd6/action-download-artifact@b6e2e70617bc3265edd6dab6c906732b2f1ae151 # v21 continue-on-error: true with: workflow: superset-python-integrationtest.yml run_id: ${{ github.event.workflow_run.id }} name: database-diagnostics path: docs/src/data/ - name: Try to download latest diagnostics (for push/dispatch triggers) if: github.event_name != 'workflow_run' uses: dawidd6/action-download-artifact@b6e2e70617bc3265edd6dab6c906732b2f1ae151 # v21 continue-on-error: true with: workflow: superset-python-integrationtest.yml name: database-diagnostics path: docs/src/data/ branch: master search_artifacts: true if_no_artifact_found: warn - name: Use diagnostics artifact if available working-directory: docs run: | if [ -f "src/data/databases-diagnostics.json" ]; then echo "Using fresh diagnostics from integration tests" mv src/data/databases-diagnostics.json src/data/databases.json else echo "Using committed databases.json (no artifact found)" fi - name: yarn build working-directory: docs run: | yarn build # The check-freshness job above narrows the window but doesn't close it: an # older run can observe is-current=true, then sit through this build while a # newer run's own freshness check also passes and it deploys and finishes # first. If this (stale) run then wins entry into the concurrency group, it # would overwrite the newer content that already deployed. Re-check right # before the one step that actually mutates superset-site, so a stale run # skips deploying instead of clobbering a fresher one that already ran. - name: "Re-check freshness immediately before deploying" id: recheck-freshness if: github.event_name != 'workflow_dispatch' env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} BUILD_SHA: ${{ github.event.workflow_run.head_sha || github.sha }} REPO: ${{ github.repository }} OUTPUT_NAME: still-current run: .github/workflows/scripts/check-docs-deploy-freshness.sh - name: deploy docs if: github.event_name == 'workflow_dispatch' || steps.recheck-freshness.outputs.still-current == 'true' uses: ./.github/actions/github-action-push-to-another-repository env: API_TOKEN_GITHUB: ${{ secrets.SUPERSET_SITE_BUILD }} with: source-directory: "./docs/build" destination-github-username: "apache" destination-repository-name: "superset-site" target-branch: "asf-site" commit-message: "deploying docs: ${{ github.event.head_commit.message || 'triggered by integration tests' }} (apache/superset@${{ github.event.workflow_run.head_sha || github.sha }})" user-email: dev@superset.apache.org