GitHub
docker
Terraform

GitHub の Organization を Terraform で管理する

Otaku Dev と言う GitHub Organization を管理(放置)しているのだが、2018年から真面目に使おうと思い手始めに Terraform で管理する事にした。
あまり日本語の記事を見かけないので(多分 AWS や GCP の構築記事に埋もれてる)誰かのためになればと思い書いておく。

コードだけ見ればいいと言う方はこちらをどうぞ。
https://github.com/otaku-dev/github-management

1. Terraform のインストール

同僚の影響で brew でインストールしたくない病にかかっているので、 Terraform の実行には Docker を使う。
イメージは hashicorp のをそのまま採用。
https://hub.docker.com/r/hashicorp/terraform/

Docker のインストールなどは割愛するけど自分は普通に Docker for Mac を利用している。
まずは手元で実行できるようにイメージを落として確認してみる。

$ docker pull hashicorp/terraform:light
$ docker run -i -t hashicorp/terraform:light

2. GitHub のトークンを発行

この記事読むような人ならサクッと発行できるはず。

3. 新規にリポジトリを作ってみる

公式ドキュメントを参考にまずは適当なリポジトリを作ってみる。
https://www.terraform.io/docs/providers/github/index.html

github.tf
provider "github" {
  token        = "${var.github_token}"
  organization = "${var.github_organization}"
}
variables.tf
variable "github_token" {}
variable "github_organization" {}
example.tf
resource "github_repository" "example" {
  name = "example"
}
$ docker run -i -t -v $(pwd):/code/ -w /code/ hashicorp/terraform:light init \
  -var 'github_token=foo' \
  -var 'github_organization=bar'
$ docker run -i -t -v $(pwd):/code/ -w /code/ hashicorp/terraform:light plan \
  -var 'github_token=foo' \
  -var 'github_organization=bar'
$ docker run -i -t -v $(pwd):/code/ -w /code/ hashicorp/terraform:light apply \
  -var 'github_token=foo' \
  -var 'github_organization=bar'

これで新規に example リポジトリが作成されたはずです。
テスト用に作成しただけなので次のコマンドでリポジトリを削除します。

$ docker run -i -t -v $(pwd):/code/ -w /code/ hashicorp/terraform:light destroy \
  -var 'github_token=foo' \
  -var 'github_organization=bar'

4. コマンドの実行を簡単にする

毎回長いオプションを叩くのは面倒なのでスクリプトを書きましょう。
シェルスクリプトは得意ではないので、もっと良い書き方があれば教えてくれると助かります。

bin/terraform
#!/usr/bin/env bash

set -eu

SCRIPT_DIR=$(cd $(dirname $0); pwd)

cd $SCRIPT_DIR/../

docker run --env-file .env -i -t -v $(pwd):/code/ -w /code/ hashicorp/terraform:light $@
.env
GITHUB_ORGANIZATION=bar
GITHUB_TOKEN=foo
github.tf
- provider "github" {
-  token        = "${var.github_token}"
-  organization = "${var.github_organization}"
- }
+ provider "github" {} 
variables.tf
- variable "github_token" {}
- variable "github_organization" {}

トークンについては色々と検討しましたが、最終的に CircleCI で実行するようにしたかったので環境変数を利用する事にしました。
また後述する Backends を使う為にも環境変数である必要がありました。

これで次のコマンドだけで実行できるようになったはずです。

$ ./bin/terraform plan

5. tfstate ファイルを S3 で管理する

Terraform v0.11でAmazon S3 backendを使ってtfstateファイルを管理する
説明はこの記事に任せた。

変更点はこんな感じです。

terraform.tf
terraform {
  backend "s3" {
    bucket = "example-bucket"
    key    = "terraform.tfstate"
  }
}
.env
+ AWS_ACCESS_KEY_ID=Hoge
+ AWS_SECRET_ACCESS_KEY=Fuga
+ AWS_DEFAULT_REGION=ap-northeast-1
GITHUB_ORGANIZATION=bar
GITHUB_TOKEN=foo
$ ./bin/terraform init

6. CircleCI でビルドする

CircleCI に適切な環境変数を設定し、下記の設定を追加します。
今回は Pull Requests で terraform plan を実行し、マージされたタイミングで terraform apply するようにしました。
多分もっと正しい書き方があるとは思うのですが、正直調べるのが面倒だったのとこれで動いたからいいやーで放置してます。

.circleci/config.yml
version: 2
jobs:
  terraform-plan:
    docker:
      - image: hashicorp/terraform:light
    steps:
      - checkout
      - run: terraform init
      - run: terraform plan
  terraform-apply:
    docker:
      - image: hashicorp/terraform:light
    steps:
      - checkout
      - run: terraform init
      - run: terraform apply -auto-approve

workflows:
  version: 2
  build-deploy:
    jobs:
      - terraform-plan:
          filters:
            branches:
              ignore: master
      - terraform-apply:
          filters:
            branches:
              only: master  

7. 管理するリソースを追加する

あとは黙々と管理するリソースを追加していくだけです。

気をつける点としては次のブログのような事故をおこなさいことくらいでしょうか。
TerraformでGitHubのチーム管理を自動化して事故った話

この対策として管理者である自分のアカウントだけは Terraform で管理させないようにしました。
それで特に問題ないと思っています。

また GitHub Pages を使う為に otaku-dev.github.io というリポジトリ名などにしていると、命名規則でエラーになって管理できません。
もしかしたら管理する方法があるのかもしれませんが、そこまで厳密に管理したいわけじゃないのでこちらも調べていません。

まとめ

GitHub Organization の管理が増えて大変になる前に Terraform を使ってスマートにやっていきましょう。