diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a923c00..c693c28 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -10,6 +10,8 @@ on: permissions: contents: read actions: read + pages: write + id-token: write env: # Improve pip performance @@ -158,6 +160,39 @@ jobs: path: docs/api/ retention-days: 30 + publish-docs: + name: Publish Documentation + runs-on: ubuntu-latest + needs: [quality, test] + # Only run when a PR is merged to main (push event), not on PRs + if: github.event_name == 'push' && github.ref == 'refs/heads/main' + permissions: + contents: write + + steps: + - name: Checkout code + uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.1 + + - name: Install uv + uses: astral-sh/setup-uv@cdfb2ee6dde255817c739680168ad81e184c4bfb # v4.0.0 + with: + enable-cache: true + cache-dependency-glob: "uv.lock" + + - name: Set up Python 3.13 + run: uv python install 3.13 + + - name: Install dependencies + run: uv sync --locked --all-extras --dev + + - name: Build and publish documentation + run: uv run task doc-publish + env: + GIT_AUTHOR_NAME: github-actions[bot] + GIT_AUTHOR_EMAIL: github-actions[bot]@users.noreply.github.com + GIT_COMMITTER_NAME: github-actions[bot] + GIT_COMMITTER_EMAIL: github-actions[bot]@users.noreply.github.com + # Security summary job security-summary: name: Security Summary diff --git a/Dockerfile b/Dockerfile index 6917616..26a4260 100644 --- a/Dockerfile +++ b/Dockerfile @@ -46,6 +46,6 @@ CMD ["python", "-m", "python_package_template.python_module_template"] # Labels LABEL maintainer="eol" -LABEL version="2.0.20260411" -LABEL description="Python project template - simplified Docker setup" +LABEL version="3.0.20260414" +LABEL description="Python template with some awesome tools to quickstart any Python project" LABEL org.opencontainers.image.source="https://github.com/nullhack/python-project-template" \ No newline at end of file diff --git a/docs/features/in-progress/auto-publish-docs.md b/docs/features/in-progress/auto-publish-docs.md new file mode 100644 index 0000000..34b4ca1 --- /dev/null +++ b/docs/features/in-progress/auto-publish-docs.md @@ -0,0 +1,43 @@ +# Feature: Auto-Publish Documentation on Merge to Main + +## User Stories +- As a maintainer, I want documentation to be automatically built and published to GitHub Pages every time a PR is merged to main, so that the published docs are always in sync with the latest code. + +## Acceptance Criteria + +- `e9b6be8c-c786-4113-9920-f098a954869d`: Docs publish job only runs on push to main. + Given: A workflow event is triggered + When: The event is a pull_request (not a merge to main) + Then: The docs publish job is skipped + Test strategy: integration + +- `75619a7d-7eb8-45ac-901c-b86486c30690`: Docs are built before publishing. + Given: A commit is merged to main + When: The publish job runs + Then: `task doc-build` runs successfully and produces output in `docs/api/` and `docs/coverage/` + Test strategy: integration + +- `23cf4a4e-3960-458d-994d-efea5d854895`: Docs are published to GitHub Pages. + Given: The doc-build step succeeded + When: The publish step runs + Then: `ghp-import` (or equivalent) deploys the `docs/` directory to the `gh-pages` branch + Test strategy: integration + +- `c580dcb9-00c7-4124-9762-70ff1192bd09`: Publish job runs only after quality and tests pass. + Given: The quality or test job fails + When: The CI workflow runs on main + Then: The publish job does not execute + Test strategy: integration + +- `c942990a-a69c-473e-a820-8ce51e337262`: Workflow has least-privilege permissions for Pages deployment. + Given: The publish job needs to write to GitHub Pages + When: The job is defined + Then: It has `contents: write` (or `pages: write` + `id-token: write`) and no broader permissions + Test strategy: integration + +## Notes +- GitHub Pages must be configured on the repo (source: `gh-pages` branch or GitHub Actions deployment) +- The existing `task doc-publish` already runs `ghp-import -n -p -f docs` — reuse it or inline the equivalent steps +- Out of scope: publishing on tags/releases (covered by git-release skill), PR preview deployments +- Out of scope: changing the docs toolchain (pdoc stays) +- Priority: Must diff --git a/pyproject.toml b/pyproject.toml index 25b9f05..07cb87c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,23 +1,23 @@ [project] -name = "test-project" +name = "python-project-template" version = "3.0.20260414" -description = "A test project" +description = "Python template with some awesome tools to quickstart any Python project" readme = "README.md" requires-python = ">=3.13" license = { file = "LICENSE" } authors = [ - { name = "Test Author", email = "testuser@users.noreply.github.com" } + { name = "eol", email = "nullhack@users.noreply.github.com" } ] maintainers = [ - { name = "Test Author", email = "testuser@users.noreply.github.com" } + { name = "eol", email = "nullhack@users.noreply.github.com" } ] dependencies = [ "fire>=0.7.1", ] [project.urls] -Repository = "https://github.com/testuser/test-project" -Documentation = "https://github.com/testuser/test-project/tree/main/docs/api/" +Repository = "https://github.com/nullhack/python-project-template" +Documentation = "https://github.com/nullhack/python-project-template/tree/main/docs/api/" [project.optional-dependencies] dev = [ diff --git a/uv.lock b/uv.lock index ec8e794..e6e3da4 100644 --- a/uv.lock +++ b/uv.lock @@ -720,6 +720,52 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/ec/57/56b9bcc3c9c6a792fcbaf139543cee77261f3651ca9da0c93f5c1221264b/python_dateutil-2.9.0.post0-py2.py3-none-any.whl", hash = "sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427", size = 229892, upload-time = "2024-03-01T18:36:18.57Z" }, ] +[[package]] +name = "python-project-template" +version = "3.0.20260414" +source = { virtual = "." } +dependencies = [ + { name = "fire" }, +] + +[package.optional-dependencies] +dev = [ + { name = "ghp-import" }, + { name = "hypothesis" }, + { name = "pdoc" }, + { name = "pyright" }, + { name = "pytest" }, + { name = "pytest-cov" }, + { name = "pytest-html" }, + { name = "pytest-mock" }, + { name = "ruff" }, + { name = "taskipy" }, +] + +[package.dev-dependencies] +dev = [ + { name = "safety" }, +] + +[package.metadata] +requires-dist = [ + { name = "fire", specifier = ">=0.7.1" }, + { name = "ghp-import", marker = "extra == 'dev'", specifier = ">=2.1.0" }, + { name = "hypothesis", marker = "extra == 'dev'", specifier = ">=6.148.4" }, + { name = "pdoc", marker = "extra == 'dev'", specifier = ">=14.0" }, + { name = "pyright", marker = "extra == 'dev'", specifier = ">=1.1.407" }, + { name = "pytest", marker = "extra == 'dev'", specifier = ">=8.3.5" }, + { name = "pytest-cov", marker = "extra == 'dev'", specifier = ">=6.1.1" }, + { name = "pytest-html", marker = "extra == 'dev'", specifier = ">=4.1.1" }, + { name = "pytest-mock", marker = "extra == 'dev'", specifier = ">=3.14.0" }, + { name = "ruff", marker = "extra == 'dev'", specifier = ">=0.11.5" }, + { name = "taskipy", marker = "extra == 'dev'", specifier = ">=1.14.1" }, +] +provides-extras = ["dev"] + +[package.metadata.requires-dev] +dev = [{ name = "safety", specifier = ">=3.7.0" }] + [[package]] name = "regex" version = "2026.4.4" @@ -958,52 +1004,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/33/d1/8bb87d21e9aeb323cc03034f5eaf2c8f69841e40e4853c2627edf8111ed3/termcolor-3.3.0-py3-none-any.whl", hash = "sha256:cf642efadaf0a8ebbbf4bc7a31cec2f9b5f21a9f726f4ccbb08192c9c26f43a5", size = 7734, upload-time = "2025-12-29T12:55:20.718Z" }, ] -[[package]] -name = "test-project" -version = "3.0.20260414" -source = { virtual = "." } -dependencies = [ - { name = "fire" }, -] - -[package.optional-dependencies] -dev = [ - { name = "ghp-import" }, - { name = "hypothesis" }, - { name = "pdoc" }, - { name = "pyright" }, - { name = "pytest" }, - { name = "pytest-cov" }, - { name = "pytest-html" }, - { name = "pytest-mock" }, - { name = "ruff" }, - { name = "taskipy" }, -] - -[package.dev-dependencies] -dev = [ - { name = "safety" }, -] - -[package.metadata] -requires-dist = [ - { name = "fire", specifier = ">=0.7.1" }, - { name = "ghp-import", marker = "extra == 'dev'", specifier = ">=2.1.0" }, - { name = "hypothesis", marker = "extra == 'dev'", specifier = ">=6.148.4" }, - { name = "pdoc", marker = "extra == 'dev'", specifier = ">=14.0" }, - { name = "pyright", marker = "extra == 'dev'", specifier = ">=1.1.407" }, - { name = "pytest", marker = "extra == 'dev'", specifier = ">=8.3.5" }, - { name = "pytest-cov", marker = "extra == 'dev'", specifier = ">=6.1.1" }, - { name = "pytest-html", marker = "extra == 'dev'", specifier = ">=4.1.1" }, - { name = "pytest-mock", marker = "extra == 'dev'", specifier = ">=3.14.0" }, - { name = "ruff", marker = "extra == 'dev'", specifier = ">=0.11.5" }, - { name = "taskipy", marker = "extra == 'dev'", specifier = ">=1.14.1" }, -] -provides-extras = ["dev"] - -[package.metadata.requires-dev] -dev = [{ name = "safety", specifier = ">=3.7.0" }] - [[package]] name = "tomli" version = "2.2.1"