Skip to content

Commit 96d340a

Browse files
Improve CI workflows for docs and publishing (#187)
* Improve CI workflows for docs and publishing * Enhance CI workflows: add preview deployment for PRs and adjust permissions * Ensure main branch checkout before committing changelog updates * Refactor preview metadata derivation in CI workflow for security * try docs preview (to be reverted) * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Refactor Python setup in CI workflow to use actions/setup-python for improved compatibility * test on docs to be deleted * added manual workflow dispatch for testing (to be reverted) * Revert "added manual workflow dispatch for testing (to be reverted)" This reverts commit 0ab6b38. * Revert "test on docs to be deleted" This reverts commit 15a5be3. --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
1 parent 907c2b6 commit 96d340a

File tree

3 files changed

+190
-37
lines changed

3 files changed

+190
-37
lines changed
Lines changed: 67 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,40 +1,89 @@
1-
name: Build and Deploy Documentation
1+
name: Docs — Build & Preview
2+
permissions:
3+
contents: read
24

35
on:
46
push:
5-
branches:
6-
- main
7+
branches: [ main ] # regular prod deploy
8+
paths:
9+
- 'mkdocs.yml'
10+
- 'docs/**'
11+
pull_request: # preview only when docs are touched
12+
branches: [ '**' ]
13+
paths:
14+
- 'mkdocs.yml'
15+
- 'docs/**'
716

817
jobs:
9-
build-and-deploy-docs:
18+
build:
1019
runs-on: ubuntu-latest
20+
permissions:
21+
contents: read
22+
actions: write
1123
steps:
1224
- uses: actions/checkout@v4
13-
with:
14-
fetch-depth: 0 # Fetch all history for .git-restore-mtime to work correctly
25+
with: { fetch-depth: 0 }
1526

16-
- name: Set up Python
17-
uses: actions/setup-python@v5
27+
- name: Set up Python 3.13
28+
uses: actions/setup-python@v6
1829
with:
19-
python-version: '3.x'
30+
python-version: "3.13"
31+
allow-prereleases: true
32+
cache: "pip"
2033

21-
- name: Install uv via GitHub Action
22-
uses: astral-sh/setup-uv@v6
34+
- uses: astral-sh/setup-uv@v7
2335

24-
- name: Install mesa-frames + docs dependencies
36+
- name: Install mesa-frames + docs deps
2537
run: |
2638
uv pip install --system .
2739
uv pip install --group docs --system
2840
29-
- name: Build MkDocs site (general documentation)
30-
run: mkdocs build --config-file mkdocs.yml --site-dir ./site
41+
- name: Convert jupytext .py notebooks to .ipynb
42+
run: |
43+
set -euxo pipefail
44+
# Convert any jupytext .py files to .ipynb without executing them.
45+
# Enable nullglob so the pattern expands to empty when there are no matches
46+
# and globstar so we recurse into subdirectories (e.g., user-guide/).
47+
shopt -s nullglob globstar || true
48+
files=(docs/general/**/*.py)
49+
if [ ${#files[@]} -eq 0 ]; then
50+
echo "No jupytext .py files found under docs/general"
51+
else
52+
for src in "${files[@]}"; do
53+
[ -e "$src" ] || continue
54+
dest="${src%.py}.ipynb"
55+
echo "Converting $src -> $dest"
56+
# jupytext will write the .ipynb alongside the source file
57+
uv run jupytext --to notebook "$src"
58+
done
59+
fi
60+
61+
- name: Build MkDocs site
62+
run: uv run mkdocs build --config-file mkdocs.yml --site-dir ./site
3163

32-
- name: Build Sphinx docs (API documentation)
33-
run: sphinx-build -b html docs/api site/api
64+
- name: Build Sphinx docs (API)
65+
run: uv run sphinx-build -b html docs/api site/api
3466

35-
- name: Deploy to GitHub Pages
67+
- name: Upload site artifact
68+
uses: actions/upload-artifact@v4
69+
with:
70+
name: site
71+
path: site
72+
73+
deploy-main:
74+
needs: build
75+
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
76+
runs-on: ubuntu-latest
77+
permissions:
78+
contents: write
79+
pages: write
80+
steps:
81+
- uses: actions/download-artifact@v4
82+
with: { name: site, path: site }
83+
- name: Deploy to GitHub Pages (main)
3684
uses: peaceiris/actions-gh-pages@v4
3785
with:
3886
github_token: ${{ secrets.GITHUB_TOKEN }}
87+
publish_branch: gh-pages
3988
publish_dir: ./site
40-
force_orphan: true
89+
force_orphan: true
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
# Deploys preview artifacts produced by the Docs — Build & Preview workflow for PRs.
2+
# The build workflow runs with read-only permissions on PRs (including forks) and
3+
# uploads the built site as an artifact. This workflow runs in the base repo with
4+
# the permissions needed to publish the preview to the gh-pages branch, but it
5+
# never checks out or executes untrusted PR code.
6+
name: Docs — Preview Deploy
7+
8+
on:
9+
workflow_run:
10+
workflows: ["Docs — Build & Preview"]
11+
types: [completed]
12+
13+
permissions:
14+
contents: write
15+
actions: read
16+
pages: write
17+
18+
jobs:
19+
deploy-preview:
20+
if: >
21+
github.event.workflow_run.event == 'pull_request' &&
22+
github.event.workflow_run.conclusion == 'success' &&
23+
(github.event.workflow_run.pull_requests || null)
24+
runs-on: ubuntu-latest
25+
steps:
26+
- name: Download built site artifact
27+
uses: actions/download-artifact@v4
28+
with:
29+
name: site
30+
path: site
31+
run-id: ${{ github.event.workflow_run.id }}
32+
github-token: ${{ secrets.GITHUB_TOKEN }}
33+
34+
- name: Derive preview metadata
35+
id: meta
36+
env:
37+
HEAD_SHA: ${{ github.event.workflow_run.head_sha }}
38+
HEAD_BRANCH: ${{ github.event.workflow_run.head_branch }}
39+
PR_NUMBER: ${{ github.event.workflow_run.pull_requests[0].number }}
40+
run: |
41+
set -euo pipefail
42+
short_sha="$(printf '%s' "$HEAD_SHA" | cut -c1-7)"
43+
{
44+
echo "short_sha=$short_sha"
45+
echo "head_branch=$HEAD_BRANCH"
46+
echo "pr_number=$PR_NUMBER"
47+
} >> "$GITHUB_OUTPUT"
48+
49+
- name: Deploy preview under subfolder
50+
uses: peaceiris/actions-gh-pages@v4
51+
with:
52+
github_token: ${{ secrets.GITHUB_TOKEN }}
53+
publish_branch: gh-pages
54+
publish_dir: ./site
55+
destination_dir: preview/${{ steps.meta.outputs.head_branch }}/${{ steps.meta.outputs.short_sha }}
56+
keep_files: true
57+
58+
- name: Print preview URL
59+
env:
60+
PREVIEW_OWNER: ${{ github.repository_owner }}
61+
PREVIEW_REPO: ${{ github.repository }}
62+
HEAD_BRANCH: ${{ steps.meta.outputs.head_branch }}
63+
SHORT_SHA: ${{ steps.meta.outputs.short_sha }}
64+
PR_NUMBER: ${{ steps.meta.outputs.pr_number }}
65+
run: |
66+
echo "Preview for PR #${PR_NUMBER}:"
67+
echo "https://${PREVIEW_OWNER}.github.io/$(basename "$PREVIEW_REPO")/preview/${HEAD_BRANCH}/${SHORT_SHA}/"

.github/workflows/publish.yml

Lines changed: 56 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -17,43 +17,80 @@ jobs:
1717
with:
1818
fetch-depth: 0
1919
token: ${{ secrets.VERSION_PUSH_TOKEN }}
20-
- name: Set up Python
21-
uses: actions/setup-python@v5
22-
with:
23-
python-version: '3.x'
24-
- name: Install dependencies
25-
run: |
26-
python -m pip install --upgrade pip
27-
pip install hatch
20+
- name: Setup uv
21+
uses: astral-sh/setup-uv@v3
2822
- name: Set release version
2923
run: |
3024
# Get the tag from the GitHub release
3125
TAG=${GITHUB_REF#refs/tags/}
3226
# Remove 'v' prefix if present
3327
VERSION=${TAG#v}
34-
hatch version $VERSION
28+
uvx hatch version $VERSION
3529
- name: Build package
36-
run: hatch build
30+
run: uvx hatch build
3731
- name: Run tests
38-
run: hatch run test:pytest
32+
run: uvx hatch run test:pytest
3933
- name: Publish package to PyPI
4034
uses: pypa/gh-action-pypi-publish@release/v1
4135
- name: Verify PyPI Release
4236
run: |
4337
# Verify PyPI release
4438
PACKAGE_NAME="mesa_frames"
45-
CURRENT_VERSION=$(hatch version)
46-
pip install $PACKAGE_NAME==$CURRENT_VERSION
39+
CURRENT_VERSION=$(uvx hatch version)
40+
uv pip install --system $PACKAGE_NAME==$CURRENT_VERSION
4741
python -c "import mesa_frames; print(mesa_frames.__version__)"
4842
- name: Update GitHub Release
4943
uses: softprops/action-gh-release@v1
5044
if: startsWith(github.ref, 'refs/tags/')
5145
with:
5246
files: |
5347
dist/*
48+
- name: Generate changelog from release notes
49+
id: notes
50+
uses: actions/github-script@v7
51+
with:
52+
script: |
53+
const fs = require('fs');
54+
const tag = (context.payload.release && context.payload.release.tag_name)
55+
? context.payload.release.tag_name
56+
: (process.env.GITHUB_REF || '').replace('refs/tags/', '');
57+
58+
const body = (context.payload.release && context.payload.release.body) ? context.payload.release.body : '';
59+
if (!body || body.trim().length === 0) {
60+
core.setFailed('Release body is empty. Ensure the GitHub Release is created with auto-generated notes configured by .github/release.yml or supply a body.');
61+
}
62+
63+
fs.writeFileSync('RELEASE_BODY.md', body, 'utf8');
64+
core.setOutput('tag', tag);
65+
- name: Prepend notes to CHANGELOG.md
66+
env:
67+
TAG: ${{ steps.notes.outputs.tag }}
68+
run: |
69+
VERSION_NO_V=${TAG#v}
70+
DATE_UTC=$(date -u +%Y-%m-%d)
71+
echo "## Version ${VERSION_NO_V} — ${DATE_UTC}" > RELEASE_HEADER.md
72+
echo "" >> RELEASE_HEADER.md
73+
if [ -f CHANGELOG.md ]; then
74+
cat RELEASE_HEADER.md RELEASE_BODY.md CHANGELOG.md > CHANGELOG.new
75+
else
76+
cat RELEASE_HEADER.md RELEASE_BODY.md > CHANGELOG.new
77+
fi
78+
mv CHANGELOG.new CHANGELOG.md
79+
- name: Commit and push CHANGELOG update
80+
env:
81+
TAG: ${{ steps.notes.outputs.tag }}
82+
run: |
83+
git config user.name github-actions
84+
git config user.email [email protected]
85+
# Ensure we are on the main branch before committing so the push lands on main.
86+
git checkout main
87+
git add CHANGELOG.md
88+
# Avoid CI cycles
89+
git commit -m "Changelog: add notes for ${TAG} [skip ci]" || echo "No changelog changes to commit"
90+
git push origin main || true
5491
- name: Create or recreate version branch
5592
run: |
56-
CURRENT_VERSION=$(hatch version)
93+
CURRENT_VERSION=$(uvx hatch version)
5794
BRANCH_NAME="v$CURRENT_VERSION"
5895
5996
git config user.name github-actions
@@ -72,15 +109,15 @@ jobs:
72109
- name: Update to Next Version
73110
run: |
74111
# Bump to next development version
75-
hatch version patch
76-
hatch version dev
112+
uvx hatch version patch
113+
uvx hatch version dev
77114
78115
# Get the new version
79-
NEW_VERSION=$(hatch version)
116+
NEW_VERSION=$(uvx hatch version)
80117
81118
# Commit and push the version bump
82119
git config user.name github-actions
83120
git config user.email [email protected]
84-
git add mesa_frames/__init__.py
121+
git add mesa_frames/__init__.py CHANGELOG.md
85122
git commit -m "Bump version to $NEW_VERSION [skip ci]"
86-
git push origin main
123+
git push origin main

0 commit comments

Comments
 (0)