Skip to content

Commit e6a5013

Browse files
authored
Merge pull request #9 from bitner/docs/v0.1.0-release-prep
Docs/v0.1.0 release prep
2 parents 579c2fc + 347439b commit e6a5013

34 files changed

Lines changed: 1677 additions & 182 deletions

.github/workflows/ci.yml

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ jobs:
3939

4040
unit:
4141
runs-on: ubuntu-latest
42+
name: unit (${{ matrix.python-version }})
4243
strategy:
4344
fail-fast: false
4445
matrix:
@@ -63,8 +64,9 @@ jobs:
6364
- name: Run unit tests
6465
run: uv run pytest tests/unit -q
6566

66-
integration-build-docs:
67+
integration:
6768
runs-on: ubuntu-latest
69+
name: integration (${{ matrix.postgres-image }})
6870
strategy:
6971
fail-fast: false
7072
matrix:
@@ -91,6 +93,29 @@ jobs:
9193
PGPKG_TEST_POSTGRES_IMAGE: ${{ matrix.postgres-image }}
9294
run: uv run pytest tests/integration -q
9395

96+
build-docs:
97+
runs-on: ubuntu-latest
98+
needs:
99+
- quality
100+
- unit
101+
- integration
102+
steps:
103+
- name: Check out repository
104+
uses: actions/checkout@v4
105+
106+
- name: Set up Python
107+
uses: actions/setup-python@v5
108+
with:
109+
python-version: "3.13"
110+
111+
- name: Set up uv
112+
uses: astral-sh/setup-uv@v5
113+
with:
114+
enable-cache: true
115+
116+
- name: Install dependencies
117+
run: uv sync --extra dev --extra diff
118+
94119
- name: Build distributions
95120
run: uv build --out-dir dist
96121

.github/workflows/publish-pypi.yml

Lines changed: 17 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,6 @@ on:
55
types: [published]
66
workflow_dispatch:
77
inputs:
8-
repository:
9-
description: Publish destination
10-
required: true
11-
default: testpypi
12-
type: choice
13-
options:
14-
- testpypi
15-
- pypi
168
expected_version:
179
description: Required for manual PyPI publish (e.g. 0.1.0)
1810
required: false
@@ -49,39 +41,35 @@ jobs:
4941

5042
- name: Smoke test wheel install
5143
run: |
44+
set -euo pipefail
5245
uv venv .venv-smoke
5346
uv pip install --python .venv-smoke/bin/python dist/*.whl
5447
.venv-smoke/bin/pgpkg --help
5548
49+
- name: Smoke test generated wrapper
50+
run: |
51+
set -euo pipefail
52+
smoke_python="$PWD/.venv-smoke/bin/python"
53+
smoke_wrapper="$PWD/.venv-smoke/bin/sampleext-migrator"
54+
tmpdir="$(mktemp -d)"
55+
cp -R tests/fixtures/sample_project/. "$tmpdir/"
56+
uv run pgpkg stageversion 0.1.0 --project-root "$tmpdir"
57+
uv run pgpkg wheel --project-root "$tmpdir" --output-dir "$tmpdir/wrapper"
58+
pushd "$tmpdir/wrapper"
59+
uv build --out-dir dist
60+
uv pip install --python "$smoke_python" dist/*.whl
61+
"$smoke_wrapper" info
62+
popd
63+
5664
- name: Upload distributions
5765
uses: actions/upload-artifact@v4
5866
with:
5967
name: python-package-distributions
6068
path: dist/*
6169
if-no-files-found: error
6270

63-
publish-testpypi:
64-
if: github.event_name == 'workflow_dispatch' && inputs.repository == 'testpypi'
65-
needs: build
66-
runs-on: ubuntu-latest
67-
permissions:
68-
id-token: write
69-
environment:
70-
name: testpypi
71-
steps:
72-
- name: Download distributions
73-
uses: actions/download-artifact@v4
74-
with:
75-
name: python-package-distributions
76-
path: dist
77-
78-
- name: Publish to TestPyPI
79-
uses: pypa/gh-action-pypi-publish@release/v1
80-
with:
81-
repository-url: https://test.pypi.org/legacy/
82-
8371
publish-pypi:
84-
if: github.event_name == 'release' || (github.event_name == 'workflow_dispatch' && inputs.repository == 'pypi')
72+
if: github.event_name == 'release' || github.event_name == 'workflow_dispatch'
8573
needs: build
8674
runs-on: ubuntu-latest
8775
permissions:

.gitignore

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,3 +34,8 @@ pip-wheel-metadata/
3434
# local-only markdown notes
3535
*_SETUP.md
3636
*_PLAN.md
37+
!GITHUB_PYPI_SETUP.md
38+
!PROJECT_PLAN.md
39+
40+
# hookify rules (personal dev tooling, never commit)
41+
.claude/*.local.md

CHANGELOG.md

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,25 +2,35 @@
22

33
All notable changes to this project will be documented in this file.
44

5-
The format is based on Keep a Changelog and this project follows Semantic Versioning.
5+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/)
6+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
67

7-
## [0.1.0] - 2026-04-27
8+
## [0.1.0] - 2026-05-05
89

910
### Added
1011
- Core migration toolkit commands: `stageversion`, `makemigration`, `graph`, `migrate`, `wheel`, `bundle`, `info`, `verify`.
1112
- Python API facade for staging, planning, migration, and verification flows.
1213
- Wrapper scaffold flow with bundled migration artifact (`tar.zst`) and sample wrapper project.
14+
- Runtime tracking configuration via `[tool.pgpkg.tracking]` and pluggable `version_source` support for application-owned version tables.
15+
- `stageversion --also-write` plus `makemigration --prepend-file`, `--append-file`, and `--append-sql` for custom packaging and wrapper migration flows.
16+
- Deterministic bundle artifacts that preserve tracking schema/table and configured version-source metadata.
1317
- Unit and integration test suites plus wrapper end-to-end test.
1418
- MkDocs documentation site with architecture, API, CLI, layout, and quickstart guides.
1519
- CI workflows for quality/unit/integration+build/docs and release publishing.
1620

1721
### Changed
22+
- Documentation now standardizes install and release examples on `uv` and documents custom tracking/runtime packaging constraints.
1823
- Publish workflow hardened with wheel install smoke test before publish.
24+
- Publish workflow now smoke-tests a generated wrapper package before uploading distributions.
1925
- Publish workflow checks release tag/version parity before PyPI publish.
26+
- Release workflow and setup docs now target PyPI only; TestPyPI setup is deferred until access is available.
2027
- Docs deployment workflow aligned to main-branch release path and updated Pages action versions.
2128
- Integration tests now support configurable PostgreSQL image for CI matrix validation.
2229

30+
### Fixed
31+
- Tracking writes now survive migration SQL that changes the active database role.
32+
2333
### Security
24-
- Trusted publishing workflow configured for TestPyPI/PyPI environments.
34+
- Trusted publishing workflow configured for the PyPI environment.
2535

2636
[0.1.0]: https://github.com/bitner/pgpkg/releases/tag/v0.1.0

CONTRIBUTING.md

Lines changed: 12 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -39,33 +39,31 @@ uv run python -m twine check dist/*
3939
uv run mkdocs build --strict
4040
```
4141

42-
3. For a smoke release, run the `Publish` workflow manually with `repository=testpypi`.
42+
3. Create release tag `v0.1.0` matching `src/pgpkg/__init__.py::__version__`.
4343

44-
4. Verify TestPyPI install path in a clean venv:
44+
4. Publish to PyPI by creating a GitHub Release from that tag.
4545

46-
```bash
47-
python -m venv .venv-testpypi
48-
. .venv-testpypi/bin/activate
49-
python -m pip install --upgrade pip
50-
python -m pip install -i https://test.pypi.org/simple/ --extra-index-url https://pypi.org/simple pgpkg
51-
pgpkg --help
52-
```
46+
Optional manual path:
47+
- Run `Publish` with `expected_version=0.1.0` only if version parity is already confirmed.
5348

54-
5. Create release tag `vX.Y.Z` matching `src/pgpkg/__init__.py::__version__`.
49+
5. Verify the PyPI install path in a clean venv:
5550

56-
6. Publish to PyPI by creating a GitHub Release from that tag (or by running `Publish` with `repository=pypi` only if version parity is confirmed).
51+
```bash
52+
uv venv .venv-pypi
53+
uv pip install --python .venv-pypi/bin/python pgpkg
54+
.venv-pypi/bin/pgpkg --help
55+
```
5756

5857
## Trusted publishing setup
5958

60-
Before the publish workflow can work, configure trusted publishing for both environments:
59+
Before the publish workflow can work, configure trusted publishing for the PyPI environment:
6160

62-
- GitHub environment `testpypi` bound to the TestPyPI project
6361
- GitHub environment `pypi` bound to the PyPI project
6462

6563
No API tokens are required when trusted publishing is configured correctly.
6664

6765
## Release policy guardrails
6866

6967
- The release tag version must match the built package version exactly.
70-
- TestPyPI install smoke test is required before first PyPI publish.
68+
- The publish build job smoke-tests both the CLI wheel and a generated wrapper before upload.
7169
- If workflow_dispatch is used for PyPI publish, confirm version parity before running it.

GITHUB_PYPI_SETUP.md

Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
# GitHub + PyPI Setup Guide
2+
3+
This checklist takes a local `pgpkg` repository to a production-ready GitHub repository with automated PyPI publishing.
4+
5+
## 1) Create and push the GitHub repository
6+
7+
1. Create an empty GitHub repo (for example, `pgpkg`).
8+
2. Add the remote and push:
9+
10+
```bash
11+
git remote add origin git@github.com:<OWNER>/pgpkg.git
12+
git push -u origin <BRANCH>
13+
```
14+
15+
3. Push all long-lived branches you want preserved.
16+
17+
## 2) Repository settings (recommended hygiene)
18+
19+
1. Enable branch protection on the default branch:
20+
- Require pull request before merging
21+
- Require status checks to pass
22+
- Require branches to be up to date before merging
23+
2. Require these checks from CI:
24+
- `quality`
25+
- `unit (3.11)`
26+
- `unit (3.12)`
27+
- `unit (3.13)`
28+
- `integration (postgres:14-alpine)`
29+
- `integration (postgres:15-alpine)`
30+
- `integration (postgres:16-alpine)`
31+
- `integration (postgres:17-alpine)`
32+
- `build-docs`
33+
3. Enable "Automatically delete head branches" after merge.
34+
4. Enable Dependabot alerts and security updates.
35+
5. In Settings -> Pages, set Source to `GitHub Actions` so `.github/workflows/docs-pages.yml` can publish the MkDocs site.
36+
37+
## 3) PyPI account and project prerequisites
38+
39+
You need an account on:
40+
- https://pypi.org
41+
42+
### Required access
43+
44+
- You must be an Owner or Maintainer for the project on PyPI.
45+
- You must have admin rights on the GitHub repository to configure environments and workflows.
46+
47+
## 4) Preferred publishing model: Trusted Publishing (OIDC)
48+
49+
This repository already includes `.github/workflows/publish-pypi.yml`, which is configured for trusted publishing.
50+
51+
### 4a) Configure GitHub environments
52+
53+
Create these environments in GitHub:
54+
- `pypi`
55+
56+
Optional hardening:
57+
- Add required reviewers for `pypi` environment
58+
- Restrict deployment branches/tags
59+
60+
### 4b) Configure trusted publisher on PyPI
61+
62+
In PyPI project settings, add a trusted publisher with:
63+
- Owner: `<OWNER>`
64+
- Repository: `pgpkg`
65+
- Workflow filename: `publish-pypi.yml`
66+
- Environment: `pypi`
67+
68+
## 5) Credentials you actually need
69+
70+
With trusted publishing configured correctly:
71+
- No PyPI API token is needed in GitHub secrets.
72+
- No username/password is needed in CI.
73+
- The only required "credential" in CI is GitHub's OIDC identity (`id-token: write`, already set in workflow).
74+
75+
You still need:
76+
- GitHub account with repo admin rights
77+
- PyPI account with project owner/maintainer rights
78+
79+
## 6) Optional fallback model: API token publishing
80+
81+
Only use this if trusted publishing cannot be enabled.
82+
83+
1. Create a project-scoped API token in PyPI.
84+
2. Add these repository secrets:
85+
- `PYPI_API_TOKEN`
86+
3. Update publish workflow to pass `password: ${{ secrets.<TOKEN_NAME> }}` to `pypa/gh-action-pypi-publish`.
87+
88+
## 7) First release flow
89+
90+
1. Run local gate:
91+
92+
```bash
93+
uv run pre-commit run --all-files
94+
uv run ty check src tests
95+
uv run pytest -q
96+
uv build --out-dir dist
97+
uv run python -m twine check dist/*
98+
uv run mkdocs build --strict
99+
```
100+
101+
2. Create GitHub Release tag `v0.1.0` to trigger PyPI publish.
102+
103+
Optional manual path:
104+
- GitHub Actions -> `Publish` -> `Run workflow` -> `expected_version=0.1.0`
105+
106+
3. Verify install from PyPI:
107+
108+
```bash
109+
uv venv /tmp/pgpkg-smoke
110+
uv pip install --python /tmp/pgpkg-smoke/bin/python pgpkg
111+
/tmp/pgpkg-smoke/bin/pgpkg --help
112+
```
113+
114+
The `Publish` workflow's build job also smoke-tests a generated wrapper wheel,
115+
so a successful publish already validates both the base CLI wheel and the
116+
wrapper packaging path before upload.
117+
118+
TestPyPI is intentionally not wired up in this repository right now. If access
119+
is restored later, add a separate environment and publish job rather than
120+
reusing the PyPI lane implicitly.
121+
122+
## 8) Post-setup metadata cleanup
123+
124+
Add canonical URLs in `pyproject.toml`:
125+
126+
```toml
127+
[project.urls]
128+
Homepage = "https://github.com/<OWNER>/pgpkg"
129+
Repository = "https://github.com/<OWNER>/pgpkg"
130+
Documentation = "https://<OWNER>.github.io/pgpkg/"
131+
Issues = "https://github.com/<OWNER>/pgpkg/issues"
132+
```
133+
134+
## 9) Quick troubleshooting
135+
136+
- "invalid-publisher" or "publisher not trusted": trusted publisher fields do not exactly match repo/workflow/environment. For this repo, confirm `bitner/pgpkg`, workflow `publish-pypi.yml`, and environment `pypi` exactly.
137+
- Publish job not starting: verify environment name in workflow matches configured environment.
138+
- Artifact missing in publish job: ensure build job used `uv build --out-dir dist` and uploaded `dist/*`.

0 commit comments

Comments
 (0)