Automated Documentation Build #856
This file contains 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
# This workflow builds versioned copies of Prefect's documentation. | |
# It is triggered automatically by two events in PrefectHQ/prefect: | |
# | |
# 1. A new release is published | |
# 2. A new commit is pushed to main branch's docs directory | |
# | |
# It also can be triggered manually by a user with write access to | |
# the PrefectHQ/docs repository. In this case, the user must provide | |
# a version number as an input to the workflow. | |
name: Documentation Build | |
permissions: {} | |
# Limit concurrency by workflow/branch combination. | |
# | |
# For pull request builds, pushing additional changes to the | |
# branch will cancel prior in-progress and pending builds. | |
# | |
# For builds triggered on a branch push, additional changes | |
# will wait for prior builds to complete before starting. | |
# | |
# https://docs.github.com/en/actions/using-jobs/using-concurrency | |
concurrency: | |
group: ${{ github.workflow }}-${{ github.ref }} | |
cancel-in-progress: ${{ github.event_name == 'pull_request' }} | |
on: | |
repository_dispatch: | |
types: | |
- "Automated Documentation Build" | |
workflow_dispatch: | |
inputs: | |
version: | |
description: 'The release tag or branch to build and deploy | |
(e.g., "2.8.0", "2.8.0-docs-hotfix"). | |
Use `unreleased` to build directly from the 2.x branch of `PrefectHQ/prefect`.' | |
type: string | |
required: true | |
default: 'unreleased' | |
display_name: | |
description: 'The display name for the version (e.g., 2.8.0, 2.8.x, 2.7.x). | |
Leave blank to use the version number.' | |
type: string | |
required: false | |
default: '' | |
jobs: | |
build_docs_version: | |
runs-on: ubuntu-latest | |
permissions: | |
contents: write | |
pull-requests: write | |
steps: | |
- name: Checkout docs | |
uses: actions/checkout@v3 | |
with: | |
ref: main | |
fetch-depth: 0 | |
path: ./docs | |
- name: Set docs version | |
run: | | |
version="${{ github.event.client_payload.version }}" | |
if [[ -z "$version" ]]; then | |
version="${{ github.event.inputs.version }}" | |
fi | |
# if version is missing, exit with error | |
if [[ -z "$version" ]]; then | |
echo "Can't build versioned docs without a version!" | |
exit 1 | |
fi | |
# If the display name is blank, use the version number as | |
# the display name | |
display_name="${{ github.event.client_payload.display_name }}" | |
if [[ -z "$display_name" ]]; then | |
display_name="${{ github.event.inputs.display_name }}" | |
fi | |
if [[ -z "$display_name" ]]; then | |
display_name="$version" | |
fi | |
echo "version=$version" >> $GITHUB_ENV | |
echo "display_name=$display_name" >> $GITHUB_ENV | |
- name: Setup Python | |
uses: actions/setup-python@v4 | |
with: | |
python-version: 3.10.x | |
- name: Clone PrefectHQ/prefect | |
run: | | |
version="${{ env.version }}" | |
if [[ $version == "unreleased" ]]; then | |
git clone --branch 2.x --depth 1 https://github.com/PrefectHQ/prefect.git prefect_source | |
else | |
git clone --branch "$version" --depth 1 https://github.com/PrefectHQ/prefect.git prefect_source | |
fi | |
working-directory: ${{ github.workspace }}/ | |
- name: Install Prefect and dependencies | |
env: | |
SETUPTOOLS_SCM_PRETEND_VERSION_FOR_PREFECT_SHELL: "0.2.0" | |
run: | | |
pip install --upgrade pip | |
pip install src/integrations/* | |
pip install --upgrade --upgrade-strategy eager -e ".[dev]" | |
working-directory: ${{ github.workspace }}/prefect_source | |
- name: Install PrefectHQ/mkdocs-material-insiders | |
env: | |
MKDOCS_MATERIAL_INSIDERS_CONTENTS_RO: ${{ secrets.MKDOCS_MATERIAL_INSIDERS_CONTENTS_RO }} | |
run: | | |
pip install git+https://oauth2:[email protected]/PrefectHQ/mkdocs-material-insiders.git@1471e7595c14a067031600ec18e3cc8d7964e4aa | |
sudo apt-get install -y libcairo2 | |
- name: Install Python dependencies | |
run: | | |
pip install -r requirements.txt | |
working-directory: ${{ github.workspace }}/docs | |
- name: Set branch name | |
run: | | |
version="${{ env.version }}" | |
display_name="${{ env.display_name }}" | |
timestamp="$(date +%s)" | |
# create branch_display_name from display_name by replacing all | |
# characters disallowed in git branch names with hyphens | |
branch_display_name="$(echo "$display_name" | tr -c '[:alnum:]._' '-' | tr -s '-')" | |
echo "branch_name=update-docs-$branch_display_name-$timestamp" >> $GITHUB_ENV | |
echo "timestamp=$timestamp" >> $GITHUB_ENV | |
- name: Update docs | |
env: | |
AMPLITUDE_API_KEY: ${{ vars.AMPLITUDE_API_KEY }} | |
AMPLITUDE_URL: ${{ vars.AMPLITUDE_URL }} | |
run: | | |
git config user.name "GitHub Actions Bot" | |
git config user.email "[email protected]" | |
version="${{ env.version }}" | |
display_name="${{ env.display_name }}" | |
branch_name="${{ env.branch_name }}" | |
# remove the 'latest' alias so we can re-add it later | |
python ./utilities/remove-docs-alias.py --versions-file-path ./versions/versions.json | |
git add ./versions/versions.json | |
git commit -m "Update versions.json" | |
# create the version branch, otherwise mike will create a branch | |
# that has no common history with main | |
git checkout -b $branch_name | |
git checkout main | |
ln -s ../prefect_source/mkdocs.yml | |
ln -s ../prefect_source/mkdocs.insiders.yml | |
ln -s ../prefect_source/src ./src | |
ln -s ../prefect_source/docs ./docs | |
# append the contents of ./overrides/templates/outdated.html to | |
# ./docs/overrides/main.html | |
cat ./overrides/templates/outdated.html >> ./docs/overrides/main.html | |
# if the version is anything other than 'unreleased', append the contents | |
# of ./overrides/stylesheets/not-latest.css to ./docs/stylesheets/extra.css | |
if [[ $version != "latest" ]]; then | |
cat ./overrides/stylesheets/not-latest.css >> ./docs/stylesheets/extra.css | |
fi | |
# if there's a file named <version>.css in ./overrides/stylesheets, | |
# append it to ./docs/stylesheets/extra.css | |
if [[ -f ./overrides/stylesheets/$version.css ]]; then | |
cat ./overrides/stylesheets/$version.css >> ./docs/stylesheets/extra.css | |
fi | |
# add version string we can reference in Mkdocs templates | |
sed -i "/extra:/a\ version_string: $display_name" ./mkdocs.yml | |
# generate API docs | |
prefect dev build-docs | |
# If the release we're building docs for is the newest release, | |
# also build the 'latest' docs version. This ensures that the | |
# docs site defaults to showing users docs for the most recently released | |
# Prefect version. | |
newest_release=$(python utilities/get-newest-version.py --versions-file-path ./versions/versions.json --build-version "$version") | |
echo "Newest release is $newest_release. Version being built is $version." | |
if [[ "$newest_release" == "$version" ]]; then | |
echo "Updating 'latest' docs version with $version." | |
mike deploy --config-file ./mkdocs.insiders.yml --update-aliases --branch $branch_name --deploy-prefix=versions "$display_name" latest | |
# There is a bug in Mike where image url aliases don't get rewritten to latest. | |
# As of Sept 2023 Mike version 1.2. | |
# Known issue that should be fixed in Mike 2.0. | |
# https://github.com/jimporter/mike/issues/157 | |
# For now, copying the latest numbered version folder to "latest" | |
# so someone doesn't have to do it manually. | |
# This attempted fix doesn't work b/c the folder isn't there yet- PR needs accepted first. | |
# cp ./versions/"$version" ./versions/latest | |
else | |
echo "Updating previous docs version with $version." | |
mike deploy --config-file ./mkdocs.insiders.yml --update-aliases --branch $branch_name --deploy-prefix=versions "$display_name" | |
fi | |
# Save newest version check to GITHUB_ENV so we can use it later | |
is_newest_release=false | |
if [[ "$newest_release" == "$version" ]]; then | |
is_newest_release=true | |
fi | |
echo "is_newest_release=$is_newest_release" >> $GITHUB_ENV | |
# clean up | |
rm -rf site | |
unlink ./src | |
unlink ./docs | |
unlink ./mkdocs.yml | |
unlink ./mkdocs.insiders.yml | |
working-directory: ${{ github.workspace }}/docs | |
- name: Update Netlify TOML | |
env: | |
PREFECT_SOURCE: ${{ github.workspace }}/prefect_source | |
run: | | |
version="${{ env.version }}" | |
# If version is not 'unreleased', skip this step. We should only need to update | |
# the Netlify TOML when building docs for commits to Prefect's main branch. | |
if [[ $version != "unreleased" ]]; then | |
exit 0 | |
fi | |
git checkout $branch_name | |
echo "Merging Netlify TOML overrides and additions..." | |
python build-netlify-config.py \ | |
--input-config-path "$PREFECT_SOURCE/netlify.toml" \ | |
--overrides-path ./netlify.overrides.toml \ | |
--additions-path ./netlify.additions.toml \ | |
--output-config-path ./netlify_temp.toml | |
# If $GITHUB_WORKSPACE/docs/netlify.toml is missing, | |
# or exist but differs from ./netlify_temp.toml, | |
# move ./netlify_temp.toml to $GITHUB_WORKSPACE/docs/netlify.toml. | |
# otherwise, just remove ./netlify_temp.toml | |
echo "Checking if Netlify TOML needs to be updated..." | |
if [[ ! -f $GITHUB_WORKSPACE/docs/netlify.toml ]] || \ | |
[[ $(diff $GITHUB_WORKSPACE/docs/netlify.toml ./netlify_temp.toml) ]]; then | |
echo "Updating Netlify TOML..." | |
mv ./netlify_temp.toml $GITHUB_WORKSPACE/docs/netlify.toml | |
# commit the change | |
git add $GITHUB_WORKSPACE/docs/netlify.toml | |
git commit -m "Update Netlify TOML for version $version" | |
else | |
rm ./netlify_temp.toml | |
fi | |
working-directory: ${{ github.workspace }}/docs/overrides/netlify | |
- name: Update Netlify edge functions | |
env: | |
PREFECT_SOURCE: ${{ github.workspace }}/prefect_source | |
run: | | |
echo "Updating Netlify Edge Functions..." | |
rm -f ./netlify/edge-functions/* | |
cp $PREFECT_SOURCE/netlify/edge-functions/* ./netlify/edge-functions/ | |
git add ./netlify/edge-functions | |
if ! git diff --quiet --cached; then | |
git commit -m "Update Netlify edge functions" | |
fi | |
working-directory: ${{ github.workspace }}/docs | |
- name: Sort docs versions | |
run: | | |
git checkout $branch_name | |
python ./utilities/sort-docs-versions.py --versions-file-path ./versions/versions.json | |
git add ./versions/versions.json | |
git commit -m "Sort docs versions" | |
working-directory: ${{ github.workspace }}/docs | |
- name: Create Pull Request | |
env: | |
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
run: | | |
version="${{ env.version }}" | |
display_name="${{ env.display_name }}" | |
branch_name="${{ env.branch_name }}" | |
is_newest_release="${{ env.is_newest_release }}" | |
# set the PR title | |
if [[ $display_name == "unreleased" ]]; then | |
pull_request_title="Update unreleased documentation" | |
else | |
pull_request_title="Update documentation for $display_name" | |
fi | |
# Delete any existing pull requests that are open for this version | |
# by checking against pull_reqeust_title because the new PR will | |
# supersede the old one. | |
gh pr list --state open --json title --jq '.[] | select(.title == "$pull_request_title") | .number' | \ | |
xargs -I {} gh pr close {} | |
# push the branch to GitHub | |
git push origin $branch_name | |
# create the PR | |
gh pr create --base main --head $branch_name \ | |
--title "$pull_request_title" \ | |
--body "Automated documentation update for $display_name" \ | |
--label "documentation" \ | |
# auto-merge the PR if the build was triggered by a commit to Prefect's main | |
# repo. This is because we only want to auto-merge PRs automatically | |
# triggered docs builds. Manual builds should be reviewed by a human. | |
if [[ $GITHUB_EVENT_NAME == "repository_dispatch" ]]; then | |
# give the PR a few seconds to be created before trying to auto-merge it | |
sleep 10 | |
gh pr merge --squash $branch_name | |
fi | |
working-directory: ${{ github.workspace }}/docs |