7
1

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で動かしてみた

Last updated at Posted at 2019-02-09

追記

バージョンアップしたので、その記事も書きました。
https://qiita.com/grandcolline/items/04c168844dfca3a8ede7

以下は、v1の頃の古い記事になります。


golangの静的解析ツールをGitHub Actionsで動かして、PRに通知してみた。GitHubTokenとかあまり考えなくていいからその辺の管理が楽そうですごくいい印象を受けた。

ただ、まだGithubActionsが理解できていない部分が多く、不備は多々ありそう・・・

TerraformのGithubActionsをかなり参考にした。(ほぼgolangに書き換えただけ)
hashicorp/terraform-github-actions
ほんと、ありがとうございます:bow:

TL;DL

結論から言うと、こんな感じファイルを .github/main.workflow に置くだけ。

.github/main.workflow
workflow "Golang Test Workflow" {
  on = "pull_request"
  resolves = [
    "go imports",
    "go vet",
    "staticcheck",
  ]
}

action "filter to pr open synced" {
  uses = "actions/bin/filter@master"
  args = "action 'opened|synchronize'"
}

action "go imports" {
  uses = "grandcolline/golang-github-actions/imports@v0.1.2"
  needs = "filter to pr open synced"
  secrets = ["GITHUB_TOKEN"]
}

action "go vet" {
  uses = "grandcolline/golang-github-actions/vet@v0.1.2"
  needs = "filter to pr open synced"
  secrets = ["GITHUB_TOKEN"]
  env = {
    FLAGS = "-shadow"
  }
}

action "staticcheck" {
  uses = "grandcolline/golang-github-actions/staticcheck@v0.1.2"
  needs = "filter to pr open synced"
  secrets = ["GITHUB_TOKEN"]
}

これで、こんな感じでPRに通知してくれる。

imports.png staticcheck.png

少し詳細

上記のワークフローの中で、下記のレポジトリを呼び出して、そのレポジトリ内にあるDockerfileから、Dockerコンテナを起動し、テストを実行している。

grandcolline/golang-github-actions

なので実際は、上記のレポジトリの部分を実装していった。
(ただ、実装といっても、静的解析ツールを入れたDockerfileと、テスト実行のシェルスクリプトのentrypoint.shを用意するだけ・・・)

例えば、goimportsを動かすジョブは、

goimports/Dockerfile
FROM golang:latest

LABEL "com.github.actions.name"="go imports"
LABEL "com.github.actions.description"="Run goimports"
LABEL "com.github.actions.icon"="terminal"
LABEL "com.github.actions.color"="purple"

LABEL "repository"="https://github.com/grandcolline/golang-github-actions"
LABEL "homepage"="https://github.com/grandcolline/golang-github-actions"
LABEL "maintainer"="grandcolline <grandcolline@gmail.com>"

RUN apt-get update && \
	apt-get -y install jq && \
	go get -u golang.org/x/tools/cmd/goimports

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

jqgoimportsを取得するDockerfileを用意する。
LABELなどの仕様は、GitHubActionsの仕様に従う。詳しくは、ここ

実行するシェルは、こんな感じ。

goimports/entrypoint.sh
# !/bin/sh
set -e
cd "${GO_ACTION_WORKING_DIR:-.}"

set +e
UNFMT_FILES=$(sh -c "goimports -l . $*" 2>&1)
test -z "${UNFMT_FILES}"
SUCCESS=$?
echo "${UNFMT_FILES}"
set -e

if [ ${SUCCESS} -eq 0 ]; then
    exit 0
fi

if [ "${GO_ACTION_COMMENT}" = "1" ] || [ "${GO_ACTION_COMMENT}" = "false" ]; then
    exit ${SUCCESS}
fi

FMT_OUTPUT=""
for file in ${UNFMT_FILES}; do
FILE_DIFF=$(goimports -d -e "${file}" | sed -n '/@@.*/,//{/@@.*/d;p}')
FMT_OUTPUT="${FMT_OUTPUT}
<details><summary><code>${file}</code></summary>

\`\`\`diff
${FILE_DIFF}
\`\`\`
</details>

"
done

COMMENT="## goimports Failed
${FMT_OUTPUT}
"
PAYLOAD=$(echo '{}' | jq --arg body "${COMMENT}" '.body = $body')
COMMENTS_URL=$(cat /github/workflow/event.json | 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

exit ${SUCCESS}

自動でカレントディレクトリ(/github/workspace)にソースコードがcheckoutさてれいるので、goimports -l . でフォーマットがおかしいファイル一覧を取得し、ファイル毎にdiffを${FMT_OUTPUT}に整形しながら入れてあげて、最後にcurlでPRに通知する。
${GITHUB_TOKEN}などは、workflow側から入れてあげれば、自然な形で環境変数として使える。

環境変数などはここをみながら。

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

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?