Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 12 additions & 7 deletions .github/workflows/publish-pypi.yml
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
name: Publish to PyPI

# A pushed `v*` tag releases that commit. The tag must be `v` + the version in pyproject.toml. The
# upload uses PyPI trusted publishing: no token is stored anywhere; PyPI trusts this workflow and
# the `pypi` environment, whose deployment policy allows `v*` tags only.
# Publishing a GitHub Release releases its tag's commit. A version cannot be uploaded to PyPI
# twice, so publishing is a deliberate step: a Release records the tag and its notes together,
# where a `v*` tag trigger would fire on a stray `git push --tags`. The Release's tag must be `v` +
# the version in pyproject.toml. The upload uses PyPI trusted publishing: no token is stored
# anywhere; PyPI trusts this workflow and the `pypi` environment, whose deployment policy allows
# `v*` tags only (a Release runs on its tag's ref).
on:
push:
tags: ['v*']
release:
types: [published]

permissions:
contents: read
Expand All @@ -21,8 +24,10 @@ jobs:
with:
python-version: '3.13'
- run: python -m pip install build twine
- name: Check the tag against pyproject.toml
run: python .github/scripts/check_release_version.py "$GITHUB_REF_NAME"
- name: Check the Release's tag against pyproject.toml
env:
RELEASE_TAG: ${{ github.event.release.tag_name }}
run: python .github/scripts/check_release_version.py "$RELEASE_TAG"
- name: Build the sdist and the wheel
run: python -m build
- run: twine check dist/*
Expand Down
9 changes: 5 additions & 4 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -222,10 +222,11 @@ worktree so a test can see it. Read it in place.

- The distribution name is `pythonx-compose` (`pyproject.toml`); the import package is
`pythonx.compose`.
- **Release.** After the maintainer approves, tag the commit to release `v<version>` (the
`pyproject.toml` version, e.g. `v0.1.0a1`) and push the tag; `.github/workflows/publish-pypi.yml`
builds, checks and publishes through PyPI trusted publishing (environment `pypi`). Never upload
by hand, and never store a PyPI token.
- **Release.** After the maintainer approves, publish a GitHub Release whose tag is `v<version>`
(the `pyproject.toml` version, e.g. `v0.1.0a1`; mark an alpha or beta as a pre-release) on the
commit to release; `.github/workflows/publish-pypi.yml` runs on the Release, checks, builds and
publishes through PyPI trusted publishing (environment `pypi`). Pushing a tag alone publishes
nothing. Never upload by hand, and never store a PyPI token.
- `.pyi` stubs, `py.typed` and the manifest must end up **inside the wheel**. A `package-data`
pattern is not proof — build the wheel and list it before claiming something ships.

Expand Down
10 changes: 6 additions & 4 deletions PROJECT.md
Original file line number Diff line number Diff line change
Expand Up @@ -125,10 +125,12 @@ python3 .github/scripts/check_guide.py # 가이드: HTML 파싱, 링
- 워크플로 이름: `tests.yml` → `test.yml`, PyPI 배포는 `publish-pypi.yml`.
- 첫 버전은 `0.1.0a1`(알파, 프리릴리스). PyPI 메타데이터(설명·README·MIT·저자·URL·분류자)는 채웠고,
README 의 링크는 pypi.org 에서 열리도록 절대 URL 이다(`main` 링크는 `main` 이 `develop` 을 따라잡은 뒤에 열린다).
- 배포 방법: 릴리스할 커밋에 `v0.1.0a1` 태그를 푸시하면 `publish-pypi.yml` 이 태그와 `pyproject.toml`
버전을 대조하고, sdist·wheel 을 빌드하고, `twine check`·새 venv 스모크를 거쳐 트러스티드 퍼블리싱으로
올린다. **현황: 업로드 전.** 태그 푸시는 메인테이너 승인을 기다리고, GitHub 환경 `pypi`(`v*` 태그만 허용)
와 PyPI pending publisher 는 메인테이너가 설정한다.
- 배포 방법: 릴리스할 커밋에 태그 `v0.1.0a1` 로 GitHub Release 를 게시하면(알파는 pre-release 표시)
`publish-pypi.yml` 이 Release 태그와 `pyproject.toml` 버전을 대조하고, sdist·wheel 을 빌드하고,
`twine check`·새 venv 스모크를 거쳐 트러스티드 퍼블리싱으로 올린다. 태그만 푸시해서는 아무것도
올라가지 않는다(같은 버전은 PyPI 에 다시 올릴 수 없으므로 의도적인 단계로 둠). **현황: 업로드 전.**
Release 게시는 메인테이너 승인을 기다린다. GitHub 환경 `pypi`(`v*` 태그만 허용)는 만들었고, PyPI
pending publisher 는 메인테이너가 등록한다.

### 결정됨 (2026-10-03, `docs/INTENT.md` §5)

Expand Down
5 changes: 3 additions & 2 deletions docs/SPEC.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,9 @@ in §9 and are not counted as features.
pypi.org cannot resolve relative ones), `license = "MIT"` with `LICENSE`, the two authors as
`LICENSE` names them (no emails), keywords, classifiers (Alpha, Python 3.11-3.13, Typed) and
project URLs. `build-system.requires` is `setuptools>=77`, which understands that license form.
- Released by pushing a tag `v<version>` (`.github/workflows/publish-pypi.yml`): the workflow checks
the tag equals `v` + the `pyproject.toml` version (`.github/scripts/check_release_version.py`,
- Released by publishing a GitHub Release tagged `v<version>` (`.github/workflows/publish-pypi.yml`,
trigger `release: published`; a bare tag push publishes nothing): the workflow checks the
Release's tag equals `v` + the `pyproject.toml` version (`.github/scripts/check_release_version.py`,
`tests/test_release_version.py`), builds the sdist and wheel, runs `twine check`, smoke-installs
the wheel in a fresh venv, then uploads through PyPI trusted publishing (environment `pypi`, no
token). Nothing is uploaded by hand.
Expand Down
Loading