コネヒト開発者ブログ

コネヒト開発者ブログ

Devin x GitHub ActionsでRenovateのPR対応を自動化する実践ノウハウ

こんにちは!Androidエンジニアの関根です。

今回は、RenovateのPR対応を自動化する取り組みについてご紹介します。

はじめに

皆さんの職場では、Renovateを使いこなせていますか?依存関係を最新に保つ上で、本当に頼もしい存在ですよね。 弊社のAndroidチームではRenovateのPullRequestを定例で確認し、マージの判断をする運用は行っていますが、だんだんとPullRequestが溜まってしまっていました。

影響の少ないアップデートならその場で判断し、マージできますが、調査が必要な場合に、先送りしてしまうということが起きていました。 「影響範囲の調査が必要だな…」「後でやろう…」 そう思っているうちに、PRはどんどん溜まっていき、上限数に達してしまうということが定常化していました。

この記事では、そんな「調査待ちRenovate PR」の渋滞を、今話題のAIエージェントDevinを使って解消する実践的なノウハウをご紹介します。

Part 1:実現したこと

まずは、この仕組みを導入したことで、私たちのチームにどんな変化があったかをお見せします。 これまで先送りしがちだった「調査が必要なPR」。ここにDevinが介在することで、人間は「Devinからの調査報告をレビューするだけ」 になりました。

システムの流れ

この自動化システムは、以下のような流れで動作します:

  1. Renovateが依存関係の更新を検知し、PullRequestを作成
  2. GitHub ActionsがPRの作成を検知し、Devin APIにリクエストを送信
  3. DevinがPlaybookを読み取り、以下のレビューを実施

この一連の流れでのレビューには、以下のような情報が含まれます:

  • ライブラリ変更点の概要

    • バージョン間の主要な変更点
    • 破壊的変更の有無
    • 新機能や非推奨機能の情報
  • コードへの影響と対応案

    • 影響を受ける箇所の特定
    • 推奨される修正方法
    • テストが必要な範囲

具体的なサンプルをお見せすると、以下の通りです。こちらは実際のレビュー内容を生成AIでマスキングしたものです。

ライブラリ変更点の概要

### com.example.library:core 2.1.0 → 2.2.0

**リリース日**: 2024年3月15日

**変更内容**:
- **バグ修正**: 特定の条件下でメモリリークが発生する問題を修正
- **パフォーマンス改善**: データ処理の最適化により、処理速度が約20%向上

**詳細**:
- 公式ドキュメント: https://example.com/library/docs/releases/2.2.0
- メモリリークの修正により、長時間の運用時の安定性が向上
- 破壊的変更はありません

**影響レベル**: 中(バグ修正とパフォーマンス改善)

## コードへの影響と対応案

### 影響範囲の調査結果

ライブラリの使用箇所を調査した結果:

**使用箇所**: 
- `src/main/java/com/example/app/ImageProcessor.kt` のみ

**現在の使用方法**:
val processor = HogeProcessor()
val data = processor.getData(source)

コードへの影響と対応案

✅ **影響なし**: 
- 現在のコードは基本的なメタデータ読み取りのみを行っており、修正対象の機能は使用していません
- 高度な機能(今回修正された部分)は使用していないため、影響はありません
- 既存の実装は基本的な機能のみを使用しており、安全です

### 対応案

**推奨対応**: 
- ✅ **コード修正不要** - このアップデートは安全に適用可能です
- ✅ **テスト実行** - 念のため既存のテストを実行して動作確認を行うことを推奨します
- ✅ **マージ可能** - 破壊的変更がないため、レビュー後にマージして問題ありません

**理由**:
1. バグ修正のみで新機能や仕様変更はありません
2. 修正対象の高度な機能は使用していません
3. 既存の基本的な機能に影響はありません

このアップデートにより、将来的に高度な機能を使用する際の安全性が向上します。

このように、人間が行っていた調査作業をDevinが自動化することで、レビュアーは「調査結果の確認と判断」に集中できるようになりました。

Part 2:実践!自動化システムの作り方

今回はDevinとGitHubActionsの機能のシンプルな組み合わせで実装しており、以下の2つの実装で完結します。

  1. DevinにPlaybookを設定する
  2. GitHubActionsからDevin APIにリクエストを送信

まずは比較的DevinのPlaybookを採用した理由から解説をさせていただきます。

Devin Playbook docs.devin.ai

Playbookを選んだ理由

DevinのPlaybookを採用した理由は、RenovateのPR対応が以下のような定型的な作業の繰り返しになるためです:

  1. 更新内容の確認

    • ライブラリの変更履歴やリリースノートの確認
    • 破壊的変更の有無の確認
  2. コードベースへの影響調査

    • 更新対象のライブラリを使用している箇所の特定
    • 影響範囲の特定と評価
  3. 必要に応じた修正作業

    • 破壊的変更への対応
    • 互換性の確保

このような明確な手順繰り返しの作業は、まさにDevinのPlaybookの得意分野だと考えたためです。Playbookは以下の内容で定義しています。

## 概要
Renovateによって自動生成されたプルリクエスト(PR)をレビューし、ライブラリのアップデートに伴う変更点の調査、コードへの影響評価、および必要な修正作業を実施します。

## ユーザーに必要なもの
- レビュー対象のRenovateのプルリクエストのURL
- (もしあれば) 対象ライブラリに関する特記事項や注意点

## 手順
1.  指定されたRenovateのプルリクエストを開き、Renovateがどのライブラリをどのバージョンからどのバージョンへアップデートしようとしているかを確認します。
2.  アップデート対象となった各ライブラリの公式ドキュメント、リリースノート、変更履歴(changelog)などを参照し、バージョン間の主要な変更点(新機能、非推奨機能、破壊的変更、バグ修正など)を特定します。
3.  特定したライブラリの変更点を、元のRenovateのプルリクエストにGitHubのコメント機能を使用して、「ライブラリ変更点の概要」として記載します。破壊的変更や対応が必須と思われる項目については特に明記してください。
4.  ライブラリの変更点を踏まえ、リポジトリ内の既存コード(アプリケーションコード、テストコード等)への影響範囲を調査します。具体的には、以下のような点を確認します。
    * 廃止されたAPIや変更されたAPIの使用箇所
    * 仕様変更に伴い、修正が必要となるロジック
    * アップデートによる潜在的なバグやパフォーマンスへの影響
5.  調査したコードへの影響範囲と、推奨される修正対応について、元のRenovateのプルリクエストにGitHubのコメント機能を使用して、「コードへの影響と対応案」として記載します。
6.  コードの修正が必要だと判断された場合、Renovateのプルリクエストのブランチ(例: `renovate/ライブラリ名-2.x`)をベースブランチとして、`fix/renovate-対応内容` の命名規則で新しい作業ブランチを作成します。
7.  作成した作業ブランチで、ステップ5で特定した影響箇所に必要なコード修正作業、および関連するテストコードの修正や追加を行います。
8.  全ての修正作業とテストが完了したら、作業ブランチから元のRenovateのプルリクエストのブランチに向けて、新しいプルリクエストを作成します。
    * 新しいプルリクエストのタイトルには、例:「Fix: Renovateによる[ライブラリ名] vX.Y.Zへのアップデート対応」のように、内容がわかるように記載します。
    * 新しいプルリクエストの説明文には、元のRenovateのプルリクエストへのリンク、実施した修正内容の概要、およびレビューしてほしいポイントを明記します。

## 仕様
1.  RenovateのPRには、「ライブラリ変更点の概要」と「コードへの影響と対応案」がコメントとして記載されていること。
2.  必要な修正作業が完了した場合、適切なターゲットブランチに対して新しいプルリクエストが作成されていること。
3.  新しいプルリクエストは、レビュアーによる確認と承認が行われるまではマージされない状態であること。

## アドバイスとポイント
1.  ライブラリの変更点を調査する際は、公式ドキュメントやリリースノートを最優先の情報源としてください。フォーラムやIssue Trackerの情報は補助的に使用してください。
2.  コードへの影響調査は、直接的な利用箇所だけでなく、間接的な影響や全体的な動作への影響も考慮に入れてください。
3.  GitHubへのコメントやプルリクエストの説明文は、他の開発者が変更の意図と内容を迅速に理解できるよう、明確かつ簡潔に記述してください。
4.  作業ブランチ名は、そのブランチの目的が容易に理解できるような命名規則に従ってください。
5.  大規模な変更や判断に迷う場合は、途中で状況を報告し、指示を仰いでください。

## 禁止事項
1.  **Renovateが自動生成したプルリクエスト、および自身が作成した作業プルリクエストを、レビュアーの承認なしに勝手にマージしないでください。**
2.  ライブラリの公式ドキュメントを確認せずに、変更点や影響範囲を憶測で判断しないでください。
3.  元のRenovate PRのブランチに直接コミットを追加しないでください

Step 1:DevinのPlaybook準備編

さて、ここからは具体的な実装方法です。 この自動化システムの心臓部となるのが、Devinに与える指示、つまりPlaybook(プロンプト)です。

「Devinへの最適な指示なんて、どうやって作ればいいんだ…」と悩みますよね。 ご安心ください。私は、AI(Gemini)に作ってもらいました!

具体的には、Devinの公式サイトにあるPlaybookのサンプルと、今回Devinに「やりたいこと」を箇条書きにしたものをGeminiに渡し、Playbookの形式に合うようにプロンプトを生成してもらったのです。

使用したDevin Playbookサンプル docs.devin.ai

Geminiに渡したプロンプト

以下が、実際に私がGeminiに渡したプロンプトの全文です。 構造としては、「Geminiへの指示」「Devinにやってほしいこと」「出力形式のサンプル」の3つを伝えています。

# あなたへの指示
生成AIへのプロンプトを考えてください。
「やりたいこと」を達成するための指示を「サンプル」を参考に生成してください。

# やりたいこと
- PRで変更されたライブラリの更新内容について調査する
- ライブラリの更新内容が明確になったら、コード内変更への影響を調査する
- 必要に応じて、修正作業を行う

# サンプル

## 概要
Rマークダウンノートブックを使用してデータサイエンスのチュートリアルを作成します。

### ユーザーからの必要事項
- データセットへのリンク(CSVファイルの添付またはKaggleリンク)
- データサイエンスチュートリアルを作成するための具体的なタスク

### 手順
1.  ユーザーから提供されたデータセットをダウンロードします。
    - 必要に応じて、Kaggle CLIを使用してデータセットをダウンロードします。これには認証情報は必要ありません。
2.  `data_science_tutorial.Rmd` というタイトルのRマークダウンノートブックを作成します。
3.  中間コードを記述および保存するために `tmp.Rmd` ファイルを作成します。
4.  `data_science_tutorial.Rmd` ファイル内に5つの主要なセクションを作成し、`tmp.Rmd` ファイルから以下の内容を含むコードを追加します。
    - **データセットの統計**: データセットの統計的要約を生成します。
    - **EDA(探索的データ分析)**: 提供されたデータに対して棒グラフと散布図を作成します。
    - **訓練データとテストデータの分割**: データを80:20の比率で分割します。訓練データとテストデータを保存します。
    - **機械学習モデルの訓練**: 訓練が完了したらモデルを保存します。
    - **保存されたモデルでの推論**: 保存されたモデルをロードし、ユーザーが指定した評価指標を使用してテストセットでのパフォーマンスを評価します。
5.  コードの記述が完了したら、各セクションに簡単な説明を追加します。
6.  RマークダウンノートブックをHTML形式に変換します。
7.  最終的なRマークダウンノートブック、HTMLファイル、保存されたモデル、およびテストデータをユーザーに送信します。

### 仕様
1.  RマークダウンノートブックとHTMLファイルをユーザーに送信してください。
2.  保存されたモデルとテストデータをユーザーに送信してください。

### アドバイスとヒント
1.  パッケージがすでにインストールされている場合は、再インストールしないでください。
2.  このタスクを完了するためにRStudioへのサインインは必要ありません。
3.  各セクションのコードを追加した後、ノートブック全体を実行してください。

### 禁止事項
1.  `data_science_tutorial.Rmd` ファイルを上書きしないでください。

このように、「正解の形」を具体的にサンプルとして見せてあげることで、AIは期待するアウトプットを非常に高い精度で生成してくれます。ぜひ皆さんも試してみてください。✨

Step 2:GitHub Actions連携編

次に、DevinとGitHub Actionsを連携させる具体的な実装方法について説明します。

ワークフローの概要

まず、RenovateのPRが作成されたときに自動的にDevinにレビューを依頼するワークフローを実装しました。 このワークフローは以下のような特徴を持っています:

  • Renovateアカウントがdevelopブランチに対してPRを作成したときのみ実行
  • 他のPRや他のブランチでは実行されない
  • PRのURLをPlaybookのマクロと共に送信

実際の内容

name: Review by Devin on Renovate PR

on:
  # `develop`ブランチへのPRのみ
  pull_request:
    types: [opened]
    branches:
      - develop

jobs:
  review-by-devin:
    # RenovateアカウントがPRを作成したときのみ実行
    if: github.actor == 'renovate[bot]'
    runs-on: ubuntu-latest
    env:
      DEVIN_API_KEY: ${{ secrets.DEVIN_API_KEY }}
      PR_URL: ${{ github.event.pull_request.html_url }}
    steps:
      - name: Review by Devin API
          # /v1/sessionsにリクエストし、Devinセッションを作成
          # PRのURLをPlaybookのマクロと共に送信
          # Bearer認証を使用。API KeyはGitHub Secretsで管理
        run: |
          JSON_PAYLOAD=$(cat <<EOF
            {
              "prompt": "!renovatepullrequest ${PR_URL}"
            }
            EOF
          )
          curl -X POST "https://api.devin.ai/v1/sessions" \
               -H "Authorization: Bearer $DEVIN_API_KEY" \
               -H "Content-Type: application/json" \
               -d "$JSON_PAYLOAD"

こちらのGitHubActionsがトリガーとなり、Devinのレビューが開始される流れとなります。 ※現在は、他のチームと共有で使えるReusable Workflowが整備されたことで、このワークフローはそちらの呼び出しに置き換えています

Devin APIの連携

DevinのAPI連携で直面した問題と解決策について共有します。

API Keyの作成画面に表示されるサンプルコードでは、playbook_idをパラメータとして渡す方法が案内されています。しかし、この方法を試したところ、私の環境ではDevinがPlaybookを参照してくれないという問題が発生しました。

試行錯誤の結果、プロンプト内にPlaybookのマクロ(例: !your-playbook-macro)を直接記述する方法で、無事にPlaybookを読み込ませることができました。

この件についてDevinのサポートに問い合わせたところ、本来はどちらの方法でも動作することを意図しており、playbook_idパラメータが機能しない問題は修正するとの回答を得ました。

Thank you so much for the kind words, and we're thrilled to hear Devin is helping advance your development—means a lot to the team!

Also, really appreciate you flagging this. We do intend for both methods—passing playbook_id as a parameter and using a Playbook macro in the prompt—to work seamlessly. I'll check in with the team about why the first method isn't working as expected and get it fixed.

Thanks again for taking the time to share this!

Best regards,

もし同じ現象に遭遇した場合は、プロンプトに直接マクロを埋め込む方法を試してみてください。

Part 3: 上手くいったこと/上手くいかないこと/困ってること

ここまで、DevinとGitHub Actionsを連携させてRenovateのPRを自動レビューする仕組みの実装方法について説明してきました。しかし、実際に運用を始めてみると、予想外の効果や課題が見えてきました。このPart 3では、実際の運用で得られた知見や、より良い運用のために気をつけるべきポイントを共有します。

上手くいったこと

アップデートのマージ判断がスムーズになった

Devinが調査と対策を検討してくれるため、人間がやることは内容の正誤判断のみになりました。 このことで、「後で調査しよう」というステップがなくなり、定例を待たずにマージ判断を行えるようになってきました。

加えて、Devinが提示してくれた作業内容を、Devinに追加でお願いすることも試行しているところです。 これにより、調査から実装までを一気通貫で自動化できる可能性が見えてきました。

副次的な効果としてCI失敗も調査してくれる

当初の目的は「Renovate PRの影響範囲調査」でしたが、副次的な効果として嬉しい発見がありました。 それは、CIが失敗したPRに対しても、Devinが自動でエラー内容を読み解き、「〇〇が原因でテストが落ちています。□□を修正すれば通るはずです」といった具体的な対策まで提示してくれたことです。 このおかげで、失敗原因の調査という、また別の面倒な作業まで効率化できました。

特にAndroidではAndroid Gradle Pluginの更新が必要なものなどの、依存関係の更新が原因でビルドが失敗するケースが多々あります。このような場合に具体的な解決策を提案してくれます。

Devinの提案内容:

## ビルドエラーの詳細

### 1. Android Gradle Plugin バージョン不足
- 要求: Android Gradle Plugin 8.x.x以上
- 現在: 8.y.y
- 影響ライブラリ:
  - androidx.navigation:navigation-compose-android:x.y.z
  - androidx.lifecycle:lifecycle-viewmodel-compose-android:x.y.z
  - androidx.lifecycle:lifecycle-runtime-compose-android:x.y.z

### 2. Compile SDK バージョン不足
- 要求: compileSdk xx以上
- 現在: compileSdk yy
- 影響: 上記と同じライブラリ群

## 必要な追加更新
このNavigation x.y.zアップデートを適用するには、以下の追加更新が必要です:

Android Gradle Plugin: 8.x.x → 8.y.y以上
Compile SDK: xx → yy
関連するlifecycleライブラリも同時にx.x.xxに更新される

## 推奨対応

### オプション1: 段階的アップデート
1. 先にAGPとcompileSdkを更新
2. その後でNavigation x.x.xを適用

### オプション2: 一括アップデート
- AGP、compileSdk、Navigation、Lifecycleを同時に更新

### オプション3: アップデート延期
- より安定したタイミングでの一括更新を検討

この作業はPlaybookで指示をしていないため、毎回必ず実行してくれるわけではないため、プロンプトの改善を考えています。

上手くいかないこと

指示した範囲外の判断は人間の役割

Devinは指示した範囲でしか作業をしてくれません。 ライブラリAのレビューをお願いした場合、ライブラリAとライブラリBに依存関係で問題が起きた場合、本来であればライブラリBの更新が望ましいという判断はDevinにはできないため、ライブラリAの更新で解決する提案になります。 具体例として、ライブラリBを更新することで必要なくなるはずの、「競合する設定をライブラリAからオプトアウトする」といったような変更が提案されました。

ここは人間が想像力を働かせて、より本質的な判断をする必要がある部分だと感じています。

困ってること

チームでの可視性に課題

普段はDevinにはSlackから指示を出しています。今回のようにDevinAPI経由で開始すると、WebUIから操作する必要があり、チームでの可視化に課題があります。 ここはCognition Support Teamに共有し、要望として伝えさせてもらいました。

まとめ

本記事では、AIエージェントDevinとGitHub Actionsを用いて、これまで手作業で行っていたRenovateのPR対応を自動化する具体的な方法をご紹介しました。 このアプローチによって、面倒な調査作業から解放され、より本質的な開発業務に集中できる時間が生まれます。 皆さんの日々の業務の中にも、きっと応用できる場面があるはずです。ぜひ、この記事を参考に、身の回りの小さな課題から自動化を試してみてはいかがでしょうか。 もし、もっと良い方法や面白いアイデアがあれば、ぜひSNSなどで教えていただけると嬉しいです。一緒にベストプラクティスを見つけていきましょう!

GitHub Copilot Agent による Go製バッチのAWS Lambda移行(Claude 3.7 Sonnet)

こんにちは。CTOの永井 (id:shnagai) です。 今回は GitHub Copilot Agent (Claude 3.7 Sonnet) を活用し、Go製バッチをAWS Lambdaへ移行した際の開発体験と学びをご紹介します。

TL;DR

  • ゴール: Go製バッチを Copilot Agent (Claude 3.7 Sonnet) 支援のもと、AWS Lambda + EventBridge (SAM利用) へ移行
  • 効果: 簡単なプロンプトでSAMテンプレートやLambda雛形を高速生成。開発効率が劇的に向上
  • 注意点: クラウド設定(特に新しいランタイム等)にはハルシネーションが見られるため、人間によるレビューと修正が必須
  • Tips:
    • .github/copilot-instructions.mdでAI生成精度を向上
    • プロンプトは具体的であれば構造化不要
    • 生成されたインフラ設定は必ず公式ドキュメントで確認

背景・課題

毎月実行しているGo製データ処理バッチの手動実行を、AWS Lambda と EventBridge によって自動化したいと考えていました。Lambda化、SAMテンプレート作成、EventBridge設定など多くの作業が必要なため着手できていませんでしたが、GitHub Copilot Agent (Claude 3.7 Sonnet) の実力を試す好機と捉え、移行に取り組みました。

Copilot Agent との対話プロセス

VS Code の Copilot Chat (Claude 3.7 Sonnet) に、以下のようなシンプルなプロンプトで依頼しました。

Goで手元でビルドして動いているコードをLambda+EventBridgeを使ってAWS環境で自動実行できるようにしたい。
デプロイにはAWS SAMを利用するので、必要なファイルの準備も合わせてお願いします。

このシンプルなプロンプトだけで、的確な SAM テンプレート (template.yaml) や Lambda 関数 (main.go) の雛形が迅速に生成されました。また、リポジトリルートに .github/copilot-instructions.md を配置し、プロジェクト固有の情報を提供することで生成精度が向上することも確認できました(このファイル自体も Copilot に生成を依頼できます)。

発生した課題と手直し

Copilot Agent は非常に強力なアシスタントですが、万能ではありません。特に AWS のような急速に進化するクラウドサービスの構成においては、いくつかの点で手直しが必要でした。

Lambda ランタイム指定のハルシネーション

  • 事象: Copilot が生成した template.yaml では、Go の Lambda ランタイムとして古い Go1.x が指定されていました。このランタイムは現在 AWS では非推奨となっており、このままデプロイするとエラーとなります。
  • 対応: 同僚からランタイム指定が古いと指摘を受け、現在推奨されているカスタムランタイム provided.al2023 に修正しました。クラウドサービスの仕様は頻繁に更新されるため、AI の生成内容を鵜呑みにせず、公式ドキュメントで最新情報を確認することの重要性を再認識しました。

認証情報の取り扱い

  • 事象: 当初生成されたコードでは、外部サービス(Google Cloud)への認証キーが適切に扱われていませんでした。
  • 対応: セキュリティ強化のため、認証情報を AWS Systems Manager (SSM) パラメータストアに SecureString として保存し、Lambda 実行時に取得・復号する方式に変更するよう Copilot に指示しました。具体的なパラメータ命名規則(/service-name/GOOGLE_APPLICATION_CREDENTIALS_PARAM 形式)や、ローカル開発環境との互換性確保などの要件を伝えることで、セキュアで実用的なコードに改善できました。

SAM ビルド時のパス依存問題

  • 事象: sam build コマンドを実行するディレクトリによっては、ビルドプロセスが期待通りに動作しないケースがありました。
  • 対応: SAM CLI の挙動や Makefile のパス指定を調整することで解決しました。

環境固有の設定

SAM がデプロイパッケージをアップロードするための中間 S3 バケットとして、組織内で共通利用している特定のバケット名を指定するなど、環境固有の調整も必要でした。

これらの修正作業は必要でしたが、ゼロからすべてのコードや設定ファイルを作成する労力と比べれば、はるかに少ない時間で済みました。Copilot Agent が「ドライバー」としてコーディングの大部分を担い、人間は「ナビゲーター」として設計判断やコード品質の確認、最終調整を行うという、新しい開発スタイルを体験できました。

学び

  • Copilot Agent (Claude 3.7 Sonnet) の強力さ: 定型コードや雛形作成で生産性が飛躍的に向上します。簡単な指示で形にしてくれる体験は、開発の未来を感じさせます。
  • ハルシネーションへの対処: 特に変化の速いクラウド技術では、生成内容の検証(公式ドキュメント確認)と修正が必須です。
  • 人間の知識とレビューの価値: 最新情報の反映や品質担保には、人間の経験やチームレビューが依然として重要です。
  • 効果的なプロンプトとコンテキスト: 指示の仕方や事前情報の与え方で成果が大きく変わります。.github/copilot-instructions.md などの活用が効果的です。
  • 時間制約の克服: まとまった時間が取れないことを理由に先延ばしにしていたタスクも、AI の支援によりスキマ時間を活用して効率的に進められるようになりました。

まとめ

GitHub Copilot Agent (Claude 3.7) は開発効率を大幅に向上させる強力なツールだと感じました。現時点ではAIによるドメイン理解や把握の難しさだったり最新の技術を利用しようとすると、生成内容の検証と手直しが必要なのはたしかですが、これはコンテキストをしっかりと与えていくこととさらなる技術革新で徐々に和らいでいくのではないかと感じています。それよりも、AI と人間が協調する開発スタイルは今後ますます重要になるでしょうし、まずは手を動かしてガンガン使いこなしこの波のど真ん中で楽しんでいきたいと思います。

コネヒトはPHPerKaigi 2025にシルバースポンサーとして協賛します!

こんにちは!今回は弊社が協賛するPHPに関するイベントを紹介します。

PHPerKaigi 2025に協賛いたします

コネヒトではメインプロダクトである「ママリ」を始めとして開発のメイン言語としてPHPを活用しており、フレームワークとしてはCakePHPを採用しています(その他、技術スタックを知りたい場合はこちらをご覧ください)

その縁もあり、この度 PHPerKaigi 2025 にシルバースポンサーとして協賛させていただくこととなりました!

イベント概要

公式サイトからの引用になりますが、PHPerKaigiは

(ペチパーカイギ)は、PHPer、つまり、現在PHPを使用している方、過去にPHPを使用していた方、これからPHPを使いたいと思っている方、そしてPHPが大好きな方たちが、技術的なノウハウとPHP愛を共有するためのイベントです。 今年の開催はオフライン会場を軸としたオフライン・オンラインハイブリッド開催です。みなさんのご都合に合う参加方法をお選び頂けます。

となっており、いろんな方が楽しめる間口の広いPHPのイベントになっていそうです!今回ははじめてのハイブリッド開催なので、都合がつく方は両方で参加して楽しむこともできそうですね!

発表内容やタイムスケジュールを知りたい方はこちらをご覧ください!

タイムテーブル | PHPerKaigi 2025 #phperkaigi - fortee.jp

また、 PHPerKaigi 公式Xも要チェックです!

@phperkaigi

今年もオンラインだけではなく、オフラインでも開催され、 技術者同士のつながりや知識の共有が広がることにワクワクしています。皆さん、楽しみましょう!

コネヒト株式会社は PHP Conference Japan 2024 にシルバースポンサーとして参加しました!当日の様子をご紹介します!

今年はシルバースポンサーとして協賛してブースを出展させて頂きました!本ブログではPHP Conference Japan 2024の当日の様子や感想などをご紹介していきたいと思います!

PHP Conference Japan 2024 とは

PHP Conference Japan 2024 は2024年12月22日(日)に開催された国内最大級のPHPイベントです!

phpcon.php.gr.jp

当日の様子

会場は昨年と同じく大田区産業プラザPiOで行われました。前回に続き、今回もコネヒトはスポンサーブースに出展させて頂きました。

ブースの内容はママリドリルとPHPの流行語調査アンケートです。ママリドリルやアンケートにお答え頂いた方には、ノベルティとしてママリオリジナルデザインのチロルチョコをお渡しさせて頂きました!

コネヒトのブースに来てくださった方々本当にありがとうございました!

ブースへの参加者を心待ちにしているコネヒトメンバー

PHPの流行語調査アンケート結果

今回は参加者の方々からPHPの流行語のアンケートを回答頂き、一時間ごとのアンケート結果をもとにワードクラウドを生成するという企画を実施させて頂きました!

結果はコネヒトの開発公式アカウントの方で投稿されていますので興味があればぜひご覧ください!下記は開催直後のワードクラウドです!

x.com

アンケートを見た時みなさんPHPの流行語!?というリアクションが多く、回答に悩まれていた方が多かったです!突然PHPの流行語と言われパッと思いつかない方もいらっしゃいましたが、みなさんなりのPHPの流行キーワードを考えてくださいました!

最終的には下記のような結果になりました!

最終的なアンケート結果から生成されたワードクラウド

特に目立ったキーワードはLaravel、PHP8、PHPStan、バージョンアップでした!

Laravelは文句なくフレームワークとしての人気の高さが伺えますね!PHP8はやはりPHP8.4がリリースされた影響が大きいでしょうか!新しく追加された機能であるプロパティフックもキーワードに入っているので新しいバージョンへの関心の高さは皆さんさすがですね!

またPHPStanはPHPStan2.0がリリースされたことが話題になった影響もありそうですね!その他のキーワードもPHP Conferenceで新たに得られた知見なども反映された結果になったのではないでしょうか!

改めてアンケートに回答頂いた参加者の皆様ご協力頂きありがとうございました!

感想

たくさんの参加者の皆様と交流することができ満足したカンファレンスとなりました!!コネヒトは今後もPHPコミュニティへの貢献を続けていきたい思います!

私自身こういったイベントには初参加でしたが社外の方々と交流する機会があるのはとてもいいなと思えたので今後はこういった活動に積極的に参加できたら良いなと思いました!

2024年のコネヒト開発組織を振り返る

こんにちは。CTOの永井(shnagai)です。

今年も残すところ数日。今回は、アドベントカレンダー最終日ということで、2024年のコネヒト開発組織における印象的な出来事を自分の視点で振り返っていこうと思います。

この記事は、コネヒト Advent Calendar 2024 - Adventarの25日目の記事です。

1. Aurora MySQL v3へのアップグレード (v2EOL対応)

今年対応されたチームも多いのではと思いますが、AWS Aurora MySQL 2系のEOL対応は、大きな挑戦でした。コネヒトでは昨年行ったv1からv2のアップグレード時からこのv3への備えをしていました。 v2→v3へのアップグレードはMySQL 5.7系相当からMySQL 8.0系相当へのアップグレードを意味しており、アプリケーションへの影響を最小限に抑えつつ、各チームが連携して大規模な移行をスムーズに事故なく実現することができました。 メンバーの入れ替わりもある中で、大規模メンテナンスをやりきるナレッジを開発組織にストックするという点を今回は強く意識した移行計画になっており、短期間でやりきったことで開発組織の底力が上がったと感じています。

詳しい内容を知りたい方は、アップグレードをリードしてくれた@sasashu が書いてくれた下記記事をご覧ください。

tech.connehito.com

2.データ基盤の整備とプロダクトでの活用

今年、データ基盤の整備に本格的に着手しました。これまでもプロダクトごとに散在していたデータをBigQueryに一元化することはしていたのですが、そこに手を入れもう一段進化させました。 Dataformを採用し、BigQueryのスケジュールクエリに頼っていた中間テーブル作成等のETL処理をコード化し、その流れからデータ基盤のモデリングを再設計しています。

使われない仕組みは意味がないということがツール導入時によく叫ばれますが、このデータ基盤はしっかりと使われる基盤となっています。 具体的には、プロダクトの主要指標をデイリーで通知する部分のデータソースになっていたり、新データ基盤で管理しているデータを使ったプロダクトの機能をリリースしたりとコネヒトの事業になくてはならない存在となりました。

データ専任のエンジニアがいない体制なので、優先度を調整しながらの進化になりますが、まだまだデータまわりの課題感は大きく、来年もより事業になくてはならないデータ基盤となるべく活用事例を増やしていければと思っています。

3. エンジニアが事業部へ

4月の組織変更で、エンジニアを事業部に直接配置する形に変更しました。これまでは、開発部というまとまりでエンジニアが所属しており、各チーム毎にPdMを事業とエンジニアリングの架け橋として配置するチーム構成にしていたのですが、より事業への解像度を上げ、スピード感のある開発を実現するための挑戦です。

こちらうまくいったのかは正直まだ評価をしていません。 というのも、組織に正解はないと思っているので、1年くらいのスパンで良い/悪い変化、事業側/開発側それぞれの観点でのFBを経て、より会社として勝てる形を考えて実行していければと考えています。

一つだけ、今時点で変えたことにも言及すると、コネヒトではエンジニアの目標制度として事業目標(プロダクト開発)と組織目標(技術的チャレンジや負債解消)という大きく2つの目標があるのですが、4月のタイミングで上期は組織目標をやめることにしました。 これは、選択と集中という意味が強く、新しい組織になり事業のことをよりインプットしたりコミュニケーションする時間が増えると予想し、そこに力をかけるのが今回の変更の成功につながると考えたからです。

しかし、やめたことで組織目標という枠があることが、エンジニアとしての技術研鑽やチームをまたいだ技術的な連携を生み出す良い契機になっていることが明るみになりました。EM陣で議論を重ねて最終的に、下期は復活させました。振り返ってみると、普段の開発での改善はもちろん各々の努力でできますが、チームで働くにあたり共通の目的をもって進むというのは大きなことを成すには必要だよなと改めて気付かされました。ちなみに組織目標は、Web、iOS、Android、インフラくらいのまとまりでそれぞれの領域ごとに日常的な改善が難しいくらいのレベル感の技術的なテーマを決め、半年スパンで取り組んでいます。

他にも、レポートラインに事業側/開発側どれくらいの比率で入るかも難しいポイントで、これも適宜見直しを行っています。

4. 全社向けに生成AIを中心とした推進プロジェクト[Run with Tech]

全社への生成AI浸透を図り従業員のスキルアップと新たな価値を生み出すためのプロジェクトにも力を入れ大きな躍進を見せた1年でもありました。 こちらは特設のアドベントカレンダーがありますので、よろしければご覧ください。

コネヒト生成AI Advent Calendar 2024 - Adventar

まとめ

ここには書ききれませんでしたが、他にも自治体向けの新規事業に向けた技術的な挑戦をしたチームがあったり、、ママリとしては初と言っていいくらいのUIの大きなリニューアルをしたりと大きなチャレンジができた2024年でした。

2025年は、コネヒトの開発組織として掲げているTech VisionのPhase2最後の年となります。「Beyond a Tech Company」を実現すべく、一人ひとりのエンジニアが楽しみながら仕事に向き合い、ビジネスやプロダクトがテクノロジーの力で成長しているその中心にいる開発組織になっていければと思っています。

コネヒトはPHP Conference Japan 2024に協賛します!

本日はPHP Conference Japan 2024の協賛するお知らせです!

コネヒトはPHP Conference Japan 2024に協賛いたします!

コネヒトではメインプロダクトである「ママリ」を始めとして開発のメイン言語としてPHPを活用しており、フレームワークとしてはCakePHPを採用しています。
そんなPHPを愛用しているコネヒトですがこの度PHP Conference2024のスポンサーとして協賛させていただくことになりました。

phpcon.php.gr.jp

スポンサーするにあたって、コネヒトは「人の生活になくてはならないものをつくる」というミッションを掲げているので、技術コミュニティについても同様に、サポートして一緒に盛り上げていくことができたら、と思っております。

イベント概要

ブースを出展します!

今年もコネヒトはブースを出します。

スタンプラリーも開催されますのでぜひコネヒトのブースにお立ち寄りください。 ノベルティや楽しい企画を用意してお待ちしております!

In App Purchaseの VerifyReceipt APIからApp Store Server APIに移行しました

はじめに

こんにちは! otukutun.bsky.social です。 今回はIn-App PurchaseのサーバーサイドAPIを、VerifyReceipt API から App Store Server API に移行した経験を共有できればと思います。

WWDC2023 で、VerifyReceipt APIのdeprecated化が発表され、 WWDC2024 では従来のStoreKit1がdeprecated化と宣言され、これまでのAPI群は「original API for In-App Purchase」に改名されました。まだ廃止日時などは明言されていないと思いますが、今後はApp Store Server APIやStoreKit 2に移行しなけばいけません。

弊社が提供している ママリプレミアム のサブスクリプションはiOSではIn-App Purchaseを使用し提供しています。今回はVerifyReceipt APIからApp Store Server APIに移行した際の手順や実装について解説していきます。主にPHPでの実装方法に焦点を当てています。

なお、この記事はコネヒトアドベントカレンダー 16日目の記事になります。

App Store Server APIの概要

App Store Server APIは、Appleが提供する新しい課金情報管理APIです。用途ごとに様々なAPIが提供され、購読情報だけでなく返金情報も取得できるようになりました。今回は GET /inApps/v1/subscriptions/{transactionId} を使用し、トランザクションIDをもとに最新の課金情報を取得することにしました。

PHPでの実装

JWSの取り扱い

App Store Server APIでは、レスポンスにJWS(JSON Web Signature)が返却されそれを検証することで購入情報の正当性を確認できるようになりました。AppleはPHP向けの公式ライブラリを提供しておらず、PHPでのJWT検証ライブラリとしてメジャーな firebase/php-jwt はx5c形式をサポートしていないため、PHP標準のOpenSSL 関数と組み合わせることで対応しました。

  1. firebase/php-jwt ライブラリを利用
    • JWTのデコードと検証を行います
  2. PHP標準の openssl ラッパー関数を活用
    • 証明書の有効性や署名の検証を行います

証明書の有効性の検証

Appleから返却されるJWSには、証明書情報(x5cフィールド)が含まれています。これを使用して、以下の手順で証明書の有効性を確認します。

  1. リーフ証明書、中間証明書、ルート証明書を検証
  2. 各証明書の情報(有効期限や発行者など)を検証
  3. JWSの検証

以下は具体的なコード例です。

1. リーフ証明書、中間証明書、ルート証明書を検証

<?php

use Firebase\JWT\JWT;
use Firebase\JWT\Key;

function toPem($certificate): string {
    return join("\\n", [
        "-----BEGIN CERTIFICATE-----",
        trim(chunk_split($certificate, 64)),
        "-----END CERTIFICATE-----",
    ]);
}

// サンプルJWS(ChatGPTに生成してもらいました
$jws = 'eyJhbGciOiJFUzI1NiIsImtpZCI6IjEiLCJ0eXAiOiJKV1QiLCJ4NXQiOiJleGFtcGxleDVjIn0.eyJ0cmFuc2FjdGlvbl9pZCI6IjEwMDAwMDAxMjM0NTY3ODkiLCJvcmlnaW5hbF90cmFuc2FjdGlvbl9pZCI6IjEwMDAwMDAxMjM0NTY3ODkiLCJ3ZWJfb3JkZXJfbGluZV9pdGVtX2lkIjoiMTAwMDAwMDEyMzQ1Njc4OSIsInByb2R1Y3RfaWQiOiJjb20uZXhhbXBsZS5wcm9kdWN0Iiwic3Vic2NyaXB0aW9uX2dyb3VwX2lkZW50aWZpZXIiOiIxMjM0NTY3OCIsInB1cmNoYXNlX2RhdGUiOiIyMDI0LTExLTAxVDEyOjM0OjU2WiIsImV4cGlyZXNfZGF0ZSI6IjIwMjUtMTEtMDFUMTI6MzQ6NTZaIiwiaXNfaW5fYmlsbGluZ19yZXRyeV9wZXJpb2QiOmZhbHNlLCJlblZpcm9ubWVudCI6IlByb2R1Y3Rpb24ifQ.SIGxEcD9EXAMPLESIGNATURE';

// JWSのデコード
list($header64, $body64, $cryptob64) = explode('.', $jws);

// ヘッダー情報の取得
$headerText = JWT::urlsafeB64Decode($header64);
$header = JWT::jsonDecode($headerText);

// 証明書を取得してPEM形式に変換
$leafCertificate = toPem($header->x5c[0]);
$intermediateCertificate = toPem($header->x5c[1]);
$rootCertificate = toPem($header->x5c[2]);
// URLは適切なものを設定してください
$rootCertificateFromApple = toPem(JWT::urlsafeB64Encode(file_get_contents('APPLE_ROOT_G3_CERTIFICATE_URL')));

// リーフ証明書の検証
$result = openssl_x509_verify($leafCertificate, $intermediateCertificate);
if ($result !== 1) {
    throw new Exception('リーフ証明書の検証に失敗しました');
}

// 中間証明書の検証
$result = openssl_x509_verify($intermediateCertificate, $rootCertificate);
if ($result !== 1) {
    throw new Exception('中間証明書の検証に失敗しました');
}

// ルート証明書の検証
$result = openssl_x509_verify($rootCertificate, $rootCertificateFromApple);
if ($result !== 1) {
    throw new Exception('ルート証明書の検証に失敗しました');
}

リーフ証明書、中間証明書はJWSのheaderに付与されているのでそれらを使って検証します。PEM形式に変換し、openssl_x509_verifyを使えば検証できます。1なら有効、0なら無効なものになります。

ルート証明書の検証はルート証明書自体で行います。検証用の証明書はアップルのサイトからダウンロードできます。CER形式なので、PEM形式に変換する必要があります。

2. 各証明書の情報(有効期限や発行者など)を検証

<?php

// 各証明書情報の検証
$leafInfo = openssl_x509_parse($leafCertificate);
$intermediateInfo = openssl_x509_parse($intermediateCertificate);
$rootInfo = openssl_x509_parse($rootCertificate);

// 検証する情報は項目が多数あるのでここでは省略します

openssl_x509_parseを使って証明書の情報が取得できるので、各証明書の有効期限やOID、issuer情報などを検証すると良いと思います。有効期限はJWSに含まれているsignedDateを使って検証できます。

3. JWSの検証

<?php

$publicKey = openssl_pkey_get_public($leafCertificate);
$result = JWT::decode($jws, new Key($publicKey, $header->alg));
if (!$result) {
    throw new Exception('JWSの署名検証に失敗しました');
}

最後に、JWS自体の署名を検証します。これで検証が無事完了されれば、Transaction情報 を使って課金ステータスなどを更新すれば良いと思います。

おわりに

App Store Server APIは、従来のVerifyReceipt APIに比べてモダンな仕様であり、より強力な課金管理機能を提供されています。実装としてはライブラリが提供されていない言語では各自で対応しなければいけないことはいくつかありますが、PHPでも firebase/php-jwt とPHP標準のOpenSSL関数を使えば、対応は難しくないかなと感じました。またこの実装に加えて、OCSPやCRLなどのオンラインでの証明書期限切れの仕組みを導入することでより強固な検証プロセスを構築できると思います。

実際にご自身で実装する際にはApple提供のライブラリの実装やWWDCの動画を実際に見られることをお勧めします。ReveneuCat提供の記事はStoreKit 2について最初に理解するのにとても役立ちました。こちらが主に参考にした動画やページになります。

今回の記事が、同じ課題に直面している開発者の参考になれば幸いです!