From ce1339c98b9e3d4110ea02516586877ddab2533c Mon Sep 17 00:00:00 2001 From: Joey Perrott Date: Wed, 13 Oct 2021 12:18:50 -0700 Subject: [PATCH] fix(ng-dev/release): run yarn integrity check before performing a release If the ng-dev command is run with an outdate version of the package, a dev may perform a release without the latest changes to the tooling. This can lead to not creating up to date artifacts and general issues. By checking if the installed dependencies match the expected dependencies before performing the action we can instruct the user to update their installed node_modules. An example where this change would have prevented issue: Framework releases from the patch branch which is currently a different version of the package as defined in package.json. Calling them version 1 and version 2, with version 2 being the latest version. A patch release is performed by checking out the latest commit from the upstream next branch, running yarn install and then running ng-dev release publish. This release process will occur using version 2 of the dev-infra package. During the release process, the patch branch is checked out and yarn install is performed, causing version 1 to be installed. Upon completion of the patch release, the next release is attempted unknowingly triggered using version 1 of the package. While generated artifacts are already ensured to built with the correct dependency by the process, the tool itself is already running before this check can occur. Instead version 1 of the package is used to process the release, potentially resulting in an errant or unexpected process. This situation will now be prevented by validating the expected version is being used for the action process, in the situation above the user would be informed that yarn install was needed before performing the second release. --- ng-dev/release/publish/external-commands.ts | 14 ++++++++++++++ ng-dev/release/publish/index.ts | 16 ++++++++++++++++ 2 files changed, 30 insertions(+) diff --git a/ng-dev/release/publish/external-commands.ts b/ng-dev/release/publish/external-commands.ts index 402f9df3ed..d14fcbe3c7 100644 --- a/ng-dev/release/publish/external-commands.ts +++ b/ng-dev/release/publish/external-commands.ts @@ -97,3 +97,17 @@ export async function invokeYarnInstallCommand(projectDir: string): Promise { + try { + await spawn('yarn', ['check', '--integrity'], {cwd: projectDir, mode: 'silent'}); + info(green(' ✓ Confirmed installed dependencies match those defined in package.json.')); + } catch (e) { + error(red(' ✘ Failed yarn integrity check, your installed dependencies are likely out of')); + error(red(' date. Please run `yarn install` to update your installed dependencies.')); + throw new FatalReleaseActionError(); + } +} diff --git a/ng-dev/release/publish/index.ts b/ng-dev/release/publish/index.ts index 4d536c4e0b..14b8f264d5 100644 --- a/ng-dev/release/publish/index.ts +++ b/ng-dev/release/publish/index.ts @@ -19,6 +19,7 @@ import {getNextBranchName, ReleaseRepoWithApi} from '../versioning/version-branc import {ReleaseAction} from './actions'; import {FatalReleaseActionError, UserAbortedReleaseActionError} from './actions-error'; import {actions} from './actions/index'; +import {invokeYarnIntegryCheck} from './external-commands'; export enum CompletionState { SUCCESS, @@ -49,6 +50,7 @@ export class ReleaseTool { const nextBranchName = getNextBranchName(this._github); if ( + !(await this._verifyInstalledDependenciesAreUpToDate()) || !(await this._verifyNoUncommittedChanges()) || !(await this._verifyRunningFromNextBranch(nextBranchName)) || !(await this._verifyNoShallowRepository()) @@ -144,6 +146,20 @@ export class ReleaseTool { return true; } + /** + * Verifiy that the install dependencies match the the versions defined in the package.json and + * yarn.lock files. + * @returns a boolean indicating success or failure. + */ + private async _verifyInstalledDependenciesAreUpToDate(): Promise { + try { + await invokeYarnIntegryCheck(this._projectRoot); + return true; + } catch { + return false; + } + } + /** * Verifies that the local repository is not configured as shallow. * @returns a boolean indicating success or failure.