GitHub Actions v2 で Packer ビルドする

## はじめに

Packer で AWS AMI をビルドする方法について調べていると各自のローカル環境で実行するのを前提に実行ファイルをダウンロードすることが多いようです。
少し試すだけならローカルから実行で十分なのですが、継続的なビルドを考えると環境差異が生じたり場合によってはローカルに接続先 AWS 設定が複数あったりして安全ではないように思えます。
そこで GitHub Actions を使い、安定した環境で実行できるようにします。

Packer や GitHub Actions （まだベータなので申請が必要）がどういうものかについての説明は割愛します。
[10分で理解するPacker](https://qiita.com/Chanmoro/items/38e9d5441141f340e805) や [GitHub ヘルプ](https://help.github.com/ja/categories/automating-your-workflow-with-github-actions) をお読みください。

## コード

```yml:.github/workflows/packer.yml
name: Packer
on:
  push:
      paths:
        - '*.json'
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v1
      - name: packer validate packer.json
        uses: docker://hashicorp/packer:1.4.3
        with:
          args: validate packer.json
      - name: packer build packer.json
        uses: docker://hashicorp/packer:1.4.3
        with:
          args: build packer.json
        env:
          AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
          AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
          AWS_DEFAULT_REGION: ap-northeast-1
```

```json:packer.json
{
    "builders": [
        {
            "type": "amazon-ebs",
            "source_ami_filter": {
                "filters": {
                    "virtualization-type": "hvm",
                    "name": "ubuntu/images/*ubuntu-xenial-16.04-amd64-server-*",
                    "root-device-type": "ebs"
                },
                "owners": [
                    "099720109477"
                ],
                "most_recent": true
            },
            "instance_type": "t2.micro",
            "ssh_username": "ubuntu",
            "ami_name": "packer-example {{timestamp}}"
        }
    ]
}
```

## 解説

### packer.json
Packer の設定ファイルです。ファイル名は任意。
AMI 定義は [Build an Image - Getting Started - Packer by HashiCorp](https://www.packer.io/intro/getting-started/build-image.html#the-template) のファイルをお借りします。中身の説明は割愛。
環境変数で渡す部分は削除しています。

### .github/workflows/packer.yml
`.github/workflows/` ディレクトリにファイルを作成します。ファイル名は任意。

```yml
name: Packer
```
Actions タブに表示される名前です。任意の文字列。

```yml
on:
  push:
      paths:
        - '*.json'
```
[トリガー](https://help.github.com/ja/articles/events-that-trigger-workflows) です。実際はもう少し複雑な条件になると思います。

```yml
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v1
```
GitHub Actions に用意されている ubuntu イメージで実行します。（ Packer の実行は Docker コンテナで行うので ubuntu じゃなくても大丈夫なはずです。）
Packer の設定ファイルを参照したいのでコードもチェックアウトしておきます。

```yml
      - name: packer validate packer.json
        uses: docker://hashicorp/packer:1.4.3
        with:
          args: validate packer.json
```
まずは `packer validate` します。エラーになるとここで終了します。
GitHub Actions では専用に定義されたアクションだけでなく Docker コンテナイメージをアクションに使用できます。
[hashicorp/packer - Docker Hub](https://hub.docker.com/r/hashicorp/packer) を使います。
ENTRYPOINT に `bin/packer` が設定されているので args には `validate` 以降を渡します。
現時点の latest である 1.4.3 を指定していますがお好みで。

[ワークフローを設定する - GitHub ヘルプ](https://help.github.com/ja/articles/configuring-a-workflow#referencing-actions-in-your-workflow) によるとアクションは以下の3つが使えます。

* パブリックリポジトリ
* ワークフローファイルがアクションを参照するのと同じリポジトリ
* Docker ハブで公開されている Docker コンテナイメージ

```yml
      - name: packer build packer.json
        uses: docker://hashicorp/packer:1.4.3
        with:
          args: build packer.json
        env:
          AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
          AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
          AWS_DEFAULT_REGION: ap-northeast-1
```
エラーにならなければ `packer build` します。
`AWS_ACCESS_KEY_ID` と `AWS_SECRET_ACCESS_KEY` はログに出力されると困るのでリポジトリの Settings > Secrets に設定します。

## 実行結果

コードは GitHub に公開していますのでこちらから実行結果を確認できます。
[SnowCait/github-actions-packer-example@2d76fe9](https://github.com/SnowCait/github-actions-packer-example/commit/2d76fe9ad1e89482d768897f41a9f9348380362d/checks)

## おわりに

Qiita へは初投稿になります。
最初の記事は何を書こうかな？と思っていたのですが、ちょうど GitHub Actions のベータ申請が通ったのと Packer を触る機会があり課題を抱えていたので実装してみました。
GitHub Actions には期待しているので今後も記事を書いていこうと思っています。
ネタがあったらコメントいただけると嬉しいです。