diff --git a/src/apps/apps.service.ts b/src/apps/apps.service.ts index 074f57c..77c4b18 100644 --- a/src/apps/apps.service.ts +++ b/src/apps/apps.service.ts @@ -726,7 +726,11 @@ export class AppsService { commitSha, ], { cwd: workDir }); } catch { - await this.resolveReleaseMergeByTakingSourceOnConflict(gitBin, workDir, mergeOptions, commitSha, repository); + try { + await this.resolveReleaseMergeByTakingSourceOnConflict(gitBin, workDir, mergeOptions, commitSha, repository); + } catch { + await this.promoteReleaseBySourceSnapshot(gitBin, workDir, mergeOptions, commitSha, targetBranch, repository); + } } } } else { @@ -774,6 +778,31 @@ export class AppsService { await execFileAsync(gitBin, ['commit', '--allow-empty', '-m', `${repository} release promotion merge`], { cwd: workDir }); } + private async promoteReleaseBySourceSnapshot( + gitBin: string, + workDir: string, + mergeOptions: string[], + commitSha: string, + targetBranch: string, + repository: string, + ) { + await this.resetPromotionWorktree(gitBin, workDir); + await execFileAsync(gitBin, [ + 'checkout', + '-B', + targetBranch, + `origin/${targetBranch}`, + ], { cwd: workDir }); + await execFileAsync(gitBin, ['reset', '--hard', `origin/${targetBranch}`], { cwd: workDir }).catch(() => undefined); + await execFileAsync(gitBin, ['read-tree', '--reset', '-u', commitSha], { cwd: workDir }); + await execFileAsync(gitBin, ['add', '-A'], { cwd: workDir }); + const { stdout } = await execFileAsync(gitBin, ['status', '--porcelain'], { cwd: workDir }); + if (!stdout.trim()) { + return; + } + await execFileAsync(gitBin, ['commit', '--allow-empty', '-m', `${repository} release promotion snapshot`], { cwd: workDir }); + } + private async resetPromotionWorktree(gitBin: string, workDir: string) { await execFileAsync(gitBin, ['merge', '--abort'], { cwd: workDir }).catch(() => undefined); await execFileAsync(gitBin, ['rebase', '--abort'], { cwd: workDir }).catch(() => undefined);