github-reporadar 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/DESIGN.md +126 -0
- package/LICENSE +21 -0
- package/README.md +212 -0
- package/bin/github-reporadar.mjs +11 -0
- package/dist/assets/index-7rO9STC2.js +73 -0
- package/dist/assets/index-B5UAXuco.css +1 -0
- package/dist/index.html +25 -0
- package/dist-cli/cli.js +655 -0
- package/package.json +69 -0
package/DESIGN.md
ADDED
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
# GitHub RepoRadarデザイン仕様
|
|
2
|
+
|
|
3
|
+
この文書は「見た目をどう決めるか」の契約です。ここに書いた値は`src/index.css`の`@theme`と一致し、`src/designTokens.test.ts`が両者の乖離を赤にします。値を変えるときは文書とCSSを同じコミットで直してください。
|
|
4
|
+
|
|
5
|
+
## コンセプト:計器盤
|
|
6
|
+
|
|
7
|
+
RepoRadarは自分のGitHubを一晩ぶん眺める道具です。画面は暗い計器盤で、光るのは「いま判断が要るもの」だけ。ヘッダーのマークはレーダーの掃引で、動いている唯一の装飾です。
|
|
8
|
+
|
|
9
|
+
この道具の読み手は開発者本人ひとりです。誰かに見せる画面ではないので、装飾で印象を作る必要がありません。代わりに、数字と名前を読み違えないこと、暗い部屋でも目が疲れないこと、100件のrepoを一目で走査できることに寄せます。
|
|
10
|
+
|
|
11
|
+
決めていること
|
|
12
|
+
|
|
13
|
+
| 決めごと | 中身 |
|
|
14
|
+
|---|---|
|
|
15
|
+
| 色を使う範囲 | 最終pushが30日以内のものだけ。緑(7日以内)・黄(14日以内)・赤(30日以内)。それより古いものはグレーの明度差で奥へ退く |
|
|
16
|
+
| 主役 | 文字。面や線は文字を読むための下地で、それ自体が目立ってはいけない |
|
|
17
|
+
| 面の作り | 黒に近い背景に、わずかに浮いたカード面。境界はヘアライン1本。影は使わない |
|
|
18
|
+
| 動き | レーダーの掃引と、一覧の行が下から出るフェードの2つだけ。`prefers-reduced-motion`で両方止まる |
|
|
19
|
+
| 書体 | 名前・数字・日付・コードは等幅(IBM Plex Mono)。文章はIBM Plex Sans |
|
|
20
|
+
|
|
21
|
+
## 色
|
|
22
|
+
|
|
23
|
+
### トークン
|
|
24
|
+
|
|
25
|
+
すべての文字色は、カード面`panel`に対してWCAG AA(文字4.5:1、非テキスト3:1)を満たします。下の「対panel」はテストが計算して照合する値です。
|
|
26
|
+
|
|
27
|
+
| トークン | 値 | 役割 | 対panel |
|
|
28
|
+
|---|---|---|---|
|
|
29
|
+
| `--color-ink` | `#0a0c10` | アプリ背景 | — |
|
|
30
|
+
| `--color-panel` | `#13171e` | カード面。背景より1段浮く | — |
|
|
31
|
+
| `--color-panel-2` | `#0d1015` | 落とし込み面。入力欄・引用 | — |
|
|
32
|
+
| `--color-line` | `#262d3a` | 装飾のヘアライン。区切り線・カード縁 | 1.30 |
|
|
33
|
+
| `--color-line-strong` | `#5d6779` | 操作部品の縁。入力欄・ボタン・リンク型ボタン | 3.15 |
|
|
34
|
+
| `--color-fg` | `#f2f4f8` | 本文・見出し・入力値・返答 | 16.31 |
|
|
35
|
+
| `--color-fg-muted` | `#a3acbd` | 補助文。説明・メタ情報・案内 | 7.86 |
|
|
36
|
+
| `--color-fg-faint` | `#858e9f` | 三次。placeholder・列見出し・件数 | 5.45 |
|
|
37
|
+
|
|
38
|
+
### 3段の使い分け
|
|
39
|
+
|
|
40
|
+
読む文字は3段のどれかです。判断の基準は「その文字を消したら、画面の用が果たせなくなるか」。
|
|
41
|
+
|
|
42
|
+
| 段 | 使う場所 | 使わない場所 |
|
|
43
|
+
|---|---|---|
|
|
44
|
+
| `fg` | repo名、コミット文、壁打ちの返答、入力した値、見出し | 見出しの下の説明 |
|
|
45
|
+
| `fg-muted` | 説明文、日付や言語などのメタ情報、空状態と読み込み中の案内文 | 本文。返答やコミット文を補助色で描くと「暗い」と感じる(2026-09-05に実測して直した) |
|
|
46
|
+
| `fg-faint` | placeholder、テーブルの列見出し、件数、押せない状態 | 文章。faintは文の単位では読まない |
|
|
47
|
+
|
|
48
|
+
`fg-faint`より暗い文字は置きません。Tailwindの`text-slate-500`(3.8:1)以下は文字色に使いません。
|
|
49
|
+
|
|
50
|
+
### 信号色
|
|
51
|
+
|
|
52
|
+
| 色 | 意味 | 値 |
|
|
53
|
+
|---|---|---|
|
|
54
|
+
| 緑`emerald-400` | 動いている。最終pushが7日以内。選択・成功・主操作のhover | `#34d399` |
|
|
55
|
+
| 黄`amber-400` | 止まりかけ。8〜14日。Bookmarkの★ | `#fbbf24` |
|
|
56
|
+
| 赤`rose-400` | 止まった。15〜30日。破壊的操作のhover、エラー | `#fb7185` |
|
|
57
|
+
| グレー3段 | 31日以降。`slate-300` → `slate-400` → `fg-faint`。すべて文字としてAAを満たす | — |
|
|
58
|
+
|
|
59
|
+
信号色は文字と点に使い、面には使いません。面に色を敷くときは`/10`以下の透過で、色の名残だけを置きます(`bg-emerald-400/[0.06]`など)。
|
|
60
|
+
|
|
61
|
+
### 縁
|
|
62
|
+
|
|
63
|
+
装飾の縁と、操作部品の縁を分けます。カードや区切り線は`border-line`。入力欄・textarea・select・ボタン・ボタンに見えるリンクは`border-line-strong`。後者は「そこが押せる」と分かるための境界なので3:1が要ります。前者は静かなほど良い。
|
|
64
|
+
|
|
65
|
+
## 文字
|
|
66
|
+
|
|
67
|
+
| 用途 | クラス | 備考 |
|
|
68
|
+
|---|---|---|
|
|
69
|
+
| 本文・ボタン | `text-sm`(14px) | 既定 |
|
|
70
|
+
| メタ情報・ラベル・件数 | `text-xs`(12px) | これが下限。12px未満は使わない |
|
|
71
|
+
| 見出し | `text-base`〜`text-lg` + `font-medium` | 太字は`font-semibold`まで。`font-bold`は使わない |
|
|
72
|
+
| 大きな数字 | `text-2xl`〜`text-3xl` + `font-mono` + `tracking-tight` | 詳細ペインのコミット数 |
|
|
73
|
+
| 列見出し・節見出し | `text-xs font-mono font-semibold tracking-wider uppercase text-fg-faint` | 計器盤の刻印 |
|
|
74
|
+
|
|
75
|
+
名前、数字、日付、コード、モデル名は等幅。文章はsans。混ぜて1行に置くときは、等幅の側に`font-mono`を明示する。
|
|
76
|
+
|
|
77
|
+
行長は幅で作らない。`max-w-*`はレイアウトの容器に当て、段落に`ch`単位の上限を当てない。
|
|
78
|
+
|
|
79
|
+
## 面と余白
|
|
80
|
+
|
|
81
|
+
| 要素 | 形 |
|
|
82
|
+
|---|---|
|
|
83
|
+
| カード | `rounded-lg border border-line bg-panel` |
|
|
84
|
+
| 入力欄 | `rounded-md border border-line-strong bg-panel-2` |
|
|
85
|
+
| ボタン | `rounded-md border border-line-strong` + `text-fg-muted hover:text-fg`。主操作のhoverは`hover:border-emerald-500/40` |
|
|
86
|
+
| 札(private・非表示・鮮度) | `rounded px-1 font-mono text-xs` |
|
|
87
|
+
| セグメント切替 | 外枠`rounded-lg border border-line`、選択中だけ`bg-panel text-fg font-medium` |
|
|
88
|
+
| メニュー・ポップアップ | `bg-panel/85` + `backdrop-filter: blur(12px)`。document.bodyへポータルする |
|
|
89
|
+
|
|
90
|
+
余白は4pxの倍数。要素内は`px-3 py-1.5`、要素間は`gap-2`、区画間は`p-4`を既定にします。角丸は`rounded-md`(6px)を基本にし、面が大きいものだけ`rounded-lg`。`rounded-xl`以上は使いません。
|
|
91
|
+
|
|
92
|
+
影は使いません。面の前後関係は明度の差と、ヘアライン1本で示します。
|
|
93
|
+
|
|
94
|
+
## 動き
|
|
95
|
+
|
|
96
|
+
| 動き | 場所 | 長さ |
|
|
97
|
+
|---|---|---|
|
|
98
|
+
| レーダーの掃引 | ヘッダーのマークだけ | 3.4秒/周 |
|
|
99
|
+
| 行のフェードイン | 一覧の各行。`animationDelay`は最大280ms | 450ms |
|
|
100
|
+
| 色の変化 | `transition-colors`。hoverと選択 | 150ms |
|
|
101
|
+
|
|
102
|
+
これ以外の動きは足しません。`prefers-reduced-motion: reduce`で掃引とフェードは止まります。
|
|
103
|
+
|
|
104
|
+
## 書かないもの
|
|
105
|
+
|
|
106
|
+
過去に却下された形と、この計器盤に合わない形です。理由を添えます。
|
|
107
|
+
|
|
108
|
+
| 形 | 理由 |
|
|
109
|
+
|---|---|
|
|
110
|
+
| 1辺だけの太い帯や色付きボーダー | 種別は札と文字色で既に示している。帯は情報を足さず、角丸と相性が悪い |
|
|
111
|
+
| 段落への`max-w-[Nch]` | 日本語では意図の半分の幅になり、文節折りと合わさって右端が波打つ。行長は容器に任せる |
|
|
112
|
+
| 12px未満の文字 | 読めない。`text-[10px]`のような任意値も使わない |
|
|
113
|
+
| 絵文字をアイコン代わりに使う | 端末で形が変わる。SVGにする。既存の`⋯`と`☆`は文字として扱っている例外 |
|
|
114
|
+
| 影・グロー・グラデーション | 計器盤は平らな面で作る。奥行きは明度差で示す |
|
|
115
|
+
| 見出しのための太字の散布 | 構造は余白と字間で示す |
|
|
116
|
+
| 中身を見せずに送る・コピーする操作 | 送る文字列は画面に出してから送る。壁打ちの「送信する内容」が例 |
|
|
117
|
+
|
|
118
|
+
## 検査
|
|
119
|
+
|
|
120
|
+
| 何を | どう | いつ |
|
|
121
|
+
|---|---|---|
|
|
122
|
+
| トークンの値と比率 | `src/designTokens.test.ts`。`index.css`とこの文書の表を照合し、AAの床を切ったら赤 | `pnpm test` |
|
|
123
|
+
| ソースの禁止パターン | `scripts/design/lint.mjs`。12px未満、暗いslate、任意hex、操作部品の弱い縁 | 保存時のhookと`pnpm test` |
|
|
124
|
+
| 実際の描画 | `pnpm design`。12px未満の要素数、横溢れ、全テキストの実効コントラスト、axeの違反 | UIを変えたPRの前 |
|
|
125
|
+
|
|
126
|
+
実測は実データで動くので、出力はクラス名と数値だけにし、repo名やコミット文を外へ出しません。スクリーンショットもPRに貼りません。
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 BoxPistols
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
# GitHub RepoRadar
|
|
2
|
+
|
|
3
|
+
多数の個人リポジトリを並行開発する人のための「どこで何を作っていたか」想起ダッシュボード。
|
|
4
|
+
GitHub の活動(commit / PR / issue)を期間指定で集約し、Web UI とターミナルの両方から確認できます。
|
|
5
|
+
|
|
6
|
+
## 機能
|
|
7
|
+
|
|
8
|
+
Web UI はヘッダーで 3 モードを切り替えます。
|
|
9
|
+
|
|
10
|
+
- **ダッシュボード**: 日次×repo ヒートマップ + repo カード/テーブル。期間(7/30/90日)・ソート(活動量/最終push/放置)・キーワード検索・タグ・Bookmark(★)。
|
|
11
|
+
絞り込みは「活動量(期間内 commit 数の下限)」×「最終push(N日以内 / N日以上放置)」の2軸と、
|
|
12
|
+
よく使う組み合わせのプリセット(🔥 活発 × 30日以内 / ⚡ 直近7日 / 💤 30日以上放置)。カードから「次にやること」メモ。
|
|
13
|
+
モバイルではカードがアコーディオンになり、既定は全て閉じた状態。単一展開/複数展開の切替と「全て開く/全て閉じる」で開き方を選べる。
|
|
14
|
+
- **ボード**: 総合 Projects。Backlog/Active/Review/Done/Dormant の列に repo や自由タスクのカードを DnD で並べる。
|
|
15
|
+
- **検索**: 全 repo の open issue/PR を横断全文検索(日本語対応)+ type/repo/label ファセット + ラベル別件数。
|
|
16
|
+
|
|
17
|
+
**User data(タグ/Bookmark/ボード/メモ)の保存先**は既定でブラウザローカル(IndexedDB)。ヘッダーの
|
|
18
|
+
「☁ 同期フォルダを接続」で OneDrive/iCloud/Dropbox 等の同期フォルダを選ぶと、端末間で共有できます
|
|
19
|
+
(BE/DB レス、同期は OS のクラウドクライアント任せ)。
|
|
20
|
+
|
|
21
|
+
## 必要なもの
|
|
22
|
+
|
|
23
|
+
- Node.js 20+ / pnpm
|
|
24
|
+
- [gh CLI](https://cli.github.com/) でログイン済みであること(`gh auth login`)
|
|
25
|
+
|
|
26
|
+
トークンは実行時に `gh auth token` から読むだけで、ファイルには一切保存しません。
|
|
27
|
+
|
|
28
|
+
## npxで使う(インストール不要)
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
npx github-reporadar # 同期してからローカルで開く
|
|
32
|
+
npx github-reporadar brief # 端末に要約を出す
|
|
33
|
+
npx github-reporadar --help # フラグの一覧
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
- 前提は`gh auth login`済みのgh CLIだけ。トークンは実行時に`gh auth token`から読み、保存しない
|
|
37
|
+
- データは`$XDG_CACHE_HOME`か`~/.cache`の`github-reporadar/data/`に置く。カレントディレクトリには落とさない(private repo名とコミット文が入るため)。`--data-dir`で変えられる
|
|
38
|
+
- 待ち受けは`127.0.0.1`だけ。ポートは既定5177で、使用中なら次を探す
|
|
39
|
+
- `--no-sync`で手元のデータだけで開く。`--days 30`で取得期間を変える
|
|
40
|
+
|
|
41
|
+
npmには実データを含めない。`files`で`dist/data`を除外し、`prepublishOnly`でも消し、`npm pack --dry-run`に`/data/`が無いことをテストで固定している。
|
|
42
|
+
|
|
43
|
+
## 使い方
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
pnpm install
|
|
47
|
+
pnpm sync # GitHub から直近90日の活動を取得して public/data/ にキャッシュ
|
|
48
|
+
pnpm dev # Web UI (http://localhost:5173)
|
|
49
|
+
pnpm brief # ターミナルで簡易確認
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
### CLI オプション
|
|
53
|
+
|
|
54
|
+
```bash
|
|
55
|
+
pnpm brief --days 7 --sort stale --limit 20
|
|
56
|
+
# --days 7|30|90 (default 30)
|
|
57
|
+
# --sort active(活動量順) | recent(最終push順) | stale(放置順)
|
|
58
|
+
# --limit 表示件数 (default 15)
|
|
59
|
+
# --private private repo も表示 (既定は public のみ。Web UI はヘッダーのチェックボックスで切替)
|
|
60
|
+
pnpm sync --days 30 # 取得期間の変更
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
## 構成
|
|
64
|
+
|
|
65
|
+
```
|
|
66
|
+
scripts/sync.ts collector: repo ごとの REST commits API → public/data/*.json
|
|
67
|
+
scripts/brief.ts CLI: キャッシュを読んでターミナルに要約表示
|
|
68
|
+
src/ viewer: Vite + React + Tailwind v4 (キャッシュを読むだけの純フロント)
|
|
69
|
+
src/lib/aggregate.ts 期間集計の純関数 (vitest でテスト)
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
### データソースについて
|
|
73
|
+
|
|
74
|
+
GraphQL `contributionsCollection` は使いません。private リポジトリの内訳を
|
|
75
|
+
`restrictedContributionsCount` に集約して返す (repo 別内訳から欠落する) ため、
|
|
76
|
+
repo ごとの REST commits API を一次ソースにしています。
|
|
77
|
+
|
|
78
|
+
- 対象: 期間内に push があった **自分が owner の repo のみ**(組織・共同 repo は収集しない)
|
|
79
|
+
- bot (`author.type === 'Bot'`) を除く全コミットを集計。期間内にコミットの無い repo は除外
|
|
80
|
+
- private repo はローカルキャッシュにのみ保存し、表示は既定オフ (Web はトグル、CLI は `--private`)。
|
|
81
|
+
公開ホスト版は既定では private を**取得しない**(下の「private を含める」参照)
|
|
82
|
+
- 日付は実行環境のローカルタイムゾーンで日別化 (UTC 境界ずれを回避)
|
|
83
|
+
- 制約: デフォルトブランチのみ (未マージのブランチ作業は反映されない)
|
|
84
|
+
|
|
85
|
+
- キャッシュ (`public/data/`) には private リポジトリ名・コミットメッセージ・issue/PR タイトルが含まれるため gitignore 済み
|
|
86
|
+
- viewer はネットワークアクセスなし。GitHub API を叩くのは collector のみ
|
|
87
|
+
|
|
88
|
+
### ローカル版のデプロイ注意
|
|
89
|
+
|
|
90
|
+
**ローカル版(`VITE_HOSTED` 無し)は公開ホストにデプロイしない**こと。`public/data/` のキャッシュに
|
|
91
|
+
private リポジトリ名・コミット文・issue タイトルが入るため。`public/data/` と `dist/` は
|
|
92
|
+
gitignore + `.vercelignore` 済み(git 連携デプロイにはデータが入らない=空画面になる)。
|
|
93
|
+
公開したい場合は下の「公開ホスト版(GitHub OAuth)」を使う(各ユーザーが自分のデータを見る方式で安全)。
|
|
94
|
+
|
|
95
|
+
## 公開ホスト版(GitHub OAuth + Vercel)
|
|
96
|
+
|
|
97
|
+
各ユーザーが自分の GitHub でログインし、**自分の public リポジトリ**の活動を見られる公開版
|
|
98
|
+
(`api/` の Vercel Functions)。`VITE_HOSTED=1` のときこのモードになる。他人がアクセスしても
|
|
99
|
+
その人自身の public データしか見えず、あなたのデータは見えない。
|
|
100
|
+
|
|
101
|
+
### 仕組み / セキュリティ
|
|
102
|
+
|
|
103
|
+
- OAuth トークンは **httpOnly + Secure Cookie**(ブラウザ JS から読めない=XSS 耐性)。`client_secret` は Vercel Function のみ
|
|
104
|
+
- OAuth `state` で CSRF 対策、**最小権限(空スコープ)**
|
|
105
|
+
- 各ユーザーのデータはそのユーザーのトークンで **実行時に GitHub API から取得**(`/api/data`)。静的キャッシュは持たない
|
|
106
|
+
- User data(タグ/ボード/メモ)は各ブラウザの IndexedDB(端末ローカル)
|
|
107
|
+
- 既定は **public のみ**(空スコープ)。private は明示同意した人だけ(下記)
|
|
108
|
+
|
|
109
|
+
### private を含める(明示同意)
|
|
110
|
+
|
|
111
|
+
既定のサインインは空スコープなので、public しか見えない。private も見たい場合は
|
|
112
|
+
サインイン画面の「private も含めてサインイン」か、ヘッダーの「🔒 private を有効化」から
|
|
113
|
+
`/api/auth/login?private=1` に進み、GitHub の認可画面で `repo` スコープを許可する。
|
|
114
|
+
|
|
115
|
+
- 許可の意思は OAuth の `state` に載せて往復し、セッション(暗号化 cookie)に `privateOptIn` として残す
|
|
116
|
+
- `/api/data` が private を取るのは **`privateOptIn` かつ 実際に付与されたスコープに `repo` がある**ときだけ。
|
|
117
|
+
OAuth App のスコープはユーザーごとに累積する(一度 `repo` を許可すると、以後は空スコープを要求しても
|
|
118
|
+
`repo` 付きのトークンが返る)ため、「読めること」を同意の証拠にしない
|
|
119
|
+
- 許可すると private の repo 名・コミット文・issue タイトルがこのホストを経由する(表示されるのは本人のデータのみ)
|
|
120
|
+
- 取り消したいときはサインアウトする。サインアウトは認可自体を revoke するので、
|
|
121
|
+
次回は public だけのサインインを選び直せる
|
|
122
|
+
|
|
123
|
+
---
|
|
124
|
+
|
|
125
|
+
## デプロイ Runbook(この repo の本番: `github-reporadar.vercel.app`)
|
|
126
|
+
|
|
127
|
+
> この repo は **private** のため、実際の URL・手順をここに記載する(secret は記載しない)。
|
|
128
|
+
|
|
129
|
+
**現在の状態**(2026-08-31)
|
|
130
|
+
- 本番 URL: **https://github-reporadar.vercel.app**
|
|
131
|
+
- **Git連携は接続済み**。mainへのpushで本番へ自動デプロイされる(手動デプロイは不要)
|
|
132
|
+
- 環境変数(Production)設定済み: `VITE_HOSTED=1` / `APP_URL=https://github-reporadar.vercel.app`
|
|
133
|
+
- 未設定(あなたの操作待ち): `GITHUB_CLIENT_ID` / `GITHUB_CLIENT_SECRET` / `SESSION_SECRET`
|
|
134
|
+
- 未設定の間、`/api/auth/login`は503の「サーバー未設定」ページを返す。これは正しい状態
|
|
135
|
+
- **3つのうち1つでも欠けると503のまま**。`getConfig()`は4つ揃って初めて設定済みと見なす
|
|
136
|
+
(`APP_URL`を含む)。`SESSION_SECRET`はセッションcookieの暗号鍵で、手順2で自分で作る
|
|
137
|
+
|
|
138
|
+
> **注意**: 2026-08-31まで、本番の`/api/*`は全て500(`FUNCTION_INVOCATION_FAILED`)だった。
|
|
139
|
+
> 原因はenv未設定ではなく、ESMの相対importに拡張子が無かったこと。
|
|
140
|
+
> ローカル検証(tsx/vite)は拡張子なしを解決するため再現せず、Vercel上のNode ESMだけで落ちていた。
|
|
141
|
+
> 修正済み。`api/esmImports.test.ts`が同じ壊れ方を止める。
|
|
142
|
+
|
|
143
|
+
> **`GITHUB_CLIENT_ID` / `GITHUB_CLIENT_SECRET` はどこかに存在する値ではなく、下の手順1で
|
|
144
|
+
> OAuth App を作った瞬間に GitHub が発行する。** Client Secret は発行直後の1回しか表示されない
|
|
145
|
+
> (控え損ねたら、同じ画面で新しい secret を再発行して古い方を失効させる)。
|
|
146
|
+
|
|
147
|
+
**残りの手順**
|
|
148
|
+
|
|
149
|
+
1. **GitHub OAuth App を作成** → https://github.com/settings/applications/new
|
|
150
|
+
(一覧は https://github.com/settings/developers の "OAuth Apps")
|
|
151
|
+
- Application name: 任意(例`RepoRadar`)。GitHubは`GitHub`で始まる名前を拒否する
|
|
152
|
+
- Homepage URL: `https://github-reporadar.vercel.app`
|
|
153
|
+
- Authorization callback URL: `https://github-reporadar.vercel.app/api/auth/callback`
|
|
154
|
+
- Allow wildcard matching / Enable Device Flowはオフのまま
|
|
155
|
+
- **「Expire user access tokens」という項目は探さなくてよい**。これはGitHub Appのラベルで、
|
|
156
|
+
OAuth Appの設定画面には無い。OAuthアプリのアクセストークンは既定で無期限に発行される
|
|
157
|
+
- 作成後の画面に **Client ID** が表示される。**Client Secret** は
|
|
158
|
+
「Generate a new client secret」を押して発行し、その場でコピーする
|
|
159
|
+
|
|
160
|
+
2. **Vercelに3つの環境変数を追加**(Production)
|
|
161
|
+
→ https://vercel.com/asagiri/github-reporadar/settings/environment-variables
|
|
162
|
+
- `GITHUB_CLIENT_ID` = 上のClient ID
|
|
163
|
+
- `GITHUB_CLIENT_SECRET` = 上のClient Secret(**secretはここ(Vercel)にのみ入れる。gitやチャットに貼らない**)
|
|
164
|
+
- `SESSION_SECRET` = 自分で生成する乱数。セッションcookieをAES-GCMで封じる鍵で、
|
|
165
|
+
GitHubから貰う値ではない。`openssl rand -base64 32`の出力をそのまま貼る
|
|
166
|
+
(**この値を変えると全員が一斉にサインアウトする**。復旧手段は再サインインのみ)
|
|
167
|
+
|
|
168
|
+
3. **再デプロイ**(`VITE_HOSTED`と違い`GITHUB_CLIENT_*`は実行時変数だが、
|
|
169
|
+
env追加だけでは既存のデプロイに反映されないので再ビルドする)
|
|
170
|
+
- Git連携は接続済みなので、**mainへpushすれば自動デプロイされる**
|
|
171
|
+
- 手元から流すなら`vercel --prod --yes`(要`vercel login`)
|
|
172
|
+
- 最新デプロイがgit由来になったので、ダッシュボードのRedeployも使える
|
|
173
|
+
|
|
174
|
+
これで `https://github-reporadar.vercel.app` が「GitHub でサインイン」画面になり、ログイン後に各自の
|
|
175
|
+
public 活動が見える。設定前にアクセスすると「このサーバーは OAuth 未設定です」と表示される
|
|
176
|
+
(サインインを押して行き止まりにならないよう、未設定を検知して案内を出す)。
|
|
177
|
+
|
|
178
|
+
**マージ前ゲート(CIが止まっている間の代替)**
|
|
179
|
+
|
|
180
|
+
GitHub ActionsはFreeプランだとprivateリポジトリで月2000分の枠がある。使い切ると
|
|
181
|
+
ジョブが起動せず、PRのチェックは「テスト失敗」ではなく未実行のまま赤くなる。
|
|
182
|
+
その間は手元の`pnpm verify`(test → typecheck → build)が唯一の関門になる。
|
|
183
|
+
|
|
184
|
+
```
|
|
185
|
+
pnpm verify
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
`.githooks/pre-push`が同じものをpush前に走らせる。クローン直後は1度だけ紐付けが要る。
|
|
189
|
+
|
|
190
|
+
```
|
|
191
|
+
git config core.hooksPath .githooks
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
飛ばしたい時は`git push --no-verify`。実Chromeのe2e(`pnpm e2e`)は`public/data/`が
|
|
195
|
+
要るのでこのゲートには入れていない。
|
|
196
|
+
|
|
197
|
+
**ローカル ⇔ 本番の切替**
|
|
198
|
+
- ローカル(`pnpm dev`/`preview`): `VITE_HOSTED` 無し → 静的 `/data/*.json`(`pnpm sync` で生成)を読む
|
|
199
|
+
- 本番(Vercel): `VITE_HOSTED=1` → OAuth + `/api/data`(実行時 GitHub 取得)
|
|
200
|
+
|
|
201
|
+
## 開発
|
|
202
|
+
|
|
203
|
+
```bash
|
|
204
|
+
pnpm test # vitest
|
|
205
|
+
pnpm typecheck # tsc -b --noEmit
|
|
206
|
+
pnpm build # 型チェック + ビルド(ローカル版)
|
|
207
|
+
pnpm e2e # 本番ビルドを実 Chrome で開き、メモがリロード後も残るかを検証
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
`pnpm test` / `pnpm typecheck` / `pnpm build` は PR と main への push で CI(`.github/workflows/ci.yml`)が実行する。
|
|
211
|
+
`pnpm e2e` は `public/data/` のキャッシュ(生成に gh トークンが必要)を前提とするため CI では回さない。
|
|
212
|
+
UI を変える PR は、CI 緑だけでなく実ブラウザでの表示確認までをマージ条件にする。
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// npmのbin。実体はviteでまとめたdist-cli/cli.js
|
|
3
|
+
import { existsSync } from 'node:fs'
|
|
4
|
+
import { fileURLToPath } from 'node:url'
|
|
5
|
+
|
|
6
|
+
const cli = new URL('../dist-cli/cli.js', import.meta.url)
|
|
7
|
+
if (!existsSync(fileURLToPath(cli))) {
|
|
8
|
+
console.error('dist-cli/cli.jsがありません。リポジトリから動かす場合は`pnpm build:cli`を先に実行してください。')
|
|
9
|
+
process.exit(1)
|
|
10
|
+
}
|
|
11
|
+
await import(cli.href)
|