fix(dev-infra): use the version from package.json rather than tags (#42872)

Use the version value from the primary package.json file rather than
checking the branch for the latest semver tag.  This allows for us
to explictly create changelogs from the previous version to the new
version.

PR Close #42872
This commit is contained in:
Joey Perrott 2021-07-15 17:06:15 -07:00 committed by Alex Rickabaugh
parent 445fee4174
commit 282e86ad71
6 changed files with 70 additions and 4 deletions

View File

@ -262,6 +262,16 @@ var GitClient = /** @class */ (function () {
}
return new semver.SemVer(latestTag, semVerOptions);
};
/** Retrieves the git tag matching the provided SemVer, if it exists. */
GitClient.prototype.getMatchingTagForSemver = function (semver$1) {
var semVerOptions = { loose: true };
var tags = this.runGraceful(['tag', '--sort=-committerdate', '--merged']).stdout.split('\n');
var matchingTag = tags.find(function (tag) { var _a; return ((_a = semver.parse(tag, semVerOptions)) === null || _a === void 0 ? void 0 : _a.compare(semver$1)) === 0; });
if (matchingTag === undefined) {
throw new Error("Unable to find a tag for the version: \"" + semver$1.format() + "\"");
}
return matchingTag;
};
/** Retrieve a list of all files in the repository changed since the provided shaOrRef. */
GitClient.prototype.allChangesFilesSince = function (shaOrRef) {
if (shaOrRef === void 0) { shaOrRef = 'HEAD'; }

View File

@ -434,6 +434,16 @@ var GitClient = /** @class */ (function () {
}
return new semver.SemVer(latestTag, semVerOptions);
};
/** Retrieves the git tag matching the provided SemVer, if it exists. */
GitClient.prototype.getMatchingTagForSemver = function (semver$1) {
var semVerOptions = { loose: true };
var tags = this.runGraceful(['tag', '--sort=-committerdate', '--merged']).stdout.split('\n');
var matchingTag = tags.find(function (tag) { var _a; return ((_a = semver.parse(tag, semVerOptions)) === null || _a === void 0 ? void 0 : _a.compare(semver$1)) === 0; });
if (matchingTag === undefined) {
throw new Error("Unable to find a tag for the version: \"" + semver$1.format() + "\"");
}
return matchingTag;
};
/** Retrieve a list of all files in the repository changed since the provided shaOrRef. */
GitClient.prototype.allChangesFilesSince = function (shaOrRef) {
if (shaOrRef === void 0) { shaOrRef = 'HEAD'; }
@ -6423,6 +6433,14 @@ class ReleaseAction {
static isActive(_trains, _config) {
throw Error('Not implemented.');
}
/** Retrieves the version in the project top-level `package.json` file. */
getProjectVersion() {
return tslib.__awaiter(this, void 0, void 0, function* () {
const pkgJsonPath = path.join(this.projectDir, packageJsonPath);
const pkgJson = JSON.parse(yield fs.promises.readFile(pkgJsonPath, 'utf8'));
return new semver.SemVer(pkgJson.version);
});
}
/** Updates the version in the project top-level `package.json` file. */
updateProjectVersion(newVersion) {
return tslib.__awaiter(this, void 0, void 0, function* () {
@ -6676,7 +6694,12 @@ class ReleaseAction {
*/
stageVersionForBranchAndCreatePullRequest(newVersion, pullRequestBaseBranch) {
return tslib.__awaiter(this, void 0, void 0, function* () {
const releaseNotes = yield ReleaseNotes.fromRange(newVersion, this.git.getLatestSemverTag().format(), 'HEAD');
/**
* The current version of the project for the branch from the root package.json. This must be
* retrieved prior to updating the project version.
*/
const currentVersion = this.git.getMatchingTagForSemver(yield this.getProjectVersion());
const releaseNotes = yield ReleaseNotes.fromRange(newVersion, currentVersion, 'HEAD');
yield this.updateProjectVersion(newVersion);
yield this.prependReleaseNotesToChangelog(releaseNotes);
yield this.waitForEditsAndCreateReleaseCommit(newVersion);

View File

@ -80,6 +80,14 @@ export abstract class ReleaseAction {
protected active: ActiveReleaseTrains, protected git: AuthenticatedGitClient,
protected config: ReleaseConfig, protected projectDir: string) {}
/** Retrieves the version in the project top-level `package.json` file. */
private async getProjectVersion() {
const pkgJsonPath = join(this.projectDir, packageJsonPath);
const pkgJson =
JSON.parse(await fs.readFile(pkgJsonPath, 'utf8')) as {version: string, [key: string]: any};
return new semver.SemVer(pkgJson.version);
}
/** Updates the version in the project top-level `package.json` file. */
protected async updateProjectVersion(newVersion: semver.SemVer) {
const pkgJsonPath = join(this.projectDir, packageJsonPath);
@ -351,8 +359,12 @@ export abstract class ReleaseAction {
protected async stageVersionForBranchAndCreatePullRequest(
newVersion: semver.SemVer, pullRequestBaseBranch: string):
Promise<{releaseNotes: ReleaseNotes, pullRequest: PullRequest}> {
const releaseNotes =
await ReleaseNotes.fromRange(newVersion, this.git.getLatestSemverTag().format(), 'HEAD');
/**
* The current version of the project for the branch from the root package.json. This must be
* retrieved prior to updating the project version.
*/
const currentVersion = this.git.getMatchingTagForSemver(await this.getProjectVersion());
const releaseNotes = await ReleaseNotes.fromRange(newVersion, currentVersion, 'HEAD');
await this.updateProjectVersion(newVersion);
await this.prependReleaseNotesToChangelog(releaseNotes);
await this.waitForEditsAndCreateReleaseCommit(newVersion);

View File

@ -108,7 +108,7 @@ export function setupReleaseActionForTesting<T extends ReleaseAction>(
// Create an empty changelog and a `package.json` file so that file system
// interactions with the project directory do not cause exceptions.
writeFileSync(join(testTmpDir, 'CHANGELOG.md'), 'Existing changelog');
writeFileSync(join(testTmpDir, 'package.json'), JSON.stringify({version: 'unknown'}));
writeFileSync(join(testTmpDir, 'package.json'), JSON.stringify({version: '0.0.0'}));
// Override the default pull request wait interval to a number of milliseconds that can be
// awaited in Jasmine tests. The default interval of 10sec is too large and causes a timeout.

View File

@ -162,6 +162,19 @@ export class GitClient {
return new SemVer(latestTag, semVerOptions);
}
/** Retrieves the git tag matching the provided SemVer, if it exists. */
getMatchingTagForSemver(semver: SemVer): string {
const semVerOptions: SemVerOptions = {loose: true};
const tags = this.runGraceful(['tag', '--sort=-committerdate', '--merged']).stdout.split('\n');
const matchingTag =
tags.find((tag: string) => parse(tag, semVerOptions)?.compare(semver) === 0);
if (matchingTag === undefined) {
throw new Error(`Unable to find a tag for the version: "${semver.format()}"`);
}
return matchingTag;
}
/** Retrieve a list of all files in the repository changed since the provided shaOrRef. */
allChangesFilesSince(shaOrRef = 'HEAD'): string[] {
return Array.from(new Set([

View File

@ -82,6 +82,14 @@ export class VirtualGitClient extends AuthenticatedGitClient {
return new SemVer('0.0.0');
}
/**
* Override the actual GitClient getLatestSemverTag, as an actual tags cannot be checked during
* testing, return back the SemVer version as the tag.
*/
override getMatchingTagForSemver(semver: SemVer) {
return semver.format();
}
/** Override for the actual Git client command execution. */
override runGraceful(args: string[], options: SpawnSyncOptions = {}): SpawnSyncReturns<string> {
const [command, ...rawArgs] = args;