概要
データ分析のためのプログラムをシステマチックにテスト/デリバリ/デプロイする技術を学ぼうと、『CI/CD』を調べてました。CI/CDのためのツールをいくつか見つけ、Github Actionsを使うことにしたのですが、躓きポイントがあったので、備忘として。
<見つけたCI/CDツール>
- Github actions:https://github.com/features/actions
- CircleCI:https://circleci.com/
- Jenkins: https://www.jenkins.io/
どれも良さそうだったのですが、筆者がGithubを利用していることと、無償で利用できることの利点がある Github Actionsを使うことにしました。
今回実行すること
- 2個のpythonファイルを作成する。
- 1個目のpythonで2個の乱数をテキストファイルとして出力する。
- 2個目のpythonは、1個目のpythonで出力したテキストファイルを読み込み、足し合わせてその計算結果をprintする。
筆者がここで苦労したのは、「3.」のところで、Github Actions上でファイルを読み込ませるところです。
Github Actionsをやってる人からすればすぐわかると思うかもしれないですが、「2つのジョブ間でファイルを共有すること」「ステップの順番によっては、ダウンロードしたファイルが消えてしまう」ということがあり、それを筆者は知らないまま作成していたため、ドツボにハマっていました(※もちろん解決済みです)。
図で描くと、以下のように単純な実行フローです。
そしてこれらのファイルの関係性を図にすると以下です。
generate_array.py
がoutput.txt
を出力し、それをinputとして利用するsum_array.py
という関係性です。
実際に作る
まずはディレクトリを作ります。
root/
├ .github/
│ └ workflows/
│ └ python.yml
├ src/
│ └ generate_array.py
│ └ sum_array.py
├ requirements.txt
各ファイルはそれぞれ以下のような内容です。
-
python.yml
- ここにGithubActionsのジョブを定義します。
- ファイル名はなんでも良いです。今回は、「python.yml」としています。
- 注意点
- GithubActionsを使うには、このジョブ設定ファイルの保存場所が決まっており、
.github/workiflows/
に保存する必要があります。
- GithubActionsを使うには、このジョブ設定ファイルの保存場所が決まっており、
-
generate_array.py
- これが1個目のpythonファイルです。
- ファイルの保存場所は特に指定はないですが、今回は、
src
ディレクトリの配下に入れることとしました。 - 2個の乱数を生成し、それをテキストファイルとして保存します。
-
sum_array.py
- これが2個目のpythonファイルです。
- ファイルの保存場所は特に指定はないですが、今回は、
src
ディレクトリの配下に入れることとしました。 -
generate_array.py
の出力テキストファイルを入力して、それらを足し合わせます。
-
requirements.txt
- 今回はnumpyを使うので、numpyをインストールできるようにするためにrequirements.txtを用意しておきます。
python.yml
の中身
Github Actionsでどんな処理をどういう順番で実行させるか、というものを定義するためのファイルです。
name: Python Workflow
on: [push]
jobs:
generate:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: '3.10'
- name: Install dependencies
run: pip install -r requirements.txt
- name: Generate random array
run: python src/generate_array.py
- name: Upload output.txt
uses: actions/upload-artifact@v4
with:
name: output-file
path: src/output.txt
sum:
runs-on: ubuntu-latest
needs: generate # このジョブはgenerateジョブが成功しなければ実行されない
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: '3.10'
- name: Download output.txt # python環境のセットアップ(actions/setup-python@v4)が完了してから、ダウンロードする必要がある.
uses: actions/download-artifact@v4
with:
name: output-file
path: src # `src/`にoutput-file(output.txt)を保存する
- name: Calculate sum
run: python src/sum_array.py
中身の解説
基本情報
-
name: Python Workflow
- ワークフローの名前です。
-
on: [push]
- このワークフローは、リポジトリに対してプッシュされたときにトリガーされます。
ジョブの定義
このYAMLファイルには2つのジョブ(generate
とsum
)があります。
1. ジョブ generate
-
runs-on: ubuntu-latest
- このジョブは最新のUbuntu環境で実行されます。
-
steps
-
ジョブ内の各ステップを定義しています。
-
Checkout code
- name: Checkout code uses: actions/checkout@v4
- リポジトリのコードをチェックアウトします。
-
Set up Python
- name: Set up Python uses: actions/setup-python@v4 with: python-version: '3.10'
- Pythonのバージョン3.10をセットアップします。
-
Install dependencies
- name: Install dependencies run: pip install -r requirements.txt
- 必要な依存関係を
requirements.txt
からインストールします。
- 必要な依存関係を
-
Generate random array
- name: Generate random array run: python src/generate_array.py
-
src/generate_array.py
を実行してランダムな配列を生成します。
-
-
Upload output.txt
- name: Upload output.txt uses: actions/upload-artifact@v4 with: name: output-file path: src/output.txt
- 生成された
output.txt
ファイルをアップロードします。ファイルはoutput-file
という名前で保存されます。 - ちなみに、
actions/upload-artifact@v4
という指示は、自動でファイルを圧縮してアップロードします。
- 生成された
-
2. ジョブ sum
-
runs-on: ubuntu-latest
- このジョブも最新のUbuntu環境で実行されます。
-
needs: generate
- このジョブは、
generate
ジョブが成功した後にのみ実行されます。
- このジョブは、
-
steps
-
ジョブ内の各ステップを定義しています。
-
Checkout code
- name: Checkout code uses: actions/checkout@v4
- リポジトリのコードを再度チェックアウトします。
-
Set up Python
- name: Set up Python uses: actions/setup-python@v4 with: python-version: '3.10'
- 再度Pythonのバージョン3.10をセットアップします。
-
Download output.txt
- name: Download output.txt uses: actions/download-artifact@v4 with: name: output-file path: src
-
generate
ジョブでアップロードされたoutput.txt
をダウンロードします。 - このステップは、python環境のセットアップの後にする必要があります。前にしてしまうと、python環境の構築時にファイルが上書きされてしまい、せっかくダウンロードしたファイルが消えてしまいます。
-
path
のパラメータは保存先のディレクトリを指定しておきます。今回作成するpythonファイルをsrc
ディレクトリに入れているため、srcを指定しておきます。 - ちなみに、この
actions/download-artifact@v4
は、zipファイルを自動で解凍してくれます。ので、1個目のジョブで実行したactions/upload-artifact@v4
がzip圧縮していたとしても問題ないのです。
-
-
Calculate sum
- name: Calculate sum run: python src/sum_array.py
-
src/sum_array.py
を実行して、配列の合計を計算します。
-
-
generate_array.py
の中身
1個目のpythonファイルの中身です。
numpyで2個の整数をランダムに作成し、それをテキストファイルで出力します。
import numpy as np
import os
# 環境変数から出力ファイル名を取得
file_name = os.getenv('OUTPUT_FILE', './src/output.txt')
# ランダムな整数を2つ持つ配列を生成
random_integers = np.random.randint(1, 100, size=2)
# 配列を.txtファイルに出力
with open(file_name, 'w') as f:
f.write(','.join(map(str, random_integers)))
sum_array.py
の中身
2個目のpythonファイルです。
1個目の出力テキストを読み込んで、足し合わせる処理です。
その結果をprint()します。
import os
# 環境変数から出力ファイル名を取得
file_name = os.getenv('INPUT_FILE', './src/output.txt')
# output.txtファイルを読み取る
with open(file_name, 'r') as f:
data = f.read()
# 整数をリストに変換
numbers = list(map(int, data.split(',')))
# 合計を計算
total = sum(numbers)
# 合計を表示
print(f'The sum of the integers is: {total}')
requirements.txt
の中身
Github Actionsでは、pythonのピュア環境(特にライブラリをインストールされていない)であるため、numpyのようなサードパーティライブラリはrequirements.txtに書き込んで、インストールさせておく必要があります。
今回は、numpyだけ必要なので、numpyだけ記載しておきます。
numpy
Github Actionsを使う
↑の設定や必要なファイルを作成したので、実際にGithub Actionsを使ってみます。
使い方は簡単です。自分のリポジトリに単純にpushするだけです(今回はGithubへのプッシュ方法については解説しないです)。
pushしたあとは、以下のように自分のリポジトリの「Actions」を開きます。
そして、そのActionsページを見ると(Actionsの動作が完了していれば)、以下のように動作実行結果を確認することができます。
この図では、何回もプッシュしてテストをしていたため、何個も画面に出てきてしまっていますが、失敗した時と成功した時とでのアイコンの違いを確認できます(赤の「バツ」と緑の「チェックマーク」でわかりやすいですね)。
まとめ
以下の2点を実施することができた。
- Github Actionsで2個のpythoファイルを別のジョブとして実行する。
- ジョブ間でファイルの共有をする。