feat(migration): sync-design-system --source + --check for DS re-home [skip-docs]
This commit is contained in:
parent
f4c36fcda5
commit
653db4785e
2 changed files with 117 additions and 14 deletions
|
|
@ -28,9 +28,18 @@ const SOURCE_DIR = path.join(MARKETPLACE_ROOT, 'shared', 'playground-design-syst
|
|||
const GENERATED_HEADER = '/* Code generated by sync-design-system.mjs; DO NOT EDIT. */\n';
|
||||
|
||||
function parseArgs(argv) {
|
||||
const args = { plugin: null, force: false };
|
||||
for (const a of argv.slice(2)) {
|
||||
const args = { plugin: null, force: false, source: null, target: null, check: false };
|
||||
const rest = argv.slice(2);
|
||||
for (let i = 0; i < rest.length; i++) {
|
||||
const a = rest[i];
|
||||
if (a === '--force') args.force = true;
|
||||
else if (a === '--check') args.check = true;
|
||||
else if (a === '--source' || a === '--target') {
|
||||
const v = rest[++i];
|
||||
if (!v) throw new Error(`${a} requires a directory argument`);
|
||||
args[a === '--source' ? 'source' : 'target'] = v;
|
||||
} else if (a.startsWith('--source=')) args.source = a.slice('--source='.length);
|
||||
else if (a.startsWith('--target=')) args.target = a.slice('--target='.length);
|
||||
else if (a.startsWith('--')) {
|
||||
throw new Error(`Unknown flag: ${a}`);
|
||||
} else if (!args.plugin) {
|
||||
|
|
@ -40,11 +49,17 @@ function parseArgs(argv) {
|
|||
}
|
||||
}
|
||||
if (!args.plugin) {
|
||||
throw new Error('Missing plugin name. Usage: node scripts/sync-design-system.mjs <plugin-name> [--force]');
|
||||
throw new Error('Missing plugin name. Usage: node scripts/sync-design-system.mjs <plugin-name> [--source <dir>] [--target <dir>] [--check] [--force]');
|
||||
}
|
||||
return args;
|
||||
}
|
||||
|
||||
// The plugin (vendor target) root: an explicit --target wins, so the script still
|
||||
// works once plugins/<name> no longer exists in-repo (post-migration / extracted repo).
|
||||
function resolvePluginDir(args) {
|
||||
return args.target ? path.resolve(args.target) : path.join(MARKETPLACE_ROOT, 'plugins', args.plugin);
|
||||
}
|
||||
|
||||
async function sha256(filePath) {
|
||||
const buf = await fs.readFile(filePath);
|
||||
return createHash('sha256').update(buf).digest('hex');
|
||||
|
|
@ -99,7 +114,7 @@ async function injectGeneratedHeader(targetDir, files) {
|
|||
}
|
||||
}
|
||||
|
||||
async function buildManifest(targetDir, files, sourceCommit) {
|
||||
async function buildManifest(targetDir, files, sourceCommit, sourceLabel) {
|
||||
const fileHashes = {};
|
||||
for (const rel of files.sort()) {
|
||||
fileHashes[rel] = await sha256(path.join(targetDir, rel));
|
||||
|
|
@ -107,7 +122,7 @@ async function buildManifest(targetDir, files, sourceCommit) {
|
|||
return {
|
||||
generated_by: 'scripts/sync-design-system.mjs',
|
||||
do_not_edit: true,
|
||||
source: 'shared/playground-design-system/',
|
||||
source: sourceLabel,
|
||||
source_commit: sourceCommit,
|
||||
sync_date: new Date().toISOString(),
|
||||
file_count: files.length,
|
||||
|
|
@ -115,10 +130,10 @@ async function buildManifest(targetDir, files, sourceCommit) {
|
|||
};
|
||||
}
|
||||
|
||||
function getCurrentCommit() {
|
||||
function getCurrentCommit(cwd) {
|
||||
try {
|
||||
return execSync('git rev-parse HEAD', {
|
||||
cwd: MARKETPLACE_ROOT,
|
||||
cwd: cwd || MARKETPLACE_ROOT,
|
||||
encoding: 'utf8',
|
||||
}).trim();
|
||||
} catch {
|
||||
|
|
@ -126,9 +141,37 @@ function getCurrentCommit() {
|
|||
}
|
||||
}
|
||||
|
||||
// --check: re-hash a plugin's vendored tree against its committed MANIFEST.json and
|
||||
// exit non-zero on drift. No source needed — makes SC5 a single command in a clean clone (D3).
|
||||
async function runCheck(args) {
|
||||
const pluginDir = resolvePluginDir(args);
|
||||
const targetDir = path.join(pluginDir, 'playground', 'vendor', 'playground-design-system');
|
||||
const manifestPath = path.join(targetDir, 'MANIFEST.json');
|
||||
const manifest = await readJsonIfExists(manifestPath);
|
||||
if (!manifest) {
|
||||
console.error(`MANIFEST DRIFT: no MANIFEST.json at ${manifestPath}`);
|
||||
process.exit(2);
|
||||
}
|
||||
const drifted = await detectDrift(targetDir, manifest);
|
||||
if (drifted.length) {
|
||||
console.error(`MANIFEST DRIFT: ${drifted.length} vendored file(s) differ from MANIFEST.json:`);
|
||||
for (const f of drifted) console.error(` - ${f}`);
|
||||
process.exit(2);
|
||||
}
|
||||
console.log(`MANIFEST OK (${manifest.file_count} files, source_commit ${manifest.source_commit})`);
|
||||
}
|
||||
|
||||
async function main() {
|
||||
const args = parseArgs(process.argv);
|
||||
const pluginDir = path.join(MARKETPLACE_ROOT, 'plugins', args.plugin);
|
||||
|
||||
if (args.check) {
|
||||
await runCheck(args);
|
||||
return;
|
||||
}
|
||||
|
||||
const pluginDir = resolvePluginDir(args);
|
||||
const sourceDir = args.source ? path.resolve(args.source) : SOURCE_DIR;
|
||||
const sourceLabel = args.source ? sourceDir : 'shared/playground-design-system/';
|
||||
|
||||
try {
|
||||
const stat = await fs.stat(pluginDir);
|
||||
|
|
@ -138,9 +181,9 @@ async function main() {
|
|||
}
|
||||
|
||||
try {
|
||||
await fs.access(SOURCE_DIR);
|
||||
await fs.access(sourceDir);
|
||||
} catch {
|
||||
throw new Error(`Source directory missing: ${SOURCE_DIR}`);
|
||||
throw new Error(`Source directory missing: ${sourceDir}`);
|
||||
}
|
||||
|
||||
const targetDir = path.join(pluginDir, 'playground', 'vendor', 'playground-design-system');
|
||||
|
|
@ -160,17 +203,17 @@ async function main() {
|
|||
|
||||
await fs.mkdir(path.dirname(targetDir), { recursive: true });
|
||||
await fs.rm(targetDir, { recursive: true, force: true });
|
||||
await fs.cp(SOURCE_DIR, targetDir, { recursive: true, force: true });
|
||||
await fs.cp(sourceDir, targetDir, { recursive: true, force: true });
|
||||
|
||||
const files = await walk(targetDir);
|
||||
await injectGeneratedHeader(targetDir, files);
|
||||
|
||||
const sourceCommit = getCurrentCommit();
|
||||
const sourceCommit = getCurrentCommit(args.source ? sourceDir : MARKETPLACE_ROOT);
|
||||
const finalFiles = await walk(targetDir);
|
||||
const manifest = await buildManifest(targetDir, finalFiles, sourceCommit);
|
||||
const manifest = await buildManifest(targetDir, finalFiles, sourceCommit, sourceLabel);
|
||||
await fs.writeFile(manifestPath, JSON.stringify(manifest, null, 2) + '\n', 'utf8');
|
||||
|
||||
console.log(`Synced shared/playground-design-system/ → plugins/${args.plugin}/playground/vendor/playground-design-system/`);
|
||||
console.log(`Synced ${sourceLabel} → ${path.relative(MARKETPLACE_ROOT, targetDir) || targetDir}`);
|
||||
console.log(` Files: ${manifest.file_count + 1} (incl. MANIFEST.json)`);
|
||||
console.log(` Source commit: ${sourceCommit}`);
|
||||
console.log(` Sync date: ${manifest.sync_date}`);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue