GitHub Actionsで作成したArtifactをAPIダウンロード

Posted on 2020/03/17

ToC

GitHub Actionsでデプロイモジュールを作成

GitHub Actionsを使いはじめました。
CI/CDを効率的にすすめるためのツールとして非常に便利です。
自分の処理したい内容を yaml 形式のworkflow ファイルとして記述することにより PythonプログラムのUnitテストやLinterなどをGitHubへのPushのタイミングや masterへのマージのタイミングなどで処理を実行できます。

そこで、GitHub上で管理しているAWS Lambdaのプログラムのデプロイパッケージ作成を GitHub Actions で生成し、その後、別のデプロイのトリガー(AWS側から実行を想定)で GitHub Actions で生成したデプロイパッケージを取得するユースケースを試してみました。

sequenceDiagram # エイリアス participant user as ユーザー participant gh as GitHub participant ac as GitHub Actions participant aws as AWS # データ取得コード user ->> gh : MasterへのMerge gh ->> ac : Workflowの起動 ac ->>+ ac : パッケージの作成 user ->> aws : デプロイ aws ->> ac : パッケージの取得

パッケージを作成するworkflow

今回のプログラムは、Pythonで作成したためLambdaファンクションのデプロイパッケージを 作成するworkflowでは、下記の処理を順番行いました。

  1. ソースのチェックアウト
  2. ミドルウエア(zip, vim-common)のインストール
  3. pipでライブラリをインストール(requirements.txt)
  4. Pythonのビルド
  5. Lambdaプログラムのデプロイパッケージ(Zip)作成
  6. デプロイパッケージのSha256Sum取得
  7. ファイルのArtifactsへのアップロード

workflowの作成については、ネット上に色々と詳しいサイトがあると思います。 今回の処理で重要な箇所を下記には記載しておきます。

# 〜 途中の処理記載を省略しています 〜

name: lambda-package
on:
  push:
    branches:
      - master

jobs:
  lambda-package:
    runs-on: ${{ matrix.platform }}
    strategy:
      matrix:
        platform: [ubuntu-latest]
        python-version: [3.7]

    steps:
      - name: Checkout
        uses: actions/checkout@v2

      - name: Set up Python ${{ matrix.python-version }}
        uses: actions/setup-python@v1
        with:
          python-version: ${{ matrix.python-version }}
          architecture: 'x64'

      - name: Install Package Tools
        shell: bash -xe {0}
        run: |
          sudo apt-get install -y vim-common
          sudo apt-get install -y zip

      # 〜 途中省略 〜

      - name: Upload package file to artifact
        if: success()
        uses: actions/upload-artifact@v1
        with:
          name: package
          path: artifacts

GitHub Actionsが正常終了すると、下記のような形で Artifacts にファイルが作成されます。

/posts/2020/03/img/7ccdc3fd_huedef22e331e176c3b0828db740f43671_74651_800x0_resize_lanczos_3.png

GitHubのアクセストークン

GitHubに対してAPIアクセスするためには、GitHubのアクセストークンの発行が必要です。
はじめはどこから発行するのかがよくわからず、GitHibのページをウロウロしていましたが、 Settings > Developer settings > Personal access tokens のところから発行ができました。

今回は、private repositoryartifacts を取得する必要があるため、スコープは repo 全体としました。

/posts/2020/03/img/d1b0fbbb_hu350722ffdef5a6f541277c5f1dd840f6_107368_800x0_resize_lanczos_3.png

APIでファイルを取得する

私の場合は、CodeBuild を利用してデプロイをしているため、上記で取得した必要なGitHubのアクセストークン を セキュアに保管するために SMS Parameter Store を利用しました。 そして、CodeBuild から GitHub に対してAPI処理でデプロイパッケージファイルをダウンロードするような構成としています。

細かいことをいろいろいうよりも、ソースコードの方がわかりやすいかと思いますので記載します。

#!/bin/bash -e

owner="owner"
repo="repo-name"
token="your-access-token"
file_name="package"

actions_artifacts_list="https://api.github.com/repos/${owner}/${repo}/actions/artifacts?per_page=100"
asset_url=$(curl -H "Authorization: token ${token}" ${actions_artifacts_list} | jq ".artifacts | sort_by(.created_at) | reverse" | jq "map(select(.name == \"${file_name}\"))" | jq -r ".[0] | .url")
curl -L -H "Authorization: token ${token}" -o ${file_name}.zip ${asset_url}/zip

細かいことになりますが、まずGitHubのAPIは取得対象のリストのオブジェクトが多くなるとページングされます。 そのため、対象が多くなる場合にはページング処理の検討が必要です。参考までにレスポンスイメージを記載します。

{
  "total_count": 1,
  "artifacts": [
    {
        "id": 1234567,
        "node_id": "ABCD1234EFGH5678XXXX0000",
        "name": "package",
        "size_in_bytes": 9335709,
        "url": "https://api.github.com/repos/username/repo/actions/artifacts/1122345",
        "archive_download_url": "https://api.github.com/repos/username/repo/actions/artifacts/1122345/zip",
        "expired": false,
        "created_at": "2020-03-16T23:11:16Z",
        "updated_at": "2020-03-16T23:11:17Z"
    }
  ]
}

上記のコードでは、file_name に一致するartifactの最新のファイルをダウンロードする処理として記載しています。 この処理を入れることで、AWS側からファイルを取得してデプロイをすすめることが可能になりそうです。

お掃除の処理は…

ちなみにですが、artifactが大量になることを防ぐためにMarketPlacepurge-artifactsというものが 準備されているようです。でも、よく考えると、ファイルをアップロードするときにTTLを指定する方がより良いのでは ないかな、とも思いました。
いずれにしても、GitHub Actions を有効に活用するためには、お掃除も重要ですね。

参照