2.9K Views
November 29, 23
スライド概要
GitHub Actionsのカスタムアクションを 作成してMarketplaceで公開した話 2023.11.30 YORIFUJI MITSUNORI
自己紹介 • YORIFUJI MITSUNORI • @yorifuji on X / GitHub / Zenn • 金融系スタートアップのiOSエンジニア • 個人向け投資アプリ(Swift)や金融機関向けの業務アプリ(Flutter)の開発 • 前職は通信会社のSIerでB2Bサービスの開発などいろいろ(10年〜) • Flutter歴は2年程度、Flutter大学は1年ほど前に入会 -> 一度退会して再度Join • #共同開発14_sansen に参戦してます
モバイルアプリ向けの主要なCIサービス
各社のCIサービスの特徴(個人の感想) • Bitrise • 老舗、安定していて枯れている、AndroidやiOSネイティブの知識が活かせる • Codemagic • 後発、Flutterに特化してる(Flutter SDKがインストール済み)、が意外と穴がある(枯れていない) • GitHub Actions • オールマイティ、publicリポジトリでの利用は無料、GitHubとの連携が強み • Xcode Cloud • Apple純正CI、証明書管理が不要、Xcode連携、安い、Flutterには不向き
今日の発表ではCI/CDに関する詳しい解説は省略 しています 過去の勉強会動画に解説動画がたくさん載ってい るのでそちらをご覧ください
About GitHub Actions • GitHubに統合されたCI機能 • 他社製のCI/CDサービスのサインアップやGitHub連携が不要 • GitHub上で発生するイベントをトリガーにワークフロー(ジョブ)を実行できる • 例)プルリクエストが作成されたらテストを実行
name: check on: pull_request permissions: contents: read GitHub Actionsで utter testを 実行するワークフローの例 (yamlファイル) jobs: test: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: subosito/flutter-action@v2 - run: flutter pub get fl - run: flutter test
name: check on: pull_request permissions: contents: read 今日話すのはワークフローで 利用するアクションの方 jobs: test: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: subosito/flutter-action@v2 - run: flutter pub get - run: flutter test
先日、自作のGitHub Actionを公開しました🎉 fl https://github.com/marketplace/actions/ utter-analyze-commenter
Flutterの静的解析 • VSCodeや utter analyzeコマンドで出力されるコレ • Error / Warning / Info の3レベル • 標準では utter_lintsに定義されたルールに基づいて解析 fl fl • pedantic_monoやvery_good_analysisがおすすめ
Flutterの静的解析の結果を Pull Requestにコメントする カスタムアクション
name: flutter-analyze-commenter example on: pull_request permissions: contents: read pull-requests: write 使い方はstepに追加する だけ jobs: flutter-analyze: runs-on: ubuntu-latest steps: ... - run: flutter analyze --write=flutter_analyze.log - uses: yorifuji/flutter-analyze-commenter@v1 if: ${{ !cancelled() }} with: analyze_log: flutter_analyze.log
GitHub Marketplace
GitHub Marketplace https://github.com/marketplace
GitHub Marketplace • GitHub公式・OSS・個人が作成したGitHub Appsやアクションが公開さ れている • アクションで検索すると 20,940 results • 必要なものは大体あるが⭐が少ないマイナーなActionを利用するときは セキュリティリスクなどに注意が必要
actions/checkout • CIのジョブでリポジトリをcloneするGitHub公式アクション
subosito/ utter-action fl • Flutterの環境構築(SDKのインストール)をするアクション
自作のアクションをMarketplaceに登録する手順 • 手順 • GitHubにpublic repositoryを作成 • アクションの定義を書いたaction.ymlを作成 • カスタムアクションの内容を実装 • GitHub 上でReleaseを作成して公開 • 詳しい手順はこちら • https://docs.github.com/ja/actions/creating-actions/about-custom-actions • 初回に利用規約への同意が必要 • https://docs.github.com/en/site-policy/github-terms/github-marketplace-developer-agreement
補足:作ったアクションを公開したくない時 • 自分のリポジトリだけで使いたい、ニッチな用途、etc • そのような場合はprivateリポジトリにカスタムアクションを作成すれ ばOK、リポジトリをpublicにしたりMarketplaceに登録する必要はな い • CIを実行するリポジトリ側からカスタムアクションのリポジトリにア クセスができればアクションを利用できる
実際のaction.yml の例
左:カスタムアクションの定義、右:CIで呼び出すコードの例
name: "Flutter Analyze Commenter"
author: "yorifuji"
inputs:
analyze_log:
description: "Path to the Flutter analyze log"
required: true
verbose:
description: "Enable verbose logging"
default: false
runs:
using: composite
steps:
- uses: actions/github-script@v7
env:
ANALYZE_LOG: ${{ inputs.analyze_log }}
VERBOSE: ${{ inputs.verbose }}
with:
script: |
const analyzeLog = process.env.ANALYZE_LOG;
...
jobs:
flutter-analyze:
runs-on: ubuntu-latest
steps:
...
- run: flutter analyze --write=flutter_analyze.log
- uses: yorifuji/flutter-analyze-commenter@v1
with:
analyze_log: flutter_analyze.log
カスタムアクションの実装方法 • Docker コンテナー アクション • Dockerを使って実行環境をパッケージ化するので必要なツールや依存関係をコンテナで管理できるので一貫性と信頼性を担 保しやすい • ただし現状はLinux(ubuntu) のランナーでのみ利用できる(macOSやWindowsは利用不可) • JavaScript アクション • Node.jsを使ってJavaScriptのコードを実行する • TypeScriptでの開発も可能(最終的にJavaScriptが生成できるならなんでも良い)、複雑な実装をするならおすすめ • 複合アクション(Comosite Action) • 通常のGitHub ActionsのJobからSetpの一部を切り出したイメージ • uses: が利用可能なので既存のアクションも利用できる
actions/github-script
• GitHub ActionsでJavaScriptを実行する
アクション
// hello world
- uses: actions/github-script@v7
with:
script: console.log('Hello, JavaScript')
// use github rest api
- uses: actions/github-script@v7
with:
script: |
github.rest.issues.get({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
})
// run separate file
- uses: actions/github-script@v7
with:
script: |
const script = require('./path/to/script.js')
console.log(script({github, context}))
// in script.js
module.exports = ({github, context}) => {
return 'Hello, JavaScript'
}
• utter analyzeコマンドの出力内容を解析する • --write= lenameオプションを使うと静的解析の内容がparseしや すい形式でファイルにも出力される • ファイル名、行番号、メッセージなどを取得する fi fl 今回のカスタムアクションの実装の詳細
--writeオプションで出力される内容の例 [error] A value of type 'int' can't be assigned to a variable of type 'String' (/Users/yorifuji/git/ flutter_analyze_commenter_ci/lib/main.dart:4:20) [warning] The value of the local variable 'x' isn't used (/Users/yorifuji/git/ flutter_analyze_commenter_ci/lib/main.dart:4:16) [info] Use 'const' for final variables initialized to a constant value (/Users/yorifuji/git/ flutter_analyze_commenter_ci/lib/main.dart:4:3)
fl 今回のカスタムアクションの実装の詳細 • GitHubのPRに対してコメントを書き込む • GitHubにはREST APIが用意されていてGUIでできることは大体APIからもできる • APIを使ってPRのコードの差分(diff)を取得して、追加削除されたファイル名や行番号を取 得する • utter analyzeの解析内容とdiffの内容をファイル名と行番号を元に突き合わせるとPRで混 入したコード・警告とファイル名・行番号が特定できる • APIを使ってPRの番号、ファイル名、行番号、メッセージなどを指定して書き込みを行 • PRにコメントが反映される
fl 今回のカスタムアクションの実装の詳細 • 古くなったコメントの削除 • PRに対して追加(修正)コミットで問題のあったコードが除去されるようなケース • utter analyzeの結果から当該箇所の出力が消える • コメントを削除する仕様にしている • APIを使ってPRのコメントを全件取得して、最新のanalyzeの結果と付き合わせて不要になっ たコメントをAPI経由で削除している • 人間が書き込んだコメントと区別するために予めアクションからコメントを書き込む際に 非表示のテキストを含ませている(<!--- hogefuga --->のようなテキスト)
リリース作業 • 開発が終わったらGitHub上でReleaseを作成する • リポジトリにaction.ymlが存在するとアクション専用の Release画面が表示される • Marketplaceへのpublishを指定できる • yml記述内容、READMEの有無がチェックされる • Categoryの設定 など
fl テストについて • 現状ではテストを書いていない🤯 • 代わりにE2Eテストをしている • utterアプリのリポジトリで今回作成したアクションを含むCIが期 待通りに動くことを確認している • カスタムアクション側のmain/develop/v1ブランチに対してubuntu/ macOS/windowsのマトリックスでE2Eテスト実施
課題や今後の予定 • 利用実績が少ないのでサイドプロジェクトなどで使ってみてください(バグ報告歓迎です) • テストを書く • Pure-JavaScriptからTypeScriptに移行したい • JavaScriptアクション(npm)への移行 • 現状は複合アクション+JavaScriptという構成 • easyではあるが規模を大きくしたり拡張する際に生産性が良くない • もうちょっと面白いことをしたい • 問題のあるコードをAIが自動的に修正(提案)してくれると嬉しかったり...?
余談:開発したモチベーション • 元々はDangerというツールを使っていた • プルリクエストの体裁や内容をチェックするツール • Swiftアプリなどでも使われていて有名で枯れている • 以下の点で不満があった • Dangerを導入する目的の説明が必要 • Ruby製で実行時にgemのインストールが必要 • 高機能だけどFlutterの静的解析の目的ではオーバースペック • カスタムアクションを作ってOSSとして公開してみたかった
ありがとうございました