From 050d0a851285ab6d51ced3cdcac7a54b7c937cbc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B3=A0=EA=B7=9C=ED=98=84?= <38392618+airmang@users.noreply.github.com> Date: Thu, 19 Feb 2026 00:12:26 +0900 Subject: [PATCH] =?UTF-8?q?ci:=20=ED=83=9C=EA=B7=B8=20=EB=A6=B4=EB=A6=AC?= =?UTF-8?q?=EC=8A=A4=20=EC=9B=8C=ED=81=AC=ED=94=8C=EB=A1=9C=EC=9A=B0=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/release.yml | 102 ++++++++++++++++++++++++++++++++++ 1 file changed, 102 insertions(+) create mode 100644 .github/workflows/release.yml diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..9934f01 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,102 @@ +name: Release + +on: + push: + tags: + - "v*" + - "[0-9]*" + +permissions: + contents: write + id-token: write + +jobs: + release: + runs-on: ubuntu-latest + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version: "3.12" + + - name: Validate tag/version consistency + shell: bash + run: | + set -euo pipefail + + TAG_NAME="${GITHUB_REF_NAME}" + TAG_VERSION="${TAG_NAME#v}" + + PYPROJECT_VERSION=$(python - <<'PY' + import tomllib + from pathlib import Path + + data = tomllib.loads(Path("pyproject.toml").read_text(encoding="utf-8")) + print(data["project"]["version"]) + PY + ) + + CHANGELOG_VERSION=$(python - <<'PY' + import re + from pathlib import Path + + changelog = Path("CHANGELOG.md").read_text(encoding="utf-8") + match = re.search(r"^## \[([^\]]+)\]", changelog, re.MULTILINE) + if not match: + raise SystemExit("CHANGELOG.md에서 버전 섹션(## [x.y.z])을 찾지 못했습니다.") + print(match.group(1).strip()) + PY + ) + + echo "Tag version: ${TAG_VERSION}" + echo "pyproject version: ${PYPROJECT_VERSION}" + echo "changelog version: ${CHANGELOG_VERSION}" + + if [[ "${TAG_VERSION}" != "${PYPROJECT_VERSION}" ]]; then + echo "태그 버전(${TAG_VERSION})과 pyproject 버전(${PYPROJECT_VERSION})이 일치하지 않습니다." >&2 + exit 1 + fi + + if [[ "${TAG_VERSION}" != "${CHANGELOG_VERSION}" ]]; then + echo "태그 버전(${TAG_VERSION})과 changelog 최신 버전(${CHANGELOG_VERSION})이 일치하지 않습니다." >&2 + exit 1 + fi + + - name: Extract latest changelog section for release notes + run: | + python - <<'PY' + from pathlib import Path + + lines = Path("CHANGELOG.md").read_text(encoding="utf-8").splitlines() + start = next((i for i, line in enumerate(lines) if line.startswith("## [")), None) + if start is None: + raise SystemExit("CHANGELOG.md에서 릴리스 섹션을 찾지 못했습니다.") + + end = next( + (i for i in range(start + 1, len(lines)) if lines[i].startswith("## [")), + len(lines), + ) + + section = "\n".join(lines[start:end]).strip() + "\n" + Path("release_notes.md").write_text(section, encoding="utf-8") + PY + + - name: Build distributions (migrated from scripts/build-and-publish.sh) + run: | + python -m pip install --upgrade build twine + rm -rf dist build + python -m build + twine check dist/* + + - name: Publish package to PyPI + uses: pypa/gh-action-pypi-publish@release/v1 + + - name: Create GitHub Release + uses: softprops/action-gh-release@v2 + with: + body_path: release_notes.md + files: dist/*