actがtask runnerとしていい感じ
GitHub Actions、Sign upしましたか? 私は開通してちょっと試して、ああまだTravisCIやCircleCIのようなCIサービスの代わりにはならないな、 とちょっと残念に思いしばらく触ってませんでした。
で、ふとblogのdeployくらいには使えるよなと思いたち改めて調べてたら actというローカルでGitHub Actionsを実行するコマンドを見つけ、これがなかなかいいのです。 GitHub Actionsをローカルで実行できるのも便利ですが、普通にタスクランナーとしてもいい感じです。
例えばblogをAWS S3 web hostingするとします。
タスクを分けるとしたら2つのタスク、build
-> deploy
となるでしょう。
実際にWorkflow定義して行きましょう。
Workflowの定義
Workflowを定義してみます。 GitHub ActionsのWorkflow editorで見るとこんな感じです。
タスクは2つだって言ったのに4タスクあるように見えますが、最初のグレーのノードは初期ノード、
2つ目のMaster
はmaster
ブランチのpush以外は以降の実行をskipするためのタスクです。
なので実際はBuild
、Deploy
の2つのタスクと考えてください。
.github/main.workflow
はこうなります。
workflow "Deploy blog" {
on = "push"
resolves = ["Deploy"]
}
action "Master" {
uses = "actions/bin/filter@master"
args = "branch master"
}
action "Build" {
needs = ["Master"]
uses = "./.github/build"
}
action "Deploy" {
needs = ["Build"]
uses = "./.github/deploy"
env = {
AWS_DEFAULT_REGION = "ap-northeast-1"
}
secrets = ["AWS_ACCESS_KEY_ID", "AWS_SECRET_ACCESS_KEY"]
args = "s3://foobar-my-blog-bucket"
}
ここでact -l
を実行すると以下のように表示が得られ、依存関係を見ることができます。
Build Actionの定義
今までタスクタスク書いてきましたが、GitHub ActionsではAction
と言うのでそれにならいます。
Build Actionを実装します。静的サイト生成にはhugoを使うことにします。
.github/build/Dockerfile
はこんな感じ。
FROM python:3.6
# See https://feathericons.com/ for icon
LABEL "com.github.actions.name"="Build"
LABEL "com.github.actions.description"="Build"
LABEL "com.github.actions.icon"="square"
LABEL "com.github.actions.color"="purple"
WORKDIR /
RUN curl -OL https://github.com/gohugoio/hugo/releases/download/v0.55.6/hugo_0.55.6_Linux-64bit.tar.gz; \
tar xfz hugo_0.55.6_Linux-64bit.tar.gz; \
chmod +x hugo
COPY entrypoint.sh /entrypoint.sh
ENTRYPOINT ["/entrypoint.sh"]
python:3.6
を使ってるのは次のDeploy Action
で使ってるからです。
/hugo
にバイナリを置いてます。
.github/build/entrypoint.sh
はシンプルです。/hugo
を実行。
#!/usr/bin/env bash
/hugo
これくらいならCMD
使ってDockerfileに書いてしまってもいいんですが、なんとなくDockerfileでは実行環境を整える、
entrypoint.shで実際の処理、とするのがいい気がしているのでそうしてます。
Build Actionの実行
ここまででこうなってます。
.github/
|-- main.workflow
|-- build/
| |-- Dockerfile
| `-- entrypoint.sh
.github/
があるディレクトリでact -a Build
を実行してみます。
master
ブランチのチェックをしてファイルを生成するログが表示されます。
$ act -a Build
INFO[0000] using github ref: refs/heads/master
INFO[0000] using github ref: refs/heads/master
[Master] git clone 'https://github.com/actions/bin' # ref=master
[Master] docker build -t bin:master /var/folders/qc/_9vx0zd114383ghrcdtt8ysr0000gn/T/act/actions/bin/filter@master/filter
[Master] docker run image=bin:master entrypoint=[] cmd=["branch" "master"]
refs/heads/master matches refs/heads/master
[Build] docker build -t build:579e412 /my/path/to/.github/build
[Build] docker run image=build:579e412 entrypoint=[] cmd=[]
...
| EN
+------------------+----+
Pages | 4
Paginator pages | 0
Non-page files | 0
Static files | 0
Processed images | 0
Aliases | 0
Sitemaps | 1
Cleaned | 0
Total in 52 ms
Hugoは./public
を作成します、GitHub Actionsではrepositoryのdirectoryは${GITHUB_WORKSPACE}
(default: /github/workspace
)に展開されますが、
ローカルではカレントディレクトリです。カレントディレクトリにpublic
が生成されているはずなので確認してください。
Deploy Actionの実装
次にDeploy Actionを実装します。(AWS CLIをDocker環境で実行するを参考にさせて頂きました。)
FROM python:3.6
# See https://feathericons.com/ for icon
LABEL "com.github.actions.name"="Deploy"
LABEL "com.github.actions.description"="Deploy to the s3 bucket"
LABEL "com.github.actions.icon"="upload"
LABEL "com.github.actions.color"="purple"
#
ARG pip_installer="https://bootstrap.pypa.io/get-pip.py"
ARG awscli_version="1.16.170"
RUN pip install awscli==${awscli_version}
ENV PATH $PATH:/root/.local/bin
COPY entrypoint.sh /entrypoint.sh
ENTRYPOINT ["/entrypoint.sh"]
#!/usr/bin/env bash
aws s3 sync \
--no-follow-symlinks --delete \
public "$1"
Dockerfileで環境を作ってentrypoint.shで実際の処理です。
ここでもう一度Deploy Actionを振り返ります。
action "Deploy" {
needs = ["Build"]
uses = "./.github/deploy"
env = {
AWS_DEFAULT_REGION = "ap-northeast-1"
}
secrets = ["AWS_ACCESS_KEY_ID", "AWS_SECRET_ACCESS_KEY"]
args = "s3://foobar-my-blog-bucket"
}
だいたい想像はつくと思いますが、entrypoint.shで環境変数AWS_DEFAULT_REGION
, AWS_ACCESS_KEY_ID
, AWS_SECRET_ACCESS_KEY
が使えます。
env
はworkflow内で定義、secrets
はGitHubのvisual editorで設定します。
args
はentrypoint.shへの引数です。S3 bucket名を渡してます。
actでローカル実行してみます。
$ act -a Deploy
INFO[0000] using github ref: refs/heads/master
INFO[0000] using github ref: refs/heads/master
Provide value for 'AWS_ACCESS_KEY_ID':
...
ローカルで環境変数が設定されていない場合は入力を求められます。 とりあえずenterを押して空で進めます。依存関係が設定されているBuild Actionが先に走ります。
...
Total in 525 ms
[Deploy] docker build -t deploy:579e412 /my/path/to/.github/deploy
[Deploy] docker run image=deploy:579e412 entrypoint=[] cmd=["s3://foobar-my-blog-bucket"]
fatal error: Unable to locate credentials
Error: exit with `FAILURE`: 1
Access keyが設定されていないので期待通り失敗します。 ちゃんと権限があるkeyが設定されていればaws s3 syncが成功してuploadするはずです。
まとめ
act
がGitHub Actionsをローカルで実行するのに使える。- 依存関係がCLIで表示できる。
- GitHub Actionsが有効でなくても、dockerを使うtask runnerとして使いやすい。
- Action名を指定して実行可能。
- もちろんGitHub Actionsが有効なアカウントでmasterへpushすれば同じworkflowが走る。シームレス。