diff --git a/dev-infra/pr/merge/defaults/branches.ts b/dev-infra/pr/merge/defaults/branches.ts index 0f40a2d0a2..293df1f0e0 100644 --- a/dev-infra/pr/merge/defaults/branches.ts +++ b/dev-infra/pr/merge/defaults/branches.ts @@ -165,6 +165,11 @@ export async function findActiveVersionBranches( latestVersionBranch: string | null, releaseCandidateBranch: string | null, }> { + // Version representing the release-train currently in the next phase. Note that we ignore + // patch and pre-release segments in order to be able to compare the next release train to + // other release trains from version branches (which follow the `N.N.x` pattern). + const nextReleaseTrainVersion = semver.parse(`${nextVersion.major}.${nextVersion.minor}.0`)!; + let latestVersionBranch: string|null = null; let releaseCandidateBranch: string|null = null; @@ -177,15 +182,21 @@ export async function findActiveVersionBranches( // next version-branch as that one is supposed to be the latest active version-branch. If it // is not, then an error will be thrown due to two FF/RC branches existing at the same time. for (const {name, parsed} of branches) { - // It can happen that version branches that are more recent than the version in the next - // branch (i.e. `master`) have been created. We could ignore such branches silently, but - // it might actually be symptomatic for an outdated version in the `next` branch, or an + // It can happen that version branches have been accidentally created which are more recent + // than the release-train in the next branch (i.e. `master`). We could ignore such branches + // silently, but it might be symptomatic for an outdated version in the `next` branch, or an // accidentally created branch by the caretaker. In either way we want to raise awareness. - if (semver.gte(parsed, nextVersion)) { + if (semver.gt(parsed, nextReleaseTrainVersion)) { throw Error( - `Discovered unexpected version-branch that is representing a minor ` + - `version more recent than the one in the "${nextBranchName}" branch. Consider ` + - `deleting the branch, or check if the version in "${nextBranchName}" is outdated.`); + `Discovered unexpected version-branch "${name}" for a release-train that is ` + + `more recent than the release-train currently in the "${nextBranchName}" branch. ` + + `Please either delete the branch if created by accident, or update the outdated ` + + `version in the next branch (${nextBranchName}).`); + } else if (semver.eq(parsed, nextReleaseTrainVersion)) { + throw Error( + `Discovered unexpected version-branch "${name}" for a release-train that is already ` + + `active in the "${nextBranchName}" branch. Please either delete the branch if ` + + `created by accident, or update the version in the next branch (${nextBranchName}).`); } const version = await getVersionOfBranch(repo, name); diff --git a/dev-infra/pr/merge/defaults/integration.spec.ts b/dev-infra/pr/merge/defaults/integration.spec.ts index d085422e90..71d8318c14 100644 --- a/dev-infra/pr/merge/defaults/integration.spec.ts +++ b/dev-infra/pr/merge/defaults/integration.spec.ts @@ -280,7 +280,21 @@ describe('default target labels', () => { .toBeRejectedWithError('Invalid version detected in following branch: 11.1.x.'); }); - it('should error if branch more recent than version in "next" branch is found', async () => { + it('should error if version-branch more recent than "next" is discovered', async () => { + interceptBranchVersionRequest('master', '11.2.0-next.0'); + interceptBranchVersionRequest('11.3.x', '11.3.0-next.0'); + interceptBranchVersionRequest('11.1.x', '11.1.5'); + interceptBranchesListRequest(['11.1.x', '11.3.x']); + + await expectAsync(getBranchesForLabel('target: lts', '10.2.x')) + .toBeRejectedWithError( + 'Discovered unexpected version-branch "11.3.x" for a release-train that is ' + + 'more recent than the release-train currently in the "master" branch. Please ' + + 'either delete the branch if created by accident, or update the outdated version ' + + 'in the next branch (master).'); + }); + + it('should error if branch is matching with release-train in the "next" branch', async () => { interceptBranchVersionRequest('master', '11.2.0-next.0'); interceptBranchVersionRequest('11.2.x', '11.2.0-next.0'); interceptBranchVersionRequest('11.1.x', '11.1.5'); @@ -288,9 +302,9 @@ describe('default target labels', () => { await expectAsync(getBranchesForLabel('target: lts', '10.2.x')) .toBeRejectedWithError( - 'Discovered unexpected version-branch that is representing a minor version more ' + - 'recent than the one in the "master" branch. Consider deleting the branch, or check ' + - 'if the version in "master" is outdated.'); + 'Discovered unexpected version-branch "11.2.x" for a release-train that is already ' + + 'active in the "master" branch. Please either delete the branch if created by ' + + 'accident, or update the version in the next branch (master).'); }); it('should allow merging PR only into patch branch with "target: patch"', async () => {