ハイパーマッスルエンジニア

Vim、ShellScriptについてよく書く

Github Actionsのアクションを作ってみる(Docker編)

f:id:rasukarusan:20210122144649p:plain:w500

1つ前のtagからの差分を出すアクションを作ってみる

前回GithubActionsを使ってHomebrewのリリースを自動化した。

www.rasukarusan.com

上記で実行している「1つ前のtagからの差分を取得する」をアクションとして切り出してみる。

イメージとしてはrunでゴリゴリ書いている箇所が、

steps:
  # 1つ前のtagからの差分を取得
  - name: Get commit summary
    id: get_commit_summary
    run: |
      PREVIOUS_TAG=$(git tag --sort=-creatordate | sed -n 2p)
      COMMIT_SUMMARY="$(git log --oneline --pretty=tformat:"%h %s" $PREVIOUS_TAG..${{ github.ref }})"
      COMMIT_SUMMARY="${COMMIT_SUMMARY//$'\n'/'%0A'}"
      echo ::set-output name=COMMIT_SUMMARY::$COMMIT_SUMMARY

usesで独自アクションを指定して、シンプルな形になる予定。

steps:
  # 1つ前のtagからの差分を取得
  - name: Get commit summary
    id: get_commit_summary
    uses: ./.github/actions/get-commit-summary

アクションの作成

docs.github.com

DockerまたはJavascriptでアクションを作れるみたい。

今回はとりあえずDockerでアクションを作ってみる。

完成形

.githubに新たにactionsディレクトリを作成。独自アクションはここにいれていく。

ディレクトリ構造

~/gitblamer
$ tree
.
├── .github
│   ├── actions
│   │   └── commit-summary
│   │       ├── Dockerfile
│   │       ├── action.yml
│   │       └── entrypoint.sh
│   └── workflows
│       └── release.yml
├── README.md
└── gitblamer

独自アクションを特定のリポジトリだけで使うプライベートアクションの場合、.github/actionsに作ればいい。他のリポジトリからも使えるようなパブリックアクションの場合、パブリックなリポジトリを作ってその中に置く必要がある。
プライベートアクションからパブリックアクションにするのは一瞬で出来るため、一旦プライベートアクションとして作る。

Dockerfile

# コードを実行するコンテナイメージ
FROM alpine/git
# アクションのリポジトリからコードファイルをコンテナのファイルシステムパス `/`にコピー
COPY entrypoint.sh /entrypoint.sh
# dockerコンテナが起動する際に実行されるコードファイル (`entrypoint.sh`)
ENTRYPOINT ["/entrypoint.sh"]

今回はgitコマンドを使いたいのでコンテナイメージにalpine/gitを指定。

action.yml

name: 'Get Commit Summary'
description: 'Get commits from previrous tag to new tag'
inputs:
  ref:
    description: 'new tag'
    required: true
    default: 'please set ${{ github.ref }}'
outputs:
  commit_summary:
    description: 'commit summary'
runs:
  using: 'docker'
  image: 'Dockerfile'
  args:
    - ${{ inputs.ref }}

引数の設定などをする。

entrypoint.sh

#!/bin/sh

NEW_TAG=$1

PREVIOUS_TAG=$(git tag --sort=-creatordate | sed -n 2p)
COMMIT_SUMMARY="$(git log --oneline --pretty=tformat:"%h %s" $PREVIOUS_TAG..$NEW_TAG)"
COMMIT_SUMMARY="${COMMIT_SUMMARY//$'\n'/'%0A'}"
echo ::set-output name=COMMIT_SUMMARY::$COMMIT_SUMMARY

アクションの肝。stepとして書いていた箇所をほぼそのままコピって貼り付けるだけ。
${{ github.ref }}などstep内でしか参照できない箇所などを修正する。
chmod +x entrypoint.shで実行権限を付与しておく。

workflows/release.ymlを修正したら終了

修正後のworkflows/release.yml

       # 1つ前のtagからの差分を取得
       - name: Get commit summary
+        uses: ./.github/actions/commit-summary
         id: get_commit_summary
-        run: |
-          PREVIOUS_TAG=$(git tag --sort=-creatordate | sed -n 2p)
-          COMMIT_SUMMARY="$(git log --oneline --pretty=tformat:"%h %s" $PREVIOUS_TAG..${{ github.ref }})"
-          COMMIT_SUMMARY="${COMMIT_SUMMARY//$'\n'/'%0A'}"
-          echo ::set-output name=COMMIT_SUMMARY::$COMMIT_SUMMARY
+        with:
+          ref: ${{ github.ref }}

すっきりした。

tagをpushしてActionsを確認。ちゃんと前回のDockerで実行されている。

f:id:rasukarusan:20210122142255p:plain

"Get commit summary"がDockerで実行されている

f:id:rasukarusan:20210122142342p:plain

リリースノートもバッチリ作成されている

独自アクションを他のリポジトリでも使えるようにする

パブリックなリポジトリを作ってその中にactionsディレクトリの中身をいれるだけ。
リポジトリ側で特に設定する箇所もない。

mkdir commit-summary
cd commit-summary
cp -r ~/gitblamer/.github/actions/* ./
git init 
git remote add origin git@github.com:Rasukarusan/commit-summary.git
git add -A
git commit -m 'initial commit'
git tag v1
git push origin v1

github.com

"Publish this Action to Marketplace"というアラートが出るが、別にしなくても他リポジトリから使えるようになるのでしなくてOK。

f:id:rasukarusan:20210122142450p:plain

Marketplaceに出したい人だけ出せばいい

あとはusesの指定を変更したら終了。

      # 1つ前のtagからの差分を取得
      - name: Get commit summary
-       uses: ./.github/actions/commit-summary
+       uses: Rasukarusan/commit-summary@v1
        id: get_commit_summary
        with:
          ref: ${{ github.ref }}

f:id:rasukarusan:20210122142603p:plain
Rasukarusan/commit-summaryが指定されて動いてる

終わり

今回はDockerで作ってみたが、Dockerはコンテナのビルドおよび取得のレイテンシがかかるため、Javascriptより遅いらしい。 次はJavascriptでアクションを書いてみよう。

今回使ったリポジトリ