@wipcomputer/wip-release 1.9.12 → 1.9.13
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/core.mjs +76 -41
- package/package.json +1 -1
package/core.mjs
CHANGED
|
@@ -273,19 +273,23 @@ function checkProductDocs(repoPath) {
|
|
|
273
273
|
const aiDir = join(repoPath, 'ai');
|
|
274
274
|
if (!existsSync(aiDir)) return { missing: [], ok: true, skipped: true };
|
|
275
275
|
|
|
276
|
-
// 1. Dev update: file
|
|
276
|
+
// 1. Dev update: must have a file modified since last release tag.
|
|
277
|
+
// Old check ("any file from last 3 days") let the same stale file pass
|
|
278
|
+
// across 11 releases in one session. Now uses the same git-based check
|
|
279
|
+
// as roadmap and readme-first: was the file actually changed since the tag?
|
|
277
280
|
const devUpdatesDir = join(aiDir, 'dev-updates');
|
|
278
281
|
if (existsSync(devUpdatesDir)) {
|
|
279
|
-
const now = new Date();
|
|
280
|
-
const recentDates = [];
|
|
281
|
-
for (let i = 0; i < 3; i++) {
|
|
282
|
-
const d = new Date(now);
|
|
283
|
-
d.setDate(d.getDate() - i);
|
|
284
|
-
recentDates.push(d.toISOString().split('T')[0]);
|
|
285
|
-
}
|
|
286
282
|
const files = readdirSync(devUpdatesDir).filter(f => f.endsWith('.md'));
|
|
287
|
-
|
|
288
|
-
|
|
283
|
+
if (files.length === 0) {
|
|
284
|
+
missing.push('ai/dev-updates/ (no dev update files)');
|
|
285
|
+
} else {
|
|
286
|
+
const anyModified = files.some(f =>
|
|
287
|
+
fileModifiedSinceLastTag(repoPath, `ai/dev-updates/${f}`)
|
|
288
|
+
);
|
|
289
|
+
if (!anyModified) {
|
|
290
|
+
missing.push('ai/dev-updates/ (no dev update modified since last release)');
|
|
291
|
+
}
|
|
292
|
+
}
|
|
289
293
|
}
|
|
290
294
|
|
|
291
295
|
// 2. Roadmap: modified since last tag
|
|
@@ -463,31 +467,23 @@ export function publishClawHub(repoPath, newVersion, notes) {
|
|
|
463
467
|
/**
|
|
464
468
|
* Publish SKILL.md to website as plain text.
|
|
465
469
|
*
|
|
466
|
-
*
|
|
467
|
-
*
|
|
470
|
+
* Auto-detects: if SKILL.md exists and WIP_WEBSITE_REPO is set,
|
|
471
|
+
* publishes automatically. No config file needed.
|
|
472
|
+
*
|
|
473
|
+
* Name resolution (first match wins):
|
|
474
|
+
* 1. .publish-skill.json { "name": "memory-crystal" }
|
|
475
|
+
* 2. SKILL.md frontmatter name: field
|
|
476
|
+
* 3. Directory name (basename of repoPath)
|
|
468
477
|
*
|
|
469
|
-
* Uses WIP_WEBSITE_REPO env var for website repo path.
|
|
470
478
|
* Copies SKILL.md to {website}/wip.computer/install/{name}.txt
|
|
471
479
|
* Then runs deploy.sh to push to VPS.
|
|
472
480
|
*
|
|
473
481
|
* Non-blocking: returns result, never throws.
|
|
474
482
|
*/
|
|
475
483
|
export function publishSkillToWebsite(repoPath) {
|
|
476
|
-
const configPath = join(repoPath, '.publish-skill.json');
|
|
477
|
-
if (!existsSync(configPath)) return { skipped: true, reason: 'no .publish-skill.json' };
|
|
478
|
-
|
|
479
484
|
const websiteRepo = process.env.WIP_WEBSITE_REPO;
|
|
480
485
|
if (!websiteRepo) return { skipped: true, reason: 'WIP_WEBSITE_REPO not set' };
|
|
481
486
|
|
|
482
|
-
let config;
|
|
483
|
-
try {
|
|
484
|
-
config = JSON.parse(readFileSync(configPath, 'utf8'));
|
|
485
|
-
} catch (e) {
|
|
486
|
-
return { ok: false, error: `bad .publish-skill.json: ${e.message}` };
|
|
487
|
-
}
|
|
488
|
-
|
|
489
|
-
if (!config.name) return { ok: false, error: '.publish-skill.json missing "name"' };
|
|
490
|
-
|
|
491
487
|
// Find SKILL.md: check root, then skills/*/SKILL.md
|
|
492
488
|
let skillFile = join(repoPath, 'SKILL.md');
|
|
493
489
|
if (!existsSync(skillFile)) {
|
|
@@ -499,7 +495,37 @@ export function publishSkillToWebsite(repoPath) {
|
|
|
499
495
|
}
|
|
500
496
|
}
|
|
501
497
|
}
|
|
502
|
-
if (!existsSync(skillFile)) return {
|
|
498
|
+
if (!existsSync(skillFile)) return { skipped: true, reason: 'no SKILL.md found' };
|
|
499
|
+
|
|
500
|
+
// Resolve target name: config > package.json > directory name
|
|
501
|
+
// SKILL.md frontmatter name is skipped because it's a short slug
|
|
502
|
+
// (e.g., "memory") not the full install name (e.g., "memory-crystal").
|
|
503
|
+
let targetName;
|
|
504
|
+
|
|
505
|
+
// 1. Explicit config (optional, overrides auto-detect)
|
|
506
|
+
const configPath = join(repoPath, '.publish-skill.json');
|
|
507
|
+
if (existsSync(configPath)) {
|
|
508
|
+
try {
|
|
509
|
+
const config = JSON.parse(readFileSync(configPath, 'utf8'));
|
|
510
|
+
if (config.name) targetName = config.name;
|
|
511
|
+
} catch {}
|
|
512
|
+
}
|
|
513
|
+
|
|
514
|
+
// 2. package.json name (strip @scope/ prefix, most reliable)
|
|
515
|
+
if (!targetName) {
|
|
516
|
+
const pkgPath = join(repoPath, 'package.json');
|
|
517
|
+
if (existsSync(pkgPath)) {
|
|
518
|
+
try {
|
|
519
|
+
const pkg = JSON.parse(readFileSync(pkgPath, 'utf8'));
|
|
520
|
+
if (pkg.name) targetName = pkg.name.replace(/^@[^/]+\//, '');
|
|
521
|
+
} catch {}
|
|
522
|
+
}
|
|
523
|
+
}
|
|
524
|
+
|
|
525
|
+
// 3. Directory name fallback (strip -private suffix)
|
|
526
|
+
if (!targetName) {
|
|
527
|
+
targetName = basename(repoPath).replace(/-private$/, '').toLowerCase();
|
|
528
|
+
}
|
|
503
529
|
|
|
504
530
|
// Copy to website install dir
|
|
505
531
|
const installDir = join(websiteRepo, 'wip.computer', 'install');
|
|
@@ -507,7 +533,7 @@ export function publishSkillToWebsite(repoPath) {
|
|
|
507
533
|
try { mkdirSync(installDir, { recursive: true }); } catch {}
|
|
508
534
|
}
|
|
509
535
|
|
|
510
|
-
const targetFile = join(installDir, `${
|
|
536
|
+
const targetFile = join(installDir, `${targetName}.txt`);
|
|
511
537
|
try {
|
|
512
538
|
const content = readFileSync(skillFile, 'utf8');
|
|
513
539
|
writeFileSync(targetFile, content);
|
|
@@ -521,13 +547,13 @@ export function publishSkillToWebsite(repoPath) {
|
|
|
521
547
|
try {
|
|
522
548
|
execSync(`bash deploy.sh`, { cwd: websiteRepo, stdio: 'pipe', timeout: 30000 });
|
|
523
549
|
} catch (e) {
|
|
524
|
-
return { ok: true, deployed: false, target:
|
|
550
|
+
return { ok: true, deployed: false, target: targetName, error: `deploy failed: ${e.message}` };
|
|
525
551
|
}
|
|
526
552
|
} else {
|
|
527
|
-
return { ok: true, deployed: false, target:
|
|
553
|
+
return { ok: true, deployed: false, target: targetName, error: 'no deploy.sh found' };
|
|
528
554
|
}
|
|
529
555
|
|
|
530
|
-
return { ok: true, deployed: true, target:
|
|
556
|
+
return { ok: true, deployed: true, target: targetName };
|
|
531
557
|
}
|
|
532
558
|
|
|
533
559
|
// ── Helpers ──────────────────────────────────────────────────────────
|
|
@@ -817,18 +843,27 @@ export async function release({ repoPath, level, notes, notesSource, dryRun, noP
|
|
|
817
843
|
console.log(` [dry run] Would publish to GitHub Packages`);
|
|
818
844
|
console.log(` [dry run] Would create GitHub release v${newVersion}`);
|
|
819
845
|
if (hasSkill) console.log(` [dry run] Would publish to ClawHub`);
|
|
820
|
-
// Skill-to-website dry run
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
console.log(` [dry run] Would publish to website but WIP_WEBSITE_REPO not set`);
|
|
846
|
+
// Skill-to-website dry run (auto-detects SKILL.md, no config needed)
|
|
847
|
+
if (hasSkill) {
|
|
848
|
+
const envSet = !!process.env.WIP_WEBSITE_REPO;
|
|
849
|
+
if (envSet) {
|
|
850
|
+
// Resolve name same way as publishSkillToWebsite
|
|
851
|
+
let dryName;
|
|
852
|
+
const publishConfig = join(repoPath, '.publish-skill.json');
|
|
853
|
+
if (existsSync(publishConfig)) {
|
|
854
|
+
try { dryName = JSON.parse(readFileSync(publishConfig, 'utf8')).name; } catch {}
|
|
830
855
|
}
|
|
831
|
-
|
|
856
|
+
if (!dryName) {
|
|
857
|
+
const pkgPath = join(repoPath, 'package.json');
|
|
858
|
+
if (existsSync(pkgPath)) {
|
|
859
|
+
try { dryName = JSON.parse(readFileSync(pkgPath, 'utf8')).name?.replace(/^@[^/]+\//, ''); } catch {}
|
|
860
|
+
}
|
|
861
|
+
}
|
|
862
|
+
if (!dryName) dryName = basename(repoPath).replace(/-private$/, '').toLowerCase();
|
|
863
|
+
console.log(` [dry run] Would publish SKILL.md to website: install/${dryName}.txt`);
|
|
864
|
+
} else {
|
|
865
|
+
console.log(` [dry run] Would publish SKILL.md to website but WIP_WEBSITE_REPO not set`);
|
|
866
|
+
}
|
|
832
867
|
}
|
|
833
868
|
}
|
|
834
869
|
console.log('');
|
package/package.json
CHANGED