リリースプロセス¶
この文書は httptap の自動化されたリリースプロセスを説明します。
概要¶
リリースは GitHub Actions を使用して完全に自動化されています。ワークフローは、バージョニング、変更履歴の生成、テスト、ビルド、署名、TestPyPI と PyPI への公開、および署名済みコンテナイメージの GHCR へのプッシュを処理します。
前提条件¶
リリースを作成する前に、以下を確認してください:
- GitHub Environments - リポジトリ設定で
release、testpypi、およびpypi環境が設定されており、いずれもmainからのデプロイのみを許可している。pypiには必須レビュアーが設定されている - PyPI Trusted Publishing - PyPI と TestPyPI の両方に設定されている(OIDC、トークンなし)
- Deploy Key - 書き込みアクセス権を持つ SSH デプロイキー。
release環境のシークレットDEPLOY_KEYとしてのみ保存され、mainのブランチ保護とrefs/tags/v*を保護するタグルールセットをバイパスできる - GHCR アクセス - リリースジョブでの
packages: write権限(ワークフローごとに付与) - すべてのテストが通過 - main ブランチで CI がグリーンでなければならない
リリースワークフロー¶
リリースプロセスは GitHub Actions を介して手動でトリガーされます。
リリースのトリガー¶
- Actions → Release ワークフローに移動する
- Run workflow をクリックする
- バージョン戦略を選択する:
- 明示的なバージョン: 正確なバージョンを入力する(例:
0.3.0) - セマンティックバンプ:
patch、minor、またはmajorを選択する
- 明示的なバージョン: 正確なバージョンを入力する(例:
セマンティックバージョニング¶
| バンプ種類 | 例 | ユースケース |
|---|---|---|
patch | 0.1.0 → 0.1.1 | バグ修正、小さな改善 |
minor | 0.1.0 → 0.2.0 | 新機能、後方互換性あり |
major | 0.1.0 → 1.0.0 | 破壊的変更 |
自動的に行われること¶
-
バージョンの更新
pyproject.tomlのversionを更新する -
ロックファイルの更新
新しいバージョンと同期を保つようにuv.lockを再生成する -
変更履歴の生成
conventional commits から変更履歴を生成する -
署名済みのコミットとタグ(ローカルのみ)
gitsign を介した鍵なしの Sigstore 署名: 短命の Fulcio 証明書がワークフローの OIDC アイデンティティを通じて発行されるため、長期間有効な GPG 鍵は不要である。この時点ではまだ何もプッシュされない: コミットとタグは git バンドルの成果物として後続のジョブに渡される。git commit -S -m "chore: release v0.2.0" git tag -s v0.2.0 -m "Release v0.2.0" git bundle create release.bundle "^$GITHUB_SHA" HEAD refs/tags/v0.2.0 -
ビルド
バンドルから取得した、まだプッシュされていないリリースタグ上で実行される。続いて、uv sync --locked --no-dev --group test uv run --no-sync pytest # Full test suite uv build # Create wheel and sdist uv venv "$RUNNER_TEMP/httptap-wheel" uv pip install --python "$RUNNER_TEMP/httptap-wheel" "$(echo dist/httptap-*.whl)[otel]" uv sync --locked --no-dev --no-install-project --group test --group e2e uv run --no-sync pytest tests/e2e --no-cov -n auto --httptap "$RUNNER_TEMP/httptap-wheel/bin/httptap"otelextra 付きでインストールした ビルド済み wheel の CLI に対してエンドツーエンドテストを実行するため、パッケージングの誤りは、何かが証明・アップロード される前にリリースを失敗させる。 -
コミットとタグのプッシュ
ビルドと証明が成功した後にのみ行われる。プッシュは fast-forward のみかつアトミックであるため、リリース中にmainが進んでいた場合、ブランチもタグも更新されず、ワークフローは何かが公開される前にここで停止する。 -
TestPyPI への公開
- 本番プッシュの前のスモークテストとして、PEP 740 の証明書とともに OIDC Trusted Publishing を介してまず TestPyPI にアップロードする。
-
PyPI への公開
- OIDC Trusted Publishing を使用する(トークン不要)
- PEP 740 の証明書とともに wheel とソース配布物をアップロードする
-
コンテナイメージの GHCR への公開
- PyPI への公開後にのみ実行されるため、
pypiのレビューを待つ - マルチアーキテクチャ(linux/amd64、linux/arm64)イメージをビルドする
{version}、{major}.{minor}、{major}、およびlatestタグとともにghcr.io/ozeranskii/httptapにプッシュする- cosign(鍵なし Sigstore)でイメージに署名する
actions/attest-build-provenanceを介して SLSA ビルドプロベナンスを添付する
- PyPI への公開後にのみ実行されるため、
-
GitHub Release
- 生成されたノートとともにリリースを作成する
- ビルド成果物、SBOM、VEX、および man ページを添付する
ワークフローの設定¶
リリースワークフローは .github/workflows/release.yml で定義されています:
主要なジョブ¶
1. Prepare Release¶
- コードをチェックアウトする(読み取り専用、デプロイキーなし)
- Python と uv を設定する
- pyproject.toml のバージョンを更新する
- 変更履歴を生成する
.vex/httptap.openvex.jsonのfixedステートメントにリリースを追加し、文書のバージョンを上げる- 署名済みのリリースコミットとタグをローカルで作成する
- それらを
release-bundle成果物としてアップロードする。何もプッシュしない
2. Build Package¶
- バンドルから、まだプッシュされていないリリースタグをチェックアウトする
- 完全なテストスイートを実行する
- wheel と sdist をビルドする
- ビルドした wheel(
otelextra 付き)に対してエンドツーエンドテスト(tests/e2e)を実行する - Syft を介して CycloneDX および SPDX JSON 形式の SBOM を生成する
.vex/httptap.openvex.jsonのfixedステートメントにリリースが含まれていなければ失敗し、その後文書をsbom/ディレクトリにhttptap-X.Y.Z.openvex.jsonとしてコピーする- argparse-manpage を介して gzip 圧縮された
man(1)ページを生成する dist/、sbom/、およびman/の成果物を個別にアップロードする
3. Push Release Commit and Tag¶
- ビルドとプロベナンスの証明が成功した後にのみ実行される
- git リポジトリに書き込む唯一のジョブである。
release環境のデプロイキーを使って SSH でプッシュするため、ワークフロートークンは読み取り専用(contents: read)である mainをリリースコミットまで fast-forward し、タグとともに 1 回のアトミックなプッシュで送る。リリース中にmainが進んでいた場合は、何も公開せずに失敗する
4. Publish to TestPyPI¶
dist/の成果物をダウンロードする- PEP 740 の証明書とともに TestPyPI OIDC Trusted Publishing を介して公開する
5. Publish to PyPI¶
- TestPyPI が成功した後にのみ実行される
- PEP 740 の証明書とともに Trusted Publishing を使用して公開する
6. Publish container image to GHCR¶
- PyPI への公開後にのみ実行されるため、
pypi環境のレビュー前に GHCR へ何も公開されない - Buildx + QEMU でマルチアーキテクチャイメージをビルドする
- cosign(鍵なし Sigstore OIDC)で署名する
- SLSA ビルドプロベナンスを添付する
7. Create GitHub Release¶
contents: writeを持つ唯一のジョブであり、リリースの作成に必要とするdist/、sbom/、およびman/の成果物をダウンロードする- 変更履歴のノートとともに GitHub リリースを作成する
- wheel、sdist、SBOM(
*.cdx.json、*.spdx.json)、VEX(*.openvex.json)、および man ページを添付する
変更履歴の生成¶
変更履歴は、conventional commits に基づいて git-cliff を使用して自動的に生成されます。
コミット形式¶
サポートされる種類¶
| 種類 | 変更履歴のセクション | 例 |
|---|---|---|
feat | Features | feat(cli): add --timeout flag |
fix | Bug Fixes | fix(tls): handle expired certificates |
perf | Performance | perf(dns): optimize resolver cache |
docs | Documentation | docs: update API reference |
refactor | Refactor | refactor(core): extract analyzer logic |
test | Testing | test: add integration tests |
chore | Miscellaneous | chore: update dependencies |
破壊的変更¶
コミットのフッターで破壊的変更をマークします:
feat(api): redesign analyzer interface
BREAKING CHANGE: HTTPTapAnalyzer constructor signature changed
バージョン戦略¶
httptap は Semantic Versioning に従います:
- メジャーバージョン(1.0.0) - 破壊的変更
- マイナーバージョン(0.1.0) - 新機能、後方互換性あり
- パッチバージョン(0.0.1) - バグ修正
1.0 以前の開発¶
1.0 以前の開発(0.x.x)の間:
- マイナーバージョンは破壊的変更を含む場合がある
- パッチバージョンはバグ修正と小さな機能のため
- API が安定したら 1.0.0 に移行する
トラブルシューティング¶
ブランチ保護エラー¶
ブランチ保護が原因でプッシュが失敗する場合:
- デプロイキーが書き込みアクセス権を持っていることを検証する
- デプロイキーがブランチ保護ルールと
refs/tags/v*のタグルールセットのバイパスリストにあることを確認する - ワークフローのチェックアウトで
ssh-keyが設定されていることを確認する DEPLOY_KEYがrelease環境のシークレットであり、ワークフローが環境で許可された唯一のブランチであるmainから実行されたことを確認する
変更履歴が空¶
変更履歴の生成が空を返す場合:
- コミットが conventional 形式に従っていることを確認する
.release/git-cliff.tomlの git-cliff 設定を確認する- タグがすでに存在しないことを検証する
PyPI 公開が失敗¶
PyPI 公開が失敗する場合:
pypi環境が存在することを検証する- Trusted Publishing が PyPI で設定されていることを確認する
- ワークフローが
id-token: write権限を持っていることを確認する
テストの失敗¶
リリース中にテストが失敗する場合:
- ワークフローは公開前に停止する
- 問題を修正してワークフローを再実行する
- 部分的なリリースは発生しない
リリース後¶
リリースが成功した後:
- PyPI でパッケージを検証する: https://pypi.org/project/httptap/
- GitHub リリースを確認する: https://github.com/ozeranskii/httptap/releases
- インストールをテストする:
uv pip install httptap=={version} - リリースを告知する(例: GitHub Discussions、Telegram)
リリースチェックリスト¶
リリースをトリガーする前に:
- main ですべての CI チェックが通過している
- 既知の重大なバグがない
- ドキュメントが更新されている
- 破壊的変更が文書化されている
- 移行ガイドが書かれている(メジャーバージョンの場合)
- 依存関係が更新されている
- セキュリティ脆弱性が対処されている