私はGitHubでソースコードを管理していますが、pythonで作成するプロジェクトのバージョンと依存関係管理でPoetryも使用しています。 プロジェクトのバージョンは しばらく運用していて、コミットごとに コミットごとに 動作としては以下の通りです。 pyproject.tomlとgit tagはバージョンは合わせる方針で手動で更新していたところ、更新を忘れることがあり、何より手動での更新が手間でした。そこで同時に更新する方法がないか検討していましたが、少なくとも私が調べた範囲では同時更新するようなツールは存在しませんでした。 git hookを使用してコミットをトリガーに 本記事では主にスクリプトと実行例について紹介します。 作成したスクリプトは下記の通りです。 pyproject.tomlのバージョンを更新するためのPythonスクリプト pyproject.tomlのtool.poetryテーブルのversionキーを取得してgit tagを実行するためのPythonスクリプト git フックスクリプトをセットアップするためのコンフィグファイル poetryコマンド、静的解析パッケージ、 以下のプロジェクトを例に上記スクリプトの実行例を示します。 0.2.8までバージョンが追加されている状態です。 プロジェクトは以下のようになります。 .git/hooks以下は下記の通りです。 poetry install後はpre-commitスクリプトとpost-commitスクリプトは存在しないため、下記コマンドを実行してインストールします。(一部記載を環境変数に置き換えています。) 再度.git/hooks以下を確認するとpre-commitとpost-commitが追加されていることを確認できます。 作成したgit hookは 次に失敗時の例として、 差分は下記の通りです。 ここで再度、 また、 それぞれ、今後改善したい部分ですが、対応は未定です。 コードはGistにコミットしていますが、下記リポジトリにもコミットしています。
試験用のため更新は非定期で、将来的にはリポジトリを変更するかもしれませんが、利用したい方は自己責任の範囲でフォークやDLをして使用してください。 本記事では、git hookを使用してコミットをトリガーに この方法により、バージョン管理と 以下の記事を参考にさせていただきました。
経緯
git tag
で作成して管理することが可能です。また、poetryではpythonプロジェクトの設定ファイルであるpyproject.toml
でもtool.poetry
テーブルのversion
キーでバージョンを記載して管理することができます。git tag
によるタグ作成とversion
キーの入力は必須ではありませんが、バージョン情報を明示的に記載することでプロジェクト管理がしやすくなります。追加情報
20230906
git tag
するのは冗長だと感じることが増えてきました。pyproject.toml
とgit tag
を更新(インクリメント)するのであれば良いですが、毎回更新しなくてよい場合は、後述する.pre-commit-config.yaml
のupdate-pyproject
フックを一式コメントアウトしてください。
pyproject.toml
のversion
キーを更新する場合は、コミットするとpyproject.toml
のversion
キーを取得して、git tag
が実行される。pyproject.toml
のversion
キーを更新しない場合は、git tag
は実行されない。課題
解決方法
poetry.toml
とgit tag
を更新するpythonスクリプトを実行する方法で解決しました。
pythonスクリプトはpre-commitとpost-commitで実行します。作成したもの
update_pyproject_version.py
: pyproject.tomlのバージョンを更新するためのPythonスクリプトrun_git_tag_base_pyproject.py
: pyproject.toml
のtool.poetry
テーブルのversion
キーを取得してgit tag
を実行するためのPythonスクリプト.pre-commit-config.yaml
: git フックスクリプトをセットアップするためのコンフィグファイルpre-commit
フック: poetryコマンド、静的解析パッケージ、update_pyproject_version.py
を含む、pre-commitスクリプトcreate_post-commit.sh
: post-commit
フックを作成するシェルスクリプトpost-commit
フック: run_git_tag_base_pyproject.py
をgit commit
後に実行するためのシェルスクリプト詳細
update_pyproject_version.py
run_git_tag_base_pyproject.py
.pre-commit-config.yaml
create_post-commit.sh
update_pyproject_version.py
を含む、pre-commitスクリプトpost-commit
run_git_tag_base_pyproject.py
をgit commit後に実行するためのシェルスクリプト実行例
コミット前の情報
ローカルタグ情報
video-grid-merge % git tag
v0.2.1
v0.2.2
v0.2.3
v0.2.4
v0.2.5
v0.2.6
v0.2.7
v0.2.8
リモートタグ情報
% git ls-remote --tags origin
0ae7fa7be0457a3512c51c7a231f24e724570ffd refs/tags/v0.2.1
197a04bcf528e4c0ef5c297dff061d4d34ffea2b refs/tags/v0.2.2
01f88f943ee8330034530c14fb417bf45c5e651b refs/tags/v0.2.3
4212bfa0733f2c2c809f9db37333096b752a451e refs/tags/v0.2.4
52b72640df2f31edbef5c21e0fec149d67eafe04 refs/tags/v0.2.5
6de440811f4adbbd614f622ebed74450dfeaa951 refs/tags/v0.2.6
03b75ea8f4688c3e3b8e02c285093b9736a38d24 refs/tags/v0.2.7
054237a84bbe9233099c55af4ff2443145fbb4d8 refs/tags/v0.2.8
pyproject.toml
[tool.poetry]
name = "video-grid-merge"
version = "0.2.8"
description = "This project allows you to use FFmpeg to arrange video files stored in a specified folder in an NxN grid layout and generate the output."
authors = ["7rikaz_h785 <7rikaz.h785.stat2ltas41lcijad@gmail.com>"]
readme = "README.md"
license = "MIT"
packages = [{include = "video_grid_merge"}]
[tool.poetry.scripts]
#video-grid-merge = "video_grid_merge.__main__:main"
#delete-temporaliy-files = "video_grid_merge.local_code.delete_files:main"
[tool.taskipy.tasks]
vgmrun = "python video_grid_merge"
vgmrn = "python video_grid_merge/rename_files.py"
vgmrm = "python video_grid_merge/delete_files.py"
vgmtest = "pytest -s -vv --cov=video_grid_merge --cov-branch --cov-report term-missing --cov-report html"
isort = "poetry run isort video_grid_merge tests"
black = "poetry run black video_grid_merge tests"
flake8 = "poetry run flake8 video_grid_merge tests"
mypy = "poetry run mypy"
[tool.poetry.dependencies]
python = "^3.10"
mdformat = "^0.7.16"
tomlkit = "^0.11.8"
[tool.poetry.group.dev.dependencies]
flake8 = "^6.0.0"
black = "^23.3.0"
isort = "^5.12.0"
mypy = "^1.3.0"
pytest = "^7.3.1"
flake8-pyproject = "^1.2.3"
taskipy = "^1.11.0"
pytest-cov = "^4.1.0"
pytest-mock = "^3.10.0"
pre-commit = "^3.3.2"
[build-system]
requires = ["poetry-core"]
build-backend = "poetry.core.masonry.api"
[tool.black]
target-version = ['py310']
[tool.isort]
[tool.flake8]
ignore = ["E402","E501","W503"]
[tool.mypy]
files = ["video_grid_merge","tests"]
python_version = "3.10"
strict = true
warn_return_any = false
ignore_missing_imports = true
scripts_are_modules = true
[tool.pytest.ini_options]
testpaths = ["tests",]
プロジェクトのインストール
git clone https://github.com/7rikazhexde/video-grid-merge.git
cd video-grid-merge
poetry install
run_git_tag_base_pyproject.py
とupdate_pyproject_version.py
はciという名前のディレクトリに格納されています。video-grid-merge % tree -L 2
.
├── LICENSE
├── README.md
├── ci
│ ├── run_git_tag_base_pyproject.py
│ └── update_pyproject_version.py
├── create_post-commit.sh
├── poetry.lock
├── pyproject.toml
├── requirements-dev.txt
├── requirements.txt
├── tests
│ ├── __init__.py
│ ├── test_data
│ └── test_main.py
└── video_grid_merge
├── __init__.py
├── __main__.py
├── delete_files.py
├── local_code
├── media
└── rename_files.py
pre-commitスクリプトとpost-commitスクリプトの作成
video-grid-merge % tree -L 2 .git/hooks
.git/hooks
├── applypatch-msg.sample
├── commit-msg.sample
├── fsmonitor-watchman.sample
├── post-update.sample
├── pre-applypatch.sample
├── pre-commit.sample
├── pre-merge-commit.sample
├── pre-push.sample
├── pre-rebase.sample
├── pre-receive.sample
├── prepare-commit-msg.sample
├── push-to-checkout.sample
└── update.sample
pre-commit作成
video-grid-merge % poetry run pre-commit install
Configuration file exists at $HOME/Library/Preferences/pypoetry, reusing this directory.
Consider moving TOML configuration files to $HOME/Library/Application Support/pypoetry, as support for the legacy directory will be removed in an upcoming release.
pre-commit installed at .git/hooks/pre-commit
post-commit作成
video-grid-merge % chmod +x ./create_post-commit.sh
video-grid-merge % ./create_post-commit.sh
[video-grid-mergeのディレクトリパス]/.git/hooks/post-commit created with execution permission.
video-grid-merge % tree -L 2 .git/hooks
.git/hooks
├── applypatch-msg.sample
├── commit-msg.sample
├── fsmonitor-watchman.sample
├── post-commit # 追加
├── post-update.sample
├── pre-applypatch.sample
├── pre-commit # 追加
├── pre-commit.sample
├── pre-merge-commit.sample
├── pre-push.sample
├── pre-rebase.sample
├── pre-receive.sample
├── prepare-commit-msg.sample
├── push-to-checkout.sample
└── update.sample
git commit例
失敗例
git commit
をトリガーに実行されますが、pre-commit
では.pre-commit-config.yaml
のプラグインオプションであるfail_fast
により、各hook処理が成功(=Passed)しない場合には実行を停止させています。これはupdate-pyprojectフック(update_pyproject_version.py
)で失敗した情報を取得できないため、エラーの場合も実行させないことで、バージョンの更新もさせないようにしています。.pre-commit-config.yaml
ファイルで改行を増やして、git add
後にgit commit
した場合、trailing-whitespaceフックにより指摘箇所は修正されますが、pre-commitフック
の実行は停止されます。> git -c user.useConfigOnly=true commit --quiet
trim trailing whitespace.................................................Failed
- hook id: trailing-whitespace
- exit code: 1
- files were modified by this hook
Fixing README.md
成功例
git commit
を実行するとpyproject.toml
とgit tag
を0.2.9で更新してgit push
していることが確認できます。(実行結果の表示について、vscodeのコミットボタン押下でも問題なく動作しますが、デフォルトではログ出力しないため、git commitコマンドを実行しています。)% git commit -m "docs(README): Changed installation description"
trim trailing whitespace.................................................Passed
fix end of files.........................................................Passed
mixed line ending........................................................Passed
check toml...........................................(no files to check)Skipped
check yaml...........................................(no files to check)Skipped
poetry-check.........................................(no files to check)Skipped
- hook id: poetry-check
poetry-lock..............................................................Passed
- hook id: poetry-lock
- duration: 2.39s
Configuration file exists at $HOME/Library/Preferences/pypoetry, reusing this directory.
Consider moving TOML configuration files to $HOME/Library/Application Support/pypoetry, as support for the legacy directory will be removed in an upcoming release.
Updating dependencies
Resolving dependencies... (0.9s)
poetry-export........................................(no files to check)Skipped
- hook id: poetry-export
poetry-export........................................(no files to check)Skipped
- hook id: poetry-export
isort................................................(no files to check)Skipped
black................................................(no files to check)Skipped
flake8...............................................(no files to check)Skipped
mypy.................................................(no files to check)Skipped
mdformat.................................................................Passed
Update pyproject.toml version............................................Passed
Configuration file exists at $HOME/Library/Preferences/pypoetry, reusing this directory.
Consider moving TOML configuration files to $HOME/Library/Application Support/pypoetry, as support for the legacy directory will be removed in an upcoming release.
v0.2.1
v0.2.2
v0.2.3
v0.2.4
v0.2.5
v0.2.6
v0.2.7
v0.2.8
v0.2.9
Enumerating objects: 7, done.
Counting objects: 100% (7/7), done.
Delta compression using up to 4 threads
Compressing objects: 100% (4/4), done.
Writing objects: 100% (4/4), 451 bytes | 451.00 KiB/s, done.
Total 4 (delta 3), reused 0 (delta 0), pack-reused 0
remote: Resolving deltas: 100% (3/3), completed with 3 local objects.
To https://github.com/7rikazhexde/video-grid-merge.git
054237a..c6f792c main -> main
Total 0 (delta 0), reused 0 (delta 0), pack-reused 0
To https://github.com/7rikazhexde/video-grid-merge.git
* [new tag] v0.2.9 -> v0.2.9
.git/hooks/post-commit end!!!
[main c6f792c] docs(README): Changed installation description
2 files changed, 5 insertions(+), 5 deletions(-)
git log(コミット後)
video-grid-merge % git log --stat
commit c6f792c39cebb9ee6c21c6ae7c040573f4ddd995 (HEAD -> main, tag: v0.2.9, origin/main, origin/HEAD)
Author: 7rikaz_h785 <7rikaz.h785.stat2ltas41lcijad@gmail.com>
Date: Fri Jun 9 21:53:03 2023 +0900
docs(README): Changed installation description
README.md | 8 ++++----
pyproject.toml | 2 +-
2 files changed, 5 insertions(+), 5 deletions(-)
ローカルタグ情報(コミット後)
video-grid-merge % git tag
v0.2.1
v0.2.2
v0.2.3
v0.2.4
v0.2.5
v0.2.6
v0.2.7
v0.2.8
v0.2.9 # 追加
リモートタグ情報(コミット後)
% git ls-remote --tags origin
0ae7fa7be0457a3512c51c7a231f24e724570ffd refs/tags/v0.2.1
197a04bcf528e4c0ef5c297dff061d4d34ffea2b refs/tags/v0.2.2
01f88f943ee8330034530c14fb417bf45c5e651b refs/tags/v0.2.3
4212bfa0733f2c2c809f9db37333096b752a451e refs/tags/v0.2.4
52b72640df2f31edbef5c21e0fec149d67eafe04 refs/tags/v0.2.5
6de440811f4adbbd614f622ebed74450dfeaa951 refs/tags/v0.2.6
03b75ea8f4688c3e3b8e02c285093b9736a38d24 refs/tags/v0.2.7
054237a84bbe9233099c55af4ff2443145fbb4d8 refs/tags/v0.2.8
c6f792c39cebb9ee6c21c6ae7c040573f4ddd995 refs/tags/v0.2.9 # 追加
注意事項
git commit
時にコミットキャンセルした場合はpre-commit
は正常終了していますので、update-pyprojectフック(update_pyproject_version.py
)は動作します。結果、pyproject.toml
のtool.poetryテーブル
のversionキー
は更新されますので、その状態で再度コミットするとさらに0.0.1増加します。なので、この場合はversion
部分を手動で変更前の値に戻す必要があります。現状、コミットキャンセル処理は考慮していないのでこのようになっています。update_pyproject_version.py
ではv[major].[minor].[pathch]
でバージョン定義しますが、major
は0以上、[minor]と[pathch]
は0から999にしています。もし、0.1.0から0.2.0にminorバージョンを更新するためには0.1.999とする必要があります。まとめ
pyprojetc.toml
とgit tag
を更新するスクリプトを紹介しました。update_version.py
とcreate_git_tag.py
の2つのPythonスクリプトを作成し、pre-commit
とpost-commit
のgit hook
を使用してバージョン情報の更新を自動化しました。git tag
の更新を手動で行う必要がなくなり、ミスも減り、より効率的にプロジェクト管理ができるようになりました。参考