GitHub Actionsに導かれし、CircleCI使いの者たちのための導きの書
はじめに
普段、CircleCIさまに大変お世話になっているのですが、とある要件でGitHub Actionsを使う機会があり、使ってみるとCircleCIでいう所のこれかと思った部分が結構あったのでまとめることにしました
CircleCIのyamlをGitHub Actionsのyamlで書くことで、CircleCI使いの人たちがGitHub Actionsの概要をざっくりと理解する参考になれば幸いです
GitHub Actionsに導かれた瞬間
ちなみにドラゴンクエスト4は未プレイです
記事のターゲット
- GitHub Actionsの基本的な部分をざっくりと知りたいCircleCI使いの人
サンプルコード全容
今回はフロントエンドのリポジトリで、任意のブランチ名でプルリクが作成された際に下記処理の実行をするワークフローをサンプルコードとします
- yarn(v3)でdependenciesのインストール
- テスト (並列で実行)
- lint (並列で実行)
- audit (並列で実行)
CircleCI
version: 2.1
executors:
default:
working_directory: /home/circleci/src/
docker:
- image: cimg/node:14.17.6
jobs:
setup:
executor: default
steps:
- checkout
# REF:(nus3) https://circleci.com/docs/ja/2.0/yarn/#caching
- restore_cache:
name: Restore Yarn Package Cache
keys:
- yarn-packages-{{ checksum "yarn.lock" }}
- run:
name: Install Dependencies
command: yarn --immutable
- save_cache:
name: Save Yarn Package Cache
key: yarn-packages-{{ checksum "yarn.lock" }}
paths:
- ~/.cache/yarn
- persist_to_workspace:
root: .
paths:
- node_modules/*
test:
executor: default
steps:
- checkout
- attach_workspace:
at: .
- run:
name: Run jest
command: yarn test # jestの実行を抽象化したコマンド
lint:
executor: default
steps:
- checkout
- attach_workspace:
at: .
- run:
name: Run lint
command: yarn lint # eslintの実行を抽象化したコマンド
- run:
name: Run check type
command: yarn check-type # TypeScriptの型チェックを抽象化したコマンド
audit:
executor: default
steps:
- checkout
- attach_workspace:
at: .
- run:
name: Run audit
command: yarn audit # dependenciesに脆弱性がないかのチェックを抽象化したコマンド
workflows:
version: 2
run_all:
jobs:
- setup:
filters:
branches:
# もっと色々書き方はあると思いますが今回はこれで許してください
only:
- /feature\/.*/
- /improved\/.*/
- /hotfix\/.*/
- main
- develop
- test:
requires:
- setup
filters:
branches:
only:
- /feature\/.*/
- /improved\/.*/
- /hotfix\/.*/
- main
- develop
- lint:
requires:
- setup
filters:
branches:
only:
- /feature\/.*/
- /improved\/.*/
- /hotfix\/.*/
- main
- develop
- audit:
requires:
- setup
filters:
branches:
only:
- /feature\/.*/
- /improved\/.*/
- /hotfix\/.*/
- main
- develop
GitHub Actions
name: Run test and lint
on:
pull_request:
branches:
- feature/**
- improved/**
- hotfix/**
- main
- develop
types: [opened, synchronize]
jobs:
setup:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Use Node.js
uses: actions/setup-node@v2
with:
node-version: '14.17.6'
- name: Cache node modules
uses: actions/cache@v2
env:
cache-name: cache-node-modules
# REF: (nus3) https://dev.to/mpocock1/how-to-cache-nodemodules-in-github-actions-with-yarn-24eh
# REF: (nus3) https://zenn.dev/link/comments/71195269e61d4f
with:
path: node_modules
key: ${{ runner.os }}-modules-${{ hashFiles(format('{0}{1}', github.workspace, '/yarn.lock')) }}
- name: Install dependencies
run: yarn --immutable
test:
runs-on: ubuntu-latest
needs:
- setup
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Use Node.js
uses: actions/setup-node@v2
with:
node-version: '14.17.6'
# REF:(nus3) https://dev.classmethod.jp/articles/github-actions-parallel-deploy/
- name: Restore node modules
uses: actions/cache@v2
env:
cache-name: cache-node-modules
with:
path: node_modules
key: ${{ runner.os }}-modules-${{ hashFiles(format('{0}{1}', github.workspace, '/yarn.lock')) }}
- name: Run jest
run: yarn test
lint:
runs-on: ubuntu-latest
needs:
- setup
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Use Node.js
uses: actions/setup-node@v2
with:
node-version: '14.17.6'
- name: Restore node modules
uses: actions/cache@v2
env:
cache-name: cache-node-modules
with:
path: node_modules
key: ${{ runner.os }}-modules-${{ hashFiles(format('{0}{1}', github.workspace, '/yarn.lock')) }}
- name: Run lint
run: yarn lint
- name: Run check type
run: yarn check-type
audit:
runs-on: ubuntu-latest
needs:
- setup
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Use Node.js
uses: actions/setup-node@v2
with:
node-version: '14.17.6'
- name: Restore node modules
uses: actions/cache@v2
env:
cache-name: cache-node-modules
with:
path: node_modules
key: ${{ runner.os }}-modules-${{ hashFiles(format('{0}{1}', github.workspace, '/yarn.lock')) }}
- name: Run audit
run: yarn audit
.circleci/config.yml
の置き場所
CircleCIでいう所の.github/workflows/
CircleCI使いの皆さんはご存知.circleci/config.yml
にCircleCIで実行するCICDを定義しますが、GitHub Actionsの場合、.github/workflows/
配下に任意の名前のymlファイルで定義します
.github/workflows/
に複数ファイルを作成した場合はそれぞれ個別のワークフローとして並列で実行されます
CircleCIでいう所のconfig.ymlの構成
CircleCIの場合、一例ですが
- version
- executors
- jobs
- steps
- workflows
- jobs
のような順にconfig.ymlで定義します
version:
executors:
jobs:
{job-name}:
executor:
steps:
-
workflows:
version:
{workflow-name}:
jobs:
- {job-name}:
requires:
filters:
GitHub Actionsでは
- name
- on
- jobs
- runs-on
- step
のような順に定義します
name: # このワークフローの名前
on: # ≒ CircleCIのworkflowsやfilters
jobs: # ≒ CircleCIのjobs
{job-name}:
runs-on: # ≒ CircleCIのdocker image
steps:
- name:
workflows
のfilters
CircleCIでいう所のタグやブランチ名など特定の条件のときにワークフローのjobを実行するときはfilters
で定義していましたが、GitHub Actionsの場合、on
で定義します
CircleCIの場合
workflows:
version: 2
{workflow_name}:
jobs:
- setup:
filters:
branches:
only:
- /feature\/.*/
GitHub Actionsの場合
on:
pull_request:
branches:
- feature/**
types: [opened, synchronize]
onとtypesでワークフローをトリガーするGitHubのイベント(プルリクエストが作られた・issueが更新されたなど)を指定することで、そのイベントが実行されたときにワークフローを実行することができます
指定できるイベント一覧
スケジュールしたイベント
schedule
手動イベント
workflow_dispatch
repository_dispatch
webhook イベント
check_run
check_suite
create
delete
deployment
deployment_status
fork
gollum
issue_comment
issues
label
milestone
page_build
project
project_card
project_column
public
pull_request
pull_request_review
pull_request_review_comment
pull_request_target
push
registry_package
release
status
Watch
workflow_run
参考リンク
docker
のimage
CircleCIでいう所のexecutor
やjobs
の配下にあるdocker
のimage
の指定はruns-on
で指定する
また、Node.jsのセットアップなどはorbs
のようなものがuses: {repository-name}
で使えて、セットアップ用のリポジトリを公式が公開してるので、それを使ってセットアップする
CircleCIの場合
executors:
{executor-name}:
working_directory: /home/circleci/src/
docker:
- image: cimg/node:14.17.6
jobs:
{job-name}:
executor: {executor-name}
GitHub Actionsの場合
jobs:
setup:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Use Node.js
uses: actions/setup-node@v2
with:
node-version: '14.17.6'
公式が公開してるsetupのactionなど
参考リンク
checkout
CircleCIでいう所のconfig.ymlで見ない日はないんじゃないでしょうか
ソースコードをチェックアウトするためのステップですね
CircleCIの場合
steps配下でcheckout
を記載するだけ
jobs:
setup:
executor: default
steps:
- checkout
GitHub Actionsの場合
actions/checkout@v2
を使う
jobs:
setup:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2
orbs
CircleCIでいう所のcircleci/aws-cli
だったりcircleci/slack
といったorbsには大変お世話になっていたんですが、GitHub Actionsではjobs
のsteps
の中
のuses
プロパティで使いたいGitHubのリポジトリを指定して使う感じになります
使い方はorbs
と似てるのですんなり使えるかと
CircleCIの場合
awsのs3のorbsを使った例
orbs:
aws-s3: circleci/aws-s3@3.0.0
jobs:
deploy_s3:
executor: default
steps:
- checkout
- attach_workspace:
at: .
- run: yarn build
- aws-s3/sync:
arguments: --delete
from: ./{path}
to: s3://{bucket-name}
GitHub Actionsの場合
GitHubのReleaseをを作るactions/create-release
を使った例
jobs:
{job-name}:
runs-on: ubuntu-latest
steps:
- name: Publish release
uses: actions/create-release@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
tag_name: {tag-name}
release_name: {release-name}
body: {body}
uses: {repository-name}
で使いたいactionを指定して、with
配下で指定したactionに必要なプロパティを渡す感じです
参考リンク
workflows
のrequires
CircleCIでいう所のJobに依存関係がある場合はCircleCIではworkflowsのrequires
で定義してましたよね
GitHub Actionsではneeds
て定義します
CircleCIの場合
※関係ある部分しか記載していません
workflows:
version: 2
{workflow-name}:
jobs:
- setup:
- test:
requires:
- setup
- lint:
requires:
- setup
- audit:
requires:
- setup
GitHub Actionsの場合
※関係ある部分しか記載していません
jobs:
setup:
steps:
-
test:
needs:
- setup
steps:
-
lint:
needs:
- setup
steps:
-
audit:
needs:
- setup
steps:
-
今回のサンプルではsetupのjobが実行された後に並列でtest, lint, auditのjobが実行されるように定義しています
参考リンク
GitHub Actions独自のもの
(もしかしたらCircleCIにも似たようなものがあるかもしれやせん)
式構文
${{ }}
で囲うことで式として評価される
例: プルリクエストがマージされた後、かつ、head_refのブランチ名にrelease/
が含まれている場合はjobを実行するみたいな条件式として評価する
jobs:
create-prerelease:
runs-on: ubuntu-latest
if: ${{ github.event.pull_request.merged == true && contains(github.head_ref, 'release/') }}
コンテキスト・関数など
github.actor
やgithub.event
など(githubだけじゃなくjobやenvのコンテキストもあるよ)、ワークフローやランナー、ジョブに関する情報を取得するためのもの
また式構文のサンプルで記載したcontainsなど、GitHub Actionsが標準で用意してる組み込みの関数もあります
環境変数
GitHub Actions内で使える環境変数たち
ワークフローコマンド
ワークフロー内で使えるコマンド
基本的には::{command-name}
でコマンドを呼び出す
例: set-outputコマンドを使って、別のstepに値を渡す
※関係ある部分しか記載していません
jobs:
create-release:
steps:
- name: set package version
id: package-version
# versionというプロパティにpackage.jsonに記載されているversionの値をoutputする
run: node -p -e '`::set-output name=version::${require("./package.json").version}`'
- name: Bump version and push tag
id: tag_version
uses: mathieudutour/github-tag-action@v5
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
release_branches: main
pre_release_branches: pre.*
# package-versionでversionプロパティにset-outputした値を呼び出す
custom_tag: ${{ steps.package-version.outputs.version }}
例のコードでは肝心な部分が見づらいかもしれませんが、::set-output name=version::{version-value}
を使って、version情報をoutputにsetしています
別のステップからはsteps.{step-id}.outputs.version
で値にアクセスできます
Discussion