2017-10-06 05:48:18 -04:00
'use strict' ;
const chalk = require ( 'chalk' ) ;
const fs = require ( 'fs-extra' ) ;
2019-02-04 09:45:45 -05:00
const lockfile = require ( '@yarnpkg/lockfile' ) ;
2017-10-06 05:48:18 -04:00
const path = require ( 'canonical-path' ) ;
2019-02-04 09:45:45 -05:00
const semver = require ( 'semver' ) ;
2017-10-06 05:48:18 -04:00
const shelljs = require ( 'shelljs' ) ;
const yargs = require ( 'yargs' ) ;
const PACKAGE _JSON = 'package.json' ;
2019-02-04 09:45:45 -05:00
const YARN _LOCK = 'yarn.lock' ;
2017-10-06 05:48:18 -04:00
const LOCAL _MARKER _PATH = 'node_modules/_local_.json' ;
const ANGULAR _ROOT _DIR = path . resolve ( _ _dirname , '../../..' ) ;
2020-02-29 12:14:34 -05:00
const ANGULAR _DIST _PACKAGES _DIR = path . join ( ANGULAR _ROOT _DIR , 'dist/packages-dist' ) ;
2021-04-05 12:05:54 -04:00
const AIMWA _DIST _PACKAGES _DIR = path . join ( ANGULAR _ROOT _DIR , 'dist/angular-in-memory-web-api-dist' ) ;
2020-02-29 14:05:23 -05:00
const ZONEJS _DIST _PACKAGES _DIR = path . join ( ANGULAR _ROOT _DIR , 'dist/zone.js-dist' ) ;
2020-02-29 12:14:34 -05:00
const DIST _PACKAGES _BUILD _SCRIPT = path . join ( ANGULAR _ROOT _DIR , 'scripts/build/build-packages-dist.js' ) ;
const DIST _PACKAGES _BUILD _CMD = ` " ${ process . execPath } " " ${ DIST _PACKAGES _BUILD _SCRIPT } " ` ;
2017-10-06 05:48:18 -04:00
/ * *
2020-02-29 14:05:23 -05:00
* A tool that can install Angular / Zone . js dependencies for a project from NPM or from the
2017-10-06 05:48:18 -04:00
* locally built distributables .
*
* This tool is used to change dependencies of the ` aio ` application and the example
* applications .
* /
class NgPackagesInstaller {
/ * *
* Create a new installer for a project in the specified directory .
*
* @ param { string } projectDir - the path to the directory containing the project .
2019-08-03 09:57:24 -04:00
* @ param { object } options - a hash of options for the install :
* * ` debug ` ( ` boolean ` ) - whether to display debug messages .
* * ` force ` ( ` boolean ` ) - whether to force a local installation even if there is a local marker file .
2020-02-29 14:05:23 -05:00
* * ` buildPackages ` ( ` boolean ` ) - whether to build the local Angular / Zone . js packages before using them .
2019-08-03 10:37:19 -04:00
* ( NOTE : Building the packages is currently not supported on Windows , so a message is printed instead . )
2019-08-03 09:57:24 -04:00
* * ` ignorePackages ` ( ` string[] ` ) - a collection of names of packages that should not be copied over .
2017-10-06 05:48:18 -04:00
* /
constructor ( projectDir , options = { } ) {
2019-08-03 11:14:27 -04:00
this . debug = this . _parseBooleanArg ( options . debug ) ;
this . force = this . _parseBooleanArg ( options . force ) ;
this . buildPackages = this . _parseBooleanArg ( options . buildPackages ) ;
2017-10-06 05:48:32 -04:00
this . ignorePackages = options . ignorePackages || [ ] ;
2017-10-06 05:48:18 -04:00
this . projectDir = path . resolve ( projectDir ) ;
this . localMarkerPath = path . resolve ( this . projectDir , LOCAL _MARKER _PATH ) ;
this . _log ( 'Project directory:' , this . projectDir ) ;
}
// Public methods
/ * *
* Check whether the dependencies have been overridden with locally built
2020-02-29 14:05:23 -05:00
* Angular / Zone . js packages . This is done by checking for the ` _local_.json ` marker file .
2017-10-06 05:48:18 -04:00
* This will emit a warning to the console if the dependencies have been overridden .
* /
checkDependencies ( ) {
if ( this . _checkLocalMarker ( ) ) {
this . _printWarning ( ) ;
}
}
/ * *
2020-02-29 14:05:23 -05:00
* Install locally built Angular / Zone . js dependencies , overriding the dependencies in the ` package.json ` .
* This will also write a "marker" file ( ` _local_.json ` ) , which contains the overridden ` package.json `
2017-10-06 05:48:18 -04:00
* contents and acts as an indicator that dependencies have been overridden .
* /
installLocalDependencies ( ) {
2019-02-04 07:55:58 -05:00
if ( this . force || ! this . _checkLocalMarker ( ) ) {
2017-10-06 05:48:18 -04:00
const pathToPackageConfig = path . resolve ( this . projectDir , PACKAGE _JSON ) ;
fix(docs-infra): avoid version mismatch error when using local Angular packages (#34213)
The local Angular packages used to build `aio/` when running
`yarn setup-local`/`yarn build-local` (and related commands), are built
by bazel. Bazel, determines the version to use for these locally built
packages based on the latest tag for a commit on the current branch.
(This works as expected during the release, because the packages are
built on the correct branch with up-to-date tags.)
During local development, however, this often leads to generating older
versions than what the current `@angular/cli` version is compatible
with, if the user has not fetched the latest tags from `angular/angular`
or the branch has not been rebased recently.
Previously, the above (common) situation would result in a build error
by the CLI. (Note that this would be a false error, because in this case
the version set by bazel would not reflect the actual version of the
local packages.) The solution would be for the user to fetch the latest
tags from `angular/angular`, rebase their branch and run a bazel build
again (ensuring that it would actually build anew and not emit cached
artifacts). This was cumbersome and most people didn't even know about
it.
This commit avoids this error and the associated pain-points by
overwriting the versions of the installed local packages with fake
versions based on the ones in the lockfile, which are guaranteed to be
compatible with the currently used CLI version.
Fixes #34208
PR Close #34213
2019-12-03 08:38:09 -05:00
const packageConfigFile = fs . readFileSync ( pathToPackageConfig , 'utf8' ) ;
const packageConfig = JSON . parse ( packageConfigFile ) ;
2019-02-04 09:45:45 -05:00
const pathToLockfile = path . resolve ( this . projectDir , YARN _LOCK ) ;
const parsedLockfile = this . _parseLockfile ( pathToLockfile ) ;
fix(docs-infra): avoid version mismatch error when using local Angular packages (#34213)
The local Angular packages used to build `aio/` when running
`yarn setup-local`/`yarn build-local` (and related commands), are built
by bazel. Bazel, determines the version to use for these locally built
packages based on the latest tag for a commit on the current branch.
(This works as expected during the release, because the packages are
built on the correct branch with up-to-date tags.)
During local development, however, this often leads to generating older
versions than what the current `@angular/cli` version is compatible
with, if the user has not fetched the latest tags from `angular/angular`
or the branch has not been rebased recently.
Previously, the above (common) situation would result in a build error
by the CLI. (Note that this would be a false error, because in this case
the version set by bazel would not reflect the actual version of the
local packages.) The solution would be for the user to fetch the latest
tags from `angular/angular`, rebase their branch and run a bazel build
again (ensuring that it would actually build anew and not emit cached
artifacts). This was cumbersome and most people didn't even know about
it.
This commit avoids this error and the associated pain-points by
overwriting the versions of the installed local packages with fake
versions based on the ones in the lockfile, which are guaranteed to be
compatible with the currently used CLI version.
Fixes #34208
PR Close #34213
2019-12-03 08:38:09 -05:00
2017-10-06 05:48:18 -04:00
const packages = this . _getDistPackages ( ) ;
2017-10-09 06:11:13 -04:00
try {
// Overwrite local Angular packages dependencies to other Angular packages with local files.
Object . keys ( packages ) . forEach ( key => {
const pkg = packages [ key ] ;
const tmpConfig = JSON . parse ( JSON . stringify ( pkg . config ) ) ;
// Prevent accidental publishing of the package, if something goes wrong.
tmpConfig . private = true ;
2020-02-29 14:05:23 -05:00
// Overwrite project dependencies/devDependencies to Angular/Zone.js packages with local files.
2017-10-09 06:11:13 -04:00
[ 'dependencies' , 'devDependencies' ] . forEach ( prop => {
const deps = tmpConfig [ prop ] || { } ;
Object . keys ( deps ) . forEach ( key2 => {
const pkg2 = packages [ key2 ] ;
if ( pkg2 ) {
2020-02-29 14:05:23 -05:00
// point the local packages at the distributable folder
2020-02-29 12:14:34 -05:00
deps [ key2 ] = ` file: ${ pkg2 . packageDir } ` ;
2017-10-09 06:11:13 -04:00
this . _log ( ` Overriding dependency of local ${ key } with local package: ${ key2 } : ${ deps [ key2 ] } ` ) ;
}
} ) ;
} ) ;
fix(docs-infra): avoid version mismatch error when using local Angular packages (#34213)
The local Angular packages used to build `aio/` when running
`yarn setup-local`/`yarn build-local` (and related commands), are built
by bazel. Bazel, determines the version to use for these locally built
packages based on the latest tag for a commit on the current branch.
(This works as expected during the release, because the packages are
built on the correct branch with up-to-date tags.)
During local development, however, this often leads to generating older
versions than what the current `@angular/cli` version is compatible
with, if the user has not fetched the latest tags from `angular/angular`
or the branch has not been rebased recently.
Previously, the above (common) situation would result in a build error
by the CLI. (Note that this would be a false error, because in this case
the version set by bazel would not reflect the actual version of the
local packages.) The solution would be for the user to fetch the latest
tags from `angular/angular`, rebase their branch and run a bazel build
again (ensuring that it would actually build anew and not emit cached
artifacts). This was cumbersome and most people didn't even know about
it.
This commit avoids this error and the associated pain-points by
overwriting the versions of the installed local packages with fake
versions based on the ones in the lockfile, which are guaranteed to be
compatible with the currently used CLI version.
Fixes #34208
PR Close #34213
2019-12-03 08:38:09 -05:00
// Overwrite the package's version to avoid version mismatch errors with the CLI.
this . _overwritePackageVersion ( key , tmpConfig , packageConfig , parsedLockfile ) ;
2019-02-04 07:31:43 -05:00
fs . writeFileSync ( pkg . packageJsonPath , JSON . stringify ( tmpConfig , null , 2 ) ) ;
2017-10-09 06:11:13 -04:00
} ) ;
2017-10-06 05:48:18 -04:00
2017-10-09 06:11:13 -04:00
const [ dependencies , peers ] = this . _collectDependencies ( packageConfig . dependencies || { } , packages ) ;
const [ devDependencies , devPeers ] = this . _collectDependencies ( packageConfig . devDependencies || { } , packages ) ;
2017-10-06 05:48:18 -04:00
2019-02-04 09:45:45 -05:00
this . _assignPeerDependencies ( peers , dependencies , devDependencies , parsedLockfile ) ;
this . _assignPeerDependencies ( devPeers , dependencies , devDependencies , parsedLockfile ) ;
2017-10-09 06:11:13 -04:00
const localPackageConfig = Object . assign ( Object . create ( null ) , packageConfig , { dependencies , devDependencies } ) ;
localPackageConfig . _ _angular = { local : true } ;
const localPackageConfigJson = JSON . stringify ( localPackageConfig , null , 2 ) ;
try {
this . _log ( ` Writing temporary local ${ PACKAGE _JSON } to ${ pathToPackageConfig } ` ) ;
fs . writeFileSync ( pathToPackageConfig , localPackageConfigJson ) ;
2019-02-04 08:03:25 -05:00
this . _installDeps ( '--pure-lockfile' , '--check-files' ) ;
2017-10-09 06:11:13 -04:00
this . _setLocalMarker ( localPackageConfigJson ) ;
} finally {
this . _log ( ` Restoring original ${ PACKAGE _JSON } to ${ pathToPackageConfig } ` ) ;
fs . writeFileSync ( pathToPackageConfig , packageConfigFile ) ;
}
2017-10-06 05:48:18 -04:00
} finally {
2020-02-29 14:05:23 -05:00
// Restore local Angular/Zone.js packages dependencies to other Angular packages.
this . _log ( ` Restoring original ${ PACKAGE _JSON } for local packages. ` ) ;
2017-10-09 06:11:13 -04:00
Object . keys ( packages ) . forEach ( key => {
const pkg = packages [ key ] ;
2019-02-04 07:31:43 -05:00
fs . writeFileSync ( pkg . packageJsonPath , JSON . stringify ( pkg . config , null , 2 ) ) ;
2017-10-09 06:11:13 -04:00
} ) ;
2017-10-06 05:48:18 -04:00
}
}
}
/ * *
* Reinstall the original package . json depdendencies
* Yarn will also delete the local marker file for us .
* /
restoreNpmDependencies ( ) {
2017-10-19 05:19:45 -04:00
this . _installDeps ( '--frozen-lockfile' , '--check-files' ) ;
2017-10-06 05:48:18 -04:00
}
// Protected helpers
2019-02-04 09:45:45 -05:00
_assignPeerDependencies ( peerDependencies , dependencies , devDependencies , parsedLockfile ) {
2017-10-06 05:48:18 -04:00
Object . keys ( peerDependencies ) . forEach ( key => {
2019-02-04 09:45:45 -05:00
const peerDepRange = peerDependencies [ key ] ;
// Ignore peerDependencies whose range is already satisfied by current version in lockfile.
const originalRange = dependencies [ key ] || devDependencies [ key ] ;
const lockfileVersion = originalRange && parsedLockfile [ ` ${ key } @ ${ originalRange } ` ] . version ;
if ( lockfileVersion && semver . satisfies ( lockfileVersion , peerDepRange ) ) return ;
2017-10-06 05:48:18 -04:00
// If there is already an equivalent dependency then override it - otherwise assign/override the devDependency
if ( dependencies [ key ] ) {
2019-02-04 09:45:45 -05:00
this . _log ( ` Overriding dependency with peerDependency: ${ key } : ${ peerDepRange } ` ) ;
dependencies [ key ] = peerDepRange ;
2017-10-06 05:48:18 -04:00
} else {
2021-04-05 12:05:54 -04:00
this . _log (
` ${ devDependencies [ key ] ? 'Overriding' : 'Assigning' } devDependency with peerDependency: ` +
` ${ key } : ${ peerDepRange } ` ) ;
2019-02-04 09:45:45 -05:00
devDependencies [ key ] = peerDepRange ;
2017-10-06 05:48:18 -04:00
}
} ) ;
}
2019-08-03 10:37:19 -04:00
/ * *
2020-02-29 14:05:23 -05:00
* Build the local Angular / Zone . js packages .
2019-08-03 10:37:19 -04:00
*
* NOTE :
* Building the packages is currently not supported on Windows , so a message is printed instead , prompting the user to
* do it themselves ( e . g . using Windows Subsystem for Linux or a docker container ) .
* /
_buildDistPackages ( ) {
const canBuild = process . platform !== 'win32' ;
if ( canBuild ) {
2020-02-29 14:05:23 -05:00
this . _log ( ` Building the local packages with: ${ DIST _PACKAGES _BUILD _SCRIPT } ` ) ;
2020-02-29 12:14:34 -05:00
shelljs . exec ( DIST _PACKAGES _BUILD _CMD ) ;
2019-08-03 10:37:19 -04:00
} else {
this . _warn ( [
2021-04-05 12:05:54 -04:00
'Automatically building the local Angular/angular-in-memory-web-api/zone.js packages is currently not ' +
'supported on Windows.' ,
2021-04-05 12:05:54 -04:00
` Please, ensure ' ${ ANGULAR _DIST _PACKAGES _DIR } ', ' ${ AIMWA _DIST _PACKAGES _DIR } ' and ` +
` ' ${ ZONEJS _DIST _PACKAGES _DIR } ' exist and are up-to-date (e.g. by running ' ${ DIST _PACKAGES _BUILD _SCRIPT } ' ` +
2021-04-05 12:05:54 -04:00
'in Git Bash for Windows, Windows Subsystem for Linux or a Linux docker container or VM).' ,
2019-08-03 10:37:19 -04:00
'' ,
'Proceeding anyway...' ,
] . join ( '\n' ) ) ;
}
}
2017-10-06 05:48:18 -04:00
_collectDependencies ( dependencies , packages ) {
const peerDependencies = Object . create ( null ) ;
const mergedDependencies = Object . assign ( Object . create ( null ) , dependencies ) ;
Object . keys ( dependencies ) . forEach ( key => {
const sourcePackage = packages [ key ] ;
if ( sourcePackage ) {
// point the core Angular packages at the distributable folder
2020-02-29 12:14:34 -05:00
mergedDependencies [ key ] = ` file: ${ sourcePackage . packageDir } ` ;
2017-10-06 05:48:18 -04:00
this . _log ( ` Overriding dependency with local package: ${ key } : ${ mergedDependencies [ key ] } ` ) ;
// grab peer dependencies
2017-10-06 17:25:27 -04:00
const sourcePackagePeerDeps = sourcePackage . config . peerDependencies || { } ;
Object . keys ( sourcePackagePeerDeps )
2020-02-29 14:05:23 -05:00
// ignore peerDependencies which are already core Angular/Zone.js packages
2017-10-06 05:48:18 -04:00
. filter ( key => ! packages [ key ] )
2017-10-06 17:25:27 -04:00
. forEach ( key => peerDependencies [ key ] = sourcePackagePeerDeps [ key ] ) ;
2017-10-06 05:48:18 -04:00
}
} ) ;
2018-03-06 12:01:25 -05:00
2017-10-06 05:48:18 -04:00
return [ mergedDependencies , peerDependencies ] ;
}
/ * *
2020-02-29 14:05:23 -05:00
* A hash of Angular / Zone . js package configs .
* ( Detected as directories in '/dist/packages-dist/' and '/dist/zone.js-dist/' that contain a top - level
* 'package.json' file . )
2017-10-06 05:48:18 -04:00
* /
_getDistPackages ( ) {
2021-04-05 12:05:54 -04:00
this . _log ( ` Distributable directory for Angular framework: ${ ANGULAR _DIST _PACKAGES _DIR } ` ) ;
this . _log ( ` Distributable directory for angular-in-memory-web-api: ${ AIMWA _DIST _PACKAGES _DIR } ` ) ;
this . _log ( ` Distributable directory for zone.js: ${ ZONEJS _DIST _PACKAGES _DIR } ` ) ;
2019-08-03 09:57:24 -04:00
2019-08-03 10:37:19 -04:00
if ( this . buildPackages ) {
this . _buildDistPackages ( ) ;
}
2020-02-29 12:14:34 -05:00
const collectPackages = containingDir => {
const packages = { } ;
for ( const dirName of shelljs . ls ( containingDir ) ) {
const packageDir = path . resolve ( containingDir , dirName ) ;
const packageJsonPath = path . join ( packageDir , PACKAGE _JSON ) ;
const packageConfig = fs . existsSync ( packageJsonPath ) ? require ( packageJsonPath ) : null ;
const packageName = packageConfig && packageConfig . name ;
if ( ! packageConfig ) {
// No `package.json` found - this directory is not a package.
continue ;
} else if ( ! packageName ) {
// No `name` property in `package.json`. (This should never happen.)
throw new Error ( ` Package ' ${ packageDir } ' specifies no name in its ' ${ PACKAGE _JSON } '. ` ) ;
} else if ( this . ignorePackages . includes ( packageName ) ) {
this . _log ( ` Ignoring package ' ${ packageName } '. ` ) ;
continue ;
2019-08-03 09:57:24 -04:00
}
2020-02-29 12:14:34 -05:00
packages [ packageName ] = {
packageDir ,
packageJsonPath ,
config : packageConfig ,
} ;
}
return packages ;
} ;
2020-02-29 14:05:23 -05:00
const packageConfigs = {
... collectPackages ( ANGULAR _DIST _PACKAGES _DIR ) ,
2021-04-05 12:05:54 -04:00
... collectPackages ( AIMWA _DIST _PACKAGES _DIR ) ,
2020-02-29 14:05:23 -05:00
... collectPackages ( ZONEJS _DIST _PACKAGES _DIR ) ,
} ;
2017-10-06 17:25:27 -04:00
2021-04-05 12:05:54 -04:00
this . _log ( 'Found the following Angular distributables:' , ... Object . keys ( packageConfigs ) . map ( key => ` \n - ${ key } ` ) ) ;
2017-10-06 05:48:18 -04:00
return packageConfigs ;
}
_installDeps ( ... options ) {
const command = 'yarn install ' + options . join ( ' ' ) ;
this . _log ( 'Installing dependencies with:' , command ) ;
shelljs . exec ( command , { cwd : this . projectDir } ) ;
}
/ * *
* Log a message if the ` debug ` property is set to true .
2021-04-05 12:05:54 -04:00
* @ param { string [ ] } messages - The messages to be logged .
2017-10-06 05:48:18 -04:00
* /
_log ( ... messages ) {
if ( this . debug ) {
const header = ` [ ${ NgPackagesInstaller . name } ]: ` ;
const indent = ' ' . repeat ( header . length ) ;
const message = messages . join ( ' ' ) ;
console . info ( ` ${ header } ${ message . split ( '\n' ) . join ( ` \n ${ indent } ` ) } ` ) ;
}
}
fix(docs-infra): avoid version mismatch error when using local Angular packages (#34213)
The local Angular packages used to build `aio/` when running
`yarn setup-local`/`yarn build-local` (and related commands), are built
by bazel. Bazel, determines the version to use for these locally built
packages based on the latest tag for a commit on the current branch.
(This works as expected during the release, because the packages are
built on the correct branch with up-to-date tags.)
During local development, however, this often leads to generating older
versions than what the current `@angular/cli` version is compatible
with, if the user has not fetched the latest tags from `angular/angular`
or the branch has not been rebased recently.
Previously, the above (common) situation would result in a build error
by the CLI. (Note that this would be a false error, because in this case
the version set by bazel would not reflect the actual version of the
local packages.) The solution would be for the user to fetch the latest
tags from `angular/angular`, rebase their branch and run a bazel build
again (ensuring that it would actually build anew and not emit cached
artifacts). This was cumbersome and most people didn't even know about
it.
This commit avoids this error and the associated pain-points by
overwriting the versions of the installed local packages with fake
versions based on the ones in the lockfile, which are guaranteed to be
compatible with the currently used CLI version.
Fixes #34208
PR Close #34213
2019-12-03 08:38:09 -05:00
/ * *
* Update a package 's version with the fake version based on the package' s original version in the projects ' s
* lockfile .
*
* * * Background : * *
* This helps avoid version mismatch errors with the CLI .
* Since the version set by bazel on the locally built packages is determined based on the latest tag for a commit on
* the current branch , it is often the case that this version is older than what the current ` @angular/cli ` version is
* compatible with ( e . g . if the user has not fetched the latest tags from ` angular/angular ` or the branch has not been
* rebased recently .
*
* @ param { string } packageName - The name of the package we are updating ( e . g . ` '@angular/core' ` ) .
* @ param { { [ key : string ] : any } } packageConfig - The package ' s parsed ` package.json ` .
* @ param { { [ key : string ] : any } } projectConfig - The project ' s parsed ` package.json ` .
* @ param { import ( '@yarnpkg/lockfile' ) . LockFileObject } projectLockfile - The projects ' s parsed ` yarn.lock ` .
* /
_overwritePackageVersion ( packageName , packageConfig , projectConfig , projectLockfile ) {
2019-12-03 15:14:48 -05:00
const projectVersionRange = ( projectConfig . dependencies || { } ) [ packageName ] ||
( projectConfig . devDependencies || { } ) [ packageName ] ;
const projectVersion = ( projectLockfile [ ` ${ packageName } @ ${ projectVersionRange } ` ] || { } ) . version ;
fix(docs-infra): avoid version mismatch error when using local Angular packages (#34213)
The local Angular packages used to build `aio/` when running
`yarn setup-local`/`yarn build-local` (and related commands), are built
by bazel. Bazel, determines the version to use for these locally built
packages based on the latest tag for a commit on the current branch.
(This works as expected during the release, because the packages are
built on the correct branch with up-to-date tags.)
During local development, however, this often leads to generating older
versions than what the current `@angular/cli` version is compatible
with, if the user has not fetched the latest tags from `angular/angular`
or the branch has not been rebased recently.
Previously, the above (common) situation would result in a build error
by the CLI. (Note that this would be a false error, because in this case
the version set by bazel would not reflect the actual version of the
local packages.) The solution would be for the user to fetch the latest
tags from `angular/angular`, rebase their branch and run a bazel build
again (ensuring that it would actually build anew and not emit cached
artifacts). This was cumbersome and most people didn't even know about
it.
This commit avoids this error and the associated pain-points by
overwriting the versions of the installed local packages with fake
versions based on the ones in the lockfile, which are guaranteed to be
compatible with the currently used CLI version.
Fixes #34208
PR Close #34213
2019-12-03 08:38:09 -05:00
2019-12-03 15:14:48 -05:00
if ( projectVersion !== undefined ) {
const newVersion = ` ${ projectVersion } +locally-overwritten-by-ngPackagesInstaller ` ;
fix(docs-infra): avoid version mismatch error when using local Angular packages (#34213)
The local Angular packages used to build `aio/` when running
`yarn setup-local`/`yarn build-local` (and related commands), are built
by bazel. Bazel, determines the version to use for these locally built
packages based on the latest tag for a commit on the current branch.
(This works as expected during the release, because the packages are
built on the correct branch with up-to-date tags.)
During local development, however, this often leads to generating older
versions than what the current `@angular/cli` version is compatible
with, if the user has not fetched the latest tags from `angular/angular`
or the branch has not been rebased recently.
Previously, the above (common) situation would result in a build error
by the CLI. (Note that this would be a false error, because in this case
the version set by bazel would not reflect the actual version of the
local packages.) The solution would be for the user to fetch the latest
tags from `angular/angular`, rebase their branch and run a bazel build
again (ensuring that it would actually build anew and not emit cached
artifacts). This was cumbersome and most people didn't even know about
it.
This commit avoids this error and the associated pain-points by
overwriting the versions of the installed local packages with fake
versions based on the ones in the lockfile, which are guaranteed to be
compatible with the currently used CLI version.
Fixes #34208
PR Close #34213
2019-12-03 08:38:09 -05:00
this . _log ( ` Overwriting the version of ' ${ packageName } ': ${ packageConfig . version } --> ${ newVersion } ` ) ;
packageConfig . version = newVersion ;
}
}
2019-08-03 11:14:27 -04:00
/ * *
* Extract the value for a boolean cli argument / option . When passing an option multiple times , ` yargs ` parses it as an
* array of boolean values . In that case , we only care about the last occurrence .
*
* This can be useful , for example , when one has a base command with the option turned on and another command
* ( building on top of the first one ) turning the option off :
* ` ` `
* "base-command" : "my-script --foo --bar" ,
* "no-bar-command" : "yarn base-command --no-bar" ,
* ` ` `
* /
_parseBooleanArg ( value ) {
return Array . isArray ( value ) ? value . pop ( ) : value ;
}
2019-02-04 09:45:45 -05:00
/ * *
* Parse and return a ` yarn.lock ` file .
* /
_parseLockfile ( lockfilePath ) {
const lockfileContent = fs . readFileSync ( lockfilePath , 'utf8' ) ;
const parsed = lockfile . parse ( lockfileContent ) ;
if ( parsed . type !== 'success' ) {
2021-04-05 12:05:54 -04:00
throw new Error (
` [ ${ NgPackagesInstaller . name } ]: Error parsing lockfile ' ${ lockfilePath } ' (result type: ${ parsed . type } ). ` ) ;
2019-02-04 09:45:45 -05:00
}
return parsed . object ;
}
2017-10-06 05:48:18 -04:00
_printWarning ( ) {
const relativeScriptPath = path . relative ( '.' , _ _filename . replace ( /\.js$/ , '' ) ) ;
const absoluteProjectDir = path . resolve ( this . projectDir ) ;
const restoreCmd = ` node ${ relativeScriptPath } restore ${ absoluteProjectDir } ` ;
// Log a warning.
2019-08-03 10:37:19 -04:00
this . _warn ( [
2020-02-29 14:05:23 -05:00
` The project at " ${ absoluteProjectDir } " is running against the local Angular/Zone.js build. ` ,
2019-08-03 10:37:19 -04:00
'' ,
'To restore the npm packages run:' ,
'' ,
` " ${ restoreCmd } " ` ,
] . join ( '\n' ) ) ;
}
/ * *
* Log a warning message do draw user ' s attention .
2021-04-05 12:05:54 -04:00
* @ param { string [ ] } messages - The messages to be logged .
2019-08-03 10:37:19 -04:00
* /
_warn ( ... messages ) {
const lines = messages . join ( ' ' ) . split ( '\n' ) ;
2017-10-06 05:48:18 -04:00
console . warn ( chalk . yellow ( [
'' ,
'!' . repeat ( 110 ) ,
'!!!' ,
'!!! WARNING' ,
'!!!' ,
2019-08-03 10:37:19 -04:00
... lines . map ( line => ` !!! ${ line } ` ) ,
2017-10-06 05:48:18 -04:00
'!!!' ,
'!' . repeat ( 110 ) ,
'' ,
] . join ( '\n' ) ) ) ;
}
// Local marker helpers
_checkLocalMarker ( ) {
this . _log ( 'Checking for local marker at' , this . localMarkerPath ) ;
return fs . existsSync ( this . localMarkerPath ) ;
}
_setLocalMarker ( contents ) {
this . _log ( 'Writing local marker file to' , this . localMarkerPath ) ;
fs . writeFileSync ( this . localMarkerPath , contents ) ;
}
}
function main ( ) {
shelljs . set ( '-e' ) ;
2019-08-03 09:57:24 -04:00
const createInstaller = argv => {
const { projectDir , ... options } = argv ;
return new NgPackagesInstaller ( projectDir , options ) ;
} ;
2021-04-05 12:05:54 -04:00
/* eslint-disable max-len */
2017-10-06 05:48:18 -04:00
yargs
. usage ( '$0 <cmd> [args]' )
. option ( 'debug' , { describe : 'Print additional debug information.' , default : false } )
. option ( 'force' , { describe : 'Force the command to execute even if not needed.' , default : false } )
2020-02-29 14:05:23 -05:00
. option ( 'build-packages' , { describe : 'Build the local Angular/Zone.js packages, before using them.' , default : false } )
. option ( 'ignore-packages' , { describe : 'List of Angular/Zone.js packages that should not be used in local mode.' , default : [ ] , array : true } )
2017-10-06 05:48:18 -04:00
2020-02-29 14:05:23 -05:00
. command ( 'overwrite <projectDir> [--force] [--debug] [--ignore-packages package1 package2]' , 'Install dependencies from the locally built Angular/Zone.js distributables.' , ( ) => { } , argv => {
2019-08-03 09:57:24 -04:00
createInstaller ( argv ) . installLocalDependencies ( ) ;
2017-10-06 05:48:18 -04:00
} )
. command ( 'restore <projectDir> [--debug]' , 'Install dependencies from the npm registry.' , ( ) => { } , argv => {
2019-08-03 09:57:24 -04:00
createInstaller ( argv ) . restoreNpmDependencies ( ) ;
2017-10-06 05:48:18 -04:00
} )
. command ( 'check <projectDir> [--debug]' , 'Check that dependencies came from npm. Otherwise display a warning message.' , ( ) => { } , argv => {
2019-08-03 09:57:24 -04:00
createInstaller ( argv ) . checkDependencies ( ) ;
2017-10-06 05:48:18 -04:00
} )
. demandCommand ( 1 , 'Please supply a command from the list above.' )
. strict ( )
. wrap ( yargs . terminalWidth ( ) )
. argv ;
2021-04-05 12:05:54 -04:00
/* eslint-enable max-len */
2017-10-06 05:48:18 -04:00
}
module . exports = NgPackagesInstaller ;
if ( require . main === module ) {
main ( ) ;
2017-10-06 17:25:27 -04:00
}