(rootDir: string)
| 400 | * Outputs JSON to stdout and sets GitHub Actions outputs when detected. |
| 401 | */ |
| 402 | export async function ciPlanCommand(rootDir: string): Promise<void> { |
| 403 | const config = await loadConfig(rootDir); |
| 404 | const { packages } = await discoverWorkspace(rootDir, config); |
| 405 | const depGraph = new DependencyGraph(packages); |
| 406 | // Channel-dir bump files count as pending on the base branch (promotion consumes them) |
| 407 | const { bumpFiles, errors: parseErrors } = await readBumpFiles(rootDir, { channels: channelNames(config) }); |
| 408 | |
| 409 | if (parseErrors.length > 0) { |
| 410 | for (const err of parseErrors) { |
| 411 | log.error(err); |
| 412 | } |
| 413 | throw new Error('Bump file parse errors must be fixed before planning.'); |
| 414 | } |
| 415 | |
| 416 | // On a channel branch, report the channel plan instead |
| 417 | const channel = matchChannelByBranch(config, detectReleaseBranch(rootDir)); |
| 418 | if (channel) { |
| 419 | await ciChannelPlan(rootDir, config, channel, packages, depGraph, bumpFiles); |
| 420 | return; |
| 421 | } |
| 422 | |
| 423 | let output: PlanOutput; |
| 424 | |
| 425 | // Assemble plan from bump files (if any) |
| 426 | const plan = bumpFiles.length > 0 ? assembleReleasePlan(bumpFiles, packages, depGraph, config) : null; |
| 427 | |
| 428 | if (plan && plan.releases.length > 0) { |
| 429 | // Bump files produce actual releases → version-pr mode |
| 430 | output = { |
| 431 | mode: 'version-pr', |
| 432 | bumpFiles: plan.bumpFiles.map((bf) => ({ |
| 433 | id: bf.id, |
| 434 | summary: bf.summary, |
| 435 | releases: bf.releases.map((r) => ({ name: r.name, type: r.type })), |
| 436 | })), |
| 437 | releases: plan.releases.map((r) => formatPlanRelease(r, packages, config)), |
| 438 | packageNames: plan.releases.map((r) => r.name), |
| 439 | }; |
| 440 | } else { |
| 441 | // No releases from bump files (none-only or no bump files) → check for unpublished packages |
| 442 | const { findUnpublishedPackages } = await import('./publish.ts'); |
| 443 | const unpublished = await findUnpublishedPackages(packages, config); |
| 444 | |
| 445 | if (unpublished.length > 0) { |
| 446 | output = { |
| 447 | mode: 'publish', |
| 448 | bumpFiles: [], |
| 449 | releases: unpublished.map((r) => formatPlanRelease(r, packages, config)), |
| 450 | packageNames: unpublished.map((r) => r.name), |
| 451 | }; |
| 452 | } else { |
| 453 | output = { |
| 454 | mode: 'nothing', |
| 455 | bumpFiles: [], |
| 456 | releases: [], |
| 457 | packageNames: [], |
| 458 | }; |
| 459 | } |
no test coverage detected
searching dependent graphs…