Build Documentation workflow (plotly/plotly.py)
The Build Documentation workflow from plotly/plotly.py, explained and optimized by Latchkey.
CI health: C - fair
Point runs-on at Latchkey and get run de-duplication, job timeouts, self-healing for flaky steps, and up to 58% lower cost, applied automatically.
What it does
This is the Build Documentation workflow from the plotly/plotly.py repository, a real project running GitHub Actions. It is shown here with attribution under its MIT license.
Below, Latchkey shows a faster, safer version produced by its optimization engine.
The workflow
name: Build Documentation
on:
push:
branches:
- doc-prod
pull_request:
types: [opened, reopened, synchronize]
jobs:
build-doc:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Set up uv
uses: astral-sh/setup-uv@cec208311dfd045dd5311c1add060b2062131d57 # v8.0.0
with:
python-version: "3.9"
- name: Install system dependencies
run: sudo apt-get update && sudo apt-get install rename
- name: Install doc dependencies
run: |
cd doc
uv venv
source .venv/bin/activate
uv pip install -r requirements.txt
- name: Install plotly in editable mode
if: github.ref_name != 'doc-prod'
run: |
cd doc
source .venv/bin/activate
uv pip uninstall plotly
uv pip install -e ..
- name: Build HTML docs
env:
MAPBOX_TOKEN: ${{ secrets.MAPBOX_TOKEN }}
run: |
cd doc
source .venv/bin/activate
echo "${MAPBOX_TOKEN}" > python/.mapbox_token
make -kj8 || make -kj8
curl https://raw.githubusercontent.com/plotly/graphing-library-docs/master/front-matter-ci.py > front-matter-ci.py
curl https://raw.githubusercontent.com/plotly/graphing-library-docs/master/check-or-enforce-order.py > check-or-enforce-order.py
python front-matter-ci.py build/html
python check-or-enforce-order.py build/html
- name: Upload HTML docs artifact
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: doc-html
path: doc/build/html/
- name: Create GitHub App token
if: github.ref_name == 'doc-prod' && github.event_name == 'push'
uses: actions/create-github-app-token@1b10c78c7865c340bc4f6099eb2f838309f1e8c3 # v3.1.1
id: app-token
with:
app-id: ${{ vars.GRAPHING_LIBRARIES_CI_GHAPP_ID }}
private-key: ${{ secrets.GRAPHING_LIBRARIES_CI_GHAPP_PRIVATE_KEY }}
owner: ${{ github.repository_owner }}
repositories: plotly.py-docs,graphing-library-docs
- name: Checkout plotly.py-docs (built)
if: github.ref_name == 'doc-prod' && github.event_name == 'push'
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
repository: plotly/plotly.py-docs
ref: built
token: ${{ steps.app-token.outputs.token }}
path: plotly.py-docs-html
- name: Deploy HTML docs
if: github.ref_name == 'doc-prod' && github.event_name == 'push'
run: |
git config --global user.name plotlydocbot
git config --global user.email accounts@plot.ly
rm -rf plotly.py-docs-html/*
cp -r doc/build/html/* plotly.py-docs-html/
cd plotly.py-docs-html
git add .
git commit -m "build of https://github.com/plotly/plotly.py/commit/${{ github.sha }}" || echo "No changes to commit"
git push --force
- name: Checkout plotly.py-docs (built_ipynb)
if: github.ref_name == 'doc-prod' && github.event_name == 'push'
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
repository: plotly/plotly.py-docs
ref: built_ipynb
token: ${{ steps.app-token.outputs.token }}
path: plotly.py-docs-ipynb
- name: Deploy notebooks
if: github.ref_name == 'doc-prod' && github.event_name == 'push'
run: |
rm -rf plotly.py-docs-ipynb/*
cp -r doc/build/ipynb/* plotly.py-docs-ipynb/
cd plotly.py-docs-ipynb
git add .
git commit -m "build of https://github.com/plotly/plotly.py/commit/${{ github.sha }}" || echo "No changes to commit"
git push --force
- name: Checkout graphing-library-docs
if: github.ref_name == 'doc-prod' && github.event_name == 'push'
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
repository: plotly/graphing-library-docs
ref: master
token: ${{ steps.app-token.outputs.token }}
path: graphing-library-docs
- name: Trigger downstream doc build
if: github.ref_name == 'doc-prod' && github.event_name == 'push'
run: |
cd graphing-library-docs
git commit --allow-empty -m "deploying https://github.com/plotly/plotly.py/commit/${{ github.sha }}"
git push
- name: Build API docs
if: github.ref_name == 'doc-prod' && github.event_name == 'push'
run: |
cd doc
source .venv/bin/activate
# For the API doc, we need to use the local version of plotly
# since we are tweaking the source because of
# graph_objs/graph_objects
uv pip uninstall plotly
uv pip install -e ..
cd apidoc
make html
- name: Checkout plotly.py-docs (gh-pages)
if: github.ref_name == 'doc-prod' && github.event_name == 'push'
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
repository: plotly/plotly.py-docs
ref: gh-pages
token: ${{ steps.app-token.outputs.token }}
path: plotly.py-docs-api
- name: Deploy API docs
if: github.ref_name == 'doc-prod' && github.event_name == 'push'
run: |
rm -rf plotly.py-docs-api/*
cp -r doc/apidoc/_build/html/* plotly.py-docs-api/
touch plotly.py-docs-api/.nojekyll
cd plotly.py-docs-api
git add .
git commit -m "build of https://github.com/plotly/plotly.py/commit/${{ github.sha }}" || echo "No changes to commit"
git push --force
The same workflow, on Latchkey
Removes redundant runs and caps runaway jobs. Added and changed lines are highlighted.
name: Build Documentation on: push: branches: - doc-prod pull_request: types: [opened, reopened, synchronize] concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true jobs: build-doc: timeout-minutes: 30 runs-on: latchkey-small steps: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Set up uv uses: astral-sh/setup-uv@cec208311dfd045dd5311c1add060b2062131d57 # v8.0.0 with: python-version: "3.9" - name: Install system dependencies run: sudo apt-get update && sudo apt-get install rename - name: Install doc dependencies run: | cd doc uv venv source .venv/bin/activate uv pip install -r requirements.txt - name: Install plotly in editable mode if: github.ref_name != 'doc-prod' run: | cd doc source .venv/bin/activate uv pip uninstall plotly uv pip install -e .. - name: Build HTML docs env: MAPBOX_TOKEN: ${{ secrets.MAPBOX_TOKEN }} run: | cd doc source .venv/bin/activate echo "${MAPBOX_TOKEN}" > python/.mapbox_token make -kj8 || make -kj8 curl https://raw.githubusercontent.com/plotly/graphing-library-docs/master/front-matter-ci.py > front-matter-ci.py curl https://raw.githubusercontent.com/plotly/graphing-library-docs/master/check-or-enforce-order.py > check-or-enforce-order.py python front-matter-ci.py build/html python check-or-enforce-order.py build/html - name: Upload HTML docs artifact uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 with: name: doc-html path: doc/build/html/ - name: Create GitHub App token if: github.ref_name == 'doc-prod' && github.event_name == 'push' uses: actions/create-github-app-token@1b10c78c7865c340bc4f6099eb2f838309f1e8c3 # v3.1.1 id: app-token with: app-id: ${{ vars.GRAPHING_LIBRARIES_CI_GHAPP_ID }} private-key: ${{ secrets.GRAPHING_LIBRARIES_CI_GHAPP_PRIVATE_KEY }} owner: ${{ github.repository_owner }} repositories: plotly.py-docs,graphing-library-docs - name: Checkout plotly.py-docs (built) if: github.ref_name == 'doc-prod' && github.event_name == 'push' uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: repository: plotly/plotly.py-docs ref: built token: ${{ steps.app-token.outputs.token }} path: plotly.py-docs-html - name: Deploy HTML docs if: github.ref_name == 'doc-prod' && github.event_name == 'push' run: | git config --global user.name plotlydocbot git config --global user.email accounts@plot.ly rm -rf plotly.py-docs-html/* cp -r doc/build/html/* plotly.py-docs-html/ cd plotly.py-docs-html git add . git commit -m "build of https://github.com/plotly/plotly.py/commit/${{ github.sha }}" || echo "No changes to commit" git push --force - name: Checkout plotly.py-docs (built_ipynb) if: github.ref_name == 'doc-prod' && github.event_name == 'push' uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: repository: plotly/plotly.py-docs ref: built_ipynb token: ${{ steps.app-token.outputs.token }} path: plotly.py-docs-ipynb - name: Deploy notebooks if: github.ref_name == 'doc-prod' && github.event_name == 'push' run: | rm -rf plotly.py-docs-ipynb/* cp -r doc/build/ipynb/* plotly.py-docs-ipynb/ cd plotly.py-docs-ipynb git add . git commit -m "build of https://github.com/plotly/plotly.py/commit/${{ github.sha }}" || echo "No changes to commit" git push --force - name: Checkout graphing-library-docs if: github.ref_name == 'doc-prod' && github.event_name == 'push' uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: repository: plotly/graphing-library-docs ref: master token: ${{ steps.app-token.outputs.token }} path: graphing-library-docs - name: Trigger downstream doc build if: github.ref_name == 'doc-prod' && github.event_name == 'push' run: | cd graphing-library-docs git commit --allow-empty -m "deploying https://github.com/plotly/plotly.py/commit/${{ github.sha }}" git push - name: Build API docs if: github.ref_name == 'doc-prod' && github.event_name == 'push' run: | cd doc source .venv/bin/activate # For the API doc, we need to use the local version of plotly # since we are tweaking the source because of # graph_objs/graph_objects uv pip uninstall plotly uv pip install -e .. cd apidoc make html - name: Checkout plotly.py-docs (gh-pages) if: github.ref_name == 'doc-prod' && github.event_name == 'push' uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: repository: plotly/plotly.py-docs ref: gh-pages token: ${{ steps.app-token.outputs.token }} path: plotly.py-docs-api - name: Deploy API docs if: github.ref_name == 'doc-prod' && github.event_name == 'push' run: | rm -rf plotly.py-docs-api/* cp -r doc/apidoc/_build/html/* plotly.py-docs-api/ touch plotly.py-docs-api/.nojekyll cd plotly.py-docs-api git add . git commit -m "build of https://github.com/plotly/plotly.py/commit/${{ github.sha }}" || echo "No changes to commit" git push --force
What changed
- Run on Latchkey managed runners with one line (
runs-on), which apply the fixes below automatically and self-heal transient failures. This example useslatchkey-small; pick the runner size that fits the job. - Cancel superseded runs when a branch or PR gets a newer push.
- Add a job timeout so a hung step cannot burn hours of runner time.
What Latchkey heals here
This workflow has steps that commonly fail on transient issues (network, registries, flaky browsers). On Latchkey managed runners they are detected, retried, and self-healed instead of failing your build:
- Dependency installs
- Network fetches
This workflow runs 1 job per trigger. On Latchkey the same minutes cost up to 58% less than GitHub-hosted, with zero queue time.