😀

GitHub Actionsアクション自作からMarketplace公開まで

2021/09/28に公開

この記事は、klis Advent Calendar 20202120日目です。
今年も去年に引き続き、klis要素の薄い記事になります…

目次

  • <a href="#%E4%BD%95%E3%82%92%E3%81%99%E3%82%8B%E3%81%AE%E3%81%8B">何をするのか</a>
  • <a href="#github-actions%E3%81%AB%E3%81%A4%E3%81%84%E3%81%A6">GitHub Actionsについて</a>
    • <a href="#%E9%81%B8%E6%8A%9E%E8%82%A2">選択肢</a>
    • <a href="#docker-container%E3%82%A2%E3%82%AF%E3%82%B7%E3%83%A7%E3%83%B3%E3%81%AE%E6%A7%8B%E6%88%90">Docker Containerアクションの構成</a>
  • <a href="#%E4%BD%9C%E3%81%A3%E3%81%A6%E3%81%BF%E3%82%8B">作ってみる</a>
    • <a href="#actionsyml">actions.yml</a>
      • <a href="#name-author-description">name, author, description</a>
      • <a href="#inputs">inputs</a>
      • <a href="#runs">runs</a>
      • <a href="#branding">branding</a>
    • <a href="#dockerfile">Dockerfile</a>
    • <a href="#%E5%AE%9F%E9%9A%9B%E3%81%AE%E5%87%A6%E7%90%86%E3%82%92%E8%A1%8C%E3%81%86%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%A0">実際の処理を行うプログラム</a>
  • <a href="#%E4%BD%9C%E6%88%90%E3%81%97%E3%81%9F%E3%82%A2%E3%82%AF%E3%82%B7%E3%83%A7%E3%83%B3%E3%82%92%E3%83%86%E3%82%B9%E3%83%88%E3%81%99%E3%82%8B">作成したアクションをテストする</a>
  • <a href="#marketplace%E3%81%AB%E5%85%AC%E9%96%8B%E3%81%99%E3%82%8B">Marketplaceに公開する</a>
  • <a href="#%E5%85%AC%E9%96%8B%E3%81%97%E3%81%9F%E3%82%A2%E3%82%AF%E3%82%B7%E3%83%A7%E3%83%B3%E3%82%92%E5%AE%9A%E6%9C%9F%E5%AE%9F%E8%A1%8C%E3%81%97%E3%81%A6%E4%BD%BF%E3%81%A3%E3%81%A6%E3%81%BF%E3%82%8B">公開したアクションを定期実行して使ってみる</a>
  • <a href="#%E3%81%8A%E3%82%8F%E3%82%8A%E3%81%AB">おわりに</a>

何をするのか

リポジトリ: eggplants/twitter-weathername-action

GitHub Actions上で動くアクションをPython+Dockerベースで作成し、GitHubのMarketplaceに公開するまでの手順を解説します。
例として作成するのは、Twitterのスクリーンネームを下の写真のように、明日の3時間天気予報にするものです。

image.png

また、普段お手持ちのサーバやVPS上で走らせているような毎日JST00:00になると自動で更新する定期実行のcronをGitHub Actions上で完全無料・サーバなしでやってみます。
但し、走らせるためのリポジトリを作成する必要がありますが…

今回作成したアクションを用いたWorkflowはこちら、またMarketplaceにアクションを公開したものはこちらです。

<blockquote class="twitter-tweet"><p lang="und" dir="ltr"><a href="https://t.co/ufco0Vy7VO">https://t.co/ufco0Vy7VO</a></p>— 明日: ☀/☀/☀/☀/☀/☀/☁/☁ (@egpl0) <a href="https://twitter.com/egpl0/status/1341039332245741569?ref_src=twsrc^tfw">December 21, 2020</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

GitHub Actionsについて

GitHub Actionsとは、GitHubが提供しているCI/CDサービスです。リポジトリの.github/workflowsディレクトリにyamlを書き、pushやpull request、また定期実行するscheduleなどのトリガで走らせることが出来ます。また、公開リポジトリであれば完全無料で回し放題なのも魅力的です。なお、非公開リポジトリやorganizationリポジトリでは一定量使用すると課金されます

選択肢

Actions作成には3つの作り方があります。(actions.ymlに記述)

action.yml
runs:
  using: 'docker'
  image: 'Dockerfile'
action.yml
runs:
  using: 'node12'
  main: 'hogehoge.js'
action.yml
runs:
  using: 'composite'

今回はこのうちのDocker Containerアクションを作ります。

Docker Containerアクションの構成

大きく分けて3つの部分を書けばよく、

  • action.yml
    • アクションの説明
    • 渡す引数の名前、説明、属性、必須かどうか、返り値を定義
    • Marketplaceでの公開時のアイコンとその背景色
  • Dockerfile
    • 環境の構築
    • 実際の処理を動かすプログラムをENTRYPOINTとして実行
  • 実際の処理を行うプログラム
    • 今回はPythonで記述

を記述します。

作ってみる

actions.yml

それぞれ記述するべき値を列挙します。

name, author, description

アクション公開時の「アクション名」、「作者」「アクションの説明」です。

inputs

アクションの実行時に渡せる、「引数の定義」です。

アクションは、workflowでの使用時にjobs.<job_id>.steps.withで渡された引数を受け取ることが出来ます。
後述しますが、渡された引数XXXは環境変数INPUT_XXXとして定義され、ENTRYPOINT内で参照できるようになります。
required: trueとしたものに関しては、使用時に指定しないと実行できません。
またrequired: falseの場合(オプション引数)に、defaultで引数のデフォルト値を定義できます。

<details><summary>今回定義した引数</summary><div>

  • 必須引数
    • open_weather_api_token
    • twitter_consumer_key, twitter_consumer_secret, twitter_access_key, twitter_access_secret
    • location_query
      • 天気予報の場所
  • オプション引数記述
    • time_zone
      • 用いる予報のタイムゾーン
      • デフォルトだとlocation_queryの場所のタイムゾーンを用いる
    • name_format
      • 天気予報をはめ込むフォーマット
    • icon_sep
      • 天気を区切るパラメータ
    • forecast_day
      • 予報する日数をn日先で設定
      • 天気APIの都合上0~2で指定
      • "明日"だと1
        </div></details>

runs

今回はDocker Containerアクションなので、

action.yml
runs:
  using: "docker"
  image: "Dockerfile"

とします。今回はimageに、自分で作成したDockerfileを指定していますが、DockerHubの公開DockerイメージやGitHub Packagesの公開コンテナも指定できます。

branding

Marketplaceでの公開時のアイコンとその背景色を指定できます。

  • icon
  • color
    • white, yellow, blue, green, orange, red, purple, gray-darkの中から選べます。
action
icon: "link"
color: "green"

だと、

image.png

のようになります。

以下作成したactions.ymlです。

<details><summary>actions.yml</summary><div>

action.yml
name: "Twitter Weathername"
author: "haruna"
description: "Update Twit記述ter Username to a daily forecast of given location"
inputs:
  open_weather_api_token:
    description: "Openweathermap API Token"
    required: true
  twitter_consumer_key:
    description: "Twitter API consumer key"
    required: true
  twitter_consumer_secret:
    description: "Twitter API consumer secret key"
    required: true
  twitter_access_key:
    description: "Twitter API access key"
    required: true
  twitter_access_secret:
    description: "Twitter API access secret key"
    required: true
  location_query:
    description: "City name, state code and country code divided by comma, use ISO 3166 country codes"
    required: true
  time_zone:
    description: "Time zone to be used as a time reference (ex. Asia/Tokyo) (def: LOCATION_QUERY's local time zone)"
    required: false
  name_format:
    description: "Username format ({} is substituted by joined weather icons with icon_sep)"
    required: false
    default: "<{}"
  icon_sep:
    description: "String for joining icons"
    required: false
    default: ":"
  forecast_day:
    description: "Show the weather in the next n days (n=0 is today)"
    required: false
    default: "0"
runs:
  using: "docker"
  image: "Dockerfile"
branding:
  icon: "link"
  color: "green"

</div></details>

Dockerfile

今回はPythonを実行するので、Pythonを動かすための実行環境を作成するDockerfileを記述する。
また引数を受け取って、実際の処理を行う(ここではTwitterのユーザ名を、取得した天気予報に更新する)プログラムをENTRYPOINTに指定します。CMD ["python", "/src/main.py"]のように指定しても良いです。

以下作成したDockerfileです。

Dockerfile
FROM python:latest

ADD src /src
ADD requirements.txt /requirements.txt

RUN pip install -r requirements.txt
RUN chmod +x src/main.py

ENTRYPOINT ["/src/main.py"]

実際の処理を行うプログラム

workflowで渡された引数(例えばXXX)は、

/src/main.py
from os import environ

xxx = environ.get('INPUT_XXX', 'default')

のように受け取れます。

今回は、

①3日間天気.jsonをOpenweathermap APIから取得
②3日間天気.jsonを名前に整形
③Twitter APIから名前を更新

を行うプログラムを書きます。作成したプログラムはこちらです。

作成したアクションをテストする

ここまでで作成したアクションがちゃんと動くかどうかはGitHub Actionsでテスト出来てしまいます。Marketplaceに公開する前に動くかどうかテストしましょう。

また、APIトークンなどの一般に公開したくない文字列は、リポジトリの[Settings]->[Secrets]->[New repository secret]から追加でき、${{ secrets.XXX }}で呼び出せます。

リポジトリでのpush毎に実行して、うまく更新できるか試すworkflowはこのようになります。

.github/workflows/test.yml
name: Test
on: [push]
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - name: Change Name
        uses: eggplants/twitter-weathername-action@main # アクションのリポジトリ
        with:
          open_weather_api_token: ${{ secrets.OPEN_WEATHER_API_TOKEN }}
          twitter_consumer_key: ${{ secrets.TWITTER_CONSUMER_KEY }}
          twitter_consumer_secret: ${{ secrets.TWITTER_CONSUMER_SECRET }}
          twitter_access_key: ${{ secrets.TWITTER_ACCESS_KEY }}
          twitter_access_secret: ${{ secrets.TWITTER_ACCESS_SECRET }}
          location_query: tsukuba
          name_format: "明日: {}"
          icon_sep: "/"
          forecast_day: 1 # 明日の天気

うまく動いたかどうかは、Actionsタブから確認できます。

image.png

Marketplaceに公開する

作成したアクションをMarketplaceに公開することで、誰にでも簡単に、すぐ作成したアクションを使ってもらえるように出来ます。

詳細な手順は公式ドキュメントがわかりやすいです。

action.ymlがリポジトリに存在していれば、リポジトリに[Draft a release]バナーが出現します。

image.png

クリックすると

image.png

のように表示されるので、accept the GitHub Marketplace Developer Agreementリンクをクリックすると、

image.png

GitHub Marketplace Developer Agreementに同意するように言われます。

同意すると、

image.png

のように、actions.ymlのメタデータが足りているか、またREADMEがあるかどうかがチェックされ、不十分だと修正するように言われます。

image.png

カテゴリを設定し、[Publish release]ボタン(画像ではUpdate releaseですが…)を押下して、公開できます。お疲れ様でした!

公開したアクションを定期実行して使ってみる

最初に書いたように、Actionsのworkflowの実行トリガには、cronのように定期実行できるscheduleトリガが存在しており、

cron_renamer.yml
on:
  schedule:
    - cron: "0 15 * * *" # JSTでは"0 0 * * *"

のように、まさにcronの構文で定期実行できます。ここで注意ですが、ActionsのworkflowはUTC(協定世界時)で実行されるため、日本時間に即した実行を行いたい場合はJST(日本標準時)-9の時間を指定しましょう。

以下が、現在実際に使っているcron workflowです。

cron_renamer.yml
name: Cron renamer

on:
  schedule:
    - cron: "0 15 * * *"

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - name: Change Name
        uses: eggplants/twitter-weathername-action@v2
        with:
          open_weather_api_token: ${{ secrets.OPEN_WEATHER_API_TOKEN }}
          twitter_consumer_key: ${{ secrets.TWITTER_CONSUMER_KEY }}
          twitter_consumer_secret: ${{ secrets.TWITTER_CONSUMER_SECRET }}
          twitter_access_key: ${{ secrets.TWITTER_ACCESS_KEY }}
          twitter_access_secret: ${{ secrets.TWITTER_ACCESS_SECRET }}
          location_query: tsukuba
          name_format: "明日: {}"
          icon_sep: "/"
          forecast_day: 1

実行ログはテスト同様Actionsタブから確認できます。

image.png

おわりに

GitHub Actionsの自作アクションの作成とテスト、公開や定期実行の手順がひとところにあるわかりやすい記事がなかなかなかったので、備忘録も兼ねて書こうとずっと思ってたんですけど、今回Adventカレンダーが良い契機となりました。

良いお年を〜

GitHubで編集を提案

Discussion