Skip to content

Commit

Permalink
Merge branch 'main' into docs-updates
Browse files Browse the repository at this point in the history
  • Loading branch information
simonbowly committed Jul 21, 2024
2 parents 6c43a60 + d920978 commit c713b45
Show file tree
Hide file tree
Showing 7 changed files with 185 additions and 5 deletions.
41 changes: 41 additions & 0 deletions .github/workflows/examples-artifact.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
name: Notebook examples zip archive

on:
workflow_call:

permissions:
contents: read

jobs:
examples-artifact:

strategy:
matrix:
os: [ubuntu-latest]
python: ["3.11"]

runs-on: ${{ matrix.os }}

steps:
- uses: actions/checkout@v4
- name: Setup Python
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python }}
- name: Install tooling
run: |
python -m pip install --upgrade pip
- name: Install dependencies
run: |
python -m pip install jupyter-client~=8.6 jupytext~=1.16
- name: Convert notebooks
run: |
python -m jupytext --opt notebook_metadata_filter=-kernelspec \
--to ipynb docs/source/examples/*.md
- name: Archive notebook and data artifact
uses: actions/upload-artifact@v4
with:
name: notebook-examples
path: |
docs/source/examples/*.ipynb
docs/source/examples/data
32 changes: 32 additions & 0 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# Regular QA workflow for main branch

name: Test

on:
push:
branches:
- main

jobs:
code-quality:
uses: ./.github/workflows/code-quality.yml
unit-tests:
uses: ./.github/workflows/unit-tests.yml
needs: [code-quality]
notebook-examples:
uses: ./.github/workflows/notebook-examples.yml
needs: [code-quality]
examples-artifact:
uses: ./.github/workflows/examples-artifact.yml
needs: [code-quality]
trigger-rtd-build:
runs-on: ubuntu-latest
needs: [examples-artifact]
steps:
- name: Trigger RTD build
env:
RTD_HOOK_TOKEN: ${{ secrets.RTD_HOOK_TOKEN }}
run: |
curl -X POST -d "branches=main" -d "token=$RTD_HOOK_TOKEN" \
-d "default_branch=main" \
https://readthedocs.com/api/v2/webhook/gurobi-optimization-gurobipy-pandas/11030/
10 changes: 5 additions & 5 deletions .github/workflows/test.yml → .github/workflows/pr.yml
Original file line number Diff line number Diff line change
@@ -1,11 +1,8 @@
# Regular QA workflow (pull requests, main branch)
# QA workflow for pull requests (no RTD trigger)

name: Test
name: Pull request

on:
push:
branches:
- main
pull_request_target:
branches:
- main
Expand All @@ -19,3 +16,6 @@ jobs:
notebook-examples:
uses: ./.github/workflows/notebook-examples.yml
needs: [unit-tests]
examples-artifact:
uses: ./.github/workflows/examples-artifact.yml
needs: [notebook-examples]
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -136,3 +136,6 @@ docs/source/examples/*.ipynb

# Vim swap files
*.swp

# Downloaded zip artifact
docs/source/artifact/*.zip
3 changes: 3 additions & 0 deletions .readthedocs.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@ build:
os: "ubuntu-22.04"
tools:
python: "3.11"
jobs:
pre_build:
- python scripts/artifacts.py

sphinx:
fail_on_warning: true
Expand Down
11 changes: 11 additions & 0 deletions docs/source/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,3 +81,14 @@
# -- Options for EPUB output

epub_show_urls = "footnote"

# -- Note pointing to notebook downloads

nbsphinx_prolog = """
.. note::
This is example is available as a Jupyter notebook. Download it and all
necessary data files :download:`here </artifact/gurobipy-pandas-examples.zip>`.
"""
90 changes: 90 additions & 0 deletions scripts/artifacts.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
# Run as a pre-build step on RTD. Use a fine-grained personal access token
# with no extra permissions (for public repos).
#
# Local test:
#
# READTHEDOCS_GIT_COMMIT_HASH=$(git rev-parse HEAD) READTHEDOCS=True \
# GH_API_TOKEN=<TOKEN> python artifacts.py

import os
import pathlib
import sys

import requests

docs_source = pathlib.Path(__file__).parent.parent.joinpath("docs/source").resolve()
target = docs_source.joinpath("artifact/gurobipy-pandas-examples.zip")


def download_executed_notebooks(runs_url, gh_token, head_sha):
headers = {
"X-GitHub-Api-Version": "2022-11-28",
"Authorization": f"Bearer {gh_token}",
}

params = {"head_sha": head_sha}
response = requests.get(runs_url, headers=headers, params=params)
response.raise_for_status()
runs_data = response.json()

for run in runs_data["workflow_runs"]:
print("Run id={id} event={event} status={status} path={path}".format(**run))

if run["path"] != ".github/workflows/test.yml":
continue
if run["status"] != "completed":
continue
if run["conclusion"] != "success":
continue

artifacts_url = run["artifacts_url"]
response = requests.get(artifacts_url, headers=headers)
response.raise_for_status()
artifacts_data = response.json()

for artifact in artifacts_data["artifacts"]:
print("Artifact id={id} name={name}".format(**artifact))

if artifact["name"] != "notebook-examples":
continue

download_url = artifact["archive_download_url"]
response = requests.get(download_url, headers=headers)
response.raise_for_status()

os.makedirs(target.parent, exist_ok=True)
if target.exists():
target.unlink()
with target.open("wb") as outfile:
outfile.write(response.content)

print(f"Downloaded {target}")
return True

return False


if not os.environ.get("GH_API_TOKEN"):
# Pull requests run in this configuration
print("No API token, can't fetch artifacts. Continuing build with dummy file.")
os.makedirs(target.parent, exist_ok=True)
with target.open("wb") as outfile:
outfile.write(b"")
sys.exit(0)

success = download_executed_notebooks(
runs_url="https://api.github.com/repos/Gurobi/gurobipy-pandas/actions/runs",
gh_token=os.environ["GH_API_TOKEN"],
head_sha=os.environ["READTHEDOCS_GIT_COMMIT_HASH"],
)

if success:
# Success, RTD build can continue
print("Artifact retrieval succeeded.")
sys.exit(0)
else:
# Cancels the RTD build (rely on a later trigger to rebuild)
print("Aritfact not found. Cancelling build.")
sys.exit(183)

# Any exception would be a build failure

0 comments on commit c713b45

Please sign in to comment.