Help us understand the problem. What is going on with this article?

GitHub Actions (Action) on CircleCI

概要

アイハブアぎっとはぶあくしょんず :raised_hand:
アイハブアさーくるしーあい :raised_hand:
ンー! :boom:
GitHub Actions on CircleCI :smirk:

前置き

GitHub Actions の Action を GitHub Actions ではなく CircleCI で動かそう、というものです。
この取り組みには2つの目的があります。

  • GitHub Actions が使えない旧プラン勢でも Action を使えるようにする
  • なんだかイケナイコトをしている気分を楽しむ

ちなみに、GitHub Actions 用の YAML を CircleCI で動かすとか、GitHub Actions のように push 以外のイベントを CircleCI でも動かそう、といった取り組みではありません。

手順

GitHub Actions (Action) on CircleCI を実現するには次の手順が必要になります。

  • GitHub Actions の Action をローカル環境で動かす
  • 動いたスクリプトを CircleCI の config.yml に書く

GitHub Actions の Action をローカル環境で動かす

今回は stale という Action で試します。
これは放置された Issue や PullRequest を見つけて「放置されてるよ!」や「クローズしとくね!」といった整理をしてくれる便利な Action です。

まずは clone します。

$ git clone https://github.com/actions/stale
$ cd stale

リポジトリには docs/contributors.md というファイルがあります。
とてもシンプルなドキュメントになっており、どうすれば手元でも使えるようになるのか予想する手助けをしてくれます。

$ cat docs/contributors.md
# Contributors

### Checkin

- Do check in source (src)
- Do not check in build output (lib)
- Do not check in node_modules

全くわかりませんね。

action.yml を読む

Actions の設定が記述された action.yml 1 を読むと nodejs v12 な環境で lib/main.js というファイルを実行すれば良さそうだと分かります。

$ cat action.yml | yq -y '.runs'
using: node12
main: lib/main.js

ちなみに yq は YAML を jq で扱えるようになる便利ツールです。

ビルドする

package.json を読むとなんとなく npm run build すれば良さそうです。
その前に npm install して依存モジュールをインストールしたいところですが、何やらエラーが出ます。

$ npm install
npm ERR! code ETARGET
npm ERR! notarget No matching version found for @actions/exec@^0.0.0.
npm ERR! notarget In most cases you or one of your dependencies are requesting
...略

細かい話はおいといて toolkit ディレクトリ以下に tgz ファイルがあるのでこれらを指定して install する必要があります。

$ npm install ./toolkit/*
# ...略
+ @actions/core@0.0.0
+ @actions/tool-cache@0.0.0
+ @actions/io@0.0.0
+ @actions/exec@0.0.0
+ @actions/github@0.0.0
added 646 packages from 453 contributors in 17.345s

これで npm run build すれば OK.

$ npm run build

> stale-action@1.0.0 build /Users/yasuhiroki/ghq/github.com/actions/stale
> tsc

 $ ls lib
main.js

ローカルで動かす

無事にビルドできたので実行してみましょう。

$ node lib/main.js
##[error]Error: Input required and not supplied: repo-token
##[error]Input required and not supplied: repo-token

何やら必須な値があるようです。
ここも action.yml を読むとヒントが書いてあります。

$ cat action.yml | yq -y .inputs
repo-token:
  description: Token for the repository. Can be passed in using {{ secrets.GITHUB_TOKEN }}
  required: true
stale-issue-message:
  description: The message to post on the issue when tagging it. If none provided, will not mark issues stale.
stale-pr-message:
  description: The message to post on the pr when tagging it. If none provided, will not mark pull requests stale
...略

repo-tokenstale-issue-message などといった値が必要のようです。これらの値は環境変数で設定するのですが stale ではさらに、 INPUT_XXX などと INPUT を prefix につけなければなりません。2

というわけでこんな感じです。

$ env INPUT_REPO-TOKEN=xxx \
      INPUT_DAYS-BEFORE-STALE=1 \
      INPUT_DAYS-BEFORE-CLOSE=1 \
      INPUT_STALE-ISSUE-LABEL=stale \
      INPUT_STALE-PR-LABEL=stale \
      INPUT_STALE-ISSUE-MESSAGE='stale issue' \
      INPUT_STALE-PR-MESSAGE='stale pull request' \
      INPUT_OPERATIONS-PER-RUN=30 \
      GITHUB_REPOSITORY=yasuhiroki/enjoy-circleci \
      node lib/main.js
##[debug]found issue: test issue last updated 2019-12-12T08:26:30Z
##[debug]marking issuetest issue as stale

お。無事に動きました。

動いたスクリプトを CircleCI の config.yml に書く

ローカルで動かせたので CircleCI でも動かしてみましょう。
stale を clone して install して build して実行すればOKなので↓のようなスクリプトになりますね。

command: |
  git clone https://github.com/actions/stale.git
  cd stale
  npm install ./toolkit/*
  npm run build
  node lib/main.js

環境変数を定義

実行には環境変数が必要でした。ということで environment で定義しましょう。

ただし INPUT_REPO-TOKEN は GitHub の Token なので YAML にベタ書きしたくありません。
CircleCI のリポジトリ設定や context などで定義しても良いですが、 INPUT_REPO-TOKEN という他では使わなさそうな名前でわざわざ設定するのはイマイチな気もします。

ここは GITHUB_TOKEN という汎用性のありそうな名前で設定をしておき、 env INPUT_REPO-TOKEN=${GITHUB_TOKEN} node lib/main.js という形にしてみましょう。3

command: |
  git clone https://github.com/actions/stale.git
  cd stale
  npm install ./toolkit/*
  npm run build
  env INPUT_REPO-TOKEN=${GITHUB_TOKEN} node lib/main.js
environment:
  # INPUT_REPO-TOKEN: xxx
  INPUT_DAYS-BEFORE-STALE: 1
  INPUT_DAYS-BEFORE-CLOSE: 1
  INPUT_STALE-ISSUE-LABEL: stale
  INPUT_STALE-PR-LABEL: stale
  INPUT_OPERATIONS-PER-RUN: 30
  GITHUB_REPOSITORY: yasuhiroki/enjoy-circleci

node が使える executor を指定

node が必要なので executor は circleci/node を使いましょう。

docker:
  - image: circleci/node:latest

config.yml の完成

そんなこんなで GitHub Actions の stale を実行する CircleCI の config.yml が完成しました。
ついでに cache の設定もして↓のようなYAMLになります。

version: 2.1

jobs:
  build:
    docker:
      - image: circleci/node:latest
    steps:
      - run:
          command: |
            git clone https://github.com/actions/stale.git
      - restore_cache:
          keys:
            - node_modules-{{checksum "stale/package.json"}}
            - node_modules
      - run:
          command: |
            cd stale
            npm install ./toolkit/*
      - save_cache:
          key: node_modules-{{checksum "stale/package.json"}}
          paths:
            - stale/node_modules
      - run:
          command: |
            cd stale
            npm run build
            env INPUT_REPO-TOKEN=${GITHUB_TOKEN} node lib/main.js
          environment:
            # INPUT_REPO-TOKEN: xxx
            INPUT_DAYS-BEFORE-STALE: 1
            INPUT_DAYS-BEFORE-CLOSE: 1
            INPUT_STALE-ISSUE-LABEL: stale
            INPUT_STALE-PR-LABEL: stale
            INPUT_STALE-ISSUE-MESSAGE: 'stale issue'
            INPUT_STALE-PR-MESSAGE: 'stale pull request'
            INPUT_OPERATIONS-PER-RUN: 30
            GITHUB_REPOSITORY: yasuhiroki/enjoy-circleci

workflows:
  version: 2
  build:
    jobs:
      - build:
          # 環境変数 GITHUB_TOKEN を定義した context
          context: my_context

実行結果

無事に CircleCI で stale が動きました。

image.png

まとめ

これで GitHub Actions が使えない環境の人でも「GitHub Actions (の Action を CircleCI上で) 使ってるよ :thumbsup:」 と言えますね。

今回紹介した stale 以外の Action も似たような流れで CircleCI 上で動かせる...と言いたいところですが、実際には github Context に依存していたり、そもそも Node.js じゃなくて Docker で動くものだったりすると、なかなか難しいところがあります。
GitHub Actions の Action を実行するための orb があれば少しは楽になるでしょうが、そこまでしてがんばって GitHub Actions の Action が使いたいなら、Action のロジック部分を抜き出してモジュール化して、orb化する方が適切のような気もします。


  1. 本記事では action.yml の説明はしません. 気になる方はドキュメントをお読みください -> https://help.github.com/ja/actions/automating-your-workflow-with-github-actions/metadata-syntax-for-github-actions 

  2. staleが依存している @actions/core のこの実装 によるものです. 

  3. GitHub Actionsのように INPUT_REPO-TOKEN: ${{secrets.GITHUB_TOKEN}} などと書けると嬉しいのですが... 

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした