本記事は カケハシ 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 の
yamllint
hook は、yamllint
でyaml
ファイルのフォーマットをチェックします - https://github.com/asottile/pyupgrade の
pyupgrade
hook は、pyupgrade
Python の古い記述を新しい記述に更新します - https://github.com/pycqa/isort の
isort
hook は、isort
を使用して Python の import 文を整形しますadditional_packages
にtoml
を指定することで、pyproject.toml
に記載された設定を読み込みます
- https://github.com/psf/black の
black
hook は、black
を使用して Python のコードをフォーマットしますargs
で引数に--config pyproject.toml
を指定することで、pyproject.toml
に記載された設定を読み込みます
- https://github.com/PyCQA/flake8 の
flake8
hook は、flake8
Python のコードを lint しますadditional_packages
にpyproject-flake8
を指定して、entry
にpflake8
を指定することで、flake8
が対応していないpyproject.toml
から設定を読み込むことができます。
- https://github.com/pre-commit/mirrors-mypy の
mypy
hook は、mypy
を使用して Python の型チェックを実行しますadditional_packages
に使用するパッケージの型スタブ パッケージを指定しています
- https://github.com/pre-commit/mirrors-prettier の
prettier
hook は、Prettier を使用してファイルフォーマットを行います- YAML ファイルや JSON ファイルに対応しているため、GitHub Actions の設定ファイルや
renovate.json
をフォーマットできるので、 Python プロジェクトのリポジトリでも入れる価値は大きいです
- YAML ファイルや JSON ファイルに対応しているため、GitHub Actions の設定ファイルや
- https://github.com/python-poetry/poetry の
poetry-check
hook は、 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つの理由」です。お楽しみに!