+++ /dev/null
-FROM python:3.7
-
-RUN pip install httpx PyGithub "pydantic==1.5.1"
-
-COPY ./app /app
-
-CMD ["python", "/app/main.py"]
+++ /dev/null
-name: Watch docs previews in PRs
-description: Check PRs and trigger new docs deploys
-author: "Sebastián Ramírez <tiangolo@gmail.com>"
-inputs:
- token:
- description: 'Token for the repo. Can be passed in using {{ secrets.GITHUB_TOKEN }}'
- required: true
-runs:
- using: docker
- image: Dockerfile
+++ /dev/null
-import logging
-from datetime import datetime
-from pathlib import Path
-from typing import List, Optional
-
-import httpx
-from github import Github
-from github.NamedUser import NamedUser
-from pydantic import BaseModel, BaseSettings, SecretStr
-
-github_api = "https://api.github.com"
-netlify_api = "https://api.netlify.com"
-main_branch = "main"
-
-
-class Settings(BaseSettings):
- input_token: SecretStr
- github_repository: str
- github_event_path: Path
- github_event_name: Optional[str] = None
-
-
-class Artifact(BaseModel):
- id: int
- node_id: str
- name: str
- size_in_bytes: int
- url: str
- archive_download_url: str
- expired: bool
- created_at: datetime
- updated_at: datetime
-
-
-class ArtifactResponse(BaseModel):
- total_count: int
- artifacts: List[Artifact]
-
-
-def get_message(commit: str) -> str:
- return f"Docs preview for commit {commit} at"
-
-
-if __name__ == "__main__":
- logging.basicConfig(level=logging.INFO)
- settings = Settings()
- logging.info(f"Using config: {settings.json()}")
- g = Github(settings.input_token.get_secret_value())
- repo = g.get_repo(settings.github_repository)
- owner: NamedUser = repo.owner
- headers = {"Authorization": f"token {settings.input_token.get_secret_value()}"}
- prs = list(repo.get_pulls(state="open"))
- response = httpx.get(
- f"{github_api}/repos/{settings.github_repository}/actions/artifacts",
- headers=headers,
- )
- data = response.json()
- artifacts_response = ArtifactResponse.parse_obj(data)
- for pr in prs:
- logging.info("-----")
- logging.info(f"Processing PR #{pr.number}: {pr.title}")
- pr_comments = list(pr.get_issue_comments())
- pr_commits = list(pr.get_commits())
- last_commit = pr_commits[0]
- for pr_commit in pr_commits:
- if pr_commit.commit.author.date > last_commit.commit.author.date:
- last_commit = pr_commit
- commit = last_commit.commit.sha
- logging.info(f"Last commit: {commit}")
- message = get_message(commit)
- notified = False
- for pr_comment in pr_comments:
- if message in pr_comment.body:
- notified = True
- logging.info(f"Docs preview was notified: {notified}")
- if not notified:
- artifact_name = f"docs-zip-{commit}"
- use_artifact: Optional[Artifact] = None
- for artifact in artifacts_response.artifacts:
- if artifact.name == artifact_name:
- use_artifact = artifact
- break
- if not use_artifact:
- logging.info("Artifact not available")
- else:
- logging.info(f"Existing artifact: {use_artifact.name}")
- response = httpx.post(
- f"{github_api}/repos/{settings.github_repository}/actions/workflows/preview-docs.yml/dispatches",
- headers=headers,
- json={
- "ref": main_branch,
- "inputs": {
- "pr": f"{pr.number}",
- "name": artifact_name,
- "commit": commit,
- },
- },
- )
- logging.info(
- f"Trigger sent, response status: {response.status_code} - content: {response.content}"
- )
- logging.info("Finished")
types:
- opened
- synchronize
- workflow_dispatch:
- inputs:
- debug_enabled:
- description: 'Run the build with tmate debugging enabled (https://github.com/marketplace/actions/debugging-with-tmate)'
- required: false
- default: false
jobs:
+ changes:
+ runs-on: ubuntu-latest
+ # Required permissions
+ permissions:
+ pull-requests: read
+ # Set job outputs to values from filter step
+ outputs:
+ docs: ${{ steps.filter.outputs.docs }}
+ steps:
+ - uses: actions/checkout@v3
+ # For pull requests it's not necessary to checkout the code but for the main branch it is
+ - uses: dorny/paths-filter@v2
+ id: filter
+ with:
+ filters: |
+ docs:
+ - README.md
+ - docs/**
+ - docs_src/**
+ - pyproject.toml
+ - mkdocs.yml
+ - mkdocs.insiders.yml
+
build-docs:
+ needs:
+ - changes
+ if: ${{ needs.changes.outputs.docs == 'true' }}
runs-on: ubuntu-latest
steps:
- name: Dump GitHub context
uses: actions/setup-python@v4
with:
python-version: "3.11"
- # Allow debugging with tmate
- - name: Setup tmate session
- uses: mxschmitt/action-tmate@v3
- if: ${{ github.event_name == 'workflow_dispatch' && github.event.inputs.debug_enabled }}
- with:
- limit-access-to-actor: true
- uses: actions/cache@v3
id: cache
with:
path: ${{ env.pythonLocation }}
- key: ${{ runner.os }}-python-${{ env.pythonLocation }}-${{ hashFiles('pyproject.toml') }}-root-docs-v2
- - name: Install poetry
+ key: ${{ runner.os }}-python-docs-${{ env.pythonLocation }}-${{ hashFiles('pyproject.toml') }}-v01
+ - name: Install Poetry
if: steps.cache.outputs.cache-hit != 'true'
run: |
python -m pip install --upgrade pip
- name: Build Docs with Insiders
if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.fork == false
run: python -m poetry run mkdocs build --config-file mkdocs.insiders.yml
- - name: Zip docs
- run: python -m poetry run bash ./scripts/zip-docs.sh
- uses: actions/upload-artifact@v3
with:
- name: docs-zip
- path: ./site/docs.zip
- - name: Deploy to Netlify
- uses: nwtgck/actions-netlify@v2.0.0
+ name: docs-site
+ path: ./site/**
+
+ # https://github.com/marketplace/actions/alls-green#why
+ docs-all-green: # This job does nothing and is only used for the branch protection
+ if: always()
+ needs:
+ - build-docs
+ runs-on: ubuntu-latest
+ steps:
+ - name: Decide whether the needed jobs succeeded or failed
+ uses: re-actors/alls-green@release/v1
with:
- publish-dir: './site'
- production-branch: main
- github-token: ${{ secrets.GITHUB_TOKEN }}
- enable-commit-comment: false
- env:
- NETLIFY_AUTH_TOKEN: ${{ secrets.NETLIFY_AUTH_TOKEN }}
- NETLIFY_SITE_ID: ${{ secrets.NETLIFY_SITE_ID }}
+ jobs: ${{ toJSON(needs) }}
+ allowed-skips: build-docs
-name: Preview Docs
+name: Deploy Docs
on:
workflow_run:
workflows:
- Build Docs
- types:
+ types:
- completed
jobs:
- preview-docs:
- runs-on: ubuntu-20.04
+ deploy-docs:
+ runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@v3.1.0
+ - name: Dump GitHub context
+ env:
+ GITHUB_CONTEXT: ${{ toJson(github) }}
+ run: echo "$GITHUB_CONTEXT"
+ - uses: actions/checkout@v3
- name: Clean site
run: |
rm -rf ./site
mkdir ./site
- name: Download Artifact Docs
- uses: dawidd6/action-download-artifact@v2.24.2
+ id: download
+ uses: dawidd6/action-download-artifact@v2.27.0
with:
+ if_no_artifact_found: ignore
github_token: ${{ secrets.GITHUB_TOKEN }}
workflow: build-docs.yml
run_id: ${{ github.event.workflow_run.id }}
- name: docs-zip
+ name: docs-site
path: ./site/
- - name: Unzip docs
- run: |
- cd ./site
- unzip docs.zip
- rm -f docs.zip
- name: Deploy to Netlify
+ if: steps.download.outputs.found_artifact == 'true'
id: netlify
- uses: nwtgck/actions-netlify@v1.1.5
+ uses: nwtgck/actions-netlify@v2.0.0
with:
publish-dir: './site'
- production-deploy: false
+ production-deploy: ${{ github.event.workflow_run.head_repository.full_name == github.repository && github.event.workflow_run.head_branch == 'main' }}
github-token: ${{ secrets.GITHUB_TOKEN }}
enable-commit-comment: false
env:
NETLIFY_AUTH_TOKEN: ${{ secrets.NETLIFY_AUTH_TOKEN }}
NETLIFY_SITE_ID: ${{ secrets.NETLIFY_SITE_ID }}
- name: Comment Deploy
+ if: steps.netlify.outputs.deploy-url != ''
uses: ./.github/actions/comment-docs-preview-in-pr
with:
token: ${{ secrets.GITHUB_TOKEN }}