* Create or update the channel's release PR. Unlike the stable version PR, its diff * is pure file moves (pending bump files → `.bumpy/ /`) — no versions, no * changelogs. The PR title/body show targets with a wildcard counter (`1.2.0-rc.x`), * derived purely from committed state; the exa
(
rootDir: string,
config: BumpyConfig,
channel: ResolvedChannel,
packages: Map<string, import('../types.ts').WorkspacePackage>,
branchOverride?: string,
)
| 1051 | |
| 1052 | // Step 1: publish if this push merged a release PR (moved files into the channel dir) |
| 1053 | const movedIds = detectChannelMoves(rootDir, channel); |
| 1054 | const shouldPublish = movedIds.length > 0 && opts.assertMode !== 'version-pr'; |
| 1055 | if (shouldPublish) { |
| 1056 | log.step(`Release PR merge detected (${movedIds.map((id) => `${id}.md`).join(', ')}) — publishing prereleases...`); |
| 1057 | const { publishCommand } = await import('./publish.ts'); |
| 1058 | await publishCommand(rootDir, { channel: channel.name, tag: opts.tag }); |
| 1059 | } |
| 1060 | |
| 1061 | if (opts.assertMode === 'publish') { |
| 1062 | if (!shouldPublish) { |
| 1063 | throw new Error( |
| 1064 | 'Expected mode "publish" but this push did not move bump files into the channel dir. ' + |
| 1065 | 'Either remove --expect-mode, or gate this step on the output of "bumpy ci plan".', |
| 1066 | ); |
| 1067 | } |
| 1068 | return; |
| 1069 | } |
| 1070 | |
| 1071 | // Step 2: create/update the release PR for pending bump files |
| 1072 | if (pending.length > 0) { |
| 1073 | await createChannelReleasePr(rootDir, config, channel, packages, opts.branch); |
| 1074 | } else if (!shouldPublish) { |
| 1075 | log.info(`Nothing to do on channel "${channel.name}" — no pending bump files, no release PR merge in this push.`); |
| 1076 | } |
| 1077 | } |
| 1078 | |
| 1079 | /** |
| 1080 | * Create or update the channel's release PR. Unlike the stable version PR, its diff |
| 1081 | * is pure file moves (pending bump files → `.bumpy/<channel>/`) — no versions, no |
| 1082 | * changelogs. The PR title/body show targets with a wildcard counter (`1.2.0-rc.x`), |
| 1083 | * derived purely from committed state; the exact counter is assigned at publish time. |
| 1084 | */ |
| 1085 | async function createChannelReleasePr( |
| 1086 | rootDir: string, |
| 1087 | config: BumpyConfig, |
| 1088 | channel: ResolvedChannel, |
| 1089 | packages: Map<string, import('../types.ts').WorkspacePackage>, |
| 1090 | branchOverride?: string, |
| 1091 | ): Promise<void> { |
| 1092 | const branch = validateBranchName(branchOverride || channel.versionPr.branch); |
| 1093 | const baseBranch = validateBranchName(channel.branch); |
| 1094 | |
| 1095 | // Check if a release PR already exists |
| 1096 | const existingPr = tryRunArgs(['gh', 'pr', 'list', '--head', branch, '--json', 'number', '--jq', '.[0].number'], { |
| 1097 | cwd: rootDir, |
| 1098 | }); |
| 1099 | |
| 1100 | log.step(`Creating branch ${branch}...`); |
| 1101 | const branchExists = tryRunArgs(['git', 'rev-parse', '--verify', branch], { cwd: rootDir }) !== null; |
| 1102 | if (branchExists) { |
| 1103 | runArgs(['git', 'checkout', branch], { cwd: rootDir }); |
| 1104 | runArgs(['git', 'reset', '--hard', baseBranch], { cwd: rootDir }); |
| 1105 | } else { |
| 1106 | runArgs(['git', 'checkout', '-b', branch], { cwd: rootDir }); |
| 1107 | } |
| 1108 | |
| 1109 | // Move pending bump files into the channel dir (the entire "version" step for a channel) |
| 1110 | const { channelVersion } = await import('./version.ts'); |
no test coverage detected
searching dependent graphs…