Skip to content

fix(release): タグからバージョンを確実に解決し、deprecated アクションを更新#280

Merged
rikunosuke merged 1 commit into
mainfrom
fix/release-workflow-setuptools-scm-version
Jun 22, 2026
Merged

fix(release): タグからバージョンを確実に解決し、deprecated アクションを更新#280
rikunosuke merged 1 commit into
mainfrom
fix/release-workflow-setuptools-scm-version

Conversation

@yo-tak

@yo-tak yo-tak commented Jun 22, 2026

Copy link
Copy Markdown
Contributor

概要

リリース時の build-n-publish ジョブが実行ごとに成功したり失敗したりする問題を修正します。失敗時は Publish a Python distribution to PyPI ステップで 400 Bad Request が発生していました。

あわせて、sunset / deprecated になっている GitHub Actions を更新し、SHA 固定にします。

根本原因

このパッケージは setuptools_scm による動的バージョニングを採用しています。

  • pyproject.tomldynamic = ["version"] / [tool.setuptools_scm]
  • バージョンはソース内に書かれておらず、setuptools_scmGit タグgit describe 相当)から算出します。

一方、release.yml の checkout は actions/checkout@v2デフォルト設定で使っていました。デフォルトは fetch-depth: 1浅い(shallow)チェックアウトで、単一コミットしか取得せずタグやフル履歴を確実には取得しません

その結果、ビルド時に対象タグが手元に存在するかどうかが実行タイミングに依存し、以下のように分岐していました。

状態 バージョン解決 結果
タグが取得できている 0.21.0 ✅ success
タグが取りこぼされる フォールバック 0.1.dev1+g<sha> ❌ failure

ログが示していた事実

失敗時の成果物名は fastlabel-0.1.dev1+g6e97b6cd0 でした。この g6e97b6cd0 は、タグ 0.21.0 が付いているコミット 6e97b6c(main の HEAD のマージコミット)そのものです。

  • ローカル確認: git rev-list -n 1 0.21.06e97b6cd0... / git describe --tags 6e97b6c0.21.0

つまり正しいコミットはチェックアウトできていたが、そのチェックアウトにタグが含まれていなかったため、setuptools_scm がフォールバック値 0.1.dev1+g<sha> を採用していた、ということです。

なぜ「タグとリリースを分けて作成すると成功する」のか

GitHub UI で「新規タグ作成」と「Publish release」を同時に行うと、release: published イベント発火 → checkout 実行 までの間にタグの伝搬が間に合わず、浅い checkout がコミットだけ取得してタグを取りこぼすレースが起きます。タグを先に作成してからリリースを公開すると、checkout 時点でタグが確実に存在するため毎回 0.21.0 に解決される、という挙動でした(操作者の観察と一致)。

PyPI の 400 Bad Request について

これは上記の二次的な症状です。0.1.dev1+g6e97b6cd0+g6e97b6cd0 は PEP 440 のローカルバージョンラベルで、PyPI はローカルラベル付きのアップロードを拒否します → 400 Bad Request。間違ったバージョンが生成された結果、アップロードが弾かれていました。

修正内容

.github/workflows/release.yml

  • checkout に fetch-depth: 0 / fetch-tags: true を追加(本質的修正)
    全履歴+タグを取得し、トリガーのタイミングに関わらず setuptools_scm が常にタグからバージョンを解決できるようにします。これによりタグとリリースを同時に作成しても確実に動作し、「分けて作成する」回避策が不要になります。
  • deprecated アクションを更新し SHA 固定
    • actions/checkout @v2@692973e… (v4)
    • actions/setup-python @v2@39cd149… (v5)
    • pypa/gh-action-pypi-publish @master(sunset) → @cef2210… (v1.14.0)
    • ※ checkout / setup-python は test.yml と同一 SHA に統一。pypi-publish は passwordPYPI_API_TOKEN)ベースの認証を従来どおり継続。

pypi_update_guide.md

  • バージョンがタグから自動導出される仕組み・タグ名がそのまま公開バージョンになること・解決失敗時に 0.1.dev1+g<sha> へフォールバックして PyPI に弾かれることを明記。手順(Step 1〜3)自体は変更なし。

動作確認方法

次回リリース時に Check ジョブのログで dist 内が fastlabel-<正しいバージョン> になっていることを確認してください(0.1.dev1+... にならない)。

補足(任意・今後の検討)

pypa/gh-action-pypi-publish v1.14.0 以降は Trusted Publishing(OIDC, トークンレス) を推奨しています。password を撤廃し permissions: id-token: write + PyPI 側の信頼設定に移行すると、シークレット管理が不要になります。本 PR では既存のトークン方式を維持しています。

🤖 Generated with Claude Code

リリース時に build-n-publish が成功したり失敗したりする問題を修正。

setuptools_scm は Git タグからバージョンを算出するが、release.yml の
actions/checkout@v2 はデフォルトの浅いチェックアウト(fetch-depth: 1)で
タグを確実に取得しないため、タグの取得有無が実行タイミングに依存していた。
タグを取りこぼすと 0.1.dev1+g<sha> にフォールバックし、PyPI が
ローカルバージョンラベルを拒否して 400 Bad Request になっていた。

- checkout に fetch-depth: 0 / fetch-tags: true を追加し、全履歴+タグを
  取得してバージョンを常に解決できるようにする
- deprecated なアクションを更新し SHA 固定
  - actions/checkout v2 -> v4
  - actions/setup-python v2 -> v5
  - pypa/gh-action-pypi-publish @master(sunset) -> v1.14.0
- pypi_update_guide.md にバージョン解決の仕組みを追記

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- name: Publish a Python distribution to PyPI
if: startsWith(github.event.ref, 'refs/tags') || github.event_name == 'release'
uses: pypa/gh-action-pypi-publish@master
uses: pypa/gh-action-pypi-publish@cef221092ed1bacb1cc03d23a2d87d1d172e277b # v1.14.0

@yo-tak yo-tak Jun 22, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

別途下記ワーニングが出ていたのでついでに修正:

[build-n-publish: # >> PyPA publish to PyPI GHA: UNSUPPORTED GITHUB ACTION VERSION <<#L0](https://github.com/fastlabel/fastlabel-python-sdk/commit/6e97b6cd02efbfce1ae4b9df93fc5b7656a5cbff#annotation_60903713951)
You are using "pypa/gh-action-pypi-publish@master". The "master" branch of this project has been sunset and will not receive any updates, not even security bug fixes.
Please, make sure to use a supported version. If you want to pin to v1 major version, use "pypa/gh-action-pypi-publish@release/v1".
If you feel adventurous, you may opt to use use "pypa/gh-action-pypi-publish@unstable/v1" instead.
A more general recommendation is to pin to exact tags or commit shas.


- name: Set up Python
uses: actions/setup-python@v2
uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f # v5

@yo-tak yo-tak Jun 22, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

別途下記ワーニングが出ていたのでついでに修正(actions/checkoutも同様):

Node.js 20 is deprecated. The following actions target Node.js 20 but are being forced to run on Node.js 24: actions/checkout@v2, actions/setup-python@v2.
For more information see: https://github.blog/changelog/2025-09-19-deprecation-of-node-20-on-github-actions-runners/

@kamei-takuma kamei-takuma left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

深く感謝です!!

@rikunosuke rikunosuke merged commit 5d7f75f into main Jun 22, 2026
9 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants