@takagaki/cortex-decisions-viewer 0.4.65 → 0.4.66

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/dist/build.js CHANGED
@@ -168,6 +168,22 @@ async function readFleetSources(repoRoot) {
168
168
  }))
169
169
  .filter((c) => c.id !== "")
170
170
  : undefined;
171
+ // 組織ごとの GitHub 接続状況。**「N件が読めていません」だけでは次の一歩が決まらない**
172
+ // ——トークンは組織ごとにしか効かないので、どの組織かが要る
173
+ const githubOwners = Array.isArray(obj.githubOwners)
174
+ ? obj.githubOwners
175
+ .filter((o) => o != null && typeof o === "object")
176
+ .map((o) => ({
177
+ owner: String(o.owner ?? ""),
178
+ repos: typeof o.repos === "number" ? o.repos : 0,
179
+ unreadable: typeof o.unreadable === "number" ? o.unreadable : 0,
180
+ // **写し忘れるとライブ経路とだけ食い違う。** op=state は素通しなので、
181
+ // 設定を変えた直後だけ数字が出て、静的ビルドのページでは undefined になる
182
+ unchecked: typeof o.unchecked === "number" ? o.unchecked : 0,
183
+ source: String(o.source ?? ""),
184
+ }))
185
+ .filter((o) => o.owner !== "")
186
+ : undefined;
171
187
  const internalSources = Array.isArray(obj.internalSources)
172
188
  ? obj.internalSources
173
189
  .filter((s) => s != null && typeof s === "object")
@@ -248,7 +264,7 @@ async function readFleetSources(repoRoot) {
248
264
  const secretSources = obj.secretSources && typeof obj.secretSources === "object"
249
265
  ? obj.secretSources
250
266
  : undefined;
251
- return { externalSources, internalSources, pipelines, tools, fleetGeneratedAt, secretSources, checks };
267
+ return { externalSources, internalSources, pipelines, tools, fleetGeneratedAt, secretSources, checks, githubOwners };
252
268
  }
253
269
  /** パスがディレクトリとして存在するか */
254
270
  async function isDirectory(dirAbs) {
@@ -1125,6 +1141,7 @@ async function build(opts) {
1125
1141
  pipelines: fleet.pipelines,
1126
1142
  tools: fleet.tools,
1127
1143
  checks: fleet.checks,
1144
+ githubOwners: fleet.githubOwners,
1128
1145
  };
1129
1146
  // サムネイル(デザイン画面等)をサイトに同梱し、ノードのパスをサイト内相対に書き換える
1130
1147
  await node_fs_1.promises.mkdir(outAbs, { recursive: true });
package/dist/render.js CHANGED
@@ -1018,6 +1018,13 @@ a.ds-name:hover { text-decoration: underline; }
1018
1018
  .ds-gate-warn { color: #b45309; }
1019
1019
  .ds-gate-muted { color: #6b7280; }
1020
1020
  .ds-pipes { display: flex; flex-direction: column; gap: 8px; }
1021
+ /* 組織ごとの接続状況。トークンは組織ごとにしか効かないので、ここが判断の単位になる */
1022
+ .ds-owners { display: flex; flex-direction: column; gap: 6px; margin-bottom: 14px; }
1023
+ .ds-owner { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; padding: 8px 12px;
1024
+ border: 1px solid var(--border); border-radius: 8px; background: var(--bg); }
1025
+ .ds-owner-name { font-weight: 700; font-size: 13px; }
1026
+ .ds-owner-state { font-size: 12.5px; }
1027
+ .ds-owner-install { font-size: 12.5px; margin-left: auto; white-space: nowrap; }
1021
1028
  /* 実行状況の行に直し方を添える。同じ run の未達を別の節にも出すと画面に2回並ぶ */
1022
1029
  .ds-pipe-wrap { display: flex; flex-direction: column; gap: 3px; }
1023
1030
  .ds-pipe-todo { font-size: 12.5px; color: var(--muted); line-height: 1.7; padding-left: 4px; }
@@ -1998,6 +2005,58 @@ ${capabilityState.toString()}
1998
2005
  // 畳まれる(既定は閉)。中に入れると**新規案件(0件)=一番追加したい場面**で消える。
1999
2006
  var adders = renderExternalAdders();
2000
2007
  pushCap("チャット", adders.querySelector('[data-adder="slack"]'));
2008
+ // **組織ごとの接続状況を、開発の一番上に置く。** トークンは組織ごとにしか
2009
+ // 効かない(Fine-grained PAT も GitHub App のインストールトークンも1組織分)ので、
2010
+ // 「N件が読めていません」だけでは何をすればよいか決まらない。
2011
+ // どの組織が繋がっていないかと、そこへの導線を出す
2012
+ var owners = fleetVal("githubOwners") || [];
2013
+ if (owners.length) {
2014
+ var obox = el("div", { class: "ds-owners" });
2015
+ obox.appendChild(el("div", { class: "ds-sub", text: "組織ごとの接続状況" }));
2016
+ owners.forEach(function (o) {
2017
+ var ok = o.source === "app" || o.source === "token";
2018
+ // **確かめられなかった夜は、そう言う。** gh の不在・タイムアウト・ネットワーク断で
2019
+ // 起きる。「接続OK」と出すと、同じ画面の集計行が「⚠️ 2件に問題」と言っている
2020
+ // 横で食い違う。「未接続」と出すと、繋がっている組織に設定を促す偽の警告になる。
2021
+ // どちらも嘘なので、確かめていないことをそのまま出す
2022
+ var unsure = o.source === "unknown";
2023
+ var row = el("div", { class: "ds-owner" }, [
2024
+ el("span", { class: "ds-owner-name", text: o.owner }),
2025
+ el("span", { class: "ds-owner-state ds-gate-" + (ok ? "ok" : "warn"),
2026
+ // **読める件数を出す。** 総数だけ出すと、同じ画面の
2027
+ // 「⚠️ 15件が読めていません」と食い違う(#101 で3度直した形)
2028
+ // **確かめられなかった件数を出す。** 未接続側は「18リポジトリ中 15件が
2029
+ // 読めていません」と出しているのに、こちらだけ総数だと同じ節の中で
2030
+ // 表現が揃わない。4リポ中1つだけ揺れた夜に「4リポジトリを確かめられて
2031
+ // いません」と読めるのも実態と違う
2032
+ text: unsure
2033
+ ? "⚠️ 確認できませんでした " + o.repos + "リポジトリ中 " +
2034
+ (o.unchecked || o.repos) + "件の接続を確かめられていません"
2035
+ : ok
2036
+ ? "● 接続OK " + o.repos + "リポジトリ" + (o.source === "app" ? "(GitHub App)" : "")
2037
+ : "⚠️ 未接続 " + o.repos + "リポジトリ中 " + o.unreadable + "件が読めていません" }),
2038
+ ]);
2039
+ // **未接続のときだけ導線を出す。** 繋がっている組織に「インストール」を
2040
+ // 出すと、押す必要が無いものを押させることになる。
2041
+ // 確かめられなかっただけの組織にも出さない——すでに入っているかもしれないので
2042
+ if (!ok && !unsure) {
2043
+ row.appendChild(el("a", {
2044
+ class: "ds-owner-install",
2045
+ // **文書化されている形だけを使う。** target_id に組織のログイン名を渡す形は
2046
+ // GitHub の文書に無く(GitHub自身のUIは数値のアカウントIDを入れる)、
2047
+ // 未ログインだとログイン画面へ転送されて 200 が返るので、
2048
+ // 効いているかを外から確かめられない。**確かめられないものを顧客に押させない。**
2049
+ // どの組織かはこの行に出ているので、選ばせる形で足りる
2050
+ href: "https://github.com/apps/classmethod-cortex-app/installations/new",
2051
+ target: "_blank", rel: "noopener",
2052
+ text: "この組織にインストール →",
2053
+ }));
2054
+ }
2055
+ obox.appendChild(row);
2056
+ });
2057
+ pushCap("開発", obox);
2058
+ }
2059
+
2001
2060
  pushCap("開発", adders.querySelector('[data-adder="github"]'));
2002
2061
 
2003
2062
  // 連携の鍵は、その能力のところへ置く(画面下まで往復させない)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@takagaki/cortex-decisions-viewer",
3
- "version": "0.4.65",
3
+ "version": "0.4.66",
4
4
  "description": "Cortexの意思決定記録(Decisions/*.md)を静的サイトにビルドして閲覧する。各レコードに「Edit on GitHub」リンクを付与する。",
5
5
  "license": "UNLICENSED",
6
6
  "private": false,