9
9

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 5 years have passed since last update.

goの静的解析ツールをGithub Actionsのv2で動かしてみた

Posted at

github actionsのバージョンが上がったので、自分が作ったアクションも書き換えてみました。

作ったもの

⬇こんな感じで通知される⬇
スクリーンショット.png

対応している静的解析ツールは以下のものです。

もの original
fmt https://golang.org/cmd/gofmt/
vet https://golang.org/cmd/vet/
imports https://godoc.org/golang.org/x/tools/cmd/goimports
lint https://godoc.org/golang.org/x/lint/golint
shadow https://godoc.org/golang.org/x/tools/go/analysis/passes/shadow/cmd/shadow
staticcheck https://godoc.org/honnef.co/go/tools/cmd/staticcheck
errcheck https://godoc.org/github.com/kisielk/errcheck
sec https://godoc.org/github.com/securego/gosec/cmd/gosec

READMEに書いてある通りなのですが、下記の感じでymlファイルを作ってもらえれば動きます。

.github/workflows/static.yml
name: static check
on: pull_request

jobs:
  fmt:
    name: Fmt
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@master
    - uses: grandcolline/golang-github-actions@v1.0.0
      with:
        run: fmt
        token: ${{ secrets.GITHUB_TOKEN }}

  lint:
    name: Lint
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@master
    - uses: grandcolline/golang-github-actions@v1.0.0
      with:
        run: lint
        token: ${{ secrets.GITHUB_TOKEN }}

withで指定できる変数は以下の通りです。

変数名 デフォルト なに
run N/A 実行するコマンド(上の表から選ぶ)
directory . 静的解析を実行する場所の相対パス
comment true PRにコメントするか否か
token "" GitHub Token
flags "" コマンド実行時に追加するフラグ
ignore-defer false errcheck実行時に deferのエラーチェックを無視するか否か

いか、アクション作成する際にやったこと

アクションには、2種類のパターンがあるそうです。

今回はgoを使いたかったので、container actionsにしました。
公式のテンプレート通りに以下の構成にしました。

.
├── Dockerfile
├── LICENSE
├── README.md
├── action.yml
└── entrypoint.sh

Dockerfileは使いたいツールをインストールして、最終的にentrypoint.shを実行するだけのシンプルなもの。
やりたい処理などは、entrypoint.shにゴリゴリ書いていく。

Dockerfile
FROM golang::1.12.9

ENV GO111MODULE=on

RUN apt-get update && \
	apt-get -y install jq && \
	go get -u \
		github.com/kisielk/errcheck \
		golang.org/x/tools/cmd/goimports \
		golang.org/x/lint/golint \
		github.com/securego/gosec/cmd/gosec \
		golang.org/x/tools/go/analysis/passes/shadow/cmd/shadow \
		honnef.co/go/tools/cmd/staticcheck

COPY entrypoint.sh /entrypoint.sh
ENTRYPOINT ["/entrypoint.sh"]

action.yamlは、公式のドキュメントを参考に作成。

action.yml
name: "static analysis checker"
description: "static code analysis checker for golang"
author: "grandcolline"
inputs:
  run:
    description: "excute command. [errcheck/fmt/imports/lint/sec/shadow/staticcheck/vet]"
    required: true
  directory:
    description: "action wroking directory."
    default: "."
    required: false
  comment:
    description: "send comment to PR if true."
    default: true
    required: false
  token:
    description: "github token. this is require when comment is true."
    default: ""
    required: false
  flags:
    description: "add flags"
    default: ""
    required: false
  ignore-defer:
    description: "if this is true, do not detect 'defer' with error. This is only valid when run is errcheck."
    default: false
    required: false
runs:
  using: "docker"
  image: "Dockerfile"
  args:
    - ${{ inputs.run }}
    - ${{ inputs.directory }}
    - ${{ inputs.comment }}
    - ${{ inputs.token }}
    - ${{ inputs.flags }}
    - ${{ inputs.ignore-defer }}
branding:
  icon: "alert-triangle"
  color: "yellow"

args以外にもenvironmentでも渡せるので、どちらにするかは迷いどころだと思いました。どのようにかくのが綺麗なんだろう🤔
あと、Dockerのビルド時に渡すARGもここから指定できれば、golang自体のバージョン管理もアクション側でしなくて良くなりそうで良さそうだなぁと感じました。(ドキュメントを読み込めてないので、もしかしたらできるのかもしれない・・・)

最後に、entrypoint.shはシェルを書く。
長いので一部だけ書くとこんな感じ。全体はこちらから。

entrypoint.sh
# !/bin/sh
set -e

# ------------------------
#  Environments
# ------------------------
RUN=$1
WORKING_DIR=$2
SEND_COMMNET=$3
GITHUB_TOKEN=$4
FLAGS=$5
IGNORE_DEFER_ERR=$6

COMMENT=""
SUCCESS=0


# ------------------------
#  Functions
# ------------------------
send_comment() {
	PAYLOAD=$(echo '{}' | jq --arg body "${COMMENT}" '.body = $body')
	COMMENTS_URL=$(cat ${GITHUB_EVENT_PATH} | jq -r .pull_request.comments_url)
	curl -s -S -H "Authorization: token ${GITHUB_TOKEN}" --header "Content-Type: application/json" --data "${PAYLOAD}" "${COMMENTS_URL}" > /dev/null
}

mod_download() {
	if [ ! -e go.mod ]; then go mod init; fi
	go mod download
	if [ $? -ne 0 ]; then exit 1; fi
}

check_errcheck() {
	if [ "${IGNORE_DEFER_ERR}" = "true" ]; then
		IGNORE_COMMAND="| grep -v defer"
	fi

	set +e
	OUTPUT=$(sh -c "errcheck ${FLAGS} ./... ${IGNORE_COMMAND} $*" 2>&1)
	test -z "${OUTPUT}"
	SUCCESS=$?

	set -e
	if [ ${SUCCESS} -eq 0 ]; then
		return
	fi

	if [ "${SEND_COMMNET}" = "true" ]; then
		COMMENT="## ⚠ errcheck Failed
\`\`\`
${OUTPUT}
\`\`\`
"
	fi
}

# ------------------------
#  Main Flow
# ------------------------
cd ${GITHUB_WORKSPACE}/${WORKING_DIR}

case ${RUN} in
	"errcheck" )
		mod_download
		check_errcheck
		;;
	* )
		echo "Invalid command"
		exit 1

esac

if [ ${SUCCESS} -ne 0 ]; then
	echo "Check Failed!!"
	echo ${COMMENT}
	if [ "${SEND_COMMNET}" = "true" ]; then
		send_comment
	fi
fi

exit ${SUCCESS}

最後に

アクションの書き方などのページがなくて辛かったですが、このあたりの記事がとても参考になりました。
感謝:pray:

https://qiita.com/homines22/items/0bc6c17e038b35fc8113
https://github.com/actions/container-template

9
9
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
9
9

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?