こんにちは。BASE BANK株式会社 Dev Division にて、 Software Developer をしている東口(@hgsgtk)です。Stay Homeで仕事していく中で、ちょっとした面倒事を解消するような小ネタが溜まってきたので、一つお届けします。
TL;DR
- リポジトリ作成時には、毎回CIの設定・
.editorconfig
・.gitignore
の配置、最低限のHello Worldコードの作成など、定形作業が存在する - 自分たち用のボイラープロジェクトを作成するCLIを用意するのも一つの手だが、気軽にサクッと出来る方法として、GitHubのTemplate Repositoryがある
- Goプロジェクト作成時に実際に活用しているTemplate Repositoryをご紹介する
背景
BASE BANKでは、「YELL BANK(エールバンク)」というサービスの開発・運営を中心に、Goを用いてアプリケーション開発を行っています。
よくある面倒事として、新規にGoプロジェクトを作成する際に毎回作業するようなCI (Contenious Integration) の設定などがあります。
これは、Go言語に限った話ではありませんが、新規リポジトリを作成すると毎回脳死してコピペを行いがちなものがあります。
今回は、そんな面倒事をGitHubのTemplate Projectを用いてちょっとだけ省力化するお話です。
GitHubのTemplate Repositoryとは
Template Repositoryとは、「テンプレートリポジトリを作成する」で説明のある通り、既存のリポジトリをテンプレートにして同じディレクトリ構造・ブランチ・ファイルで新しいリポジトリを生成できるようになる機能です。
既存のリポジトリをテンプレートにして、自分や他の人が同じディレクトリ構造、ブランチ、およびファイルで新しいリポジトリを生成できるようにすることができます。
始め方は、非常にかんたんで、リポジトリの Settings にて、 Template repository にチェックを入れるだけです。
こうして、チェックを入れると、新規リポジトリ作成時に、次のようにテンプレートが選択できるようになります。
実際にテンプレートを選択すると、Template Repositoryの内容をコピーした形で新規リポジトリを作成できます。この機能を用いて、自分たちの定形作業をTemplate Repositoryに入れておくと、面倒事を少し解消することができます。
以下、具体的にどういう内容を入れているか、実際に活用しているGoプロジェクト用のTemplate Repositoryをご紹介します。
どういうことをしているか
BASE BANK Devでは、Goアプリケーションの新規リポジトリを作成することが多いのですが、次の内容をTemplate Repositoryに入れています。
- CircleCIの設定
- GitHub Actionの設定
- Hello WorldなGoコード(
go.mod
・go.sum
と一緒に)
$ tree -L 2 -la . ├── .circleci │ └── config.yml ├── .editorconfig ├── .github │ ├── PULL_REQUEST_TEMPLATE.md │ └── workflows ├── .gitignore ├── .golangci.yml ├── README.md └── app ├── Dockerfile ├── Makefile ├── go.mod ├── go.sum └── main.go
CircleCIの設定
GoコードにおけるCircleCIの自動Lint・テストは、次世代型イメージのcimg/goを使用した設定をしています。毎回コピペするのも面倒なので、レポジトリ作成時に生まれてくれると面倒事をさばく人生の時間が減って少しだけ幸せです。
version: 2.1 jobs: test-app: environment: TZ: "Asia/Tokyo" GO111MODULE: "on" docker: - image: cimg/go:1.14.4 environment: GOCACHE: "/tmp/go/cache" TEST_RESULTS: /tmp/test-results steps: - checkout - run: mkdir -p $TEST_RESULTS - restore_cache: key: gopkg-{{ checksum "app/go.sum" }} - run: name: mod download command: | cd app go mod download - save_cache: key: gopkg-{{ checksum "app/go.sum" }} paths: - /home/circleci/go/pkg/mod - restore_cache: keys: - build-cache-{{ .Branch }}-{{ .Environment.CIRCLE_PREVIOUS_BUILD_NUM }} - run: name: install-gotools command: | cd app go get github.com/fzipp/gocyclo - run: name: build command: | cd app mkdir -p $GOCACHE go build -v - run: name: test command: | cd app gotestsum --junitfile ${TEST_RESULTS}/unit-tests.xml -- -p 6 -race -cover ./... - run: name: calcurate-cyclomatic-complexities command: | cd app gocyclo -avg $(find . -name "*.go" | grep -v _test) - save_cache: key: build-cache-{{ .Branch }}-{{ .Environment.CIRCLE_BUILD_NUM }} paths: - /tmp/go/cache - store_artifacts: path: /tmp/test-results - store_test_results: path: /tmp/test-results workflows: version: 2 test: jobs: - test-app
この設定内容自体については、同僚の@budougumi0617さんが「[Go]次世代イメージcimg/goとcircleci/go Orbsを使った2020年版CircleCIの環境構築」で解説しているのでそちらをご覧になってみてください。
GitHub Actionの設定
.github
ディレクトリ以下も、おまじないのように作るものが多い場所の一つでしょう。たとえば、PULL_REQUEST_TEMPLATE.md
などは初手で作ることが多いです。それに加えて、GitHub Actionの設定もある程度共有できるものが多くなるため、それらもTemplate Repositoryという形で共有しています。
ReviewDogによるgolangci-lint実行
GoコードのLintにgolangci-lintを用いているのですが、その指摘内容をGitHubのコメントとして反映するため、ReviewDogを用いています。
具体的には、reviewdog/action-golangci-lintを活用しています。
実際に行っているのは、公式の解説どおりですが、以下のような設定を配置しています。
name: reviewdog on: [pull_request] jobs: golangci-lint: name: runner / golangci-lint runs-on: ubuntu-latest steps: - name: Check out code into the Go module directory uses: actions/checkout@v1 - name: golangci-lint uses: reviewdog/action-golangci-lint@v1 with: github_token: ${{ secrets.GITHUB_TOKEN }} golangci_lint_flags: "--config=.golangci.yml ./..."
golangci-lint自体の設定もTemplate Repositoryに同梱しているため、レポジトリを作成すれば即座にgolangci-lintのチェック下に置かれます。
Hello WorldなGoコード
Go Modulesを用いる前提で Hello World コードを用意しています。主にAPIサービスを作る際に、app/
ディレクトリ以下にアプリケーションコードを置くことが多いため、app/
以下にmain.goを配置します。配置しているコードは、Go公式ブログの「Using Go Modules」に例示されているコードを微修正して置いています。
package main import ( "fmt" "rsc.io/quote" ) var ( revision = "default" ) func main() { fmt.Println(hello()) } func hello() string { return quote.Hello() + "by " + revision }
また、テンプレ的に毎回用意するようなDockerfileも合わせて用意しています。
FROM golang:1.14.3-alpine3.11 as deploy-builder WORKDIR /app RUN apk add --no-cache git ENV GO111MODULE=on COPY . . ARG REVISION="default" RUN go build -ldflags "-X main.revision=${REVISION}" FROM alpine as deploy RUN apk add --no-cache tzdata && \ cp /usr/share/zoneinfo/Asia/Tokyo /etc/localtime && \ echo "Asia/Tokyo" > /etc/timezone COPY --from=deploy-builder /app/app . CMD ["./app"]
これらでどう嬉しくなったか
上記で紹介した以外にも脳死してコピペしていた .editorconfig
なども最初から用意されるので、新規リポジトリ作成時の心のハードルが下がりました。
これからの課題としては、既存リポジトリの知見をTemplate Repositoryに反映していく流れや、デプロイフローについてのある程度の共有を図りたいと思っています。
最後に
Template Repositoryは、とくに特別な工数が発生するわけではない手軽な方法として、身近な面倒事を減らせる手になります。活用の仕方として参考になれば幸いです。