@@ -4,32 +4,22 @@ const path = require('path');
44const tmp = require ( 'tmp' ) ;
55const shelljs = require ( 'shelljs' ) ;
66
7+ const nodeCleanup = require ( 'node-cleanup' ) ;
78const publishYalcPackage = require ( './publish_yalc_package' ) ;
9+
810const util = require ( './util' ) ;
911util . packageDir ( ) ;
1012const PKG_DIR = process . cwd ( ) ;
1113
1214const config = JSON . parse ( fs . readFileSync ( 'downstream_projects.json' ) ) ;
1315const pkgjson = JSON . parse ( fs . readFileSync ( 'package.json' ) ) ;
1416
15- const DOWNSTREAM_CACHE = path . resolve ( PKG_DIR , '.downstream_cache' ) ;
16- const TEMP = tmp . dirSync ( ) ;
17- const TEMP_DIR = TEMP . name ;
18-
19- const UPSTREAM_PKGS = ( process . env . UPSTREAM_PKGS || '' ) . split ( ',' ) . filter ( x => x ) . concat ( pkgjson . name ) ;
2017const DOWNSTREAM_PKGS = ( process . env . DOWNSTREAM_PKGS || '' ) . split ( ',' ) . filter ( x => x ) ;
2118
22- function forEachDownstream ( callback ) {
23- Object . keys ( config ) . forEach ( key => {
24- if ( DOWNSTREAM_PKGS . length && DOWNSTREAM_PKGS . indexOf ( key ) === - 1 ) {
25- console . log ( callback . constructor . name + ": " + key + ' not in DOWNSTREAM_PKGS, skipping...' ) ;
26- return ;
27- }
28-
29- process . chdir ( path . resolve ( DOWNSTREAM_CACHE , key ) ) ;
30- callback ( key , config [ key ] ) ;
31- } ) ;
32- }
19+ const TEMP = tmp . dirSync ( ) ;
20+ const TEMP_DIR = TEMP . name ;
21+ const TEMP_DOWNSTREAM_CACHE = path . resolve ( TEMP_DIR , '.downstream_cache' ) ;
22+ const DOWNSTREAM_CACHE = path . resolve ( PKG_DIR , '.downstream_cache' ) ;
3323
3424function makeDownstreamCache ( ) {
3525 if ( ! fs . existsSync ( DOWNSTREAM_CACHE ) ) {
@@ -38,27 +28,19 @@ function makeDownstreamCache() {
3828 }
3929}
4030
41- function localPublish ( ) {
42- process . chdir ( PKG_DIR ) ;
31+ function localPublish ( packageDir ) {
32+ packageDir = packageDir || PKG_DIR ;
33+ process . chdir ( packageDir ) ;
4334 console . log ( 'Publishing using yalc...' ) ;
4435 util . _exec ( 'yalc publish' ) ;
4536}
4637
47- function installUpstreamDeps ( ) {
48- UPSTREAM_PKGS . forEach ( upstream => util . _exec ( 'yalc add ' + upstream ) ) ;
38+ function installUpstreamDeps ( upstreamPackages ) {
39+ upstreamPackages . forEach ( upstream => util . _exec ( 'yalc add ' + upstream ) ) ;
4940}
5041
5142function runTests ( ) {
52- util . _exec ( `UPSTREAM_PKGS="${ UPSTREAM_PKGS . join ( ',' ) } " npm test` ) ;
53- }
54-
55- function runDownstreamTests ( ) {
56- const downstreamPkgJson = JSON . parse ( fs . readFileSync ( 'package.json' ) ) ;
57- const hasDownstreamTests = downstreamPkgJson . scripts && ! ! downstreamPkgJson . scripts [ 'test:downstream' ] ;
58-
59- if ( hasDownstreamTests ) {
60- util . _exec ( `UPSTREAM_PKGS="${ UPSTREAM_PKGS . join ( ',' ) } " npm run test:downstream` ) ;
61- }
43+ util . _exec ( `npm test` ) ;
6244}
6345
6446function revertLocalChanges ( source ) {
@@ -68,53 +50,97 @@ function revertLocalChanges(source) {
6850 util . _exec ( 'git clean --force -d' ) ;
6951}
7052
71- try {
72- console . log ( ` ===> Making .downstream_cache working directory <===` ) ;
73- makeDownstreamCache ( ) ;
53+ function fetchDownstreamProjects ( downstreamConfig , prefix , downstreamTreeNode ) {
54+ prefix = prefix || "" ;
55+
56+ Object . keys ( downstreamConfig ) . forEach ( key => {
57+ const installDir = prefix ? `${ prefix } .${ key } ` : key ;
7458
75- console . log ( ` ===> Publishing ${ pkgjson . name } to yalc registry <===` ) ;
76- localPublish ( ) ;
59+ console . log ( ` ===> Fetching downstream project to '${ installDir } ' <===` ) ;
60+ const installSource = downstreamConfig [ key ] ;
61+ const isFile = / ^ \. / . exec ( installSource ) ;
62+ const installSourcePath = prefix ? path . resolve ( DOWNSTREAM_CACHE , prefix , installSource ) : path . resolve ( PKG_DIR , installSource ) ;
63+ const installSourceForYalc = isFile ? './' + path . relative ( process . cwd ( ) , installSourcePath ) : installSource ;
64+ const flags = { noBuild : true , noPublish : true , noInstall : true } ;
65+ publishYalcPackage ( path . resolve ( DOWNSTREAM_CACHE , installDir ) , installSourceForYalc , flags ) ;
7766
78- Object . keys ( config ) . forEach ( key => {
79- if ( DOWNSTREAM_PKGS . length && DOWNSTREAM_PKGS . indexOf ( key ) === - 1 ) {
80- console . log ( `${ key } not in DOWNSTREAM_PKGS, skipping...` ) ;
81- return ;
67+ const children = { } ;
68+ downstreamTreeNode [ key ] = { installDir, installSource, children } ;
69+
70+ const nestedDownstreamConfigPath = path . resolve ( DOWNSTREAM_CACHE , installDir , 'downstream_projects.json' ) ;
71+ if ( fs . existsSync ( nestedDownstreamConfigPath ) ) {
72+ const nestedDownstreamConfig = JSON . parse ( fs . readFileSync ( nestedDownstreamConfigPath ) ) ;
73+ fetchDownstreamProjects ( nestedDownstreamConfig , installDir , children ) ;
8274 }
75+ } ) ;
76+ }
77+
78+ function getDownstreamInstallDirs ( downstreamTreeNode ) {
79+ const children = Object . keys ( downstreamTreeNode . children ) ;
80+ const childrenInstallDirs = children . map ( key => getDownstreamInstallDirs ( downstreamTreeNode . children [ key ] ) ) ;
81+ return [ downstreamTreeNode . installDir ]
82+ . concat ( childrenInstallDirs )
83+ . reduce ( ( acc , arr ) => acc . concat ( arr ) , [ ] )
84+ . filter ( x => ! ! x ) ;
85+ }
8386
84- const DOWNSTREAM_PACKAGE_DIR = path . resolve ( DOWNSTREAM_CACHE , key ) ;
85- process . chdir ( PKG_DIR ) ;
86-
87- console . log ( ` ===> Fetching downstream project '${ key } ' and its dependencies <===` ) ;
88- const installTargetDir = DOWNSTREAM_PACKAGE_DIR ;
89- const installSource = config [ key ] ;
90- const flags = { noBuild : true , noPublish : true } ;
91- publishYalcPackage ( installTargetDir , installSource , flags ) ;
92-
93- console . log ( ` ===> Installing freshly built upstream packages <===` ) ;
94- process . chdir ( DOWNSTREAM_PACKAGE_DIR ) ;
95- installUpstreamDeps ( ) ;
96-
97- const DOWNSTREAM_PACKAGE_TEMP_DIR = path . resolve ( TEMP_DIR , path . basename ( DOWNSTREAM_PACKAGE_DIR ) ) ;
98- try {
99- console . log ( ` ===> Moving downstream project '${ key } ' to temp dir '${ TEMP_DIR } ' <===` ) ;
100- shelljs . mv ( DOWNSTREAM_PACKAGE_DIR , TEMP_DIR ) ;
101-
102- console . log ( ` ===> Running '${ key } ' tests <===` ) ;
103- process . chdir ( DOWNSTREAM_PACKAGE_TEMP_DIR ) ;
104- runTests ( ) ;
105- } finally {
106- console . log ( ` ===> Moving downstream project '${ key } ' back from temp dir <===` ) ;
107- shelljs . mv ( DOWNSTREAM_PACKAGE_TEMP_DIR , DOWNSTREAM_CACHE ) ;
87+ function installDependencies ( downstreamInstallDirs ) {
88+ const yarnWorkspacePackageJsonPath = path . resolve ( DOWNSTREAM_CACHE , "package.json" ) ;
89+ const yarnWorkspacePackageJson = {
90+ private : true ,
91+ "workspaces" : {
92+ "packages" : downstreamInstallDirs ,
93+ "nohoist" : [
94+ "**/webpack" ,
95+ "**/karma-webpack" ,
96+ ]
10897 }
98+ } ;
10999
110- console . log ( ` ===> Running '${ key } ' downstream tests <===` ) ;
111- process . chdir ( DOWNSTREAM_PACKAGE_DIR ) ;
112- runDownstreamTests ( ) ;
100+ fs . writeFileSync ( yarnWorkspacePackageJsonPath , JSON . stringify ( yarnWorkspacePackageJson , null , 2 ) ) ;
101+ process . chdir ( DOWNSTREAM_CACHE ) ;
102+ util . _exec ( 'yarn && yarn upgrade' ) ;
103+ }
113104
114- console . log ( ` ===> Cleaning downstream project '${ key } ' <===` ) ;
115- process . chdir ( DOWNSTREAM_PACKAGE_DIR ) ;
116- revertLocalChanges ( installSource ) ;
117- } ) ;
118- } finally {
119- shelljs . rm ( '-rf' , TEMP_DIR )
105+ function runDownstreamTests ( key , upstreamPackages , downstreamTreeNode ) {
106+ if ( DOWNSTREAM_PKGS . length && DOWNSTREAM_PKGS . indexOf ( key ) === - 1 ) {
107+ console . log ( `${ key } not in DOWNSTREAM_PKGS, skipping...` ) ;
108+ return ;
109+ }
110+
111+ process . chdir ( TEMP_DOWNSTREAM_CACHE ) ;
112+
113+ console . log ( ` ===> Running '${ key } ' tests <===` ) ;
114+ console . log ( ` ===> Installing freshly built upstream packages <===` ) ;
115+ process . chdir ( downstreamTreeNode . installDir ) ;
116+ installUpstreamDeps ( upstreamPackages ) ;
117+ runTests ( ) ;
118+ revertLocalChanges ( downstreamTreeNode . installSource ) ;
120119}
120+
121+ console . log ( ` ===> Creating .downstream_cache working directory <===` ) ;
122+ makeDownstreamCache ( ) ;
123+
124+ console . log ( ` ===> Publishing ${ pkgjson . name } to yalc registry <===` ) ;
125+ localPublish ( ) ;
126+
127+ console . log ( ` ===> Fetching downstream projects <===` ) ;
128+ const tree = { children : { } } ;
129+ fetchDownstreamProjects ( config , "" , tree . children ) ;
130+
131+ console . log ( ` ===> Installing downstream dependencies <===` ) ;
132+ const downstreamDirs = getDownstreamInstallDirs ( tree ) ;
133+ installDependencies ( downstreamDirs ) ;
134+
135+ console . log ( ` ===> Moving working directory to temp dir ${ TEMP_DIR } <===` ) ;
136+ shelljs . mv ( DOWNSTREAM_CACHE , TEMP_DIR ) ;
137+
138+ nodeCleanup ( ( ) => {
139+ shelljs . mv ( TEMP_DOWNSTREAM_CACHE , PKG_DIR ) ;
140+ } ) ;
141+
142+ console . log ( ` ===> Running downstream tests <===` ) ;
143+ Object . keys ( tree . children ) . forEach ( key => {
144+ console . log ( ` ===> Running tests for '${ key } ' <===` ) ;
145+ runDownstreamTests ( key , [ pkgjson . name ] , tree . children [ key ] ) ;
146+ } ) ;
0 commit comments