0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Github Actionsの作り方(Docker編)

Posted at

以前、checkovをreviewdogに対応させた話terraformのコードリポジトリで静的解析を実行する仕組みを作りましたが、それをGithub Actionsとして世に公開していこうと思います。

Github Actionsの種類

Github ActionsにはPrivate ActionPublic Actionの2種類があります。

Private ActionはCIを実行するリポジトリのなかに直接埋め込まれているタイプで、以下のようなディレクトリ構成になっています。

├ .github/
 ├ actions/
    └ action.yml
    └ Dockerfile
    └ entrypoint.sh
 ├ workflows/
   └ main.yml
... 以下略

Private Action./github/workflows/main.yamlで以下のように相対パスで呼び出すことができます。

- uses: ./.github/actions/tflint-reviewdog
  with:
    github_token: ${{ secrets.github_token }}
    reporter: github-pr-check
    fail_on_error: "true"
    filter_mode: "nofilter"

一方でPublic Actionは専用のリポジトリとして作成され、別のリポジトリから呼び出すことができます。

Public Actionは一度作ってしまえば複数のリポジトリで使いまわしが出来きるという点で便利です。今回はPublic Actionの作り方を説明していきます。

ディレクトリ構成

今回作成するPublic Actionのディレクトリ構成は以下の通りです。

├ .github/
 ├ workflows/
   └ test.yml
 ├ testdata/
   └ example.tf
└ action.yml
└ Dockerfile
└ entrypoint.sh
└ parse.py
└ requirements.txt

action.yml

Github Actionを作るえうで必ず必要になるファイルです。とは言え設定はとても簡単です。
設定項目は主に引数と動作環境の指定です。

以下の内容ですと、引数としてリポジトリを操作するために必要なgithub_tokenに加えて、checkovreviewdogというツールのオプション値を引数として受け取れるように設定しています。

また、using: 'docker'でコンテナとして動作するように指定しています(コンテナ以外にもJavascriptなどで動作させることもできます)。

name: 'Checkov with Reviewdog GitHub Action'
author: 'Ishii1648'
description: 'Run Checkov with Reviewdog against Terraform/CloudFormation infrastructure code, as a pre-packaged GitHub Action.'
inputs:
  github_token:
    description: 'GITHUB_TOKEN'
    required: true
  reporter:
    description: |
      Reporter of reviewdog command [github-pr-check,github-pr-review].
      Default is github-pr-check.
    default: 'github-pr-check'
  filter_mode:
    description: |
      Filtering for the reviewdog command [added,diff_context,file,nofilter].
      Default is added.
    default: 'added'
  fail_on_error:
    description: |
      Exit code for reviewdog when errors are found [true,false]
      Default is `false`.
    default: 'false'
  working_directory:
    description: |
      Directory to run the action on, from the repo root.
      Default is . ( root of the repository)
    default: '.'
  skip_check:
    description: 'Run scan on all checks but a specific check identifier (comma separated)'
    required: false

runs:
  using: 'docker'
  image: 'Dockerfile'
  env:
    INPUT_GITHUB_TOKEN: ${{ inputs.github_token }}
    INPUT_REPORTER: ${{ inputs.reporter }}
    INPUT_FILTER_MODE: ${{ inputs.filter_mode }}
    INPUT_FAIL_ON_ERROR: ${{ inputs.fail_on_error }}
    INPUT_WORKING_DIRECTORY: ${{ inputs.working_directory }}
    INPUT_SKIP_CHECK: ${{ inputs.skip_check }}

Dockerfile

Dockerfileではreviewdogcheckovをインストールしています。加えてcheckovの出力結果をreviewdogで受取可能な形式に変換するparse.pyという自作スクリプトも入れています。

FROM python:slim

ARG REVIEWDOG_VERSION="v0.11.0"
ENV PATH $PATH:/usr/local/bin

RUN apt-get update && \
    apt install -y git curl

RUN curl -sfL https://raw.githubusercontent.com/reviewdog/reviewdog/master/install.sh | sh -s -- -b "/usr/local/bin/" "${REVIEWDOG_VERSION}" 2>&1

COPY requirements.txt /requirements.txt
COPY parse.py /parse.py
COPY entrypoint.sh /entrypoint.sh

RUN pip install -r /requirements.txt

ENTRYPOINT ["/entrypoint.sh"]

entrypoint.sh

コンテナ起動時に実行されるスクリプトです。特徴としてはパイプで連結している3つのスクリプト(checkov, parse.py, reviewdog)の返り値をそれぞれ変数に格納している点です。

何故わざわざこのような事をしているのかと言うと、後述するテストで各スクリプトの返り値を元にテスト結果の成否を判定するためです。

# !/bin/bash

[[ ! -z "$INPUT_SKIP_CHECK" ]] && SKIP_CHECK_FLAG="--skip-check $INPUT_SKIP_CHECK"

export REVIEWDOG_GITHUB_API_TOKEN="${INPUT_GITHUB_TOKEN}"

checkov -d $INPUT_WORKING_DIRECTORY $SKIP_CHECK_FLAG -o json \
    | python3 /parse.py \
    | reviewdog -efm="%f:%l: %m" -name="checkov" -reporter="${INPUT_REPORTER}" -fail-on-error="${INPUT_FAIL_ON_ERROR}" -filter-mode="${INPUT_FILTER_MODE}"

checkov_return="${PIPESTATUS[0]}" reviewdog_return="${PIPESTATUS[2]}" exit_code=$?
echo ::set-output name=checkov-return-code::"${checkov_return}"
echo ::set-output name=reviewdog-return-code::"${reviewdog_return}"

exit $exit_code

.github/workflows/test.yml

テストのためにPR作成時とmainブランチへのマージ時にアクションが実行されるよう設定しています。
ここではreviewdogの3つの出力パターンをそれぞれ実行するよう設定しており、name: Check return codesで成否を判定しています。

name: Test
on:
  push:
    branches:
      - main
  pull_request:
jobs:
  test-check:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v2
      - uses: ./
        id: test
        continue-on-error: true
        with:
          github_token: ${{ secrets.github_token }}
          reporter: github-pr-check
          working_directory: testdata
      # The check is expected to fail on the test data
      - name: Check return codes
        if: success() || failure ()
        run: |
          checkov_return="${{ steps.test.outputs.checkov-return-code }}"
          reviewdog_return="${{ steps.test.outputs.reviewdog-return-code }}"
          if [ "$checkov_return" -eq 1 ]; then
            echo "checkov correctly returned failure ${checkov_return}"
          else
            echo "checkov returned ${checkov_return}, expected '1'. Failing..."
            exit 1
          fi
          if [ "$reviewdog_return" -eq 0 ]; then
            echo "reviewdog correctly returned success: ${reviewdog_return}"
          else
            echo "reviewdog returned ${reviewdog_return}, expected '0'. Failing..."
            exit 1
          fi
  test-pr-check:
    if: github.event_name == 'pull_request'
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v2
      - uses: ./
        continue-on-error: true
        id: test
        with:
          github_token: ${{ secrets.github_token }}
          reporter: github-pr-check
          working_directory: testdata
      # The check is expected to fail on the test data
      - name: Check return codes
        if: success() || failure ()
        run: |
          checkov_return="${{ steps.test.outputs.checkov-return-code }}"
          reviewdog_return="${{ steps.test.outputs.reviewdog-return-code }}"
          if [ "$checkov_return" -eq 1 ]; then
            echo "checkov correctly returned failure ${checkov_return}"
          else
            echo "checkov returned ${checkov_return}, expected '1'. Failing..."
            exit 1
          fi
          if [ "$reviewdog_return" -eq 0 ]; then
            echo "reviewdog correctly returned success: ${reviewdog_return}"
          else
            echo "reviewdog returned ${reviewdog_return}, expected '0'. Failing..."
            exit 1
          fi
  test-pr-review:
    if: github.event_name == 'pull_request'
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v2
      - uses: ./
        continue-on-error: true
        id: test
        with:
          github_token: ${{ secrets.github_token }}
          reporter: github-pr-review
          working_directory: testdata
      # The check is expected to fail on the test data
      - name: Check return codes
        if: success() || failure ()
        run: |
          checkov_return="${{ steps.test.outputs.checkov-return-code }}"
          reviewdog_return="${{ steps.test.outputs.reviewdog-return-code }}"
          if [ "$checkov_return" -eq 1 ]; then
            echo "checkov correctly returned failure ${checkov_return}"
          else
            echo "checkov returned ${checkov_return}, expected '1'. Failing..."
            exit 1
          fi
          if [ "$reviewdog_return" -eq 0 ]; then
            echo "reviewdog correctly returned success: ${reviewdog_return}"
          else
            echo "reviewdog returned ${reviewdog_return}, expected '0'. Failing..."
            exit 1
          fi

以上がGithub Actionsの作り方(Docker編)になります。

Github Actionsはとても簡単に作成することができ、かつCIとして必要な機能も充分に備えているのでこれからどんどん使っていこうと思います。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?