All files / packages/design-system/scripts/scs rehearse.js

51.06% Statements 24/47
52.77% Branches 19/36
66.66% Functions 6/9
50% Lines 21/42

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106                                                1x 1x 1x 1x                           12x       9x 7x     9x   16x 15x 15x     9x 6x 6x 6x       4x 4x 4x 2x   4x                 1x                                                        
#!/usr/bin/env node
/**
 * release:scs:rehearse orchestrator
 *
 * End-to-end dry-run: runs `release:scs`, then the appropriate compare report:
 *   - patch-pairs (newest-vs-previous within slds/) when a patch context is detected
 *   - baseline-vs-source (default) otherwise
 *
 * Patch context = either:
 *   - The current monorepo git branch ends in "-patch" (e.g. develop-264-patch), OR
 *   - The SLDS1 version is a patch increment of the highest-existing version in
 *     packages/slds-scs/slds/ for the slds.css family (same major.minor, higher patch).
 *
 * Both reports are run — they're cheap and complementary. Patch-pairs is run
 * first (more useful for patch reviewers); baseline-vs-source runs second.
 */
import { execSync, spawnSync } from 'node:child_process';
import { fileURLToPath } from 'node:url';
import path from 'node:path';
import fs from 'node:fs';
 
import { loadConfig } from './config-loader.js';
import { parseVersionedFile, compareSemver } from '../validation/compare-output-patch-pairs.js';
 
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
const packageRoot = path.resolve(__dirname, '../..');
const monorepoRoot = path.resolve(packageRoot, '../..');
 
function getCurrentBranch() {
  try {
    return execSync('git rev-parse --abbrev-ref HEAD', {
      cwd: monorepoRoot,
      encoding: 'utf8',
    }).trim();
  } catch {
    return null;
  }
}
 
export function isPatchBranch(name) {
  return typeof name === 'string' && /-patch$/.test(name);
}
 
export function isPatchVersionBump(sldsVersion, slds1FilenamesOrDir) {
  if (!sldsVersion) return false;
  const filenames = Array.isArray(slds1FilenamesOrDir)
    ? slds1FilenamesOrDir
    : (fs.existsSync(slds1FilenamesOrDir) ? fs.readdirSync(slds1FilenamesOrDir) : []);
  const newest = filenames
    .map(parseVersionedFile)
    .filter((entry) => entry && entry.family === 'slds' && entry.ext === 'css')
    .map((entry) => entry.version)
    .filter((v) => v !== sldsVersion)
    .sort(compareSemver)
    .pop();
  if (!newest) return false;
  const [newMajor, newMinor] = sldsVersion.split('.').map(Number);
  const [oldMajor, oldMinor] = newest.split('.').map(Number);
  return newMajor === oldMajor && newMinor === oldMinor;
}
 
export function detectPatchContext({ branch, config, slds1Filenames } = {}) {
  const reasons = [];
  if (isPatchBranch(branch)) reasons.push(`monorepo branch ${branch} matches *-patch`);
  if (isPatchVersionBump(config?.sldsVersion, slds1Filenames || [])) {
    reasons.push(`sldsVersion ${config.sldsVersion} is a patch bump`);
  }
  return { isPatch: reasons.length > 0, reasons };
}
 
function run(cmd, args) {
  const result = spawnSync(cmd, args, { stdio: 'inherit', cwd: packageRoot });
  return result.status === 0;
}
 
// Skip the orchestration when imported by tests
Iif (import.meta.url === `file://${process.argv[1]}`) {
  const config = loadConfig(packageRoot);
  const slds1Dir = path.join(monorepoRoot, 'packages/slds-scs/slds');
  const slds1Filenames = fs.existsSync(slds1Dir) ? fs.readdirSync(slds1Dir) : [];
  const ctx = detectPatchContext({
    branch: getCurrentBranch(),
    config,
    slds1Filenames,
  });
 
  console.log(ctx.isPatch ? '\nšŸ“¦ Patch context detected:' : '\nšŸ“¦ Standard release context');
  ctx.reasons.forEach((r) => console.log(`  • ${r}`));
 
  const releaseOk = run('yarn', ['release:scs', ...process.argv.slice(2)]);
  if (!releaseOk) process.exit(1);
 
  if (ctx.isPatch) {
    console.log('\n→ Running patch-pairs comparison');
    const patchOk = run('yarn', ['release:scs:compare:patch-pairs']);
    if (!patchOk) {
      console.warn('āš ļø  patch-pairs compare exited non-zero — continuing to baseline-vs-source');
    }
  }
 
  console.log('\n→ Running baseline-vs-source comparison');
  const compareOk = run('yarn', ['release:scs:compare']);
  process.exit(compareOk ? 0 : 1);
}