Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
12 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
379 changes: 139 additions & 240 deletions .github/workflows/dev-deploy.yml

Large diffs are not rendered by default.

17 changes: 14 additions & 3 deletions app/functions-go/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ functions-go/
register_test.go
ogp_rewrite.go # ogpRewriteGo エンドポイント
ogp_rewrite_test.go
userogp.go # userOGPGo エンドポイント(OGP画像生成)
ranking_update.go # rankingUpdateGo (Pub/Subトリガー、スケジュール関数)
ranking_update_test.go
ranking_cache.go # rankingCacheGo (Pub/Subトリガー、スケジュール関数)
Expand All @@ -52,9 +53,16 @@ functions-go/
performance/
performance.go # app/functions/performance.js の対象範囲のGoポート
performance_test.go # performance.test.js と同一の入出力を検証
ogpimage/ # OGP画像合成(userOGPGoが利用)。設計は同ディレクトリのREADME参照
ogpimage.go # 合成本体(座標/クロップ/縮小/WebPエンコード)
radar.go # レーダーチャート描画
base.png # ベース画像(2500x1313, go:embed)
fonts/ # Noto Sans JP(go:embed)
```

`userOGP`(OGP画像生成)は対象外(理由は `docs/backend.md`「Go移植を見送った機能」を参照)。
OGP画像生成 `userOGP` も Go へ移植済み(`userOGPGo`)。画像描画は `internal/ogpimage`
に分離している(詳細は `docs/backend.md`「`userOGP` エンドポイントのGo移植」および
`internal/ogpimage/README.md` を参照)。

## 関数の命名規則(既存Node関数との共存)

Expand Down Expand Up @@ -126,10 +134,13 @@ gcloud functions deploy statusGo \
`projectID == 'd-shrine' ? 300 : 60` とプロジェクトIDで分岐しているが、Go版は
デプロイ時に明示的な値を渡す(dev: `60`。prod移植時は `300` を指定する)。

`rankingGo`/`registerGo`/`ogpRewriteGo` も同様のパターンでデプロイしている。
`rankingGo`/`registerGo`/`ogpRewriteGo`/`userOGPGo` も同様のパターンでデプロイしている。
`ogpRewriteGo` は追加で `FUNC_BASE_URL`(Node版の
`functions.config().func.base_url` 相当)と `OGP_PROJECT_ID` を
`--set-env-vars` で渡す必要がある。
`--set-env-vars` で渡す必要がある。`userOGPGo` は画像合成・WebPエンコード・
アバター取得・GCSアップロードを行うため他HTTP関数より余裕を持たせ
(`--memory=512Mi --timeout=60s`)、OGPキャッシュ書き込み先の
`STORAGE_BUCKET_NAME` を `--set-env-vars` で渡す。

## スケジュール関数(Pub/Subトリガー)のデプロイ

Expand Down
4 changes: 4 additions & 0 deletions app/functions-go/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,10 @@ require (
cloud.google.com/go/storage v1.63.0
firebase.google.com/go/v4 v4.20.0
github.com/GoogleCloudPlatform/functions-framework-go v1.9.2
github.com/HugoSmits86/nativewebp v1.3.0
github.com/cloudevents/sdk-go/v2 v2.15.2
github.com/fogleman/gg v1.3.0
golang.org/x/image v0.43.0
google.golang.org/api v0.287.0
google.golang.org/grpc v1.81.1
)
Expand Down Expand Up @@ -35,6 +38,7 @@ require (
github.com/go-logr/logr v1.4.3 // indirect
github.com/go-logr/stdr v1.2.2 // indirect
github.com/golang-jwt/jwt/v4 v4.5.2 // indirect
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 // indirect
github.com/golang/protobuf v1.5.4 // indirect
github.com/google/s2a-go v0.1.9 // indirect
github.com/google/uuid v1.6.0 // indirect
Expand Down
8 changes: 8 additions & 0 deletions app/functions-go/go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/cloudmock v0
github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/cloudmock v0.57.0/go.mod h1:dzcEjy1WJ0Q4u9twNR3LcLhNoYMRCrMCMafpxa0TjPQ=
github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.57.0 h1:RoO5+d7uCmDqovLrHCr2/BuViUXvdcrNxyNM1pN9dDQ=
github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.57.0/go.mod h1:YqwkQPrWSC7+byyc1VlKbWLBF5JsW5IoL6xUkemYSXk=
github.com/HugoSmits86/nativewebp v1.3.0 h1:n1egtEzSV4KwFtealr7dzdYq1wI/uj/bOQ/QcTcIyVE=
github.com/HugoSmits86/nativewebp v1.3.0/go.mod h1:YNQuWenlVmSUUASVNhTDwf4d7FwYQGbGhklC8p72Vr8=
github.com/MicahParks/keyfunc v1.9.0 h1:lhKd5xrFHLNOWrDc4Tyb/Q1AJ4LCzQ48GVJyVIID3+o=
github.com/MicahParks/keyfunc v1.9.0/go.mod h1:IdnCilugA0O/99dW+/MkvlyrsX8+L8+x95xuVNtM5jw=
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
Expand All @@ -58,6 +60,8 @@ github.com/envoyproxy/protoc-gen-validate v1.3.3 h1:MVQghNeW+LZcmXe7SY1V36Z+WFMD
github.com/envoyproxy/protoc-gen-validate v1.3.3/go.mod h1:TsndJ/ngyIdQRhMcVVGDDHINPLWB7C82oDArY51KfB0=
github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg=
github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
github.com/fogleman/gg v1.3.0 h1:/7zJX8F6AaYQc57WQCyN9cAIz+4bCJGO9B+dyW29am8=
github.com/fogleman/gg v1.3.0/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k=
github.com/go-jose/go-jose/v4 v4.1.4 h1:moDMcTHmvE6Groj34emNPLs/qtYXRVcd6S7NHbHz3kA=
github.com/go-jose/go-jose/v4 v4.1.4/go.mod h1:x4oUasVrzR7071A4TnHLGSPpNOm2a21K9Kf04k1rs08=
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
Expand All @@ -68,6 +72,8 @@ github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre
github.com/golang-jwt/jwt/v4 v4.4.2/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0=
github.com/golang-jwt/jwt/v4 v4.5.2 h1:YtQM7lnr8iZ+j5q71MGKkNw9Mn7AjHM68uc9g5fXeUI=
github.com/golang-jwt/jwt/v4 v4.5.2/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0=
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 h1:DACJavvAHhabrF08vX0COfcOBJRhZ8lUbR+ZWIs0Y5g=
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k=
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
Expand Down Expand Up @@ -139,6 +145,8 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.53.0 h1:QZ4Muo8THX6CizN2vPPd5fBGHyogrdK9fG4wLPFUsto=
golang.org/x/crypto v0.53.0/go.mod h1:DNLU434OwVakk9PzuwV8w62mAJpRJL3vsgcfp4Qnsio=
golang.org/x/image v0.43.0 h1:FLxcP4ec2350nTfOC8ysKtqYSIFbk/QGjw1ZHNP4tsY=
golang.org/x/image v0.43.0/go.mod h1:rrpelvGFt+kLPAjPM4HeWPgrl0FtafueU//e5N0qk/Q=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
Expand Down
57 changes: 57 additions & 0 deletions app/functions-go/internal/ogpimage/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
# internal/ogpimage

ユーザーOGP画像(でばっぐのうりょくカード)を生成するパッケージ。
`userOGPGo`(`app/functions-go/userogp.go`)から利用する。Node版
(`app/functions/index.js` の `createOgp`、`canvas` + `chartjs-node-canvas`)相当の
カード合成を、外部プロセス依存なしのGoネイティブ実装として再現する。

## ファイル構成

| ファイル | 役割 |
| --- | --- |
| `ogpimage.go` | 合成本体。座標定数・フォント/base読込・テキスト/アイコン描画・クロップ&縮小・WebP/PNGエンコード。 |
| `radar.go` | レーダーチャート描画(Chart.js の radar 設定に対応)。ピクセル指定で解像度非依存。 |
| `base.png` | ベースカード画像(2500×1313)。`go:embed` で同梱。 |
| `fonts/NotoSansJP-Regular.otf` | 日本語フォント。`go:embed` で同梱(OFL)。 |
| `ogpimage_test.go` | 出力寸法・WebPマジック・レーダー幾何の単体テスト+QCサンプル生成。 |
| `testdata/` | QC用に生成したサンプルOGP(目視確認用の参照画像)。 |

## 描画パイプライン

1. `base.png`(2500×1313)を `gg.Context` に読み込む。
2. デザイン基準(Node版=2500×1313)の座標定数を `scale = baseW/2500` で比例させて、
表示名・アイコン(円形クリップ)・ステータス・レーダーチャートを合成する。
3. **カード領域をOG比(1200:630)でクロップ**する。元画像は上下左右の暗い背景余白が
広く、そのまま縮小するとカード=文字が小さくなるため、カード塗り(黒/青)の実測
外接矩形に小マージンを付けた矩形を切り出す。
4. クロップ結果を**一度だけ**最終出力サイズ(1200×630)へ高品質縮小(CatmullRom)する。
縮小前にクロップすることで、再拡大による画質劣化を避ける。
5. WebP(可逆VP8L)でエンコードして返す(`EncodeWebP`)。QC比較用に `EncodePNG` もある。

## 座標・定数のメンテナンス

- レイアウト座標はすべて Node版のデザイン基準(2500×1313)で `ogpimage.go` の定数として保持。
- クロップに使うカード外接矩形(`cardMinX/MaxX/MinY/MaxY`)は `base.png` から実測した値。
**`base.png` を差し替えたら再計測して更新すること。**
- 出力サイズは `outputWidth`/`outputHeight`(1200×630)。`ogpRewrite` が注入する
`og:image:width`/`:height` と一致させること。

## QC(画質確認)

`TestWriteQCArtifacts` は環境変数 `OGP_QC_OUT` が指すディレクトリにサンプルOGP
(PNG/WebP)を書き出す。ローカルでの生成例:

```bash
cd app/functions-go
OGP_QC_OUT="$PWD/internal/ogpimage/testdata" go test ./internal/ogpimage/ -run TestWriteQCArtifacts -v
```

CI(`.github/workflows/dev-deploy.yml`)でも同テストを実行し、生成物を
`actions/upload-artifact`(名前 `ogp-sample`)としてアップロードして目視確認できる。

## 依存

- `github.com/fogleman/gg` — 2D描画。
- `golang.org/x/image/draw` — 高品質リサイズ(CatmullRom)。
- `golang.org/x/image/font/opentype` — フォント読込。
- `github.com/HugoSmits86/nativewebp` — 純Goの可逆WebPエンコーダ(cgo不要)。
Binary file added app/functions-go/internal/ogpimage/base.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file not shown.
Loading
Loading