nikkie-ftnextの日記

イベントレポートや読書メモを発信

PyPIに公開するライブラリ開発で同じGitHub Actions定義を毎回書くことに気づき、実験的に ftnext/cookiecutter-develop-pypackage はじめました🍪

はじめに

ミリオンライブ!の劇場上映、めっちゃよかったあああ!! nikkieです。

自分の開発で繰り返し書くファイルを、Cookiecutterでコマンド一発で生成できるようにするのをお試し中という話です(※やってみるけどうまくいかないかもしれません)

目次

ライブラリを開発していて

先日hayasaka1をリリースする中で、いつも書いているGitHub Actionsの定義(YAMLファイル群)に気づきました。

過去に開発したライブラリのActionsの定義を見て写経するのですが、「ライブラリごとに変わる箇所はなさそうだぞ」と気づきました。
ちょうどCookiecutterを触り出した2こともあり、テンプレート化しようと考えたのです、はいほー!

ftnext/cookiecutter-develop-pypackage

実行すると(デフォルト値で作る例です)

% cookiecutter https://github.com/ftnext/cookiecutter-develop-pypackage --checkout 0.1.0
  [1/2] project_dir_name (awesome-project):
  [2/2] package_name (awesome_project):

次のようなファイル群ができます!

.
└── awesome-project/
    ├── .github/
    │   └── workflows/
    │       ├── testing.yml
    │       └── publish.yml
    ├── awesome_project/
    │   ├── __init__.py
    │   └── __main__.py
    ├── tests/
    │   └── __init__.py
    ├── pyproject.toml
    └── setup.py

開発の一番最初にこれらを生成することで、開発のスタートダッシュを切るのが目的です

生成するファイルの内訳

パッケージ

2つのPythonパッケージ(__init__.pyを持つディレクトリ)を生成します

  • 開発対象のプロジェクト(例ではawesome_project
    • python -mに対応する__main__.pyも作っておきます(不要なら消す想定)
  • テストコード(tests

pyproject.toml

以下で一覧した設定値をTODO項目を含めて生成します。
TODOはライブラリごとに異なるので(例:description)、開発者が都度解消する想定です

なお、taskipyの設定はftnext/cookiecutter-taskipy3に譲ることにしました

GitHub Actionsの定義ファイル

2つのYAMLファイルを生成します。
これらの元はGitHub Actionsのドキュメントの中にあるんですよ〜

  • testing.yml
    • Python スターター ワークフローの使用YAMLファイルをベースにしています
      • Ruffを使うなど先進的!
    • 私はtaskipyを使うことが多いのでtask testに置き換えました(書いてて気づきましたが、上で譲った点とちょっと矛盾がありますね。TODOです)
  • publish.yml

テンプレートを書く中での学び

GitHub ActionsのYAMLファイルの中には${{ matrix.python-version }}${{ secrets.PYPI_API_TOKEN }}があります。
cookiecutterコマンドを実行すると、このmatrixやsecretsが未定義変数ということでエラーが送出されたのです

対処法を調べたところ、Jinja2テンプレートの{% raw %}ブロックを使うと展開されなくできることを知ります https://github.com/cookiecutter/cookiecutter/issues/1624#issuecomment-1076475537

  • {% raw %}
  • Whitespace Controlも参照しました
    • {% raw %}だと空行が入る(YAMLファイルとしてはあってもよいが、ちょっとかっこ悪い4
    • {%- raw %}にすると、rawブロックのの空白文字を除く、つまり、{% raw %}だと入る空行が除けます
      • If you add a minus sign (-) to the start or end of a block」というところに書いてあります

Jinja2がテンプレート中の全変数表記を展開しようとするのは驚きでしたが、今回は{% raw %}ブロックで対処できました🙌

終わりに

ftnext/cookiecutter-develop-pypackage 0.1.0を公開しました。
毎回同じGitHub Actions定義を書いているので、開発の最初にコマンド一発で生成し、スタートダッシュを切るという意図があります。
{{ ham }}を含むファイルをテンプレートに加えたことで学びもありました。

このテンプレートは自分で使いながら(=ドッグフーディング🐶)ちょっとずつでも改善していく想定です。
実験中ではありますが、私も使いたいと思ってくださった方は(とっても嬉しい!)、cookiecutterコマンドの--checkoutでタグを指定してください〜

P.S. 同じ定義をいくつも自動生成する代わりに、再利用という道もある

GitHub Actionsの再利用にキャッチアップするという道もあります(宿題事項)

今回のテンプレートは、依存するActionのバージョンアップにも追従するように変更していけるかなと目論んでいますが、その場合いろんなリポジトリにちょっとずつ違うYAMLファイルができちゃうのでは。
再利用の道の方がよいかもですね(大本のワークフローを更新していけば全リポジトリに反映されるため)


  1. 最高の一枚を撮れるように引き続き開発中です。
  2. カッコつけたいお年頃なのです😎