Skip to content

Commit ef0a354

Browse files
jenstroegerlecram
andauthored
feat: add workflow to publish code documentation to the Github Wiki upon package releases (#396)
Co-authored-by: Marcel Rodrigues <marcelgmr@gmail.com>
1 parent e4b27a9 commit ef0a354

6 files changed

Lines changed: 133 additions & 8 deletions

File tree

.github/workflows/_build.yaml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,8 +110,9 @@ jobs:
110110
REQUIREMENTS_PATH=$(find dist/ -type f -name "*-requirements.txt")
111111
SBOM_PATH=$(find dist/ -type f -name "*-sbom.json")
112112
HTML_DOCS_PATH=$(find dist/ -type f -name "*-docs-html.zip")
113+
MARKDOWN_DOCS_PATH=$(find dist/ -type f -name "*-docs-md.zip")
113114
BUILD_EPOCH_PATH=$(find dist/ -type f -name "*-build-epoch.txt")
114-
DIGEST=$(sha256sum "$TARBALL_PATH" "$WHEEL_PATH" "$REQUIREMENTS_PATH" "$SBOM_PATH" "$HTML_DOCS_PATH" "$BUILD_EPOCH_PATH" | base64 -w0)
115+
DIGEST=$(sha256sum "$TARBALL_PATH" "$WHEEL_PATH" "$REQUIREMENTS_PATH" "$SBOM_PATH" "$HTML_DOCS_PATH" "$MARKDOWN_DOCS_PATH" "$BUILD_EPOCH_PATH" | base64 -w0)
115116
echo "Digest of artifacts is $DIGEST."
116117
echo "artifacts-sha256=$DIGEST" >> "$GITHUB_OUTPUT"
117118
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
# This reusable workflow publishes Markdown docs to Github Wiki. Some manual
2+
# setup is required before using it: enable Wiki in repository and create at
3+
# least one page.
4+
5+
name: Publish Github Wiki documentation
6+
on:
7+
workflow_call:
8+
inputs:
9+
release_tag:
10+
required: true
11+
type: string
12+
release_url:
13+
required: true
14+
type: string
15+
artifact_name:
16+
required: true
17+
type: string
18+
git_user_name:
19+
required: true
20+
type: string
21+
git_user_email:
22+
required: true
23+
type: string
24+
secrets:
25+
REPO_ACCESS_TOKEN:
26+
required: true
27+
28+
permissions:
29+
contents: read
30+
31+
jobs:
32+
publish-wiki:
33+
name: Publish Github Wiki
34+
if: github.repository.has_wiki == true
35+
runs-on: ubuntu-latest
36+
steps:
37+
38+
- name: Harden Runner
39+
uses: step-security/harden-runner@2e205a28d0e1da00c5f53b161f4067b052c61f34 # v1.5.0
40+
with:
41+
egress-policy: audit # TODO: change to 'egress-policy: block' after couple of runs
42+
43+
# Check out the repository's Wiki repo into the wiki/ folder. The token is required
44+
# only for private repositories.
45+
- name: Check out repository
46+
uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 # v3.1.0
47+
with:
48+
token: ${{ secrets.REPO_ACCESS_TOKEN }}
49+
repository: ${{ format('{0}.wiki', github.repository) }}
50+
path: wiki
51+
52+
# Download the build artifacts attached to this workflow run.
53+
- name: Download artifact
54+
uses: actions/download-artifact@9782bd6a9848b53b110e712e20e42d89988822b7 # v3.0.1
55+
with:
56+
name: ${{ inputs.artifact_name }}
57+
path: dist
58+
59+
# Unpack the Markdown docs into the Wiki repository. Delete existing files first
60+
# to ensure that no stale files stay behind.
61+
- name: Copy Markdown documentation
62+
run: |
63+
mkdir docs/
64+
unzip -d docs/ "$(ls dist/*-docs-md.zip)"
65+
rm --recursive --force wiki/*
66+
cp --recursive --verbose --target-directory wiki/ docs/markdown/*
67+
68+
# If there was any change to the Wiki then push the update.
69+
- name: Push to Wiki
70+
run: |
71+
cd wiki/
72+
if [ -n "$(git status --porcelain)" ]; then
73+
git add .
74+
git config --global user.name "$USER_NAME"
75+
git config --global user.email "$USER_EMAIL"
76+
git commit --message "$WIKI_COMMIT_MESSAGE"
77+
git push
78+
fi
79+
env:
80+
USER_NAME: ${{ inputs.git_user_name }}
81+
USER_EMAIL: ${{ inputs.git_user_email }}
82+
WIKI_COMMIT_MESSAGE: |
83+
docs: update for ${{ inputs.release_tag }}
84+
85+
Link: ${{ inputs.release_url }}

.github/workflows/release.yaml

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ on:
1010
permissions:
1111
contents: read
1212
env:
13+
# Duplicate these values for the `wiki` job below!
1314
ARTIFACT_NAME: artifact-ubuntu-latest-python-3.10
1415
# This is the username and email for the user who commits and pushes the release
1516
# commit. In an organisation that should be a dedicated devops account.
@@ -226,3 +227,24 @@ jobs:
226227
release_url: ${{ needs.release.outputs.release-url }}
227228
secrets:
228229
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}
230+
231+
# Publish the generated Markdown documentation to the repository's Wiki.
232+
# Uncomment the `if` to disable generating Wiki documentation.
233+
wiki:
234+
# if: ${{ false }}
235+
needs: [release]
236+
name: Publish Github Wiki documentation
237+
uses: ./.github/workflows/_wiki-documentation.yaml
238+
permissions:
239+
contents: read
240+
with:
241+
release_tag: ${{ needs.release.outputs.release-tag }}
242+
release_url: ${{ needs.release.outputs.release-url }}
243+
# Github disallows passing environment variables as arguments to a reusable
244+
# workflow, so we have to duplicate these values here. Related discussion
245+
# here: https://github.com/actions/toolkit/issues/931
246+
artifact_name: artifact-ubuntu-latest-python-3.10
247+
git_user_name: jenstroeger
248+
git_user_email: jenstroeger@users.noreply.github.com
249+
secrets:
250+
REPO_ACCESS_TOKEN: ${{ secrets.REPO_ACCESS_TOKEN }}

Makefile

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -173,21 +173,34 @@ test:
173173
# When building these artifacts, we need the environment variable SOURCE_DATE_EPOCH
174174
# set to the build date/epoch. For more details, see: https://flit.pypa.io/en/latest/reproducible.html
175175
.PHONY: dist
176-
dist: dist/$(PACKAGE_NAME)-$(PACKAGE_VERSION)-py3-none-any.whl dist/$(PACKAGE_NAME)-$(PACKAGE_VERSION).tar.gz dist/$(PACKAGE_NAME)-$(PACKAGE_VERSION)-docs-html.zip dist/$(PACKAGE_NAME)-$(PACKAGE_VERSION)-build-epoch.txt
176+
dist: dist/$(PACKAGE_NAME)-$(PACKAGE_VERSION)-py3-none-any.whl dist/$(PACKAGE_NAME)-$(PACKAGE_VERSION).tar.gz dist/$(PACKAGE_NAME)-$(PACKAGE_VERSION)-docs-html.zip dist/$(PACKAGE_NAME)-$(PACKAGE_VERSION)-docs-md.zip dist/$(PACKAGE_NAME)-$(PACKAGE_VERSION)-build-epoch.txt
177177
dist/$(PACKAGE_NAME)-$(PACKAGE_VERSION)-py3-none-any.whl: check test
178178
flit build --setup-py --format wheel
179179
dist/$(PACKAGE_NAME)-$(PACKAGE_VERSION).tar.gz: check test
180180
flit build --setup-py --format sdist
181-
dist/$(PACKAGE_NAME)-$(PACKAGE_VERSION)-docs-html.zip: docs
182-
python -m zipfile -c dist/$(PACKAGE_NAME)-$(PACKAGE_VERSION)-docs-html.zip docs/_build/html
181+
dist/$(PACKAGE_NAME)-$(PACKAGE_VERSION)-docs-html.zip: docs-html
182+
python -m zipfile -c dist/$(PACKAGE_NAME)-$(PACKAGE_VERSION)-docs-html.zip docs/_build/html/
183+
dist/$(PACKAGE_NAME)-$(PACKAGE_VERSION)-docs-md.zip: docs-md
184+
python -m zipfile -c dist/$(PACKAGE_NAME)-$(PACKAGE_VERSION)-docs-md.zip docs/_build/markdown/
183185
dist/$(PACKAGE_NAME)-$(PACKAGE_VERSION)-build-epoch.txt:
184186
echo $(SOURCE_DATE_EPOCH) > dist/$(PACKAGE_NAME)-$(PACKAGE_VERSION)-build-epoch.txt
185187

186-
# Build the HTML documentation from the package's source.
187-
.PHONY: docs
188-
docs: docs/_build/html/index.html
188+
# Build the HTML and Markdown documentation from the package's source.
189+
.PHONY: docs docs-html docs-md
190+
docs: docs-html docs-md
191+
docs-html: docs/_build/html/index.html
189192
docs/_build/html/index.html: check test
193+
if [ ! -d docs/source/_static ]; then \
194+
mkdir docs/source/_static/; \
195+
fi
190196
$(MAKE) -C docs/ html
197+
docs-md: docs/_build/markdown/Home.md
198+
docs/_build/markdown/Home.md: check test
199+
if [ ! -d docs/source/_static ]; then \
200+
mkdir docs/source/_static/; \
201+
fi
202+
$(MAKE) -C docs/ markdown
203+
mv docs/_build/markdown/index.md docs/_build/markdown/Home.md
191204

192205
# Prune the packages currently installed in the virtual environment down to the required
193206
# packages only. Pruning works in a roundabout way, where we first generate the wheels for

README.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ Comprehensive unit testing is enabled using [pytest](https://pytest.org/) combin
4343

4444
### Documentation
4545

46-
Documentation is important, and [Sphinx](https://www.sphinx-doc.org/en/master/) is set up already to produce standard documentation for the package, assuming that code contains [docstrings with reStructuredText](https://www.python.org/dev/peps/pep-0287/) (see [below](#generating-documentation)).
46+
Documentation is important, and [Sphinx](https://www.sphinx-doc.org/en/master/) is already set up to produce standard documentation in HTML and Markdown formats for the package, assuming that code contains [docstrings with reStructuredText](https://www.python.org/dev/peps/pep-0287/); the generated Markdown documentation can also optionally be pushed to the repository’s Github Wiki (see [below](#generating-documentation)).
4747

4848
### Versioning and publishing
4949

@@ -93,6 +93,7 @@ If you’d like to start your own Python project from scratch, you can either co
9393
- one PAT with `repo` scope (including _all_ of the `repo` permissions) for the secret named `REPO_ACCESS_TOKEN`; this secret is used by the [Release Action](https://github.com/jenstroeger/python-package-template/blob/main/.github/workflows/release.yaml) to push the release commit and attach assets to the generated [Github release](https://github.com/jenstroeger/python-package-template/releases).
9494
- one PAT with `public_repo`, `read:discussion`, `read:org`, and `read:repo_hook` scopes ([detailed docs](https://github.com/ossf/scorecard-action#authentication-with-pat)) for the secret named `SCORECARD_READ_TOKEN`; this secret is used by the [Scorecard Action](https://github.com/jenstroeger/python-package-template/blob/main/.github/workflows/scorecards-analysis.yaml) to analyze the code and add its results to your repository.
9595
- one PAT with `repo` scope for the secret named `DEPENDABOT_AUTOMERGE_TOKEN`; this secret is used by the [Dependabot Automerge Action](https://github.com/jenstroeger/python-package-template/blob/main/.github/workflows/dependabot-automerge.yaml) to comment on Dependabot PRs.
96+
- Create a Wiki and a first empty Wiki page for your new repository. Using the [Wiki Documentation](https://github.com/jenstroeger/python-package-template/blob/main/.github/workflows/_wiki-documentation.yaml) Action the repository’s Wiki will be automatically updated as part of publishing a new release.
9697

9798
To develop your new package, first create a [virtual environment](https://docs.python.org/3/tutorial/venv.html) by either using the [Makefile](https://www.gnu.org/software/make/manual/make.html#toc-An-Introduction-to-Makefiles):
9899

@@ -210,6 +211,8 @@ This example generates documentation in HTML, which can then be found here:
210211
open docs/_build/html/index.html
211212
```
212213

214+
In addition to the default HTML, Sphinx also generates Markdown documentation compatible with [Github Wiki](https://docs.github.com/en/communities/documenting-your-project-with-wikis), and the [Wiki Documentation](https://github.com/jenstroeger/python-package-template/blob/main/.github/workflows/_wiki-documentation.yaml) Action automatically updates the project repository’s Wiki.
215+
213216
## Versioning, publishing and changelog
214217

215218
To enable automation for [semantic versioning](https://semver.org/), package publishing, and changelog generation it is important to use meaningful [conventional commit messages](https://www.conventionalcommits.org/)! This package template already has a built-in semantic release support enabled which is set up to take care of all three of these aspects — every time changes are merged into the `main` branch.

pyproject.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ dev = [
5050
]
5151
docs = [
5252
"sphinx >=5.1.1,<6.0.0",
53+
"sphinxnotes-markdown-builder >=0.5.6,<1.0.0",
5354
]
5455
hooks = [
5556
"pre-commit >=2.18.0,<2.22.0",

0 commit comments

Comments
 (0)