Stockmark Tech Blog

自然言語処理テクノロジーで社会を進化させる ストックマークのテックブログです。

Devinがモバイルアプリに秩序をもたらしてくれた話

こんにちは。 Anews の開発に携わっている Engineer の 羽柴 と申します。
Anewsは企業向けに記事を個人や組織にレコメンド配信する機能を主としたアプリケーションで、モバイルアプリも提供しています。

しかし、このモバイルアプリは歴史的な経緯もあり「あまりアクティブには開発していない(≒使えるリソースが限られている)」かつ「コードに技術的負債が溜まっている」という無秩序な状態でした。 したがって、ちょっとした変更が障害に繋がることもある非常に運用負荷が高い状態です。
当然ですが、お客様に提供し続けるために運用を続けなくてはいけないので、この無秩序なアプリに一定の秩序が必要でした。

この記事では、 そのような状態でDevinも活用しつつ、モバイルアプリ開発に一定の秩序をもたらした話を紹介します。

モバイルアプリの状況

Anewsのモバイルアプリは、2020年にリリースされてから約5年が経過していますが、その間に複雑な変遷を辿りました。

まずは、特定のお客様からのご要望がありモバイルアプリのリリースをスピード優先で進めました。当時いたメンバーによってFlutterで開発されています。
その後、途中から参画したFlutterに慣れていたメンバーが、よりメンテナブルにしようとレイヤードアーキテクチャに方向転換しました。
しかし、その方向転換を主導していた人たちは居なくなってしまい、残ったメンバーの中にFlutter経験者、もっというとモバイル開発経験者がほとんどいない状態でした。

その後、モバイルよりも主力のWebアプリケーションに開発リソースを集中することになり、モバイルアプリのメンテナンスは最小限に留められていました。
一定のコアなお客様は利用いただいているのですが、新規機能の追加はおろか既存機能の改修がやっとの状態でした。

抱えていた問題

  1. format/lintが無視されている: dart formatやdart analyzeが無視されている状態
  2. テストもない: ユニットテスト、ウィジェットテスト、インテグレーションテストが皆無
  3. CIがない: ビルドのみで、テストやlintチェックがCI/CDパイプラインに組み込まれていない
  4. ライブラリの更新が追いついていない: 古いXcodeやAndroid Studioがずっと必要で、最新の開発環境では動かない。さらに、各レイヤーで同じライブラリなのにversionが違うなど混沌とした状態

色々と課題は多く抱えているのですが、整理した結果まずは上記の4点に取り組むことにしました。

Devinにお願いしたこと

1. 3. のformat/lint やCIに関しては手作業でパパッとできるので解決しちゃいます。
2. 4. は自分で動くと手がかかるのでDevinを利用することにしました。

今回はその中でも以下の2点について話します。
① 依存関係の調査とバージョンアップ計画の策定
②dependabot導入後のフォロー

1. 依存関係の調査とバージョンアップ計画の策定

まず、現在のプロジェクトでflutter pub outdatedの結果を全てDevinに渡し、それぞれのライブラリについて以下の情報をまとめてもらいました。
指示の内容的には↓のような形です。

Devinに指示を出している様子

Devinが指示から作成したissue

major updateが周回遅れになっているライブラリが10個近くある状態でした。しかも、1周と言わず2周、3周と...
このようなissueがあれば実装する側もやることが整理できていますし、reviewする側も概要の把握が楽になったかなと思います。

ACUは0.5(=$1)程度で、人間がやると確認だけでも1つ数十分はかかるので費用対効果の面でも大変助かりました!

2. dependabot導入後のフォロー

単に古いライブラリをがさっと上げただけだと、また同じ状態になるのでdependabotを使いversionをなるべく最新状態で維持します。
ただ、dependabotを入れただけだと放置されがちなので、開発者がさっとreviewできる手助けをしてもらいました。

具体的にはこの記事を参考にしつつ、定期的にDevinにdependabotのPRをcheckしてもらいます。


name: check dependabot PR for Devin

on:
  schedule:
    - cron: "0 0 * * 1" # 毎週月曜9時(JST)に回す例
  workflow_dispatch:

jobs:
  call-devin:
    runs-on: ubuntu-latest

    steps:
      - name: Check if dependabot PRs exist
        id: check-prs
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        run: |
          PR_COUNT=$(curl -s \
            -H "Authorization: token $GITHUB_TOKEN" \
            -H "Accept: application/vnd.github.v3+json" \
            "https://api.github.com/repos/${{ github.repository }}/pulls?state=open&per_page=100" \
            | jq '[.[] | select(.user.login == "dependabot[bot]")] | length')

          echo "dependabot_pr_count=$PR_COUNT" >> $GITHUB_OUTPUT
          echo "Found $PR_COUNT dependabot PRs"

      - name: create devin session
        if: steps.check-prs.outputs.dependabot_pr_count > 0
        env:
          DEVIN_API_KEY: ${{ secrets.DEVIN_API_KEY }}
        run: |
          curl -X POST "https://api.devin.ai/v1/sessions" \
            -H "Authorization: Bearer $DEVIN_API_KEY" \
            -H "Content-Type: application/json" \
            -d '{
              "prompt": "このplaybookを進めてください。{repository-name}が対象repositoryです。",
              "max_acu_limit": {5},
              "playbook_id": "playbook-{id}"
            }'

      - name: No dependabot PRs found
        if: steps.check-prs.outputs.dependabot_pr_count == 0
        run: |
          echo "No open dependabot PRs found. Skipping Devin session creation."

該当のplaybookはこちら↓

# 背景・目的
セキュリティや依存関係の管理のため、dependabotを運用しています。
ただし、開発者がそのPR(Pull Request)をmergeしていいかどうかの判断に時間がかかっており、コストが高くなっています。
 本Playbookでは、そのコストを軽減するため、AIエージェントがPRごとに変更内容を要約・確認する手順を定義します。

## 確認する対象PRの条件
以下すべてを満たすPull Requestを対象にしてください。

- author が dependabot
- 状態が open
- approve されていない

### 確認手順
以下の手順で対象PRを順次確認してください(最大10件まで、major バージョン更新を優先)。

1. PRで変更されているライブラリの公式Change Logやリリースノートを確認する
2. 主な変更内容を日本語で要約し、PRのコメントに記載する
3. 破壊的変更(Breaking Change)の有無を明記する
4. 破壊的変更がある場合は、必要なコード修正点や注意点も併せて記載する

コメントテンプレート例(破壊的な変更がある場合)
### ライブラリ名: flutter
- バージョン変更: 3.0.0 → 4.0.0
- 変更内容概要:
  - 新しい rendering engine の導入
  - `FooWidget` が非推奨になり、`BarWidget` に置き換えられました
- 破壊的変更の有無: **あり**
  - `doSomething()` メソッドが削除されています
  - `build.gradle` に追加の設定が必要です
- 参考URL:
  - https://github.com/flutter/flutter/releases/tag/4.0.0

コメントテンプレート例(破壊的な変更がない場合)
### ライブラリ名: axios
- バージョン変更: 1.3.4 → 1.4.0
- 変更内容概要:
  - パフォーマンスの改善
  - 複数のバグ修正(例: エラーメッセージの出力改善)
- 破壊的変更の有無: **なし**
  - 既存のコードに影響はありません
- 参考URL:
  - https://github.com/axios/axios/releases/tag/v1.4.0

## Advice & Pointers

- すべてのコミュニケーションやPull Requestコメントは日本語で行ってください
- このplaybookが使われているときは、CIから実行されているので許可は待たないでください
- CIが通っているかどうかは関係ありません
- 必ずDevinが参考にしたURLはコメントに載せてください

DevinがdependabotのPRにしたコメント

PRの数によって変動しますが0.4~0.8ACU(=$1前後)ぐらいでcheckしてくれます。
これも細かいですが、reviewer視点だと大変助かっています。

playbookを使う際の注意点

  • promptを基本的に優先する傾向にあるので、「playbookを進めてください」以外の余計なwordを入れない方がいいです。 最初、「これはdependabotの作ったPRをcheckしてもらう依頼です。」みたいな概要を先頭に載せていたらplaybook一切見なかったのでw
  • docsにも書いていないですが、playbook-idは先頭にplaybookのprefixが必要ですw あとの値はURLから取得できます。
  • DevinAPIを使われた方ならわかると思うのですが、documentとそこそこ乖離がありますw 挙動を確認しながら進めてください。

振り返り

良かった点

このほかでも活用させてもらっていますが、コード調査はピカイチですね。自分は現状CSの方からの質問について半数以上そのままDevinに投げています。
今回のような活用例(公式を見にいって要約して、影響範囲を調べて...)って1つ1つは小さくても、いざとりかかるとしんどいのでそれを任せられてよかったです。

改善点

  • テストをどうするか: テストもDevinに書かせようと試していますが、DevinはCIが複数回落ちるとテストの方を修正しようとする事があり、意味のあるテストを生成できるのかが検討し切れていません。かと言ってここで人がゴリゴリテストを書くコストも掛けづらいので、引き続き検証予定です。
  • setupができていない: 今回setup最初のsectionさえ通れば調査や修正をしてくれる!というのが分かったのは嬉しかったですが。Devinは「screen shotを撮って ~~」や「testが通ったから」といったcheckをすることでより精度が上がると思っています。
    現状 Flutterをリモートで動かすことはおそらく難しく、今後のversion upに期待したいです。

さいごに

今回のDevin活用により、Flutter経験者がいない状況 & コストも大きくはかけられない中で、体系的にライブラリ更新の計画を立て、継続的な運用体制を構築できました。特に、各ライブラリのBreaking changesを網羅的に調査し、概要を把握できるのには大変助かっています。

Devinは「魔法の杖」ではありませんが、適切にタスクを切り分けて依頼することで、技術スタックに詳しくないメンバーでも効率的に技術的負債の解消に取り組める強力なツールだと実感しました。 同じような課題を抱えている方の参考になれば幸いです。質問やご意見があれば、ぜひコメントでお聞かせください。

また、Stockmark社では一緒にプロダクトと組織を成長させていただける方を募集していますので、カジュアル面談 からお気軽にご連絡ください。
あとは、もうあまりいらっしゃらないかもしれませんが、Devinの Referrals URL を置いておきますw