追記
バージョンアップしたので、その記事も書きました。
https://qiita.com/grandcolline/items/04c168844dfca3a8ede7
以下は、v1の頃の古い記事になります。
golangの静的解析ツールをGitHub Actionsで動かして、PRに通知してみた。GitHubTokenとかあまり考えなくていいからその辺の管理が楽そうですごくいい印象を受けた。
ただ、まだGithubActionsが理解できていない部分が多く、不備は多々ありそう・・・
TerraformのGithubActionsをかなり参考にした。(ほぼgolangに書き換えただけ)
hashicorp/terraform-github-actions
ほんと、ありがとうございます
TL;DL
結論から言うと、こんな感じファイルを .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に通知してくれる。


少し詳細
上記のワークフローの中で、下記のレポジトリを呼び出して、そのレポジトリ内にあるDockerfileから、Dockerコンテナを起動し、テストを実行している。
grandcolline/golang-github-actions
なので実際は、上記のレポジトリの部分を実装していった。
(ただ、実装といっても、静的解析ツールを入れたDockerfileと、テスト実行のシェルスクリプトのentrypoint.shを用意するだけ・・・)
例えば、goimportsを動かすジョブは、
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"]
jq
とgoimports
を取得するDockerfileを用意する。
LABELなどの仕様は、GitHubActionsの仕様に従う。詳しくは、ここ。
実行するシェルは、こんな感じ。
# !/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側から入れてあげれば、自然な形で環境変数として使える。
環境変数などはここをみながら。