本記事は カケハシ Advent Calendar 2022 10 日目の記事です。
Musubi 開発チームの加藤です。1 年ぶり ですね。 今回は「私の開発環境 2022 冬」をお送りしようと思ったのですが、今年はリポジトリをたくさんセットアップしたので、 「リポジトリを作成したら最初にすること」をお送りします1。
はじめに
プロジェクトなり個人開発なりでリポジトリを作成する際、組織や開発者の中で共通して使用するツールやその設定ファイルがあると思います。
2022 年を通じて自分の中である程度型ができてきたので、それをご紹介しようと思います。
前提
Python で実装したコードを Serverless Framework で AWS Lambda にデプロイするケースをモデルとして、リポジトリを設定していきます。
初期状態は、GitHub リポジトリを作成直後のリポジトリ名が入った README.md がある状態から開始します。
思想
- 「計算機がチェックできることはすべてチェックさせる」
- 「各コミット時点で可能な限り環境が固定されている状態を保つ」
- 「可能な限り仕組みを自作せずにサードパーティーのツールに頼り、楽をする」
の 3 点です。
.gitignore を作成する
.gitignore は、リポジトリに含めたくないファイルを指定するファイルです。
手作りすることもできますが、使用するツールや環境に合わせて gitignore.io で作成すると良いです。
今回は実装言語である Python, デプロイするために用いる Serverless Framework, その実行言語の Node.js, そして各 OS を指定して作成しました。

作成ボタンを押下すると、生成された .gitignore が表示されます。
ブラウザからコピペするか、URL をコピペして、 curl で取得することもできます。
curl $(pbpaste) > .gitignore
また、ファイル冒頭には作成時の情報の URL がコメントに記載されているため、 対象を追加・削除するときはその URL を参照してください。
Created by をクリックすると同じ対象で .gitignore を取得できます。
Edit at をクリックすると同じ対象を選択した状態で選択画面に遷移します。
# Created by https://www.toptal.com/developers/gitignore/api/macos,linux,windows,python,serverless,node # Edit at https://www.toptal.com/developers/gitignore?templates=macos,linux,windows,python,serverless,node
.editorconfig を作成する
.editorconfig は、エディタに依存せずにインデントや改行の扱いを共有するためのファイルです。
Visual Studio Code, Vim, JetBrains 製品 など多くのエディタ でサポートされています。
公式ページ に基礎的な使い方が記載されています。
今回は以下の内容にしました。
# Editor configuration, see https://editorconfig.org/ root = true # リポジトリトップに配置する場合は、より上位のディレクトリの影響を防ぐために必要 [*] # 全ファイル共通の設定(上書き可) charset = utf-8 # 文字コードを UTF-8 とする end_of_line = lf # 改行コードを LF とする indent_size = 2 # インデント幅を 2 とする indent_style = space # インデントをスペースで行う insert_final_newline = true # ファイル末尾に改行を入れる trim_trailing_whitespace = true # 行末の空白を削除する [*.py] # .py ファイルのみに適用する設定 indent_size = 4 # インデント幅を 4 とする
Renovate を設定する
Renovate は、依存ライブラリや言語処理系の更新を自動化するツールです(無料!)。
デフォルトブランチにある renovate.json 2 に設定を記載することで、自動的に PR 作成やマージをおこなってくれます。
初期段階で入れるのはこんな感じです。
{ "$schema": "https://docs.renovatebot.com/renovate-schema.json", "extends": [ "config:base", ":timezone(Asia/Tokyo)", ":enablePreCommit", "group:recommended", "group:monorepos" ], "schedule": [ "after 10:30 before 18:00 every weekday except after 12:00 before 13:00" ], "labels": ["renovate"], "pin": { "automerge": false }, "pinDigest": { "automerge": false }, "lockFileMaintenance": { "enabled": true }, "packageRules": [ { "matchManagers": ["pre-commit"], "automerge": true }, { "matchPackageNames": ["python"], "allowedVersions": "<3.10" }, { "groupName": "boto3", "matchPackageNames": [ "boto3", "boto3-stubs", "botocore", "botocore-stubs" ], "automerge": true }, { "groupName": "serverless", "matchPackageNames": [ "serverless", "serverless-plugin-lambda-insights", "serverless-prune-plugin", "serverless-python-requirements" ] } ] }
上から設定内容を説明します。
$schemaで、このファイルのスキーマを指定する。これをすることで Visual Studio Code などのエディタで補完が効くようになるconfig:baseをextendsに指定して、基本的な設定を継承する:timezone(Asia/Tokyo)をextendsに指定して、時刻指定のタイムゾーンを日本時間にする:enablePreCommitで、後述のpre-commitの hook の更新を有効にするgroup:recommended,group:monoreposをextendsに指定して、メジャーなパッケージをグループ化して 1 つの PR で更新できるようにするscheduleで、平日の 10:30 〜 18:00 のみ動作させるlabelsで、Renovate が作成した PR にrenovateラベルを付与するpin,pinDigestに"automerge": trueを指定して、ピン留めの PR を自動マージするlockFileMaintenanceに"enabled": trueを指定して、package-lock.jsonやpoetry.lockの更新 PR を有効にする- 以下
packageRulesの指定pre-commit(後述)の hook の更新は自動マージする- Python のバージョンを 3.10 未満に制限する(AWS Lambda のランタイムが 3.9 までなので)
- boto3 および関連パッケージは 1 つの PR にまとめて自動マージする(デプロイに含めず AWS Lambda 上のものを使用するので、ローカルも常に最新を使う)
- Serverless Framework および関連プラグインを 1 つの PR にまとめる
プロジェクトや開発フェーズによってポリシーが異なるので、適宜変更すると良いと思います。
また、 renovate.json の記述ミスに備えて、以下の GitHub Actions workflow を設定します。
name: Validate renovate.json on: push: branches: - main # メインブランチ名で置き換えてください paths: - renovate.json pull_request: branches: - main # メインブランチ名で置き換えてください paths: - renovate.json jobs: validate: runs-on: ubuntu-latest timeout-minutes: 10 steps: - uses: actions/checkout@v3 - name: Validate renovate.json uses: rinchsan/renovate-config-validator@v0.0.12 with: pattern: renovate.json
.python-version と .node-version の設定
pyenv と nodenv を使っている場合3、 .python-version と .node-version に、プロジェクトの Python と Node.js のバージョンを記載します。
このファイルは開発者間のバージョン分散を防ぐ他にも
actions/setup-python action や actions/setup-node action の
python-version-file や node-version-file に渡すことができ、また Renovate が更新 PR を作成してくれるため、
Renovate が更新 PR を作成する -> GitHub Actions で新しいバージョンで CI を実行 -> 通過したらマージ
というフローを組むことができるので大変便利です。
pre-commit と各種 hook の設定
pre-commit は、 Git の pre-commit hook から lint, formatter 等を実行するツールです。 pre-commit の個々の処理もまた "hook" と呼ばれています。
Homebrew 等で pre-commit をインストールした後、設定ファイル .pre-commit-config.yaml があるリポジトリで pre-commit install を実行すると、
Git hooks に自身を呼び出すコードをインストールしします。
すると git commit コマンドを実行するときに各 hook を実行して、そのうち 1 つでも失敗するとコミットを中止します4。
Formatter の hook は未フォーマットのため失敗した時はファイルを書き換えた状態で停止するので、再度 git add してからもう一度 git commit をすればコミットができます。
.pre-commit-config.yaml に、以下のような hook の設定を記載します。
- https://github.com/pre-commit/pre-commit-hooks は、
pre-commitが提供する共通の hook リポジトリです。trailing-whitespaceは行末の空白を削除します.gitignoreに CR で終わる行があるため、この hook の適用対象から除外しています
end-of-file-fixerはファイルの末尾に改行を追加しますcheck-added-large-filesはコミットに大きなサイズのファイルのコミットを防ぎます
- https://github.com/adrienverge/yamllint.git の
yamllinthook は、yamllintでyamlファイルのフォーマットをチェックします - https://github.com/asottile/pyupgrade の
pyupgradehook は、pyupgradePython の古い記述を新しい記述に更新します - https://github.com/pycqa/isort の
isorthook は、isortを使用して Python の import 文を整形しますadditional_packagesにtomlを指定することで、pyproject.tomlに記載された設定を読み込みます
- https://github.com/psf/black の
blackhook は、blackを使用して Python のコードをフォーマットしますargsで引数に--config pyproject.tomlを指定することで、pyproject.tomlに記載された設定を読み込みます
- https://github.com/PyCQA/flake8 の
flake8hook は、flake8Python のコードを lint しますadditional_packagesにpyproject-flake8を指定して、entryにpflake8を指定することで、flake8が対応していないpyproject.tomlから設定を読み込むことができます。
- https://github.com/pre-commit/mirrors-mypy の
mypyhook は、mypyを使用して Python の型チェックを実行しますadditional_packagesに使用するパッケージの型スタブ パッケージを指定しています
- https://github.com/pre-commit/mirrors-prettier の
prettierhook は、Prettier を使用してファイルフォーマットを行います- YAML ファイルや JSON ファイルに対応しているため、GitHub Actions の設定ファイルや
renovate.jsonをフォーマットできるので、 Python プロジェクトのリポジトリでも入れる価値は大きいです
- YAML ファイルや JSON ファイルに対応しているため、GitHub Actions の設定ファイルや
- https://github.com/python-poetry/poetry の
poetry-checkhook は、 Poetry の設定ファイルをチェックします localリポジトリで custom hook を作成しますadditional_packagesに書いたパッケージをインストールした上で、entryに記載のsecretlintを実行します
# See https://pre-commit.com for more information # See https://pre-commit.com/hooks.html for more hooks repos: - repo: https://github.com/pre-commit/pre-commit-hooks rev: v4.3.0 hooks: - id: trailing-whitespace exclude_types: - gitignore - id: end-of-file-fixer - id: check-added-large-files - repo: https://github.com/adrienverge/yamllint.git rev: v1.28.0 hooks: - id: yamllint - repo: https://github.com/asottile/pyupgrade rev: v3.2.2 hooks: - id: pyupgrade - repo: https://github.com/pycqa/isort rev: 5.10.1 hooks: - id: isort additional_dependencies: - toml - repo: https://github.com/psf/black rev: 22.10.0 hooks: - id: black args: ["--config", "pyproject.toml"] - repo: https://github.com/PyCQA/flake8 rev: 5.0.4 hooks: - id: flake8 entry: pflake8 additional_dependencies: - pyproject-flake8 - repo: https://github.com/pre-commit/mirrors-mypy rev: v0.971 hooks: - id: mypy name: mypy additional_dependencies: - "boto3-stubs[s3,dynamodb,cloudfront,stepfunctions]" - typing-extensions - types-python-dateutil - repo: https://github.com/pre-commit/mirrors-prettier rev: v2.7.1 hooks: - id: prettier - repo: https://github.com/python-poetry/poetry rev: 1.2.2 hooks: - id: poetry-check - repo: local hooks: - id: secretlint name: secretlint language: node additional_dependencies: - "secretlint" - "@secretlint/secretlint-rule-preset-recommend" entry: secretlint
.pre-commit-config.yaml に記載した各 hook の設定内容は別途必要です。
yamllint の設定
.yamllint を以下の内容で作成します。
デフォルトのルールからマッチしないものを削っています。
--- # https://yamllint.readthedocs.io/en/stable/configuration.html yaml-files: - "*.yaml" - "*.yml" - ".yamllint" rules: braces: enable brackets: enable colons: enable commas: enable comments: level: warning comments-indentation: level: warning document-end: disable document-start: disable empty-lines: enable empty-values: disable hyphens: enable indentation: enable key-duplicates: enable key-ordering: disable line-length: disable new-line-at-end-of-file: enable new-lines: enable octal-values: disable quoted-strings: disable trailing-spaces: enable truthy: level: warning
isort, black, flake8, mypy の設定
isort, black, flake8, mypy の 4 つのツールは、 pyproject.toml に設定を記載します。
[tool.isort] combine_as_imports = true default_section = "THIRDPARTY" include_trailing_comma = true sections = "FUTURE,STDLIB,THIRDPARTY,FIRSTPARTY,LOCALFOLDER" line_length = 119 # black と合わせる multi_line_output = 3 [tool.black] line-length = 119 # isort と合わせる target-version = ['py39'] include = '\.pyi?$' [tool.flake8] # black や isort と干渉するチェックを除外 # https://www.flake8rules.com/ # Whitespace before ':' (E203) # Line too long (82 > 79 characters) (E501) # Redefinition of unused name from line n (F811) # Line break occurred before a binary operator (W503) # Do not use variables named 'I', 'O', or 'l' (E741) ignore = "E203,E501,F811,W503,E741" exclude = ".git,__pycache__/*" max-complexity = 10 [tool.mypy] disallow_untyped_defs = true ignore_missing_imports = true python_version = 3.9
Prettier の設定
package.json, package-lock.json はフォーマットされると困ることがあるので、
Prettier の適用外にするため .prettierignore を作成して記載します。
package*.json
secretlint の設定
secretlint の設定は .secretlint.json で行います。
{ "rules": [ { "id": "@secretlint/secretlint-rule-preset-recommend" } ] }
pre-commit を GitHub Actions で実行する
pre-commit は、ローカルでユーザが pre-commit install を実行することで、
そのリポジトリの Git hooks にインストールされ git commit 等を実行した時に実行されるようになり、
チェックを通過しない場合はコミットを中断します。
稀にユーザが pre-commit install を実行せずにコミットを行ってしまった場合にそなえ、
pre-commit/action action を CI で実行すると良いです。
pre-commit/action は、 pre-commit run --all-files を実行して、Pass すれば成功、Fail すれば失敗となる action です。
.github/workflows/pre-commit.yml を以下の内容で作成します。
name: pre-commit on: pull_request: push: branches: - main # メインブランチ名で置き換えてください jobs: pre-commit: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - uses: actions/setup-python@v3 - uses: pre-commit/action@v3.0.0
README.md
せっかくツールを導入しても、使ってもらわないと意味がありません。
リポジトリの玄関である README.md に使い方を記載しましょう。
# 【リポジトリ名】 【リポジトリを端的に説明する文章】 ## 必要なツール 以下のツールを事前にインストールしてください。 - [nodenv]() - [pyenv]() - 上記 2 つは [anyenv]() を経由してインストールすると良い - [pre-commit]() 使用しているエディタが [EditorConfig](https://editorconfig.org/) に対応しているか確認してください。 https://editorconfig.org/#pre-installed ## セットアップ リポジトリをチェックアウトしたら最初に以下を実行してください。 ```shell pre-commit install nodenv install pyenv install ``` 【その他】 大事なこと
さいごに
以上が、2022 年中のリポジトリセットアップで共通して設定している内容です。
初期にガッチリ設定してしまえば、以降の開発はかなり楽になります。 テンプレートリポジトリ化しておきましょう。
Node.js バージョンなどもそのうち書きたいと思います。
もっと便利なツールを知ってる方は是非カケハシへ!
明日は中野さんの「Prophetが新型ウイルス感染者数予測に適していない2つの理由」です。お楽しみに!