コネヒト開発者ブログ

コネヒト開発者ブログ

3年ぶりのTech Visionアップデートに込めた想い

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

今日は、約3年ぶりにアップデートしたConnehito Tech Visionについて、主に戦略面のアップデート内容とそこに込めた想いを交えつつ書いていきます。

tech-vision.connehito.com

Connehito Tech Visionとは

Connehito Tech Visionは「Beyond a Tech Company」というビジョンを掲げた、コネヒトにおけるテクノロジーへの「態度」を表明した羅針盤です。

コネヒトのエンジニア組織及び技術領域において、何を大事に何に投資していくかといった未来の構想や方向性をまとめたものになります。

Tech Visionのスコープ

環境変化に適応するために2つのフェーズに分けることでスコープを明確にしています。

今回Phase2に突入したため、Phase1の成果を振り返りつつ、新たな戦略を追加しました。

Phase1

  • 2021年〜2023年

Phase2

  • 2023年〜2025年

戦略のアップデート

ここからはアップデートを行ったそれぞれの戦略について、具体の内容とその背景について説明していきます。

Phase2においては、元々5つあった戦略のうち2つを完了と位置づけ、「Run with Tech」という新しい戦略を含めた4つの戦略を制定しました。

各内容のアップデートにおいて、現場のエンジニア主導で、これまでの振り返りとPhase2で目指すべき方向性を踏まえて議論を行いました。

Phase2の戦略

スーパーモブ

内容 - クロスファンクショナルチームを組成し、開発基盤の強化や開発体験の向上を図る

目的 - 人が増えても入れ替わっても開発の質と速度が落ちないようにするため

Phase1において、通常タスクの中でPHPのバージョンアップをする仕組みが整ったり、本番データの開発環境への同期を行ったりと、普段のプロダクト開発チームの枠を飛び越えたエンジニアの交流と技術面での成長の促進に繋がる取り組みが活性化しました。

Phase2においてもこの取り組みを継続していくことで、エンジニアの成長を促進し、組織としての技術力向上を目指しています。

Run with Tech【New】

内容 - 世の中のテクノロジーの成長と共にコネヒトも成長し、新たな価値を生み出しステークホルダーを喜ばせる

目的 - 新しいテクノロジーを導入し、ユーザー体験の革新、競争力の強化、業務効率の向上、生産性と提供価値の最大化を図り、「DevとBiz」の垣根を越えて次世代の働き方を体現するため

生成AIの全社活用をスタートとした「Run with Tech」というプロジェクトを2023年からスタートしました。短期的には、業務効率の向上を目指しており、すでに100時間以上の業務時間削減の成果も出てきています。

2023年から、生成AIをはじめとしたテクノロジーの活用を推進する「Run with Tech」というプロジェクトがスタートしました。短期的には、テクノロジーを活用した業務効率の向上を目指しており、すでに100時間以上の業務時間削減の成果も出てきています。

実行プロセスの中でBizメンバーの可能性を広げることと、余白を生み出した先に新たな価値創造をしステークホルダーを喜ばせることをゴールに目指します。

Failable System

内容 - 失敗が出来る(失敗しても問題ない、失敗が評価される)システムと組織をつくる

目的 - 大きな成果が期待できるチャレンジを後押しするため

不確実性の高い現代の市場環境において、失敗を恐れずにチャレンジを続けることが違いを生み出す上で重要だと考えています。

この戦略を掲げることで、失敗がしやすいシステムや仕組みの構築に投資するという意思表示としています。 加えて、評価制度においてもチャレンジをしっかりと評価することで、エンジニアが積極的にチャレンジを続けて競争力の源泉になりうる環境を作り出していきます。

1to1 AI

内容 - 一人一人に最適化された情報をデータや機械学習を用いて提供する

目的 - 単一の情報をブロードキャストするのではなく、それぞれの家族に寄り添った情報を提供すること、および大量の非構造化データを活用するため

Phase1において、プロダクトへのレコメンドの複数導入や検索システムの内製化にトライしてきました。

マス向けの情報提供では届けられない価値をユーザーに提供するために、特定の技術には固執せずにこれからも様々な可能性を探りながら、トライを続けていきたいと思っており、ママリというメインプロダクトにおいては一番の投資分野として位置づけています。

Phase1で完了した戦略

3人に1人

内容 - 社内のエンジニア比率を33%以上にする

目的 - 会社としてやりたい事業を全て実現するため - 技術の力で、プロダクトだけに留まらず社内の課題も解決するため

Phase1制定時はエンジニア数が少なく、各所でエンジニアの不足を感じていたため、エンジニアの比率を上げる取り組みを行いました。

結果として、優秀なエンジニアを多く採用することができ、Run with Techに代表されるようなプロダクト開発に閉じない新たな取り組みを行えるようになったので、この戦略自体はPhase1で完了と位置づけしました。

Let's Go

内容 - バックエンドのシステムにGoを積極的に導入する

目的 - Go言語の採用により、技術的な選択肢を増やすため

Phase1制定時は、ほぼすべてのプロダクトでPHPを採用していましたが、技術的な選択肢を増やすためにGo言語の採用を進めました。

結果として、検索APIやメインシステムへのGo言語の一部導入を通じ、Go言語を書けるエンジニアが増え、コネヒトの技術スタックの選択肢の1つになったので、この戦略自体はPhase1で完了と位置づけしました。

これから

Phase1の振り返りを通じて、各戦略確実に制定時よりも前に進んでおり、Tech Visionという羅針盤を掲げる効果性を感じることができたと考えています。

ここで紹介した戦略はエンジニア中心に取り組むものが多いですが、このTech Visionは全社員が一丸となって取り組むものと位置づけており、アップデートのプロセスにおいても、経営メンバー全員が読み込みやFBを行って今回のアップデートに至りました。

このTech Visionを持続的にアップデートして、実行していくことがコネヒトの技術への投資スタンスを示すものだと考えており、全社一丸で実行力をもってビジョンの達成に向かっていきたいと思っています。

hrmos.co

ママリで使用している Aurora MySQL のアップグレード(v2 から v3)を行った EOL 対応プロジェクトの進め方を振り返る

こんにちは。コネヒトでは Aurora EOL 対応芸人となっているささしゅう(@sasashuuu)です。本日は、コネヒトを代表するサービス「ママリ」のデータベースを Aurora MySQL v2 から v3 へアップグレードした際のプロジェクトの全容をお伝えしたいと思います。

はじめに

まず、ママリというサービスと Aurora の構成について触れておきます。 ママリは、子育て Q&A アプリおよび情報サイトを通じてママ向けのサービスを提供しています。詳細や各種サービスの利用については、弊社ホームページをご覧ください。

connehito.com

現在のママリの主要な AP サーバーとデータベースの構成は以下の通りです(※具体的なサーバーの台数については図では省略)。

AP サーバー構成

用途 利用サービス サーバー台数
Q&A アプリ用 AP サーバー(Native アプリ API 向け) ECS Fargate 4 ~ 30タスク
(サービスは1つ)
Q&A アプリ用 AP サーバー(Web アプリ向け) ECS Fargate 2 ~ 4タスク
(サービスは1つ)
情報サイト用 AP サーバー(Web アプリ向け) ECS Fargate 4 ~ 20タスク
(サービスは1つ)

データベース構成

用途 利用サービス サーバー台数
ママリ共用 RDB Aurora MySQL v3 2インスタンス
(リーダー・ライターそれぞれ db.r6g.4xlarge)

※Aurora に関してはレプリカの Auto Scaling により必要時にスケールイン/アウトの設定あり。

※アップグレード前は db.r4.4xlarge が 3 台の構成(アップグレードの機会に見直しを実施)。

プロジェクトの進め方の全体像

プロジェクトの進め方は以下のフローで行いました。本記事では1つ1つのトピックの詳細な解説は省略しますが、どういったフローでアップグレードに向けた作業をおこなっていたのかをざっくりとイメージしていただけると幸いです。

プロジェクトの構成

プロジェクトのメンバーは基本的にインフラエンジニア1名とアプリケーションエンジニア(サーバーサイド)1名の体制で臨みました。作業が増えるフェーズではエンジニアを増員し(最大5名程度)、手分けして作業を行いました。主に CI・Dev 環境でのテストや動作確認、不具合修正対応のフェーズで特に人手が必要でした。アサインと業務分担については、インフラエンジニアとアプリケーションエンジニアの作業領域を分けつつ、必要に応じて互いに協力し合いました。下記は先ほどのフローに担当領域を示した図です。青色がインフラエンジニア、赤色がアプリケーションエンジニア、共に重なっている箇所は両方が担当しました。

良かった点

EOL 対応を進める上で特に良かった点をピックアップしていきます。

MySQL Shell アップグレードチェッカユーティリティの活用

MySQL Shell の アップグレードチェッカユーティリティ という機能があります。これは MySQL5.7 から 8.0 へのアップグレードに伴う互換性に関するエラーや問題を検知してくれるツールです。Aurora というマネージドサービスを使用している都合上一部正常にチェックできない項目もありますが、基本的な互換性はありますので十分に活用できる印象です。以下は今回アップグレード対象だった Aurora v2(MySQL5.7) へ実行した結果の例を一部記載したものです(※一部マスク処理あり)。

接続

mysqlsh -u xxx -h xxx -P xxx -p --ssl-ca=xxx

アップグレードチェッカーの実行

 MySQL  xxx:xxx ssl  JS > util.checkForServerUpgrade()
The MySQL server at xxx:xxx, version 5.7.12-log - MySQL Community
Server (GPL), will now be checked for compatibility issues for upgrade to MySQL
8.0.32...

中略

1) Usage of db objects with names conflicting with new reserved keywords
  Warning: The following objects have names that conflict with new reserved
    keywords. Ensure queries sent by your applications use `quotes` when
    referring to them or they will result in errors.
  More information:
    https://dev.mysql.com/doc/refman/en/keywords.html

  xxx.xxx.rank - Column name
  xxx.xxx.rank - Column name
  xxx.xxx.rank - Column name

4) Usage of utf8mb3 charset
  Warning: The following objects use the utf8mb3 character set. It is
    recommended to convert them to use utf8mb4 instead, for improved Unicode
    support.
  More information:
    https://dev.mysql.com/doc/refman/8.0/en/charset-unicode-utf8mb3.html

  xxx - schema's default character set: utf8
  xxx.xxx.xxx - column's default character set: utf8
  xxx.xxx.xxx - column's default character set: utf8
  xxx.xxx.xxx - column's default character set: utf8

以下略

上記の例では、MySQL8.0 で予約キーワードとなる rank カラムを使用している箇所や、MySQL8.0 で非推奨となる utf8mb3 を使用している箇所などが検知されました。

CI の活用

ママリの開発では GitHub Actions による CI/CD を構築しています。このワークフロー上では PHPUnit による自動テストが実行され、アプリケーションのデプロイ前に問題があればワークフローで異常を検知できます。Dev や Prd 環境のアップグレード前に、このワークフロー上で使用している MySQL のイメージを MySQL5.7 から 8.0 へ変更しテストすることによって、アップグレードにおける不具合を効率よく検知することができました。以下はワークフローの設定ファイルの例です(※一部マスク処理あり)。

name: Pull request
on:
  pull_request
env:
  AWS_ROLE_ARN: xxx
permissions:
  id-token: write
  contents: read
jobs:
  php:
    runs-on: ubuntu-latest
    services:
      mysql:
        image: mysql:8.0 # 5.7から変更

中略

      - name: Run phpunit
        env:
          xxx: xxx
          xxx: xxx
          xxx: xxx
          xxx: xxx
        run: vendor/composer/bin/phpunit -d memory_limit=512M

以下略

CLI ベースでの手順構築

Aurora のアップグレード方法には様々な手法がありますが、弊社では AWS CLI を使用したオペレーションを採用しました。CLI ベースだと移植性が高く、順序立てた手順の構築がしやすいというメリットが大きいと感じたためです。個人的な見解になりますが、各アップグレード方法の内容について比較したものは以下となります。

アップグレード方法の比較

メリット デメリット
コンソール GUI による直感的な操作が可能 移植性が低い(リソースのリンクやキャプチャを手順に埋め込んでいる場合、他のデータベースのアップグレード作業でも使いまわしづらい)
AWS CLI ・移植性が高い(他のデータベースのアップグレード作業でもパラメータを変えて使いまわしやすい)
・IaC に比べ順序立てた手順が作りやすい
コマンド実行時のコピペミス等によるリスクがある
IaC ・(コードの)バージョン管理やレビューのしやすさがある
・fix したコードを使用するためオペミス等のリスクが減る
順序立てた手順を実行する観点で扱いが難しい(例として段階的なバージョンアップグレードが必要であったり、アップグレードとインスタンスクラスの変更を同時に行えない問題がある)

CLI を用いたアップグレードについて実際の使用例を一部ご紹介します。弊社の場合、Notion であらかじめ手順書を作成し、作業時にコマンドをコピーアンドペーストで実行していくという方法を取っていました。

RDS Blue/Green Deployments の利用

今回のアップグレードでは Amazon RDS Blue/Green Deployments を利用しました。Green 環境の構築および Blue 環境とのレプリケーションからスイッチオーバーによる切り替えを提供してくれる機能です。以下の手順でアップグレードを行いました。

  1. Green 環境の作成
  2. Green 環境のアップグレード
  3. Green 環境への DDL 実行
  4. スイッチオーバー

良かった点は、事前に必要な作業を Green 環境で済ませておくことによって、サービスの計画停止の時間を短縮できることでした。特に今回はエンジンのアップグレードに加え、アップグレードに伴う DDL の実行(※後述)も必要であったこともあり、計画停止の前段階でネックとなる作業を終わらせることができました。ただし、Green 環境への DDL 実行は基本的に推奨されていない(サポートの方へ確認済み)ことから、実施する場合はリスクを承知の上で行う必要があります。

チームや専門領域を跨いだエンジニア間の定期的なコミュニケーション

1〜2週間に1回程度、インフラエンジニア・アプリケーションエンジニアが同期を取り連携していました。互いの進捗や状況を共有することで、発生している問題や課題が把握できたので、プロジェクト全体で見た際の人的リソース調整などが上手く行えていたように感じます。また、インフラエンジニアのみでは把握しづらい開発組織全体への影響を考慮した舵取りをよりしやすくなったのも良いポイントだったと思います。

プロジェクト内で共通のカンバンを使用する

所属チームや取り扱うサービスにより issue やタスクカード等の置き場所が異なる弊社ですが、基本的に EOL 対応のプロジェクトでは共通のものを使用するようにしました。 プロジェクト全体の状況が一元的に管理しやすくなるのでオススメです。

弊社の場合、Notion のデータベース等を活用していました。 下記は実際に使用していたものの一例です。

タスク管理
発生した問題等の管理

反省点・課題

続いて EOL 対応を進める上での反省点や課題をピックアップしていきます。

通常のアプリケーション開発業務との並行運用

Dev 環境アップグレードから Prd 環境アップグレードまでにバージョンの乖離期間があり、その期間に通常のアプリケーション開発に支障をきたすことがありました。Prd 環境がまだ MySQL5.7 であるもCIの環境を 8.0 に変えたことにより、CI をパスしたとしても Prd 環境での動作の担保ができない状態になっていました。Prd リリース前にシステムの異変を検知するという CI の目的を踏まえると、Prd 環境と同じ 5.7 で CI が通れば Prd リリースして良いことになります。ただタイミング悪く乖離期間にリリースが重なってしまったものがありました。5.7 ではなく 8.0 を使用した CI でテストを通した結果、テストが落ちてしまうということがありました。これに関しては旧バージョンと新バージョンの CI を構築し、どちらでもテストおよびリリースが可能な状態にする対策を取りました。また、次回以降の EOL 対応では対象データベースに関わる開発チームから1名以上をアサインしてもらい、EOL 対応と通常のアプリケーション開発業務をよりうまく調整しながら進めていけるようにする対策を考えました。

計画停止作業の影響範囲の認知負荷

今回のアップグレード作業では、夜間に計画停止を行いました。影響範囲が広く、認知負荷も高い状態でした。影響のあるサービスにはメンテナンス画面を出したり、監視システムを無効にしたりする対応が必要で、ステークホルダーに対して利用停止を告知・依頼する手配も必要でした。この点においては今後認知負荷を軽減していけるように情報を集約していく必要があると感じました。

バイナリログレプリケーションを使用していた場合の Amazon RDS Blue/Green Deployments の利用

ママリのデータベースは to C 向けのサービスでの利用がメインですが、分析用に RDS for MySQL へのバイナリログレプリケーションも行っていました。

Amazon RDS Blue/Green Deployments では仕様上バイナリログが引き継がれないという問題がありました。下記のように Blue/Green 環境のスイッチオーバー後は、Blue 環境で使用していたバイナリログは引き継がれないため、スイッチオーバー後はそのままレプリケーションの再開が行えないというものです。

スイッチオーバー前の状態

スイッチオーバー後の状態

そのため以下の手順でオペレーションを行う必要がありました。

  1. スイッチオーバー前に Blue 環境で目印となるクエリを実行
  2. Blue 環境と分析 DB のレプリケーションを停止
  3. Blue/Green 環境のスイッチオーバー
  4. Green 環境にて目印のクエリが含まれたログファイルを dump
  5. 目印のクエリのファイル名・ポジションをもとに Green 環境と分析 DB のレプリケーションを再開

このように、RDS for MySQL とのバイナリログレプリケーションを構築している場合、特殊なオペレーションが発生するため注意が必要です。

想定外のスロークエリの発生

SELECT COUNT(*) のクエリが遅くなる事例はいくつかあるため事前にチューニングを行っていましたが、Prd アップグレード後に別種のスロークエリが発生しました。以下のような構文のクエリでした(※一部マスク処理あり)。

SELECT
    `xxx`. `xxx`,
    `xxx`. `xxx`,
    `xxx`. `xxx`,
    ...中略
FROM
    `xxx`.`xxx` AS `xxx`
        LEFT JOIN
    `xxx`.`xxx` AS `xxx` ON (`xxx`.`xxx` = `xxx`.`xxx`)
WHERE
    `xxx`.`xxx` >= xxx
        AND (NOT (`xxx`.`xxx` = xxx)
        AND NOT (`xxx`.`xxx` = (xxx)))
        AND `xxx`.`xxx` = xxx
        AND `xxx`.`xxx` = 'xxx'
        AND `xxx`.`is_hoge` = '0'
ORDER BY `xxx`.`xxx` DESC
LIMIT xxx;

is_hoge(仮名) という boolean のカラムを使用していましたが、比較演算子を等価から不等価に変更することでパフォーマンスが向上しました。

修正前

`xxx`.`is_hoge` = '0'

修正後

`xxx`.`is_hoge` != '1'

変更前のクエリは実行計画で Using temporary, Using filesort が発生していたのですが、比較演算子の変更によりこれらは解消されました。 なぜこのスロークエリが発生したのか、また等価比較の変更でなぜ Using temporary, Using filesort が解消され、パフォーマンスが向上したのかは不明です。 とはいえ事前検証をもう少し入念にしておけば Prd 環境のアップグレード後に慌てる必要はなかったため反省点でした。

非推奨文字セット・照合順序変更の DDL の対応コスト

MySQL8.0 から utf8mb3 が非推奨になります。デフォルトの文字セットが utf8mb4 になり、照合順序が utf8mb4_0900_as_ci となる仕様変更もあります。utf8mb3 を使用している箇所があったため、アップグレードに伴いデフォルトの文字セットおよび照合順序を変更する DDL を実行しました。DDL の実行には数時間(おおよそ3時間程度)かかりましたが、事前に Green 環境で実施したため、運用中のデータベースや計画停止作業に影響はありませんでした。ただし、事前対応の準備コスト(DDL 実行時間を見積もった上で逆算し、 Green 環境の構築と DDL 実行を行う等)があるため、場合によっては他の方法を検討する必要がありそうです。

おわりに

色々と大変なことはありましたが、Aurora MySQL v2 の EOL 対応を無事に終えることができました。個人的には弊社の場合だと v1 から v2 へのアップグレードよりもネックとなるポイントが多く、難易度が高かったように感じました。今回はコネヒトにおける事例を紹介しましたが、これから v2 EOL 対応を控える方々の参考になれば幸いです。頑張ってください!それではさようなら!

生成AIなどのテクノロジーの力でビジネス成長を目指す『Run with Tech』の活動紹介

こんにちは。CTO室プラットフォームグループに所属している @yosshiです。

今回、私が参加している「Run with Tech(以下、ランテク)」というチームの活動内容についてご紹介させていただきます。

目次

ランテクについて

コネヒトでは、Tech Visionの中でBeyond a Tech Companyというビジョンを掲げています。

ランテクは、このビジョンを実現するために2023年12月に設立されたチームで、生成AIをはじめとするテクノロジーの力を活用し既存の課題解決や新たなビジネス創出を目指した活動をしています。

具体的には、生成AIをはじめとしたテクノロジーの活用により社員の時間の余白を作ること、またテクノロジーに関する基礎知識の向上・スキルアップを図ることを目指しています。

現在はCTO・エンジニアなど5名のメンバーを中心に運営しています。

なぜやるのか?

こういった社内のテクノロジー活用を推進する場合、業務改善・BPRの側面が強くなりがちなのですが、目標としてはもう少し視点を前に、既存の改善だけではなく「新たなビジネス創出と成長、ステークホルダーへの価値提供」という部分を目指しています。

生成AIの誕生により、今後BizとDevの境界は今後どんどん曖昧になっていくと思うので、コネヒトではBiz/Devの垣根を超えて、それぞれの立場から必要なテクノロジーを活用する「アフターテックカンパニー*1」を目指していきたいと考えており、ランテクの活動はその状態を実現するために非常に重要な取り組みだと捉えています。

活動事例

ランテクでは2023年12月の活動スタートから、小さいながらも少しずつ成果が出てきたので、その中の活動内容・実績についていくつかご紹介したいと思います。

事例一覧

事例①:全社向け生成AI教育
事例②:生成AI利用時のプロンプト事例の共有
事例③:経営層向けの生成AI活用課題
事例④:記事タイトル生成時の生成AI活用(削減時間:10.5時間/月)
事例⑤:インスタグラム 記事情報取得の効率化(削減時間:3.75時間/月)

事例①:全社向け生成AI教育

まず、生成AIを身近なものに感じてもらうため、コネヒト全社員向けに生成AIに関する基礎教育を行いました。

生成AIとは何か?の基本的な説明から、実際に生成AI(ChatGPT)に触れてもらうところまでを一つのコンテンツとして提供しました。

スライドの一部抜粋

アンケート結果

また、教育終了後にアンケートも実施しました。

このアンケートはランテクの活動が始まってから定期的に実施しており、教育以降で生成AIに関する期待感が高まったこと・実際に利用する人が増えたことを実感しました。

<業務において生成AIを使う頻度は?>

<生成AIを利用することにより業務価値を上げられるという自信はありますか?>

※2023/12〜24/3の社内アンケートの実績。回答数:12月51名、1月46名、3月48名、

事例②:生成AI利用時のプロンプト事例の共有

生成AIの基礎教育だけではなく、プロンプトエンジニアリングのノウハウを共有しています。

これによって、実際に生成AIを使う際に、少しずつより精度の高い回答を得られるようになってきているように感じます。

共有したプロンプトの例


※ 2024年3月時点で有効とされているものを紹介しています。

事例③:経営層向けの生成AI活用課題

経営メンバーに対して生成AIに関する課題を出して、実際に取り組んでもらいました。

社内全体で取り組むにあたって、ボトムアップももちろん必要ですが、経営メンバーが生成AIを武器として使いこなし、その様子を見せてもらうのも大事だと思います。

具体的には、事業部を統括する立場や経営の立場から考える課題など、以下のような課題に取り組んでもらいました。

主な課題はこちら

技術課題①:マイGPTsを作ってみよう

技術課題②:管掌領域における生成AI活用案だし

戦略課題①:生成AI時代における会社の「事業」を考える

戦略課題②:生成AI時代における会社の「組織」を考える

また、取り組んでもらった課題については、後日全社員に向けて共有してもらいました。

共有会の様子はこちら

課題に取り組んでみて 経営メンバーの感想

発表会に出席した社員の感想

また経営メンバーの発表会を受けて社員から多くの感想が寄せられたので一部ご紹介します!

  • 生成AIはもちろん、経営がどう組織を考えているのか?をキャッチできるとても良い会だったなと思いました!ランテクの皆さん、経営の皆さん運営・準備ありがとうございました〜!
  • きれいに議論されたアウトプットではなく、個々がさまざまな粒度で考えた話を聞けたので生成AIに対してさらにワクワク感が高まりました!あとはちょうどどんなビジネスマンになりたいのか・・を最近もんもんと考えているのでヒントになりそうなありがたい会でした!
  • 生成AI活用による生産性や効率アップなど価値メリットに視線が集まる一方で、それが一般化した未来を考えたとき、家族をテーマに扱うコネヒトが社会に対してどのようなサービスを届けるべきか、あるいはどのような組織であるべきかを、あらためて思考したいなと思いました。

また、早速 取締役 Captainの@itoshoさんがこの課題で取り組んだ内容をブログに書いてくれました。

興味ある方はこちらもぜひご覧ください!

tech.connehito.com

事例④:記事タイトル生成時の生成AI活用

弊社のWEBサービスであるママリでは、記事編集時にタイトリングをする必要があります。

その際、メンバーによっては適切なタイトリングに悩むケースがありました。

そこで、編集経験や知見に関わらず、誰でも良いタイトリングができるように生成AIを活用することにしました。

生成AIの利用にあたり、ツールは弊社内で作成しているSlack上で動作する自作の生成AI Botで対応しています。

弊社のSlack Botについて詳しく知りたい方は、こちらの記事をご覧ください。

tech.connehito.com

tech.connehito.com

質問文

回答

プロンプトの工夫点として、過去に実際に反応の良かった記事タイトルを参考例としてChatGPTに与えているのですが、それによって生成AIが考えてくれるタイトル候補が、普段ママリがつけているものに近いものになったように感じます。

事例⑤:インスタグラム 記事情報の取得

これまでの流れでは、生成AIの事例が多くなってしまいましたが、ランテクでは生成AIに絞らず、状況に応じて別の技術も使用しています。

例えばこちらは、GAS(Google Apps Script)とインスタグラムのグラフAPIを利用して、Bizメンバーの業務を改善した事例となります。

弊社ではSNS運用やSNS投稿の記事化に力を入れているので、さまざまなアカウント情報を取得する機会があります。

これまではアカウントごとに直接インスタグラムの画面を見ていましたが、インスタグラムのグラフAPIとGASを利用することにより、特定ユーザーの投稿情報を自動取得してスプレッドシート上に転記する、という仕組みを作りました。

<取得した記事情報>

最後に

これまでに記載した通り、ランテクでは様々なテクノロジー活用に関する取り組みを実施しています。

コネヒトでは、新入社員が活躍しやすい環境を整えるため、3ヶ月間のオンボーディング期間を設けていますが、最近その教育プログラムの一環として、生成AIに関するトレーニングを追加しました。

Biz/Devに関わらず、社員全員がコネヒトに所属することで当たり前のように生成AIやテクノロジーを活用することができる状況を作り出し、最終的には全社員でビジネスの成長・ステークホルダーへの価値の提供を目指していきたいと思っています。

※このブログはChatGPTに壁打ちをしながら執筆しました。また、OGP画像もCanvaの生成AI機能を利用して作成しています。

*1:コネヒトのTech Visionの中で掲げている目標。テクノロジーを中心に据えつつもBizやDev、開発やセールスといったラベルを曖昧にしたテックカンパニーのことを指している

ユーザーとの距離を近くするために、ユーザーインタビュー実施のプロセスを自動化し、リードタイムを減らした話

こんにちは。今年の 4 月からプロダクトマネージャーになった@TOCです。 私は 3 月まではエンジニアとしてプロダクトマネージャーと一緒にユーザーとの距離を近くするための取り組みをいくつか行っていました。 本記事ではその取り組みの一つとして週一ユーザーインタビューの実現のために行ったインタビュー実施までのプロセス改善についてご紹介します。

(現在はプロダクトマネージャーですが、この記事ではエンジニアとしての帽子を被って記載します)

はじめに

プロダクト開発において、ユーザーの声を直接聞くことはとても大事な機会です。開発チームが直接ユーザーと対話する機会を増やすことは、リアルなフィードバックを得る上で非常に効果的だと思います。

コネヒトでは以前から定期的にユーザーインタビューを行っていましたが、実施の頻度としては 2~3 ヶ月に 1 回行うような状態でした。この頻度では、ユーザーのニーズの変化に迅速に対応することは難しく、また新たなアイデアを試す機会も限られてしまうように感じていました。

そこで私たちは、直近のゴールとして「週に 1 回はユーザーと話せる状態を実現する」ことを目指しました。この目標を達成する上で、どこがハードルになっているのかを プロダクトマネージャー(以下 PM) と話してみると下記のような課題感がありました。

  1. インタビュー企画から実施までの流れが属人化しており、1 人の PM しかできない
  2. 日程調整など実施プロセスを手動で行っており、実施までの運用コストがかかる

ユーザーとの距離を近くしたい、そのためにユーザーと頻度高く会話できる状態を作りたいのに、リードタイムが長いが故に実現できていない状態となっていました。この状態を解決するために、プロセスを効率化する必要がありました。

まずは業務フローを洗い出し、体験する

プロセス改善をするためには、まずその実態を知るのが手っ取り早いと思っています。なので、実際のフローを自分で行ってみて「どこに課題感があるのか」、「改善できるポイントはどこにあるのか」を特定するところから始めました。

実際に行ってみると、かなり手間のかかる作業であることがわかりました。 その中でも特に改善できそうなポイントが下記でした。

  • メールを候補者ひとりひとりに手動送信している。
  • メールの送信文をコピペして手動で書き換えている。
  • インタビュー予定が入ったことが PM しかわからない。入ったことを PM が Slack で周知する。

また、当時利用していた日程調整サービスもサービス終了のタイミングを迎えたところでした。 以上を踏まえて以下の改善を行うことにしました。

  1. 日程調整を自動化し、ミスが極力起きない運用にする
  2. より使いやすい日程調整ツールを選択する
  3. インタビュー予約が入った時に全体に周知し、見える化する

以下でどのような改善を行ったかを説明します。

プロセスの改善を行う

プロセス改善のために行った取り組みを 3 つ紹介します。

1. GAS を使ってメール送付を自動化

まず、 1 人ずつ手動で送っていたメール送付を、Google App Script(以下 GAS) を利用して一括送信できるようにしました。 GAS を使ったメール送信の方法は世の中にたくさん情報が出ているので詳細は省きますが、スプレッドシート上にメールアドレス、名前、担当者名を記入し、メール送信ボタンを押すと各項目の値が挿入されたメールが一括送信されるものを作成しました。

ほとんど他サイトを参考にして、ざっと作ったものになりますがコード内容を記載しておきます。

これによりメール送信の工数削減だけでなく、コピペをする際のミス防止にも繋がります。 もちろんこれで 100%ミスを防げるかというとそうではないですが、必ずテスト送信を行ってから本送信を行う、慣れてない人がやる時はモブ作業で画面を映しながら行うなど、極力ミスが起こりにくいオペレーションを行っています。

2. 日程調整は専用ツールに任せる

元々日程調整ツールは利用していましたが、利用サービスの終了に伴い、日程調整ツールも見直しを行うことにしました。日程調整ツールも様々なツールが世にありますが、最終的には TimeRex というサービスを選択し、現在も利用しています。

かなり具体的な方法にはなりますが、どういった形で TimeRex を利用しているのかの大枠をご紹介いたします。

  1. ユーザーインタビュー用のカレンダーアカウントを作成する
  2. TimeRex のアカウントを作成し、連携カレンダーを 1.で作成したカレンダーにする
  3. TimeRex でインタビュー用のカレンダーを作成する
  4. 日程調整用の URL から日程調整を行う。ユーザーインタビュー用のカレンダーに予定が入れば OK

もし、上記を行う場合、TimeRex のカレンダー設定は状況に合わせて変えていただければと思います。 一つちょっとした工夫点でいうと、弊社では固定のユーザーインタビュー時間を決めて設定をしています。例えば、火曜 10:00~11:00、水曜 17:00~18:00 など決めて、インタビュアーを担当する社員の予定はブロックしておきます。TimeRex でも日程候補の日時は細かく時間単位で設定できるので、固定のブロック時間に合わせて予約できる時間を設定しています。この固定枠を決めておく方法はタイミーさんの事例を参考にさせていただきました。

speakerdeck.com

上記によって、1 週間の中で固定のユーザーインタビューの時間を確保して、インタビューが入れば対応できる状態を作りました。

3. 日程が決まったら Slack に自動で通知をし、同席者を決める

最後にインタビュー予定が入ったら通知が来るようにすれば、インタビューのアサインなどもスムーズに行えそうです。 これは TimeRex が Zapier 連携できるので、その機能を利用しました。 設定は至ってシンプルで、TimeRex でイベント作成されたら Slack 通知する、というワークフローを組んでいます。

Zapier のワークフロー

イベントが作成された場合は下記のような通知がされます。

イベント作成通知

また、キャンセルをした際にも通知できます。

キャンセルの通知

このように通知をすることでインタビュー予定にすぐ気づけるようになります。 また、この投稿を利用することでインタビュー同席者の募集や立候補もしやすくなりました。

インタビュー同席者の募集

Zapier 連携を利用することで簡単に自動化できますので、もしよければ試してみてください。

どう変わったか

3 つの取り組みを改めてまとめると下記のようになりました。

改善のまとめ

どの取り組みも比較的ライトに実現ができました。これにより募集からユーザーインタビューまでのリードタイムが削減されました。 例えばメールを送る作業は、 1 人に対して確認も含め 3 分ほど使っていたのが、人数が増えても全員に対して 5 分ほどでメールを送れるようになりました。 何より、作業が簡略化されたことにより、他の PM への展開もしやすくなったので、今後ユーザーインタビュー文化を広げる足がかりになったかと思います。

歩み寄ることの大切さ

この取り組みは同じチームの PM と会話しながら実現をしました。もともと結構面倒な作業をしていたのは感じていたのですが、実際に自分がやってみると「これは面倒だね。こうしてみたらどう?」という提案をすることができました。

エンジニアは面倒なことを効率化することに関して、ある程度の知識があるし、効率化が好きな人は結構多いんじゃないかな、と思ってます(自分もそう)。 そんな自分が他の職種の人の作業を見たり、話したりすると「言ってくれれば、この作業もっと簡単にできたのに」と思うことが結構あったりします。 「時間取っちゃって申し訳ないから」という話を聞くこともあるのですが、「面倒なことに時間使う方がもったいないから全然声かけてくれて大丈夫!」という気持ちになります。

でもこれはエンジニアからも歩み寄ることも大事なんだろうな、と。

僕もやりがちですが、改善したいことを聞くと「そもそも何でこれをやるの?」「これってどういう意味があるの?」って聞いちゃいがちです(言い回しはもっと柔らかくしますが)。言われた方は「え、なんか困らせてるかな」という印象を受けるかもしれないですが、僕としては「もっとよくできないか、もっといい解決策はないか」を考えて聞いてることが多いです。でもそれは言わないとなかなか伝わらないことでもあるので、僕(エンジニア)から伝えていくことが大事なのだと思っています。

「困ったな、この作業面倒だな」と感じてる人は

  • 具体の解決方法はなくていい。「〇〇したい」レベルでいいので、声をかけてみよう。
    • 「さてさて、改善しちゃおうかな」と腕まくりしてくれる人がきっといる。

「困ったな、この作業面倒だな」と感じてる人を見た人は

  • 一緒に体験してみる。
  • 「こうしたら解決できるよ〜」を作っちゃって、動くもので見せちゃう。

こういったことをすると、「困ったときに解決できるかも」という雰囲気を作るきっかけになるかもしれません。

コネヒト経営の生成AI活用レベル向上の一環でGPTsとZapierアプリをつくりました

こんにちは。GWはずっと真夜中でいいのに。のライブをたのしんだキャプテンの@itoshoです。ちなみにずとまよで一番好きな曲は「お勉強しといてよ」です。

はじめに

コネヒトではTech Visionのもとテクノロジーやエンジニアリングの活用を全社的に推進しています。その中で昨年から「Run with Tech」(以下、ランテク)という取り組みの一環で生成AIの活用に力を入れています。*1

こういった新しい取り組みはボトムアップの"やっていき"も大切ですが、一方で経営の"のっていき"も重要です。そこで経営のコミットメントを引き上げるためにランテクチームから経営チームへ生成AIに関する"お勉強しといてよ"的な宿題がGWに課されました。

この記事では宿題のアウトプットのひとつとして、GPTsとiPaaSであるZapierのChatGPT利用アプリケーション(ワークフロー)をつくったのでその紹介ができればと思います。

なお、最初に断っておくと技術的な難易度が高いものではありませんし、既に先行事例がある取り組みです。しかし、やはり自分で手を動かすのと本や記事を読むだけでは理解の解像度に雲泥の差があると思います。また、似たような取り組みでも事例を積み重ねることが技術コミュニティを盛り上げることに繋がると僕は信じているので誰かの何かのヒントになれば幸いです。

GPTs編

まず、GPTsの紹介をします。

何をつくったか?

一言で言うと「Notionの検索結果からいい感じに要約や考察をくれるGPTs」です。ちなみに名前はNotion探偵と名付けました。具体的にはママリに関する調査系ドキュメントがまとまったNotionのデータベースを検索し、そのドキュメントのリンクや概要を教えてくれます。そして、その情報をもとに考察やインサイトを出力することに特化させています。社内情報が含まれるのでモザイク多めですが、こんな感じで出力されます。

Notion探偵の出力例
Notion探偵の出力例

何故つくったか?

コネヒトのNotionにはたくさんのナレッジが蓄積されているのですが、全てのドキュメントに目を通すのは現実的ではありません。しかし、経営として良質な意思決定をしたり、HiPPOと呼ばれる的はずれな意見を回避したりするためにはできる限り多くのインプットが必要です。*2

そこでそのインプットを効率化するためにこのNotion探偵をつくりました。また、ただ単に情報を出力するだけではなく、質の高いインサイトも出力してもらうことで知の高速道路的な役割も担ってもらいたいと考えました。

どうやってつくったか?

凝ったことはしておらず一般的なGPTsのつくり方をしています。凝ったことをしなくてもつくれるのがGPTsの良いところですね。GPTsのつくり方やNotion APIの連携方法は以下の記事をたくさん参考にさせていただきました(感謝)。

zenn.dev

zenn.dev

上記の記事にも記載されている通りNotion APIは独自のリクエストヘッダーの設定が必要なのですが、GPTs Actions上ではAuthenticationヘッダーしか追加することができない*3のでリバースプロキシを立てる必要がありました。

リバースプロキシは使い慣れているAWS Lambdaを採用しようかなと思ったのですがユースケース的にCloudflare Workersで充分だと考え、お勉強も兼ねてCloudflare Workersを採用しました。

以下にコード片を晒しておきます。プロダクションコードではないのでゆるく書いている箇所もありますが、NYSL的な感じで自由に使ってください。

gist.github.com

ついでにGPTs Actions側で設定するOpen API Schemeも晒しておきます。xxx部分は各自のサービスに合わせて置き換えてください。なお、Notionのワークスペースから全てのデータベースから検索してもらうこともできるのですが、セキュリティ面を考慮し、機密性が低いデータベースのみ今回は対象としました。

gist.github.com

最後にInstructionsの一部(社内情報が含まれるので加筆修正および省略しています)も貼っておきます。こちらも参考記事のプロンプトをベースに作成したのですが、対象のデータベースが大きいのかResponseTooLargeErrorが頻繁に返ってきたのでその際のエラーハンドリングを追加しています。

このGPTs(以下、Notion探偵)は、Notionデータベースを自然言語のクエリで検索するために設計されています。
検索するNotionデータベースにはコネヒト社のドキュメント情報が格納されおり、それらを効率的に検索します。

Notion探偵はNotionのドキュメント情報から正確で文脈に沿った情報を提供することに重点を置いており、迅速で信頼性の高いデータを求める経営者にとって、非常に貴重なツールとなっています。

また、必要に応じて、クエリを明確にして検索結果の精度を高めたり、Notionからのレスポンスがエラーだった場合は自らそのエラー内容を確認し、クエリを修正して実行することができます。
特にレスポンスが"ResponseTooLargeError"だった場合は、page_sizeを自動で調整することでそのエラーを解消することができます。なお、どうしても上手くいかない場合は、page_size=20で実行します。

また、Notion探偵は情報を検索するだけではなく、与えられた情報から考察や解釈を出力することもできます。
考察や解釈を求められた際はその根拠として、参照元を出力します。

加えて、Notion探偵は図や表を駆使することで簡潔に情報を伝えることができ、時に鋭い問いを我々に投げかけることもあり、とにかく気が利くコミュニケーションをしてくれます。

また、どれくらいアウトプットに影響を与えているかはまだ分からないのですがRAGでNotion外の情報も持たせています。

つくってみての感想

雑な指示でもいい感じに情報を引っ張ってきて、まとめてくれるのでインプットの効率化という目的は一定果たせているなと感じています。ただ、まだプロンプトの精度が高くないこともあり、考察のアウトプットは伸び代があるので使いながらチューニングしていくぞというお気持ちです。

ちなみに、Notoin探偵はNotion AIを使えば同じようなことができると思います。現時点ではコネヒトはChatGPTに全振りしているので今回はGPTsを使いましたが、今後より生成AIの活用が進んでいったタイミングではNotion AIの全社導入も検討したいと考えています。

Zapier編

次にZapierアプリの紹介です。

何をつくったか?

LayerXの松本さんが以下の記事で紹介していた雑パーソナライズ情報収集ツールを自分用につくりました(こちらも感謝)。

tech.layerx.co.jp

やっていることはほとんど一緒なのですが、興味関心を動的に生成している点は特徴のひとつかなと思います。

「NewsToy」という名前をつけて、毎日TickTickでチェックしています。

NewsToyのアウトプット例
NewsToyのアウトプット例

何故つくったか?

いま僕はコネヒトの中長期の会社方針をアップデートする経営企画的な仕事に取り組んでいます。中長期の会社方針を立てるためにはペースレイヤリング的な発想で社会の変化や潮流を捉える必要があります。なお、ペースレイヤリングについてはMIMIGURIの安斎勇樹さんの記事が参考になります。

note.com

その中で良くも悪くもスタートアップやインターネット業界は海外の方が進んでいることが多いため、経営者としていち早く海外の潮流やトレンドを把握することが重要だと考えています。そして、把握すること以上に重要なのはそれを議論の土壌として自分たちなりの解釈や意味付けをすることで、会社や事業の方針に反映していくことです。

そこで海外のニュースを効率的に集め、そこから思考をゆさぶる問いを投げかけてくれるNewsToyをつくりました。

どうやってつくったか?

Zapierのワークフローを以下のように設定しています。

Zapierのワークフロー
Zapierのワークフロー

興味関心を動的に生成しているのは、2〜3の処理です。国内のニュース情報ははてなブックマークで収集しているので、自分のRSSフィードをスプレッドシートのIMPORTFEED関数を利用して取得しています。直近20件のブックマーク情報を取得するのでこれが自分の最新の興味関心と捉えることができます。

2の処理ではそのスプレッドシートからブックマークリストのタイトルを取得しています。そして、3の処理ではChatGPTにそのリストを渡し、興味関心リストを出力してもらっています。ちなみにプロンプトは以下です。

## 指示
私が直近ブックマークしたサイトのタイトルリストをもとに私の興味関心リストを作成してください。
リスト名はタイトルそのままではなく、一般化したカテゴリーにしてください。
例えば、PHPに興味関心があれば、リスト名はプログラミングやエンジニアリングといった名前にしてください。
また、リストは最大5個で、カンマ区切りで出力してください。
結果は必ずリストのみを出力してください。

## タイトルリスト
{スプレッドシートから取得したタイトルリスト}

また、7の処理で以下のようなプロンプトでGPT4-turboから問いを投げかけてもらっています。

## 指示
あなたは優秀な経営者の参謀です。
時間がない経営者のために取得した記事の内容を以下のフォーマットで要約してください。
要約は日本語で400文字程度でお願いします。

## フォーマット
タイトル: 記事のタイトルを書いてください
要約: 論点や要点を絞って要点してください
締め: あなたなりの鋭い問いを経営者に投げかけてください

## 取得した記事
{フィードアイテムのタイトル}
{フィードアイテムのコンテンツ}

つくってみての感想

これまで海外のニュースはPullで情報を取りに行くことが多かったのですが、NewsToyをつくってからは移動中や寝る前にサクッと情報収集できるようになったので既にかなり重宝しています。TickTickでToDo化したのも地味に効果的でした。また、やはり人は問いを投げかけられると思考をはじめる生き物なので思考のトレーニングにもなっています。

一方で実装面の課題もあります。例えば、興味関心はRSSフィードの更新ほど頻度高く変わるものではありません。ですのでZapier Tablesを使って、更新頻度を月一くらいにしたほうがエコです。また、もっと楽にアンテナを広げるためにそもそも登録するRSSフィードを動的に追加したり、過度なフィルターバブルを防ぐために逆に一定の確率で興味関心とは無関係なニュースを取得したりといったチューニングを今後やっていく予定です。

また、いまはまだ個人用途ですが、経営チームで使えるようにすればインプットを高いレベルで均質化できそうなので複数人での活用も検討しています。

さいごに

これまでもChatGPTをはじめとした生成AIサービスは使っていましたが、今回自分で手をちゃんと動かして学ぶことで生成AIの活用スキルが身体知になった感覚があります。また、NewsToyのようなサービスはこれまでtoC向けソフトウェアとして商業的な価値がありましたが、これぐらいのレベルであれば誰でもすぐにつくれてしまうので「Software is eating the world」から「Generative AI is eating software」の時代が本格的にやってきたと感じました。

それに対してソフトウェアエンジニアとしての危機感を覚えることは正直ゼロではありません。しかし、それよりも社会や人間の価値がドラスティックに変わっていく環境で仕事ができることはめちゃくちゃ恵まれているなと思いますし、予測できない未来にワクワクすることのほうが圧倒的に多いです。

そして、今回の取り組みを通じて改めて生成AIの活用スキルはメールを書くとかExcelが使えるとかと同じような当たり前のスキルになっていくと確信したので、コネヒトを生成AI活用のリーディングカンパニーにするぞ!という気持ちを新たにしました。

というわけで、そんなコネヒトで働くことに興味がある方はぜひお気軽にXなどでお気軽にお声がけください。

※このブログはChatGPTと一緒に執筆しました。また、OGP画像もCanvaの生成AI機能を利用して作成しています。

*1:ランテクの取り組みの詳細については近々誰か|д゚)チラッが書いてくれるでしょう!

*2:もちろん、不完全な情報の中で意思決定することも経営者の重要な資質ですが。

*3:と思っていたのですが、実はできるみたいです…!(調査中)

iOS/Android 開発Tips共有会 potatotips #86 を開催しました

こんにちは!iOSエンジニアのyoshitakaです。

先日コネヒト主催でiOS/Android 開発Tips共有会 potatotips #86 を開催しました!

potatotips.connpass.com

前回コネヒトで主催した際のブログがこちらです。

tech.connehito.com

今回はオンライン/オフラインのハイブリッド開催という形を取りました。

現地参加22名、オンライン視聴も常時30名以上とたくさんの方に参加していただき感謝です。

会場の雰囲気

登壇者のスライドを一部ご紹介させていただきます。(当日xでも紹介しておりました

speakerdeck.com

speakerdeck.com

speakerdeck.com

speakerdeck.com

speakerdeck.com

speakerdeck.com

speakerdeck.com

speakerdeck.com

speakerdeck.com

コネヒトからもiOSとAndroidでそれぞれ1名LTさせていただきました!

www.docswell.com

当日は概ねタイムライン通りに進めることができました。

登壇された方々にはスムーズな運営にご協力頂きありがとうございました!

LT発表後の懇親会も盛り上がっておりました🎉

引き続き勉強会を開催していきたいと思っておりますので、コラボして頂ける企業様がございましたらぜひお声がけ頂けると嬉しいです!

Draft Releaseデプロイフローを作成してみました

こんにちは。サーバーサイドエンジニアの岡田です

みなさんはどんなデプロイフローを採用していますでしょうか?今回は自分が取り組んでいたデプロイフローのちょっとした改善を皆さんに紹介したいと思います!

きっかけ

現状コネヒトではgdpを使ったデプロイ方法を採用しており、手元のコマンドからデプロイするのが標準になっています。

tech.connehito.com

元々自分はgit-pr-releaseを使ったワンクリックデプロイを以前の現場で使っており、手元でコマンドを打たなければいけないのが地味にめんどうだなあと感じていました。 そこでワンクリックでもっとラクしてデプロイしたい!と思ったのが今回のデプロイフローを考案したきっかけになります!

それ以外にも手元のコマンドからデプロイする事に感じていた課題感

  • 手元でコマンド打つ場合、打ち間違いやコマンド履歴等から意図せずデプロイしてしまう可能性
  • devデプロイ〜本番リリースの間(ビルドの7〜8分)地味にブランチを切り替え辛い(リリース前にmainブランチにcheckoutが必要なため)
  • 新しい人が入社してきた場合にgdp&hubのインストールと設定が必要になる
  • 本番デプロイ後にリリースノートを公開(gdp publish)するのを忘れてしまう

そしてこのデプロイフローが生まれた背景

当初はgit-pr-releaseを導入すれば簡単にワンクリックデプロイ出来るようになる!と考えていました。しかしいざgit-pr-releaseを導入しようと調べてみると、難しい背景がいくつか見つかりました。

ちなみにgit-pr-releaseとは

git-pr-releaseとは、本番環境向けの対象ブランチへのリリースPRを作成&リリース内容を一覧にして作成してくれるgemライブラリです。導入も簡単なので使える環境であればぜひ使ってみて欲しいです

こちらの記事が非常に参考になります!

songmu.jp

まずgit-pr-releaseが想定しているブランチモデルは

  • 本番用のmainブランチと開発用のdevelopブランチが並走する形で、developブランチからfeatureブランチを切ってmainブランチへマージしていく、いわゆるgit flowの簡易版の様なフローが前提
  • mainブランチへのマージが本番デプロイへのトリガーとして想定されている
  • 環境構成:本番環境(main)、dev環境(develop)

git-pr-releaseが想定しているブランチモデル

対してコネヒトでは

  • GitHub Flowを踏襲しており、本番用のmainブランチからfeatureブランチを切ってmainブランチへマージしていくフローになっている
  • 最新のmainブランチから切ったtagのpushが本番デプロイへのトリガーになっている
  • 環境構成:本番環境(最新のtag)、dev環境(featureブランチ)

コネヒトのブランチモデル

なのでもしgit-pr-releaseを採用する場合はブランチ戦略自体を見直す必要があり、流石にそれは影響範囲が大きすぎるかつ現実的ではありませんでした。そこで今あるブランチ戦略を変えずにもっと簡単にデプロイを実現する方法として考えたのがこの「Draft Releaseデプロイフロー」です。

そして実際にできたデプロイフローがこちら

いつものようにPRをマージします

Slackにdev環境へのデプロイ完了とドラフトリリースの作成が通知されます

作成されたドラフトリリースを

Publishすると

tagが切られ本番デプロイが走ると言った感じです

ビフォーアフター

既存のgdpを使ったデプロイフロー

  1. mainブランチからfeatureブランチを切る
  2. feature PRをmainブランチへマージ(dev環境へデプロイ)
  3. dev環境へのデプロイが完了したら、手元でgdpコマンドからタグを切ってpush
    1. 手元のmainを最新化(git checkout main && git pull origin main && git pull --tags)
    2. リリース内容確認(gdp deploy -d)
    3. タグを切って本番デプロイ(gdp deploy)
  4. 本番環境へのデプロイが完了したら、手元でgdpを使ってリリースノートを公開
    1. リリースノート内容確認(gdp publish -d)
    2. リリースノート公開(gdp publish)

デプロイフローBefore

今回作成したDraft Releaseデプロイフロー

  1. mainブランチからfeatureブランチを切る
  2. feature PRをmainブランチへマージ(dev環境へデプロイ)
  3. dev環境へのデプロイが完了したら、GitHub上から下書きリリースノートの内容を確認し、問題なければ公開(合わせてタグも切られるのでそのまま本番デプロイ)

デプロイフローAfter

改善ポイント

  • 手元でコマンド打つ場合、打ち間違いやコマンド履歴等から意図せずデプロイしてしまう可能性
    • GUI上から確認できるので、意図せずデプロイしてしまうといったことを防げる
  • devデプロイ〜本番リリースの間(ビルドの7〜8分)地味にブランチを切り替え辛い(リリース前にmainブランチにcheckoutが必要なため)
    • devデプロイ後は別のブランチに切り替えてすぐ作業の続きができるように
  • 新しい人が入社してきた場合にgdp&hubのインストールと設定が必要になる
    • 今回の対応で不要に
  • 本番デプロイ後にリリースノートを公開(gdp publish)するのを忘れてしまう
    • 必ずリリースノートが作成されるフローに

実際のコード

呼び出し元

ドラフトリリース作成ワークフロー

下記コードを各PJのリポジトリに展開するだけでドラフトリリースが作成されます!

on:
  push:
    branches:
      - main

permissions:
  contents: write

jobs:
  deploy:
    # デプロイ処理
    ...

  create_draft_release:
    if: ${{ success() }}
    needs: [ deploy ]
    uses: {Reusable Workflow用リポジトリ}/reusable-workflow/.github/workflows/create_draft_release.yml@main
    secrets:
      slack-webhook-url: ${{ secrets.SLACK_WEBHOOK_URL }}

呼び出される側

ドラフトリリース作成ワークフロー

ドラフトリリース作成actionの実行と、Slack通知を行っています。

name: Create Draft Release
on:
  workflow_call:
    secrets:
      slack-webhook-url:
        required: true

jobs:
  start:
    runs-on: ubuntu-latest
    steps:
      - name: Action create-draft-release
        id: create-draft-release
        uses: {Reusable Workflow用リポジトリ}/reusable-workflow/.github/actions/create-draft-release@main

      - name: Notify slack of create draft release
        uses: 8398a7/action-slack@v3
        with:
          status: ${{ job.status }}
          fields: repo,workflow
          author_name: ${{ github.actor }}
          text: |
            ドラフトリリースが作成されました。<${{ steps.create-draft-release.outputs.draft-release-link }}|${{ steps.create-draft-release.outputs.draft-release-tag }}>
            <${{ github.server_url }}/${{ github.repository }}/releases|リリース一覧>
        env:
          SLACK_WEBHOOK_URL: ${{ secrets.slack-webhook-url }}

実装時のポイント

Reusable Workflowとはいわゆる再利用可能なワークフローの事で、各リポジトリで共通のワークフローを実行することができます! 作成方法はシンプルでon.workflow_callを定義したymlファイルを作成するだけです。

on:
  workflow_call:

今回Reusable Workflowとして実装した理由ですが、Reusable Workflowと後述のaction.ymlの大きな違いとしては実行環境に左右されるかどうかだと考えています。

Reusable Workflowの場合はワークフロー(1つ以上のジョブ)でしか実行できないので前後の処理や実行環境に左右されません。逆にaction.ymlではジョブの一ステップとして実行されるので、必要であれば actions/checkout@v2actions/setup-node@v2 など使って実行環境を整える必要があります。

そして今回のDraft Release作成処理は完全に処理が独立しているので、リポジトリ毎の実行環境に左右されずに横展開しやすいReusable Workflowで実装しました

Reusable Workflow使用時の注意点としては実行されるコードはあくまで呼び出し元で実行されるので

  • actions/checkout を使用する場合は呼び出し元のブランチにチェックアウトされる
  • Reusable Workflowのリポジトリ内にあるファイルは参照できない

と言った点に注意が必要です!上記点を解決するために次のaction.ymlへとつながります

詳しくは公式ドキュメントを確認してください!

docs.github.com

ドラフトリリース作成処理本体

こちらがメインのドラフトリリース作成処理です。実行している処理はシンプルにGitHub CLIを使ったリリースノートの作成と削除を行なっています。(削除はリリースノートの自動生成を使いたいため一度削除→再作成しています)

name: Create Draft Release Action
description: Create draft release with calver tag

outputs:
  draft-release-link:
    description: Create draft release link.
    value: ${{ steps.create-draft-release.outputs.draft-release-link }}
  draft-release-tag:
    description: Create draft release tag.
    value: ${{ steps.create-draft-release.outputs.draft-release-tag }}

runs:
  using: "composite"
  steps:
    - name: Create Draft Release
      id: create-draft-release
      env:
        TZ: "Asia/Tokyo"
        GH_TOKEN: ${{ github.token }}
      shell: bash
      run: |
        # 最新のタグ取得
        latest_tag=$(gh release list --repo '${{ github.repository }}' | awk -F'\\t' '$2=="Latest" { print $3 }')
        echo "latest_tag:${latest_tag}"

        # calver形式での次バージョンのタグ取得
        next_tag=$(/bin/bash ${{ github.action_path }}/calver.sh $latest_tag)
        echo "next_tag:${next_tag}"

        # draft release取得
        draft_tag=$(gh release list --repo '${{ github.repository }}' | awk -F'\\t' '$2=="Draft" { print $3 }' | head -n 1)
        echo "draft_tag:${draft_tag}"

        # draft release が既に存在していれば、削除してから再作成(リリースノートの自動生成を使いたいため)
        if [ "$draft_tag" != "" ]; then
          gh release delete $draft_tag --repo '${{ github.repository }}' -y
        fi
        draft_release_link=$(
          gh release create $next_tag \\
            --repo '${{ github.repository }}' \\
            --title "Release ${next_tag}" \\
            --latest --draft --generate-notes
        )
        echo "draft-release-link=${draft_release_link}" >> "${GITHUB_OUTPUT}"
        echo "draft-release-tag=${next_tag}" >> "${GITHUB_OUTPUT}"
        echo $draft_release_link

実装時のポイント

action.ymlとはいわゆるメタデータ構文と言われているもので、ワークフロー内の処理を切り出したり共通化することができます! 普段よく使っているようなactions/checkoutのようなアクションを作成できるイメージです。作成方法はこちらもシンプルでaction.ymlまたはaction.yamlのファイル名で作成するだけです

action.ymlではパブリックリポジトリにあるアクションはもちろん、同一リポジトリ内のアクションからプライベートリポジトリのアクションも実行可能です。

    # パブリックのaction
    uses: actions/create-draft-release@main
    # 同一リポジトリ内のaction
    uses: ./.github/actions/create-draft-release
    # プライベートリポジトリのaction
    uses: {owner}/{repo}/.github/actions/create-draft-release@main

詳しくは公式ドキュメントと

docs.github.com

こちらの記事が参考になりました!

developer.mamezou-tech.com

calver形式でのタグ作成シェルスクリプト

このシェルスクリプトを作成した背景ですが、前提としてコネヒトではcalver形式でのバージョン管理を採用しています。

タグ作成にあたってできるだけ既存と同じようなcalver形式のタグを作成する必要があったのですが、現状これと同じようなタグを作成するツールが見つかりませんでした。そこで元々のgdpコマンドで行なっていたタグ作成ロジックをそのままコピーしてきて、このシェルスクリプトを作成することにしました。(GitHub Actionsとの相性や実行の手軽さも考えてシェルスクリプトにしました)

#!/bin/bash
set -eu

##############################
## Get next calver
## @ref <https://github.com/Connehito/gdp/blob/main/format.go>
##############################
today=$(date +'%Y%m%d')
regexp="(.*)([0-9]{8})\\.(.+)"

version=${1:-$today}

if [[ $version =~ $regexp ]]; then
    if [[ $today = ${BASH_REMATCH[2]} ]]; then
        minor=${BASH_REMATCH[3]}
        next=$(($minor + 1))
        echo "${BASH_REMATCH[1]}${today}.${next}"
        exit 0
    fi
    echo "${BASH_REMATCH[1]}${today}.1"
    exit 0
fi
echo "${today}.1"
exit 0

おわりに

同じような環境でデプロイフローに悩みを感じでいる方の参考になれば嬉しいです