@cocorograph/hub-agent 0.6.68 → 0.6.70

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.
Files changed (2) hide show
  1. package/package.json +1 -1
  2. package/src/claude-md.mjs +59 -10
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cocorograph/hub-agent",
3
- "version": "0.6.68",
3
+ "version": "0.6.70",
4
4
  "description": "Hub Hosted Cockpit のローカル常駐 agent。Hub と outbound WSS で接続し、ローカルの tmux/pty を中継する。",
5
5
  "type": "module",
6
6
  "license": "UNLICENSED",
package/src/claude-md.mjs CHANGED
@@ -82,7 +82,19 @@ async function fetchRepositories({ hubUrl, accessToken, dirName, fetchImpl }) {
82
82
  *
83
83
  * リポジトリが 1 件もない場合は空文字列を返し、CLAUDE.md には何も追記しない。
84
84
  */
85
- function renderRepositorySection(repositories) {
85
+ /**
86
+ * repo_url が GitHub の `owner/repo` slug 形式かを判定する。
87
+ *
88
+ * `://` や `@` を含むフル URL(GitLab の `git@gitlab.com:...` や
89
+ * `https://gitlab.com/...` 等)は false を返す。これらは `gh` ではなく
90
+ * 素の `git clone` でチェックアウトする。
91
+ */
92
+ function isGitHubSlug(repoUrl) {
93
+ if (/:\/\/|@/.test(repoUrl)) return false
94
+ return /^[A-Za-z0-9_.-]+\/[A-Za-z0-9_.-]+$/.test(repoUrl)
95
+ }
96
+
97
+ function renderRepositorySection(repositories, dirName = "") {
86
98
  if (!Array.isArray(repositories) || repositories.length === 0) return ""
87
99
 
88
100
  const lines = ["## Cockpit クローンレス開発フロー", ""]
@@ -113,16 +125,28 @@ function renderRepositorySection(repositories) {
113
125
  if (productionName) lines.push(`- **本番**: ${productionName}`)
114
126
  lines.push("")
115
127
 
128
+ const githubSlug = isGitHubSlug(repoUrl)
116
129
  lines.push("**作業手順(クローンレス)**:")
117
130
  lines.push("")
118
131
  lines.push("```bash")
119
132
  lines.push("TMPDIR=$(mktemp -d)")
120
- lines.push(`gh repo clone ${repoUrl} "$TMPDIR" -- --depth 1 --filter=blob:none --no-checkout`)
121
- lines.push(`cd "$TMPDIR" && git fetch origin ${branch} && git checkout -b feat/<your-change> origin/${branch}`)
122
- lines.push("# ファイル編集 動作確認")
123
- lines.push('git commit -am "<message>"')
124
- lines.push("git push -u origin HEAD")
125
- lines.push("gh pr create --base " + branch + " --fill")
133
+ if (githubSlug) {
134
+ // GitHub: gh CLI clone・PR 作成
135
+ lines.push(`gh repo clone ${repoUrl} "$TMPDIR" -- --depth 1 --filter=blob:none --no-checkout`)
136
+ lines.push(`cd "$TMPDIR" && git fetch origin ${branch} && git checkout -b feat/<your-change> origin/${branch}`)
137
+ lines.push("# ファイル編集 動作確認")
138
+ lines.push('git commit -am "<message>"')
139
+ lines.push("git push -u origin HEAD")
140
+ lines.push(`gh pr create --base ${branch} --fill`)
141
+ } else {
142
+ // GitLab 等: 素の git clone。MR は push 後に Web/glab で作成
143
+ lines.push(`git clone --depth 1 --filter=blob:none --no-checkout ${repoUrl} "$TMPDIR"`)
144
+ lines.push(`cd "$TMPDIR" && git fetch origin ${branch} && git checkout -b feat/<your-change> origin/${branch}`)
145
+ lines.push("# ファイル編集 → 動作確認")
146
+ lines.push('git commit -am "<message>"')
147
+ lines.push("git push -u origin HEAD")
148
+ lines.push("# MR は GitLab の Web UI(push 時に表示される URL)か `glab mr create` で作成")
149
+ }
126
150
  lines.push("# 作業終了後")
127
151
  lines.push('cd / && rm -rf "$TMPDIR"')
128
152
  lines.push("```")
@@ -136,11 +160,36 @@ function renderRepositorySection(repositories) {
136
160
  lines.push("```")
137
161
  lines.push("")
138
162
  }
163
+
164
+ // デプロイ接続情報の安全な取得手順(秘匿値を会話に出さない)。
165
+ if (stagingName || productionName) {
166
+ const envExample = productionName ? "production" : "staging"
167
+ lines.push("**デプロイ接続情報の取得(秘匿値を会話に出さない)**:")
168
+ lines.push("")
169
+ lines.push("```bash")
170
+ lines.push(
171
+ "# 秘密鍵を ~/.ssh/hub_deploy/ に書き出し、ssh コマンドだけ受け取る",
172
+ )
173
+ lines.push(
174
+ `python3 ~/.claude/scripts/hub_helper.py deploy_creds ${dirName || "<dir_name>"} --env ${envExample}`,
175
+ )
176
+ lines.push("```")
177
+ lines.push("")
178
+ lines.push(
179
+ "返り値の `ssh_command` をそのまま使って接続します。`key_file` は",
180
+ "chmod 600 で書き出されます。パスワード認証のサーバーは `password_set: true`",
181
+ "だけ返るので、その場合は Hub の「サーバー情報」タブから人手で取得します。",
182
+ "",
183
+ )
184
+ }
139
185
  }
140
186
 
187
+ lines.push("### デプロイ前の必須ガード", "")
141
188
  lines.push(
142
- "> Git 認証はローカルの `gh` CLI / SSH 鍵を使用します。",
143
- "> サーバー接続情報(パスワード・秘密鍵)は Hub の「サーバー情報」タブから取得してください。",
189
+ "- **本番反映の前に必ず現状バックアップを取る**(DB ダンプ / 対象ディレクトリの退避)。",
190
+ "- ステージングで動作確認してから本番へ。",
191
+ "- 破壊的操作(`reset --hard` / `rm -rf` / DB 操作)の前に対象を確認する。",
192
+ "- Git 認証はローカルの `gh` CLI(GitHub)/ SSH 鍵(GitLab 等)を使用します。",
144
193
  "",
145
194
  )
146
195
  return lines.join("\n")
@@ -280,7 +329,7 @@ export async function ensureClaudeMd({
280
329
  ])
281
330
  : [null, []]
282
331
 
283
- const repositorySection = renderRepositorySection(repositories)
332
+ const repositorySection = renderRepositorySection(repositories, dirName)
284
333
  const body = director
285
334
  ? renderWithDirector(dirName, director, repositorySection)
286
335
  : renderPlaceholder(dirName, repositorySection)