Skip to content

Commit d111086

Browse files
committed
feat(scripts): auto-commit after each vendor sync
Each vendor submodule update now creates an atomic git commit with the vendor name and SHA, enabling proper tracking of upstream changes. - Add hasGitChanges() helper using git status --porcelain - Add commitChanges() helper to stage and commit given paths - syncSubmodules() now commits per vendor: "chore(sync): sync {name} to {sha}" - Move turborepo command sync inside the turborepo vendor iteration - Type 3 manual skills (antfu) also committed if changed - Skip commit when nothing changed, report summary at the end
1 parent c14a409 commit d111086

1 file changed

Lines changed: 68 additions & 26 deletions

File tree

scripts/cli.ts

Lines changed: 68 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -140,22 +140,27 @@ async function initSubmodules() {
140140
console.log("\nDone.")
141141
}
142142

143+
// ---------------------------------------------------------------------------
144+
// sync helpers
145+
// ---------------------------------------------------------------------------
146+
function hasGitChanges(paths: string[]): boolean {
147+
const status = execSafe(`git status --porcelain -- ${paths.join(" ")}`)
148+
return status !== null && status.trim() !== ""
149+
}
150+
151+
function commitChanges(paths: string[], message: string) {
152+
exec(`git add -- ${paths.join(" ")}`)
153+
exec(`git commit -m ${JSON.stringify(message)}`)
154+
}
155+
143156
// ---------------------------------------------------------------------------
144157
// sync
145158
// ---------------------------------------------------------------------------
146159
async function syncSubmodules() {
147-
// 1. Update each vendor submodule
148-
process.stdout.write("Updating vendor submodules... ")
149-
for (const name of Object.keys(vendors)) {
150-
const submodulePath = `vendor/${name}`
151-
if (isSubmoduleRegistered(submodulePath)) {
152-
execSafe(`git submodule update --remote --merge ${submodulePath}`)
153-
}
154-
}
155-
console.log("done\n")
160+
const committed: string[] = []
156161

157-
// 2. Sync Type 2 vendor skills → plugins/{plugin}/skills/{skill}/
158-
console.log("Syncing vendor skills to plugins...")
162+
// 1. Sync Type 2 vendor skills → plugins/{plugin}/skills/{skill}/ + commit per vendor
163+
console.log("Syncing vendor skills to plugins...\n")
159164
for (const [name, config] of Object.entries(vendors)) {
160165
const submodulePath = `vendor/${name}`
161166
const vendorPath = join(ROOT, submodulePath)
@@ -165,12 +170,20 @@ async function syncSubmodules() {
165170
continue
166171
}
167172

173+
// Update submodule to latest
174+
process.stdout.write(`[${name}] updating submodule... `)
175+
execSafe(`git submodule update --remote --merge ${submodulePath}`)
176+
const sha = getGitSha(vendorPath)
177+
console.log(`${sha?.slice(0, 7) ?? "?"}`)
178+
168179
const vendorSkillsDir = join(vendorPath, "skills")
169180
if (!existsSync(vendorSkillsDir)) {
170181
console.warn(` ! no skills/ in vendor/${name}`)
171182
continue
172183
}
173184

185+
const changedPaths: string[] = [submodulePath]
186+
174187
for (const [srcSkill, outSkill] of Object.entries(config.skills)) {
175188
const src = join(vendorSkillsDir, srcSkill)
176189
const plugin = SKILL_TO_PLUGIN[outSkill]
@@ -185,8 +198,9 @@ async function syncSubmodules() {
185198

186199
ensurePlugin(plugin)
187200
const dest = join(PLUGINS_DIR, plugin, "skills", outSkill)
201+
const destRelative = `plugins/${plugin}/skills/${outSkill}`
188202

189-
process.stdout.write(` ${srcSkill}plugins/${plugin}/skills/${outSkill} ... `)
203+
process.stdout.write(` ${srcSkill}${destRelative} ... `)
190204
rmSync(dest, { recursive: true, force: true })
191205
mkdirSync(dest, { recursive: true })
192206
cpSync(src, dest, { recursive: true })
@@ -202,16 +216,41 @@ async function syncSubmodules() {
202216
}
203217

204218
// Write SYNC.md
205-
const sha = getGitSha(vendorPath)
206219
const date = new Date().toISOString().split("T")[0]
207220
writeFileSync(join(dest, "SYNC.md"), `# Sync Info\n\n- **Source:** \`vendor/${name}/skills/${srcSkill}\`\n- **Git SHA:** \`${sha}\`\n- **Synced:** ${date}\n`)
208221

222+
changedPaths.push(destRelative)
209223
console.log("done")
210224
}
225+
226+
// turborepo: also sync command file
227+
if (name === "turborepo") {
228+
const turborepoCommandSrc = join(PLUGINS_DIR, "turborepo/skills/turborepo/command/turborepo.md")
229+
if (existsSync(turborepoCommandSrc)) {
230+
const commandsDir = join(PLUGINS_DIR, "turborepo/commands")
231+
mkdirSync(commandsDir, { recursive: true })
232+
const dest = join(commandsDir, "turborepo.md")
233+
rmSync(dest, { force: true })
234+
cpSync(turborepoCommandSrc, dest)
235+
changedPaths.push("plugins/turborepo/commands/turborepo.md")
236+
console.log(" turborepo command synced")
237+
}
238+
}
239+
240+
// Commit this vendor's changes
241+
if (hasGitChanges(changedPaths)) {
242+
const shortSha = sha?.slice(0, 7) ?? "unknown"
243+
commitChanges(changedPaths, `chore(sync): sync ${name} to ${shortSha}`)
244+
committed.push(name)
245+
console.log(` → committed: chore(sync): sync ${name} to ${shortSha}\n`)
246+
} else {
247+
console.log(` → no changes\n`)
248+
}
211249
}
212250

213-
// 3. Copy Type 3 manual skills from vendor/antfu-skills/skills/ → plugins/{plugin}/skills/
214-
console.log("\nCopying manual skills to plugins...")
251+
// 2. Copy Type 3 manual skills from vendor/antfu-skills/skills/ → plugins/{plugin}/skills/
252+
console.log("Syncing manual skills to plugins...")
253+
const manualPaths: string[] = []
215254
for (const skill of ["antfu"]) {
216255
const plugin = SKILL_TO_PLUGIN[skill]
217256
if (!plugin) continue
@@ -228,22 +267,25 @@ async function syncSubmodules() {
228267
process.stdout.write(` ${skill} → plugins/${plugin}/skills/${skill} ... `)
229268
rmSync(dest, { recursive: true, force: true })
230269
cpSync(src, dest, { recursive: true })
270+
manualPaths.push(`plugins/${plugin}/skills/${skill}`)
231271
console.log("done")
232272
}
233273

234-
// 4. turborepo: copy command file
235-
const turborepoCommandSrc = join(PLUGINS_DIR, "turborepo/skills/turborepo/command/turborepo.md")
236-
if (existsSync(turborepoCommandSrc)) {
237-
const commandsDir = join(PLUGINS_DIR, "turborepo/commands")
238-
mkdirSync(commandsDir, { recursive: true })
239-
const dest = join(commandsDir, "turborepo.md")
240-
rmSync(dest, { force: true })
241-
cpSync(turborepoCommandSrc, dest)
242-
console.log("\n turborepo command synced")
274+
if (manualPaths.length > 0 && hasGitChanges(manualPaths)) {
275+
const sha = getGitSha(join(ROOT, "vendor/antfu-skills"))
276+
const shortSha = sha?.slice(0, 7) ?? "unknown"
277+
commitChanges(manualPaths, `chore(sync): sync antfu manual skills to ${shortSha}`)
278+
committed.push("antfu-skills")
279+
console.log(` → committed: chore(sync): sync antfu manual skills to ${shortSha}`)
280+
} else {
281+
console.log(" → no changes")
243282
}
244283

245-
const pluginCount = new Set(Object.values(SKILL_TO_PLUGIN)).size
246-
console.log(`\nDone. Synced skills for ${pluginCount} plugins.`)
284+
if (committed.length === 0) {
285+
console.log("\nAll skills are up to date. Nothing to commit.")
286+
} else {
287+
console.log(`\nDone. ${committed.length} commit(s): ${committed.join(", ")}`)
288+
}
247289
}
248290

249291
// ---------------------------------------------------------------------------

0 commit comments

Comments
 (0)