GitHub ActionsでPyInstallerを使ったWindows実行ファイルのリリース自動化
はじめに
Pythonアプリケーションを.exeファイルとして配布する際、PyInstallerを使うことが一般的ですが、手動でのビルドとリリース作業は手間がかかります。本記事では、GitHub ActionsとPyInstallerを組み合わせて、Windows実行ファイルのビルドからGitHubリリースまでを完全に自動化する方法をまとめます。
対象読者
- Pythonアプリケーションを.exeファイルとして配布したい開発者
- GitHub Actionsを使ったCI/CDに興味がある方
- リリース作業を自動化したい開発者
前提条件
- GitHubリポジトリでPythonプロジェクトを管理している
- 基本的なGitHub Actionsの知識がある
- PyInstallerを使ったことがある、または興味がある
全体方針
1. 対象環境とランナー
-
CI/CDツール: GitHub Actions
-
実行環境: Windows ランナー(
windows-latest)- PyInstallerはクロスコンパイルに対応していないため、Windows向けビルドにはWindowsランナーが必須
2. トリガー設定
ワークフローのトリガーは2種類を想定:
通常のCI(ブランチpush/PR時)
-
対象ブランチ:
main,develop,feature/** -
実行内容:
- Lint(コード品質チェック)
- 型チェック
- テスト実行
- ビルド(.exe生成)
- Artifactsへの成果物保存
リリース(タグpush時)
-
トリガー: タグpush(例:
v1.2.3) -
実行内容: 上記CI処理に加えて
- GitHub Releaseの自動作成
- .exeファイルとzipファイルの添付公開
3. ジョブ構成(署名なし版)
基本的なワークフローのステップ構成:
Step 1: Checkout
- uses: actions/checkout@v4
Step 2: Python環境セットアップ
- デフォルト: Python 3.11
- 必要に応じてマトリクスビルドで複数バージョン対応も可能
- uses: actions/setup-python@v5
with:
python-version: '3.11'
Step 3: 依存関係のインストール
-
requirements.txtがあればそれを使用 -
なければ、以下をインストール:
- pytest(テスト)
- ruff(Lint)
- mypy(型チェック)
- pyinstaller(ビルド)
- 開発インストール(
pip install -e .)
Step 4: Lint
ruff check src tests
Step 5: 型チェック
mypy src
Step 6: テスト
pytest -q --maxfail=1 --disable-warnings
Step 7: ビルド(PyInstaller)
-
your_tool.specファイルがあればそれを使用 -
なければコマンドラインオプションで実行:
pyinstaller -F -n your_tool -p src src/your_tool/cli.py
Step 8: パッケージング
-
dist/your_tool.exeをpackage/your_tool-<version>.exeにコピー -
zipファイルも作成
-
<version>の決定ルール:- タグpush時: タグ名(例:
v1.2.3) - それ以外:
0.0.0-<短縮コミットハッシュ>
- タグpush時: タグ名(例:
Step 9: Artifactsアップロード(ブランチ/PR時)
- ビルド成果物をArtifactsとして保存(保存期限付き)
Step 10: GitHub Release作成(タグpush時のみ)
-
リリースタイトル:
your_tool vX.Y.Z -
リリース本文: 簡易的なテンプレート
-
添付ファイル:
dist/your_tool.exepackage/*.zip
4. リポジトリ構成の前提
推奨されるプロジェクト構造:
your-tool/
├─ src/
│ └─ your_tool/
│ └─ cli.py # エントリポイント (main関数)
├─ tests/ # pytestテストコード
├─ pyproject.toml # or requirements.txt
├─ your_tool.spec # PyInstaller設定(任意)
└─ .github/
└─ workflows/
└─ build-release.yml # CI/CDワークフロー
重要なポイント:
-
cli.pyにはif __name__ == "__main__": main()の構成が推奨 - 依存関係は
requirements.txtまたはpyproject.tomlで管理
5. バージョニングとリリース運用
タグを使ったリリースフロー
-
開発が完了したら、バージョンタグを作成:
git tag v1.0.0 git push origin v1.0.0 -
GitHub Actionsが自動的にトリガーされ、Releaseが作成される
-
Releaseページから.exeファイルとzipファイルをダウンロード可能に
開発中のビルド
- タグなしの通常のCI実行時は、Artifactsから成果物を取得(期限付き保存)
6. セキュリティと配布の注意点(署名なし版)
SmartScreen警告について
- コード署名なしの.exeファイルは、Windows SmartScreen警告が表示される
- これは正常な動作であり、署名がないファイルに対する標準的なセキュリティ対策
社内配布での対応策
- 許可リスト方式: WDAC(Windows Defender Application Control)やDefenderポリシーで許可
- 配布手順の周知: ユーザーに警告画面の突破方法を説明
- 社内ネットワーク配布: 信頼できるネットワーク経路での配布
将来的なコード署名導入
- 予算に余裕ができたら、コード署名証明書の取得を検討
- できればEV証明書を推奨(即座にSmartScreen警告を回避可能)
7. 追加オプション(段階的に導入可能)
アイコンとバージョン情報の埋め込み
pyinstaller --icon=app.ico --version-file=version_info.txt ...
データファイルの同梱とhiddenimports
-
.specファイルで詳細に管理
a = Analysis(
['src/your_tool/cli.py'],
datas=[('data/*', 'data')],
hiddenimports=['your_hidden_module'],
...
)
SBOMとセキュリティスキャン
- Syft: SBOM(Software Bill of Materials)生成
- Grype: 脆弱性スキャン
パッケージマネージャーへの配布
- winget: Microsoftの公式パッケージマネージャー
- Chocolatey: Windows向けパッケージマネージャー
- 別ワークフローで自動登録を実装可能
マトリクスビルド
- 複数のPythonバージョンでビルド&テストを実行
strategy:
matrix:
python-version: ['3.9', '3.10', '3.11', '3.12']
8. 実装チェックリスト
実際にCursorなどのエディタで作業する際の手順:
-
.github/workflows/build-release.ymlワークフローファイルの作成- 署名ステップは不要(初期段階)
-
src/your_tool/cli.pyがエントリポイントになっているか確認-
if __name__ == "__main__":の記述を確認
-
-
requirements.txtまたはpyproject.tomlの準備- 必要な依存関係が全て記載されているか確認
-
PRを作成してCIが正常に動作するか確認
- Artifactsから.exeと.zipファイルがダウンロードできること
-
タグpushでリリース動作を確認
git tag v1.0.0 git push origin v1.0.0- GitHub Releaseが自動作成されること
- ファイルが正しく添付されていること
後続の最適化作業
-
.specファイルの最適化- アイコン設定
- データファイルのバンドル
- UPXによる圧縮
- hiddenimportsの追加
-
リリースノートの自動生成
- Changelog生成ツールの導入
- コミットメッセージからの自動抽出
ワークフローファイルのサンプル
以下は基本的な .github/workflows/build-release.yml のサンプルです:
name: Build and Release
on:
push:
branches:
- main
- develop
- 'feature/**'
tags:
- 'v*'
pull_request:
branches:
- main
- develop
jobs:
build:
runs-on: windows-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: '3.11'
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install pytest ruff mypy pyinstaller
if (Test-Path requirements.txt) {
pip install -r requirements.txt
}
pip install -e .
- name: Lint with ruff
run: ruff check src tests
- name: Type check with mypy
run: mypy src
- name: Test with pytest
run: pytest -q --maxfail=1 --disable-warnings
- name: Build with PyInstaller
run: |
if (Test-Path your_tool.spec) {
pyinstaller your_tool.spec
} else {
pyinstaller -F -n your_tool -p src src/your_tool/cli.py
}
- name: Package artifacts
run: |
$version = if ($env:GITHUB_REF -match '^refs/tags/v(.+)$') {
$matches[1]
} else {
"0.0.0-$($env:GITHUB_SHA.Substring(0,7))"
}
New-Item -ItemType Directory -Force -Path package
Copy-Item dist/your_tool.exe package/your_tool-$version.exe
Compress-Archive -Path dist/your_tool.exe -DestinationPath package/your_tool-$version.zip
- name: Upload artifacts
if: startsWith(github.ref, 'refs/tags/v') == false
uses: actions/upload-artifact@v4
with:
name: your_tool-artifacts
path: package/*
- name: Create Release
if: startsWith(github.ref, 'refs/tags/v')
uses: softprops/action-gh-release@v1
with:
files: |
dist/your_tool.exe
package/*.zip
body: |
## Release ${{ github.ref_name }}
### Changes
- See commits for details
### Installation
1. Download `your_tool.exe`
2. Run the executable
**Note**: Windows SmartScreen warning may appear (unsigned binary)
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
まとめ
この構成により、以下のメリットが得られます:
- 自動化によるミス削減: 手動ビルドとリリースのヒューマンエラーを防止
- 継続的品質保証: 全てのコミットに対してLint、型チェック、テストを自動実行
- 迅速なリリース: タグをpushするだけで数分でリリースが完了
- トレーサビリティ: 全てのビルドとリリースがGitHub上で管理される
- 段階的な改善: 基本構成から始めて、必要に応じて機能を追加できる
初期段階では署名なしで運用し、配布規模が大きくなってきたらコード署名の導入を検討するのが現実的なアプローチです。
参考リンク
次のステップ
この記事の内容を実装した後は、以下のような拡張も検討できます:
- Linux/macOS向けのクロスプラットフォームビルド
- Docker内でのビルド実行
- 自動テストカバレッジレポート
- 脆弱性スキャンの統合
- より詳細なリリースノートの自動生成
この記事が、Pythonアプリケーションのリリース自動化の参考になれば幸いです。
Discussion