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
10 changes: 10 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -44,3 +44,13 @@ jobs:
run: |
pip install -e ".[dev]"
pytest

# release workflow 只在合进默认分支之后才打包, 那时 tag 和 GitHub Release
# 都已经生成 —— 构建到那一步才炸, 等于白烧一个版本号。在这里先构建一次,
# 让坏掉的 pyproject.toml 挡在 PR 上。
# 这里**不**改写版本号: 要验的就是当前树能不能构建, 版本由 tag 决定是
# release workflow 的事。
- name: Build the package
run: |
pip install --upgrade build
python -m build
107 changes: 98 additions & 9 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -1,13 +1,10 @@
# Copy this file into a downstream repository as `.github/workflows/release.yml`.
# `scripts/sync.sh` does that automatically when the file does not exist yet.
# Release pipeline: version, tag, GitHub release, then the built package.
#
# This is the source-only shape: compute the version, create the tag, create the
# GitHub release. GitHub attaches the source tarball and zip to every release by
# itself, so nothing else is required.
#
# Add the `publish` job from examples/publish.yml when the repository publishes to
# a registry, and the `package` job from examples/package.yml when it ships build
# artifacts. Both are independent siblings of `release`: add or delete them freely.
# Adapted from nexform-tech/repo-template: the `release` job is the synced stub
# and stays as written, while `publish` and `package` come from
# `examples/publish.yml` and `examples/package.yml`. All three are siblings and
# both new jobs are gated on `release` producing a tag, so either can be deleted
# without touching the others.
name: Release

on:
Expand All @@ -30,3 +27,95 @@ jobs:
release:
# Pin to a moving major tag (`@v1`), or to a commit SHA for maximum safety.
uses: nexform-tech/repo-template/.github/workflows/release.yml@v1

# Publish to PyPI through Trusted Publishing: GitHub mints an OIDC token that
# PyPI exchanges for a one-shot upload credential, so this repository stores no
# API token at all. PyPI must know about the repository first — a pending
# publisher for owner `nexform-tech`, repository `litearm-python`, workflow
# `release.yml` and no environment. Without it the upload is refused and this
# run goes red.
publish:
needs: release
# Nothing released (no feat/fix/perf in the merge) means nothing to publish.
if: needs.release.outputs.new_tag != ''
runs-on: ubuntu-22.04
permissions:
contents: read
id-token: write # the OIDC token PyPI exchanges for an upload credential
env:
VERSION: ${{ needs.release.outputs.new_tag }}
steps:
- name: Checkout Code
uses: actions/checkout@v4

- name: Setup Python
uses: actions/setup-python@v5
with:
python-version: "3.12"

# The tag is the only source of truth: semantic-release never commits the
# version back (AGENTS.md §3), so the two places that spell it out are
# rewritten here, in the workspace, and nowhere else. `__version__` is one
# of them because the README tells users to verify an install by reading it;
# leaving it alone would ship a wheel whose metadata says 1.2.0 while
# `litearm.__version__` still says 2.1.0.
- name: Set the release version
run: |
set -euo pipefail
V="${VERSION#v}"
sed -i "s/^version = .*/version = \"${V}\"/" pyproject.toml
sed -i "s/^__version__ = .*/__version__ = \"${V}\"/" src/litearm/__init__.py
# A sed that matched nothing would build the version already in the
# file, so assert the rewrite rather than trusting it.
grep -qx "version = \"${V}\"" pyproject.toml
grep -qx "__version__ = \"${V}\"" src/litearm/__init__.py

- name: Build sdist and wheel
run: |
python -m pip install --upgrade build
python -m build

- name: Publish to PyPI
uses: pypa/gh-action-pypi-publish@release/v1

# Attach the same artifacts to the GitHub release, so the files that reached
# PyPI are also downloadable from this repository without going through PyPI.
#
# The version rewrite and the build repeat what `publish` does. That is
# deliberate: the two jobs are independent siblings, and coupling them so the
# build happens once would mean deleting one breaks the other.
package:
needs: release
if: needs.release.outputs.new_tag != ''
runs-on: ubuntu-22.04
permissions:
contents: write # attach artifacts to the GitHub release
env:
VERSION: ${{ needs.release.outputs.new_tag }}
steps:
- name: Checkout Code
uses: actions/checkout@v4

- name: Setup Python
uses: actions/setup-python@v5
with:
python-version: "3.12"

- name: Set the release version
run: |
set -euo pipefail
V="${VERSION#v}"
sed -i "s/^version = .*/version = \"${V}\"/" pyproject.toml
sed -i "s/^__version__ = .*/__version__ = \"${V}\"/" src/litearm/__init__.py
grep -qx "version = \"${V}\"" pyproject.toml
grep -qx "__version__ = \"${V}\"" src/litearm/__init__.py

- name: Build artifacts
run: |
python -m pip install --upgrade build
python -m build

- name: Attach artifacts to the release
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: gh release upload "$VERSION" dist/* --clobber
Loading