@@ -4,32 +4,22 @@ const path = require('path');
4
4
const tmp = require ( 'tmp' ) ;
5
5
const shelljs = require ( 'shelljs' ) ;
6
6
7
+ const nodeCleanup = require ( 'node-cleanup' ) ;
7
8
const publishYalcPackage = require ( './publish_yalc_package' ) ;
9
+
8
10
const util = require ( './util' ) ;
9
11
util . packageDir ( ) ;
10
12
const PKG_DIR = process . cwd ( ) ;
11
13
12
14
const config = JSON . parse ( fs . readFileSync ( 'downstream_projects.json' ) ) ;
13
15
const pkgjson = JSON . parse ( fs . readFileSync ( 'package.json' ) ) ;
14
16
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 ) ;
20
17
const DOWNSTREAM_PKGS = ( process . env . DOWNSTREAM_PKGS || '' ) . split ( ',' ) . filter ( x => x ) ;
21
18
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' ) ;
33
23
34
24
function makeDownstreamCache ( ) {
35
25
if ( ! fs . existsSync ( DOWNSTREAM_CACHE ) ) {
@@ -38,27 +28,19 @@ function makeDownstreamCache() {
38
28
}
39
29
}
40
30
41
- function localPublish ( ) {
42
- process . chdir ( PKG_DIR ) ;
31
+ function localPublish ( packageDir ) {
32
+ packageDir = packageDir || PKG_DIR ;
33
+ process . chdir ( packageDir ) ;
43
34
console . log ( 'Publishing using yalc...' ) ;
44
35
util . _exec ( 'yalc publish' ) ;
45
36
}
46
37
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 ) ) ;
49
40
}
50
41
51
42
function 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` ) ;
62
44
}
63
45
64
46
function revertLocalChanges ( source ) {
@@ -68,53 +50,97 @@ function revertLocalChanges(source) {
68
50
util . _exec ( 'git clean --force -d' ) ;
69
51
}
70
52
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 ;
74
58
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 ) ;
77
66
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 ) ;
82
74
}
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
+ }
83
86
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
+ ]
108
97
}
98
+ } ;
109
99
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
+ }
113
104
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 ) ;
120
119
}
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