| 
									
										
										
										
											2020-09-09 15:01:18 +02:00
										 |  |  | /** | 
					
						
							|  |  |  |  * @license | 
					
						
							|  |  |  |  * Copyright Google LLC All Rights Reserved. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Use of this source code is governed by an MIT-style license that can be | 
					
						
							|  |  |  |  * found in the LICENSE file at https://angular.io/license
 | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import {readFileSync} from 'fs'; | 
					
						
							|  |  |  | import {join} from 'path'; | 
					
						
							|  |  |  | import * as semver from 'semver'; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import {getBranchPushMatcher} from '../../../utils/testing'; | 
					
						
							| 
									
										
										
										
											2021-05-21 10:49:40 -07:00
										 |  |  | import {ReleaseNotes} from '../../notes/release-notes'; | 
					
						
							| 
									
										
										
										
											2021-05-17 19:00:50 +02:00
										 |  |  | import {NpmDistTag} from '../../versioning'; | 
					
						
							| 
									
										
										
										
											2020-09-09 15:01:18 +02:00
										 |  |  | import {ActiveReleaseTrains} from '../../versioning/active-release-trains'; | 
					
						
							|  |  |  | import * as npm from '../../versioning/npm-publish'; | 
					
						
							|  |  |  | import {ReleaseTrain} from '../../versioning/release-trains'; | 
					
						
							|  |  |  | import {ReleaseAction} from '../actions'; | 
					
						
							|  |  |  | import {actions} from '../actions/index'; | 
					
						
							| 
									
										
										
										
											2021-05-21 10:49:40 -07:00
										 |  |  | import {changelogPath} from '../constants'; | 
					
						
							| 
									
										
										
										
											2020-09-09 15:01:18 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-06 12:30:35 -07:00
										 |  |  | import {fakeNpmPackageQueryRequest, getTestingMocksForReleaseAction, parse, setupReleaseActionForTesting, testTmpDir} from './test-utils'; | 
					
						
							| 
									
										
										
										
											2020-09-09 15:01:18 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | describe('common release action logic', () => { | 
					
						
							|  |  |  |   const baseReleaseTrains: ActiveReleaseTrains = { | 
					
						
							|  |  |  |     releaseCandidate: null, | 
					
						
							|  |  |  |     next: new ReleaseTrain('master', parse('10.1.0-next.0')), | 
					
						
							|  |  |  |     latest: new ReleaseTrain('10.0.x', parse('10.0.1')), | 
					
						
							|  |  |  |   }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   describe('version computation', async () => { | 
					
						
							|  |  |  |     const testReleaseTrain: ActiveReleaseTrains = { | 
					
						
							|  |  |  |       releaseCandidate: new ReleaseTrain('10.1.x', parse('10.1.0-next.3')), | 
					
						
							|  |  |  |       next: new ReleaseTrain('master', parse('10.2.0-next.0')), | 
					
						
							|  |  |  |       latest: new ReleaseTrain('10.0.x', parse('10.0.1')), | 
					
						
							|  |  |  |     }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     it('should not modify release train versions and cause invalid other actions', async () => { | 
					
						
							|  |  |  |       const {releaseConfig, gitClient} = getTestingMocksForReleaseAction(); | 
					
						
							|  |  |  |       const descriptions: string[] = []; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-22 19:46:09 +02:00
										 |  |  |       // Fake the NPM package request as otherwise the test would rely on `npmjs.org`.
 | 
					
						
							|  |  |  |       fakeNpmPackageQueryRequest(releaseConfig.npmPackages[0], {'dist-tags': {}}); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-09 15:01:18 +02:00
										 |  |  |       for (const actionCtor of actions) { | 
					
						
							| 
									
										
										
										
											2021-05-17 19:00:50 +02:00
										 |  |  |         if (await actionCtor.isActive(testReleaseTrain, releaseConfig)) { | 
					
						
							| 
									
										
										
										
											2020-09-09 15:01:18 +02:00
										 |  |  |           const action = new actionCtor(testReleaseTrain, gitClient, releaseConfig, testTmpDir); | 
					
						
							|  |  |  |           descriptions.push(await action.getDescription()); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       expect(descriptions).toEqual([ | 
					
						
							|  |  |  |         `Cut a first release-candidate for the feature-freeze branch (v10.1.0-rc.0).`, | 
					
						
							|  |  |  |         `Cut a new patch release for the "10.0.x" branch (v10.0.2).`, | 
					
						
							|  |  |  |         `Cut a new next pre-release for the "10.1.x" branch (v10.1.0-next.4).`, | 
					
						
							|  |  |  |         `Cut a new release for an active LTS branch (0 active).` | 
					
						
							|  |  |  |       ]); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   describe('build and publishing', () => { | 
					
						
							|  |  |  |     it('should support a custom NPM registry', async () => { | 
					
						
							|  |  |  |       const {repo, instance, releaseConfig} = | 
					
						
							|  |  |  |           setupReleaseActionForTesting(TestAction, baseReleaseTrains); | 
					
						
							|  |  |  |       const {version, branchName} = baseReleaseTrains.next; | 
					
						
							|  |  |  |       const tagName = version.format(); | 
					
						
							|  |  |  |       const customRegistryUrl = 'https://custom-npm-registry.google.com'; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       repo.expectBranchRequest(branchName, 'STAGING_SHA') | 
					
						
							|  |  |  |           .expectCommitRequest('STAGING_SHA', `release: cut the v${version} release`) | 
					
						
							|  |  |  |           .expectTagToBeCreated(tagName, 'STAGING_SHA') | 
					
						
							|  |  |  |           .expectReleaseToBeCreated(`v${version}`, tagName); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       // Set up a custom NPM registry.
 | 
					
						
							|  |  |  |       releaseConfig.publishRegistry = customRegistryUrl; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       await instance.testBuildAndPublish(version, branchName, 'latest'); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       expect(npm.runNpmPublish).toHaveBeenCalledTimes(2); | 
					
						
							|  |  |  |       expect(npm.runNpmPublish) | 
					
						
							|  |  |  |           .toHaveBeenCalledWith(`${testTmpDir}/dist/pkg1`, 'latest', customRegistryUrl); | 
					
						
							|  |  |  |       expect(npm.runNpmPublish) | 
					
						
							|  |  |  |           .toHaveBeenCalledWith(`${testTmpDir}/dist/pkg2`, 'latest', customRegistryUrl); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   describe('changelog cherry-picking', () => { | 
					
						
							|  |  |  |     const {version, branchName} = baseReleaseTrains.latest; | 
					
						
							|  |  |  |     const forkBranchName = `changelog-cherry-pick-${version}`; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-19 11:58:32 -07:00
										 |  |  |     it('should prepend the changelog to the next branch', async () => { | 
					
						
							| 
									
										
										
										
											2020-09-09 15:01:18 +02:00
										 |  |  |       const {repo, fork, instance, testTmpDir} = | 
					
						
							|  |  |  |           setupReleaseActionForTesting(TestAction, baseReleaseTrains); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       // Expect the changelog to be fetched and return a fake changelog to test that
 | 
					
						
							|  |  |  |       // it is properly appended. Also expect a pull request to be created in the fork.
 | 
					
						
							| 
									
										
										
										
											2021-05-06 12:30:35 -07:00
										 |  |  |       repo.expectFindForkRequest(fork) | 
					
						
							| 
									
										
										
										
											2021-01-27 13:30:04 -08:00
										 |  |  |           .expectPullRequestToBeCreated('master', fork, forkBranchName, 200) | 
					
						
							|  |  |  |           .expectPullRequestWait(200); | 
					
						
							| 
									
										
										
										
											2020-09-09 15:01:18 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |       // Simulate that the fork branch name is available.
 | 
					
						
							|  |  |  |       fork.expectBranchRequest(forkBranchName, null); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       await instance.testCherryPickWithPullRequest(version, branchName); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       const changelogContent = readFileSync(join(testTmpDir, changelogPath), 'utf8'); | 
					
						
							| 
									
										
										
										
											2021-05-06 12:30:35 -07:00
										 |  |  |       expect(changelogContent).toEqual(`Changelog Entry for 10.0.1\n\nExisting changelog`); | 
					
						
							| 
									
										
										
										
											2020-09-09 15:01:18 +02:00
										 |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     it('should push changes to a fork for creating a pull request', async () => { | 
					
						
							|  |  |  |       const {repo, fork, instance, gitClient} = | 
					
						
							|  |  |  |           setupReleaseActionForTesting(TestAction, baseReleaseTrains); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       // Expect the changelog to be fetched and return a fake changelog to test that
 | 
					
						
							|  |  |  |       // it is properly appended. Also expect a pull request to be created in the fork.
 | 
					
						
							| 
									
										
										
										
											2021-05-06 12:30:35 -07:00
										 |  |  |       repo.expectFindForkRequest(fork) | 
					
						
							| 
									
										
										
										
											2021-01-27 13:30:04 -08:00
										 |  |  |           .expectPullRequestToBeCreated('master', fork, forkBranchName, 200) | 
					
						
							|  |  |  |           .expectPullRequestWait(200); | 
					
						
							| 
									
										
										
										
											2020-09-09 15:01:18 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |       // Simulate that the fork branch name is available.
 | 
					
						
							|  |  |  |       fork.expectBranchRequest(forkBranchName, null); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       await instance.testCherryPickWithPullRequest(version, branchName); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       expect(gitClient.pushed.length).toBe(1); | 
					
						
							|  |  |  |       expect(gitClient.pushed[0]).toEqual(getBranchPushMatcher({ | 
					
						
							|  |  |  |         targetBranch: forkBranchName, | 
					
						
							|  |  |  |         targetRepo: fork, | 
					
						
							|  |  |  |         baseBranch: 'master', | 
					
						
							|  |  |  |         baseRepo: repo, | 
					
						
							|  |  |  |         expectedCommits: [{ | 
					
						
							|  |  |  |           message: `docs: release notes for the v${version} release`, | 
					
						
							|  |  |  |           files: ['CHANGELOG.md'], | 
					
						
							|  |  |  |         }], | 
					
						
							|  |  |  |       })); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /** | 
					
						
							|  |  |  |  * Test release action that exposes protected units of the base | 
					
						
							|  |  |  |  * release action class. This allows us to add unit tests. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | class TestAction extends ReleaseAction { | 
					
						
							|  |  |  |   async getDescription() { | 
					
						
							|  |  |  |     return 'Test action'; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   async perform() { | 
					
						
							|  |  |  |     throw Error('Not implemented.'); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-17 19:00:50 +02:00
										 |  |  |   async testBuildAndPublish(version: semver.SemVer, publishBranch: string, distTag: NpmDistTag) { | 
					
						
							| 
									
										
										
										
											2021-05-06 12:30:35 -07:00
										 |  |  |     const releaseNotes = await ReleaseNotes.fromRange(version, '', ''); | 
					
						
							| 
									
										
										
										
											2021-05-05 09:11:05 -07:00
										 |  |  |     await this.buildAndPublish(releaseNotes, publishBranch, distTag); | 
					
						
							| 
									
										
										
										
											2020-09-09 15:01:18 +02:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   async testCherryPickWithPullRequest(version: semver.SemVer, branch: string) { | 
					
						
							| 
									
										
										
										
											2021-05-06 12:30:35 -07:00
										 |  |  |     const releaseNotes = await ReleaseNotes.fromRange(version, '', ''); | 
					
						
							| 
									
										
										
										
											2021-04-19 11:58:32 -07:00
										 |  |  |     await this.cherryPickChangelogIntoNextBranch(releaseNotes, branch); | 
					
						
							| 
									
										
										
										
											2020-09-09 15:01:18 +02:00
										 |  |  |   } | 
					
						
							|  |  |  | } |