feat(functions): 残りのHTTPエンドポイントをGoへ移植(sanpai/ranking/register/ogpRewrite)#127
Merged
Conversation
- RawUserDataFromStatus / ComputePerformanceIncrement / LatestActivityCreatedAt を Node版(performance.js)と同一ロジックでポート - 全件計算と増分計算の一致をランダム生成データで検証するプロパティテストを追加 (2バッチ2000ケース、3バッチ1000ケース) Co-authored-by: kojira <kojira@users.noreply.github.com>
- Firebase Admin Go SDK(auth)でIDトークンを検証 - GitHub Events APIを取得し、Node版と同一のロジックで参拝処理を実装 (クールダウン判定・ボーナスブランチ加点・増分/フル計算の切替・ Firestoreへのアクティビティ/ログ/ステータス書き込み) - 別関数名 sanpaiGo としてデプロイし、既存の sanpai(Node) と共存させる - Firestoreエミュレータ + モックGitHub APIサーバーによる統合テストを追加 (FIRESTORE_EMULATOR_HOST未設定時は自動スキップしCIに影響しない) Co-authored-by: kojira <kojira@users.noreply.github.com>
- firebase functions:config:get で既存のGitHub OAuth資格情報を取得し、 ::add-mask:: でマスクした上で gcloud functions deploy の環境変数として渡す (新規のGitHub Secretsは追加しない) - クールダウン秒数は SANPAI_NEXT_TIME_SECONDS 環境変数でdev/prodを明示的に指定 - docs/backend.mdとfunctions-go/READMEにsanpai移植の設計・既知の挙動を追記 Co-authored-by: kojira <kojira@users.noreply.github.com>
- 増分計算パスでGitHubイベントのpayloadを引き継ぐよう修正 (IssuesEvent判定は文字列一致のみで実害はないが、フル計算パスとの 一貫性のため) - 季節ボーナス(2022年正月キャンペーン)を意図的に未移植とする理由を コード・docsに明記 - GitHub API呼び出しのクライアント側タイムアウトを撤廃しNode版(axios)に 合わせる(独自改善を入れない方針のため。上限はCloud Run functionsの リクエストタイムアウトで担保) - GitHubレート制限ヘッダーのロギングを追加(Node版と同様の運用監視情報) - 不正なJSONボディ時のステータスコード差異をdocsに明記 - go mod tidyでfirebase-admin/grpcの直接依存マーキングを修正 Co-authored-by: kojira <kojira@users.noreply.github.com>
- cache_data/ranking_cacheを読み、上位100件+自分の順位をNode版と同一形式で返す
- latest_updateはNode版がFirestore Timestampをそのままjson化した際の
{_seconds,_nanoseconds}形式を再現
- screen_name未指定/該当なしの場合はmy_rankキー自体を省略(Node版と同じ)
- Firestoreエミュレータによる統合テストを追加
Co-authored-by: kojira <kojira@users.noreply.github.com>
- Firebase Admin Go SDKでIDトークンを検証 - 新規ユーザー作成/auth_user_uid補完/登録済みの3分岐をNode版と同一ロジックで実装 - Firestoreエミュレータによる統合テストを追加 Co-authored-by: kojira <kojira@users.noreply.github.com>
- SPAのビルド済みHTML(base_url)を取得しOGP/Twitterカード用メタタグを Node版と同一の文字列置換で書き換え - base_url/プロジェクトIDはデプロイ時の環境変数として明示的に注入 - モックHTTPサーバーによるテストを追加(置換内容・Cache-Controlヘッダー・ パス不一致時の挙動を検証) Co-authored-by: kojira <kojira@users.noreply.github.com>
- func.base_urlもGitHub資格情報と同様にfirebase functions:config:getから取得し ogpRewriteGoの環境変数として渡す - docs/backend.mdにuserOGP(画像生成)とスケジュール関数を今回のGo移植対象外と した理由を明記 Co-authored-by: kojira <kojira@users.noreply.github.com>
- register: 不正なJSONボディ時、Node版(Expressのbody-parser)と同じ順序
(メソッド判定・認証チェックより前)でパースし400を返すよう修正。
sanpaiも同様に統一(共通ヘルパー decodeJSONBody を追加)
- ranking: cache_data/ranking_cache に ranking フィールドが欠落している
異常系で、Go版が {"ranking":null} を200で黙って返していたのを
internal error(500)にするよう修正。Node版は同状況で例外化するため、
Go版が壊れたキャッシュを正常応答として隠してしまわないようにする
- テストカバレッジ不足の指摘に対応:
- registerHandler/sanpaiHandlerのHTTPレベル分岐(メソッド判定・認証
ヘッダー欠落・不正ボディ)のテストを追加
- ogpRewriteのog:descriptionのもう一方の置換パターン(property属性
なし)とtwitter:imageの明示的な検証を追加
- rankingのレスポンスJSONに実際に_seconds/_nanosecondsキーが出力
されることを検証するテストを追加
- docs/backend.mdを更新
Co-authored-by: kojira <kojira@users.noreply.github.com>
- sanpai → sanpaiGo (web/pages/sanpai.vue) - register → registerGo (web/pages/index.vue) - ranking → rankingGo (web/components/ranking.vue) - ogpRewrite → ogpRewriteGo (app/firebase.json のHosting rewrite) いずれもNode版とレスポンス形式は同一(docs/backend.md参照)。既存のNode版 function自体は当面残し、切替のみ行う(即座にロールバックできるようにするため)。 statusGoの切替(ae502ab)と同じ方針。 Co-authored-by: kojira <kojira@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
概要
statusエンドポイントのGo移植(#126)に続き、ユーザーが直接待つ残りのHTTPエンドポイントをすべてGo(Cloud Run functions)に移植します(それぞれ別関数名でデプロイし、既存のNode版と共存)。sanpai→sanpaiGo(参拝処理。Firebase認証・GitHub API・Firestore書き込み)ranking→rankingGo(ランキング表示)register→registerGo(ユーザー登録)ogpRewrite→ogpRewriteGo(プロフィールページのOGPメタタグ書き換え。Firebase Hostingの/u/*リライト経由で全プロフィール閲覧のたびに呼ばれるため、実はstatusと並んで体感速度に直結する)挙動はNode版と同一にすることを優先し、独自の改善は入れていません。
移植を見送った機能とその理由(詳細は
docs/backend.md「Go移植を見送った機能」参照):userOGP(OGP画像生成):canvas/chartjs-node-canvasによるサーバーサイド画像合成に強く依存しており、Goで同等の結果を得るには画像処理を一から実装し直す必要がある(他のエンドポイントとは技術的難易度が大きく異なる)。またページの初期表示をブロックしない経路のため、レイテンシー改善の優先度は相対的に低い。rankingUpdate/rankingCache/statusCacheBackfill/scheduledOgpDelete): ユーザーが待つものではないためコールドスタート短縮の恩恵がなく、Pub/Subトリガーの構成変更(専用のCloudEventハンドラ・Cloud Scheduler設定)が別途必要になるため対象外とした。第三者視点のレビューを2回実施済み(1回目: sanpai部分、2回目: ranking/register/ogpRewrite部分。指摘事項は全て対応済み)。
主な変更
sanpai → sanpaiGo
app/functions-go/internal/performance/: 増分計算ロジック(RawUserDataFromStatus/ComputePerformanceIncrement/LatestActivityCreatedAt)をポート。全件計算と増分計算の一致をプロパティテスト(2000/1000ケース)で検証app/functions-go/sanpai.go: Firebase Admin Go SDKでのID検証、GitHub Events API呼び出し、クールダウン判定、増分/フル計算の切替、Firestore書き込みを実装app/functions-go/sanpai_test.go: Firestoreエミュレータ+モックGitHub APIでの統合テスト、HTTPレベルの分岐テストranking → rankingGo
app/functions-go/ranking.go:cache_data/ranking_cacheから上位100件+自分の順位を返す。latest_updateはNode版のFirestore Timestamp JSON化形式(_seconds/_nanoseconds)を再現register → registerGo
app/functions-go/register.go: Firebase IDトークン検証、新規作成/auth_user_uid補完/登録済みの3分岐ogpRewrite → ogpRewriteGo
app/functions-go/ogp_rewrite.go: SPAのビルド済みHTMLを取得しOGP/Twitterカード用メタタグを文字列置換共通
.github/workflows/dev-deploy.yml: 各関数のデプロイステップを追加。GitHub OAuth資格情報・func.base_urlは新規Secretsを増やさず、既存のfirebase functions:config:getから取得しマスクした上で環境変数として渡すdecodeJSONBody共通ヘルパーを追加し、sanpai/registerとも不正なJSONボディの場合にNode版(Expressのbody-parser)と同じ順序・ステータスコード(400、メソッド判定・認証チェックより前)で応答するよう統一docs/backend.md/app/functions-go/README.md: 設計・既知の挙動・見送った機能の理由をドキュメント化既存Node版からそのまま引き継いだ、あえて修正していない挙動
詳細は
docs/backend.mdを参照。主なもの:sanpai: IDトークンのuidとgithub_idの一致チェックなし、exp表示キャッシュの非原子性、GitHub取得失敗時のレスポンスregister: POST以外は400を返す(sanpai/statusは同状況で200を返すNode版の既存の不整合をそのまま踏襲)ogpRewrite:/u/を含まないパスへの直接アクセス時、Node版の未到達コードパスでの例外化(500)をそのまま踏襲第三者レビュー(2回目)で見つかり対応した点
ranking_cacheドキュメントにrankingフィールドが欠落する異常系で、Go版が{"ranking":null}を200で返し壊れたキャッシュを黙って正常応答していたのを、internal error(500)にするよう修正テスト
go build ./.../go vet ./.../go test ./...(いずれもOK)FIRESTORE_EMULATOR_HOSTを設定してのFirestoreエミュレータ統合テスト(全エンドポイント27件パスOK)actionlintでCIワークフローの構文チェック(OK)未実施
statusGoと同様、安定稼働確認後に別途実施)