Corredor

ウェブ、プログラミングの勉強メモ。

GitHub Actions を触ってみた

GitHub 上で CI/CD を実現できるコンテナ・パイプライン機能である GitHub Actions を使ってみた。

お試ししたリポジトリは以下。

github.com

Effective DevOps ―4本柱による持続可能な組織文化の育て方

Effective DevOps ―4本柱による持続可能な組織文化の育て方

The DevOps ハンドブック 理論・原則・実践のすべて

The DevOps ハンドブック 理論・原則・実践のすべて

  • 作者: ジーン・キム,ジェズ・ハンブル,パトリック・ボア,ジョン・ウィリス
  • 出版社/メーカー: 日経BP
  • 発売日: 2017/07/04
  • メディア: Kindle版
  • この商品を含むブログを見る

DevOps導入指南 Infrastructure as Codeでチーム開発・サービス運用を効率化する (DEV Engineer’s Books)

DevOps導入指南 Infrastructure as Codeでチーム開発・サービス運用を効率化する (DEV Engineer’s Books)

  • 作者: 河村聖悟,北野太郎,中山貴尋,日下部貴章,株式会社リクルートテクノロジーズ
  • 出版社/メーカー: 翔泳社
  • 発売日: 2016/10/14
  • メディア: 単行本(ソフトカバー)
  • この商品を含むブログを見る

まずはテキトーに動かしてみる

使い方がよく分からないが、いきなり解説記事を読んでもやっぱりよく分からないので、試しに動かしてみる。

新規リポジトリを作り、「Actions」タブに移動する。

f:id:neos21:20191118140935p:plain

「Simple workflow」というサンプルっぽいヤツを試してみる。「Set up this workflow」ボタンを押す。

すると次のようなエディタ画面に移動する。自分で調べながらコメントを付け足してみた。

f:id:neos21:20191118140948p:plain

GitHub 画面上でこのファイルをコミットしてみると、早速ワークフローが動いた。トリガーとなるイベントを on: [push] と実装していたので、GitHub 画面上でコミットした場合は git push と同じ扱いになり、動作したというワケ。

f:id:neos21:20191118140958p:plain

ジョブを選択し、右端の3点リーダアイコン から View raw logs を押下すると、詳細なログが見える。

f:id:neos21:20191118141008p:plain

見てみると、確かにワークフローで実装していた echo コマンドの動作が確認できた。

f:id:neos21:20191118141015p:plain

Secret : クレデンシャル情報を渡してみる

続いて、よくありそうな仕組みとして、アクセストークンやパスワードなどのクレデンシャル情報を別に定義しておいて、ジョブ内で使用するというモノだ。

GitHub 画面の「Settings」タブより「Secrets」メニューに進み、「Add a new secret」リンクを押してシークレットを追加する。

f:id:neos21:20191118141022p:plain

今回はサンプルとしてどうでもいい文字列を追加した。my-password-value が、パスワードとして使用する文字列の「テイ」だ。

f:id:neos21:20191118141029p:plain

追加するとこのような画面になる。一度追加したシークレットは、中身を参照したり変更したりできないので注意。値を変更したい場合は一度「Remove」してから同名で作成することになる。

f:id:neos21:20191118141035p:plain

このシークレットを、ワークフロー内のシェルスクリプトで利用してみる。シェルスクリプト内の環境変数として利用できるようにするには、env プロパティにてシークレットを渡しておく必要がある。

f:id:neos21:20191118141042p:plain

- name: Run a multi-line script
  env:
    NEOS_EXAMPLE_PASSWORD: ${{ secrets.NEOS_EXAMPLE_PASSWORD }}
  run: |
    echo "This is Secret : [ ${NEOS_EXAMPLE_PASSWORD} ]"
    echo "${NEOS_EXAMPLE_PASSWORD}" > ./test.txt
    cat ./test.txt
    echo 'Finished'

ちょっとイジワルだが、シークレット情報を echo したり、ファイルに書き出して cat したりしてみる例だ。

コレをコミットして実行させてみたが、ログには一切パスワード文字列が出力されなかった。コレは安全である。

f:id:neos21:20191118141049p:plain

ちなみに、ワークフローの YAML ファイルに問題があったりすると、次のようにエラーとなる。

f:id:neos21:20191118141055p:plain

成功・失敗・実行中というステータスの他、「手動でジョブを中断 (Cancel)」ということもできる。

f:id:neos21:20191118141103p:plain

もう少し複雑な例として、Node.js スクリプトから、あるサーバに FTP 接続する、というスクリプトを作ってみた。

  • ./.github/workflows/nodejs.yaml
name: Node CI
on: [push]
jobs:
  build:
    name: Node.js Job
    runs-on: ubuntu-latest
    steps:
    - name: Checkout
      uses: actions/checkout@v1
    - name: Use Node.js v10
      uses: actions/setup-node@v1
      with:
        node-version: '10.x'
    - name: Run npm Scripts
      env:
        MY_FTP_PASS: ${{ secrets.MY_FTP_PASS }}
      run: |
        npm install
        npm run ftp

package.jsonscripts にて、npm run ftp が動作するよう npm-run-scripts を定義しておく。

{
  "scripts": {
    "ftp": "node ftp.js"
  }
}

ftp.js 内の実装、promise-ftp という npm パッケージを使って FTP 接続するようにしている。シークレットで定義した MY_FTP_PASS を環境変数から読み取るため、次のように実装している。

const PromiseFtp = require('promise-ftp');
const promiseFtp = new PromiseFtp();

promiseFtp.connect({
  user    : 'example-user',
  password: process.env.MY_FTP_PASS,
  host    : 'example.com'
})
  .then((serverMessage) => {
    console.log('★ Connected ', serverMessage);
  });

Node.js は process.env.MY_FTP_PASS という風に書くことで環境変数を参照できるので、このように書いている。

コレを実行してみると、無事シークレット情報が渡されて正常動作したのだが、全角文字 (上のコードの 部分) が文字化けしていた。

f:id:neos21:20191118141109p:plain

日本語のログ出力には対応していなさそうなので、注意が必要だ。

結構使えるやんけ!

以上がザッと使ってみた例。結構使えそうだ。

構文の勉強

もう少し使い方を調べるため、以下の公式の記事を見てみた。

最初はなかなかとっつきにくかったが、ひとしきりサンプルの Workflow や Action を使ってみた後に読むとよく分かった。

  • ワークフロー (1ファイル・トリガーとなるイベントを定義できる単位) → ジョブ (ワークフロー内で行う処理の塊) → ステップ (ジョブ内の1つの処理) という関係
  • ワークフローは複数作成できる。それぞれのワークフローに同じ on イベントを指定しておくと、並列実行される
  • ジョブはデフォルトで並列実行されるが、jobs.【Job ID】.needs で依存ジョブを指定すれば順序の制御もできる
    • needs: job1 とか needs: [job1, job2] とか書く
  • jobs.【Job ID】.runs-on は、そのジョブを実行するホスト環境
    • コレ自体も仮想環境ではあるが、イメージ的には Jenkins サーバみたいに、1つのジョブを実行するマシン1台、と捉えて良い。CPU や RAM などのスペックが一応公開されている
    • 1つのジョブにつき1つのホスト環境を指定した上で、jobs.【Job ID】.containerjobs.【Job ID】.steps.uses でさらに Docker コンテナを指定したりできる
    • runs-on で指定したデフォルト環境ではグローバルにコマンドが足りなかったりする時は、ジョブ単位やステップ単位で Docker コンテナないしは Actions を利用することで拡張できるイメージ
  • jobs.【Job ID】.steps.name は省略できる
  • Action 1つは、1つの Step として実行することになる
    • Action とは「再利用可能なコードの単位」。コマンドを提供する、もしくはコマンドを実行する Docker コンテナを指定する、ぐらいのイメージでいいかな
    • uses: docker://apline:3.8 のように DockerHub のイメージを直接指定して使ったりもできる
  • jobs.【Job ID】.steps.run でシェルコマンドを実行できる
    • shell プロパティで PowerShell やコマンドプロンプトなども設定できる (runs-on で指定した環境が Windows じゃないとダメ)
    • Windows マシンでも shell: bash は動作する。GitBash が使用されるようだ

その他、構文に関しては以下の記事が参考になった。

他に何ができるの?の参考に

その他にどんなことができそうかは、具体的なコードを見た方がイメージが湧くと思うので、Qiita で色々記事を集めてみた。参考までに。

以上

実行基盤に Ubuntu だけでなく、Windows と MacOS も使えるようなので、クロスブラウザテストや iOS アプリのテストなんかもできそうだ。

無料でガンガン使えるので、どんどん活用していこうと思う。