ソフトウェア設計論

まつ本

モダンSW開発

モダンSW開発 -CI/CD-


目次

・CI/CD
・CIで何がうれしいのか?
・Linusの法則

・CIツール・CI環境
・GitHub Actions
・宣言的
・アクション
・演習

・CIを活用した論文執筆
・CIを活用した実験
・プログラマの三大美徳

CI: Continuous Integration

継続的インテグレーション

継続的にビルドを実行するというプラクティス
ビルド ∈ {依存の解決, コンパイル, テスト, ⋯}

自動ビルドを実行するタイミング

基本はソースの変更時(git-pushやPRマージ)
定期的に実施するケースもある(毎週や毎月)

CI適用の前提条件

ソースコードがある
テストがある
ビルドスクリプトがある
版管理上で上記リソースが管理されている

CIで何がうれしいのか?

バグの早期発見

テストが落ちたら即通知する
バグを含んだ状況を放置しない・させない

🤔💭 先程の変更でテストが落ちた
🤔💭 いつの間にかテストが落ちていた

CIはテスト実行を強制するという側面を持つ

マージ地獄の回避

ブランチがかけ離れるとマージが大変
かけ離れる前にmainブランチにマージする

🤔💭少しのdiffをmainに統合する
🤔💭大量のdiffをmainに統合する

500行のコードレビュー

雑談


https://x.com/iamdevloper/status/397664295875805184

論文でも同じことが言える

雑談



🤔💭 提案手法の図をチェックして下さい



🤔💭 原稿全体をチェックして下さい

CD: Continuous Delivery

継続的デリバリ

自動ビルドに加えてリリースも自動化する
CIをさらに推し進めた考え
CI/CDとまとめられることが多い

適切なタイミングで自動リリースする

必ずしも世界に公開しなくても良い
開発チームや顧客だけが対象でも良い

関係者が常に最新の実行バイナリを取得できる

開発者の利点

フィードバックを得やすい
要求との齟齬も発見しやすい







"Given enough eyeballs, all bugs are shallow"

Linus's Law

リリースの研究

雑談

Adopting CD in AAA Video Games


https://www.youtube.com/watch?v=8hXRvvFDztg

モダンSW開発 -CI/CD-


目次

・CI/CD
・CIで何がうれしいのか?
・Linusの法則

・CIツール・CI環境
・GitHub Actions
・宣言的
・アクション
・演習

・CIを活用した論文執筆
・CIを活用した実験
・プログラマの三大美徳

CIツール・CI環境

様々な選択肢がある

GitHub Actions / CircleCI / Jenkins / ⋯
組み合わせるという使い方もあり

GitHub Actions (GHA)

GitHubは版管理だけでなくCI環境も提供している
CIは版管理が前提になっているため合理的

ワークフローファイルをリポ内に配置するだけ

ワークフロー (WF)

CI上で自動処理させる作業のまとまりのこと
例) 1WF = Javaソースのコンパイルとテスト

GHAのワークフロー定義

ファイル名

.github/workflows/compile-and-test.yml

内容

まずはトップレベル要素のみを抜粋

name: Compile and test

# トリガ定義:いつワークフローを実行するのか?
on:
  ...

# ジョブ定義:ワークフローは何をするのか?
jobs:
  ...

参考:構文の定義

ワークフローファイルの全体

name: Compile and test

# トリガ定義:いつワークフローを実行するのか?
on:
  push:       # git-push時

# ジョブ定義:ワークフローは何をするのか?
jobs:
  compile_and_test:         # ジョブの名前
    runs-on: ubuntu-latest  # ジョブの実行環境
    steps:                  # ジョブを構成するステップ
      - uses: actions/checkout@v4     # git-pull
      - uses: actions/setup-java@v4   # install java
        with:
          distribution: 'temurin'
          java-version: '21'
      - run: ./gradlew build          # gradle build

宣言的(Declarative)

雑談

命令的と宣言的

命令的:処理の手順を記述するパラダイム
宣言的:対象の性質を記述するパラダイム

命令的なプログラムの例

for (int i = 0; i < textContents.length; i++)
    if (!textContents[i].startsWith("//"))
        count++;  // コメントではない行を数え上げ

宣言的なプログラムの例

count = textContents.stream()
                    .filter(s -> !s.startsWith("//"))
                    .count();

ループをどのように回すかは一切気にしない

ワークフローファイルは宣言的

雑談
on:
  push:       # git-push時

「このWFはgit-push時に実行する」と宣言する
git-pushをどう検出するかは一切意識しない

宣言的の利点

細かい処理ではなく本質だけを記述できる
処理の隠蔽化 & 読みやすい & バグが減る

具象レイヤと抽象レイヤの切り分け

宣言的パラダイムが広く浸透している

Javaは命令型言語だが宣言的要素もある
Streamやラムダ式等(関数型言語から由来)

命令的な記法であらゆる処理は実現できる

雑談

最後は機械語という命令的表現で動作するため

しかしSW開発は複雑になりすぎた

この複雑さを減らすためには適切な抽象化が必須
Streamを用いた配列操作はまさに抽象化
配列の操作方法をStreamが隠してくれる

count = textContents.stream()
                    .filter(s -> !s.startsWith("//"))
                    .count();

宣言的な仕組みを積極的に使おう

ビルドツールはmake / AntよりGradle / Maven

機械学習ライブラリはまだ命令的な傾向が強い
PyTorch / TensorFlow

アクション

ワークフロー内の再利用可能な作業のこと

jobs:
  compile_and_test:  # これはjob
    steps:
      - uses: actions/checkout@v4     # これがaction
      - uses: actions/setup-java@v4   # これもaction
        with:                         # ↑の設定
          distribution: 'temurin'
          java-version: '21'
      - run: ./gradlew build          # これはnot action

GHA固有の仕組みなので注意

アクションにより典型作業を宣言的に記述可

actions/checkout:作業対象リポの内容を取り出す
actions/setup-java:javaをインストールする

actions/checkoutの中身

actions/checkoutのソースコード

https://github.com/actions/checkout

宣言の舞台裏で何が起きているのか?

uses: actions/checkout@v4 で隠蔽化された処理は?
gitの内容を取り出すという操作はどう実現する?
単に git-clonegit-pull するだけではないのか?

舞台裏

src/git-source-providers.ts#getSource
計200行 & 様々な条件分岐を含む
checkout操作をあらゆる状況で動かすため

actions/setup-javaの中身

(詳細は略)

Javaインストールは環境依存が強い

CPUアーキテクチャ(x64 / x86 / aarch64)
プラットフォーム(win / mac / linux)
Javaディストリ(temurin / oracle / adopt)
Javaバージョン(23 / 21 / 17)

setup-javaは上記の条件分岐を隠蔽化する

利用者は環境依存に頭を悩ませなくて良い

CI上でトラブルが発生した際に
「Javaインストール作業」が容疑者から外れる

演習 (10m)

SvelteのCI上での処理内容を読み取れ

https://github.com/sveltejs/svelte
※SvelteはJavaScriptフレームワークの一種である (React等と同類)
 TypeScriptで実装されており実行環境はNodeJSである
 コンパイルとテストを要する一般的なSW開発と捉えて良い

0. Svelteリポからワークフローファイルを探せ

リポジトリ内に複数のWFファイルが含まれるが,
ここでは ci.ymlrelease.yml を対象とする

1. 上記2つのワークフローの処理内容を読み取れ

何がCI実行のトリガか?
どんなジョブを行っているか?

2. テスト実行を含むジョブを特定せよ

ジョブ中にテスト実行が含まれているかを考えよ

補足1

ジョブの処理内容は usesrun を調べれば良い

  • uses アクションを使った宣言的なジョブ
  • run Shellコマンドを使った命令的なジョブ

補足2

pnpmはNodeJSのパッケージマネージャである
※Pythonのpipとほぼ同じ
 デフォルトのパッケージマネージャnpmの改良版である

Svelteはpnpmを用いて依存を管理している
またビルドツールとしても利用している

提出方法

以下書式のテキストをCLEに提出すること

# ci.yml
## トリガ
...

## ジョブ
<ジョブ1の名前>: <ジョブ1の処理内容の1行サマリ>
<ジョブ2の名前>: <ジョブ2の処理内容の1行サマリ>
...

## テストを含むジョブ
<ジョブの名前>

# release.yml
## トリガ
## ジョブ
## テストを含むジョブ

Marketplace

誰かが作成したアクションを検索できる

https://github.com/marketplace?type=actions

WF内の作業は手で実装する前にまず検索すべき
命令を書くよりも宣言する
車輪を再発明しない

面白そうなアクション

ChatGPT CodeReviewer
super-linter
OpenCommit
Metrics embed
generate-snake-game-from-...

モダンSW開発 -CI/CD-


目次

・CI/CD
・CIで何がうれしいのか?
・Linusの法則

・CIツール・CI環境
・GitHub Actions
・宣言的
・アクション
・演習

・CIを活用した論文執筆
・CIを活用した実験
・プログラマの三大美徳

CIを活用した論文執筆

1. 原稿の各種リソースを版管理する

ソースコード .tex .bib
リソース .sty .bst .svg .png
ビルド方法 .latexmkrc

原稿の最新状態だけでなく執筆過程も記録する
複数人で執筆するなら適宜ブランチを使う

ただしPDFファイルはコミットしない

版管理しないほうがよいデータ

  • 生成可能なデータ
  • バイナリデータ

リポジトリの肥大化 & 履歴の邪魔 & 衝突の原因に

2. CI上でコンパイルする

.github/workflows/build-latex.yml

name: Build LaTeX document
on: push
jobs:
  latexmk:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: xu-cheng/latex-action@v3  # latexmk実行
      - uses: ... # TODO: 生成したPDFをどこかに設置

PDF公開先はGitHub Pagesや研究室のサーバなど

行儀の良く版管理しつつ最新のPDFを常に公開
"Given enough eyeballs, all bugs are shallow"

Q. Overleafではだめなのか?

CIを活用した実験

1. 実験リソースを版管理する

実験スクリプト .py
依存関係の宣言 requirements.txt
実験の入力データ .txt .json .bin
ビルド方法 (実行方法) .sh .bat pyproject.toml

実験データが巨大な場合(>100MB)

小さいテスト用データを版管理内に登録
これはスクリプトの検証に使う

本番データは研究室のWebサーバやAWS等に設置
httpでアクセス可能にしておく http://.../x.txt
(機械学習のモデルも同様)

2. GitHub Actions上で小実験を回す

git-push時にスクリプトを回す
小さなテストデータで検証する
あくまでスクリプトの検証が目的

3. CircleCI上で本実験を回す

2が成功したらCircleCIで本実験を動かす
GPUも使える https://circleci.com/docs/using-gpu/

本番データはCIからhttp経由で取得させる
(機械学習のモデルも同様)

実験結果は研究室サーバへ転送 & Slackへmsg

計算コストが高い場合は3に実行条件を加える

特定ブランチにマージした場合のみ実行する等




There are three virtues of a programmer; laziness, impatience and hubris


Larry A. Wall





by Randal Schwartz from Portland - Flickr

プログラマの三大美徳

Laziness, 怠惰

楽をするために努力する
(同じ作業の繰り返しはサボりたい)

Impatience, 短気

使いやすいプログラムを作る
(使いにくい状態に苛つく)

Hubris, 傲慢

誰も批判できないプログラムを作る
(強い自尊心がある)

モダンSW開発 -CI/CD-


目次

・CI/CD
・CIで何がうれしいのか?
・Linusの法則

・CIツール・CI環境
・GitHub Actions
・宣言的
・アクション
・演習

・CIを活用した論文執筆
・CIを活用した実験
・プログラマの三大美徳

CIの本質は作業の自動化

SW開発だけに特化していない

論文執筆にも役立つ

CIのような自動化の感覚を持っておくと良い

あらゆるところで役立つ
同じことを手で繰り返さない

最初だけ頑張る・後はサボる
楽をするために努力する

ミスも減る

エンジニアは怠惰で短期で傲慢であれ

怠惰であればCIを使うべき