1
1
const debug = require ( 'debug' ) ( 'codefresh:cli:run:pipeline' ) ;
2
2
const Command = require ( '../../Command' ) ;
3
- const { crudFilenameOption } = require ( '../../helpers/general' ) ;
4
- const RunLocalCommand = require ( './run.local' ) ;
5
- const RunExternalCommand = require ( './run.cf' ) ;
3
+ const _ = require ( 'lodash' ) ;
4
+ const CFError = require ( 'cf-errors' ) ;
5
+ const { prepareKeyValueFromCLIEnvOption, crudFilenameOption } = require ( '../../helpers/general' ) ;
6
+ const { workflow, pipeline, log } = require ( '../../../../logic' ) . api ;
7
+ const authManager = require ( '../../../../logic' ) . auth . manager ;
8
+ const Docker = require ( 'dockerode' ) ;
9
+ const { validatePipelineYaml } = require ( '../../helpers/validation' ) ;
10
+ const { printResult } = require ( '../root/validate.cmd' ) ;
11
+ const DEFAULTS = require ( '../../defaults' ) ;
12
+ const path = require ( 'path' ) ;
13
+ const regex = / # # [ 0 - 9 a - f ] { 24 } # # / i;
14
+ const imageName = 'codefresh/engine:master' ;
6
15
7
- function getCommandFlavor ( argv ) {
8
- if ( argv . local ) {
9
- return new RunLocalCommand ( argv ) ;
16
+
17
+ function _customizer ( objValue , srcValue ) {
18
+ if ( Array . isArray ( objValue ) ) {
19
+ return _ . compact ( objValue . concat ( srcValue ) ) ;
10
20
}
11
- return new RunExternalCommand ( argv ) ;
12
21
}
13
-
14
22
const run = new Command ( {
15
23
root : true ,
16
24
command : 'run <name>' ,
@@ -72,11 +80,6 @@ const run = new Command({
72
80
describe : 'Use your file system as volume in local run' ,
73
81
alias : 'lv' ,
74
82
} )
75
- . option ( 'no-cf-cache' , {
76
- describe : 'Ignore Codefresh cache optimizations' ,
77
- alias : 'ncfc' ,
78
- default : false ,
79
- } )
80
83
. example ( 'codefresh run PIPELINE_ID | PIPELINE_NAME -b=master' , 'Defining the source control context using a branch' )
81
84
. example ( 'codefresh run PIPELINE_ID | PIPELINE_NAME -s=52b992e783d2f84dd0123c70ac8623b4f0f938d1' , 'Defining the source control context using a commit' )
82
85
. example ( 'codefresh run PIPELINE_ID | PIPELINE_NAME -b=master -v key1=value1 -v key2=value2' , 'Setting variables through the command' )
@@ -99,11 +102,158 @@ const run = new Command({
99
102
return yargs ;
100
103
} ,
101
104
handler : async ( argv ) => {
102
- const flavor = getCommandFlavor ( argv ) ;
103
- await flavor . preRunAll ( ) ;
104
- const exitCode = await flavor . run ( ) ;
105
- await flavor . postRunAll ( ) ;
106
- process . exit ( exitCode ) ;
105
+ const pipelineName = argv . name ;
106
+ const branch = argv . branch ;
107
+ const sha = argv . sha ;
108
+ const noCache = argv [ 'no-cache' ] ;
109
+ const enableNotifications = argv [ 'enable-notifications' ] ;
110
+ const resetVolume = argv [ 'reset-volume' ] ;
111
+ const variablesFromFile = argv [ 'var-file' ] ;
112
+ const contexts = argv . context ;
113
+ const userYamlDescriptor = argv . yaml ;
114
+ const local = argv . local ;
115
+ const localVolume = argv [ 'local-volume' ] === true ? path . join ( DEFAULTS . CODEFRESH_PATH , pipelineName ) : argv [ 'local-volume' ] ;
116
+
117
+ try {
118
+ await pipeline . getPipelineByName ( pipelineName ) ;
119
+ } catch ( err ) {
120
+ throw new CFError ( {
121
+ message : `Passed pipeline id: ${ pipelineName } does not exist` ,
122
+ } ) ;
123
+ }
124
+
125
+ if ( userYamlDescriptor ) {
126
+ const result = await validatePipelineYaml ( undefined , userYamlDescriptor ) ;
127
+ printResult ( result ) ;
128
+ }
129
+
130
+ if ( local ) {
131
+ const docker = new Docker ( ) ;
132
+ const cleanupActions = [ ] ;
133
+ const injectedOpts = { } ;
134
+ // TODO : Move to per command's handler so each command will be handled in a seperate handler
135
+ if ( userYamlDescriptor ) {
136
+ injectedOpts . Env = [ `OVERRIDE_WORKFLOW_YAML=${ userYamlDescriptor } ` ] ;
137
+ }
138
+
139
+ console . log ( `Updating Codefresh engine ==>` ) ;
140
+ docker . pull ( imageName , ( err , stream ) => {
141
+ docker . modem . followProgress ( stream , onFinished , onProgress ) ;
142
+ function onFinished ( err ) {
143
+ if ( ! err ) {
144
+ console . log ( 'Finished Update.\n' ) ;
145
+
146
+ if ( localVolume ) {
147
+ injectedOpts . Env = [ `EXTERNAL_WORKSPACE=${ localVolume } ` ] ;
148
+ console . log ( `\nUsing ${ localVolume } as a local volume.\n` ) ;
149
+ }
150
+
151
+ const currentContext = authManager . getCurrentContext ( ) ;
152
+ console . log ( `Running pipeline: ${ pipelineName } ` ) ;
153
+
154
+ docker . run ( imageName , [ ] , [ ] , _ . mergeWith ( {
155
+ Env : [
156
+ `ACCESS_TOKEN=${ currentContext . token } ` ,
157
+ `PIPELINE_ID=${ pipelineName } ` , `BRANCH=${ branch } ` ,
158
+ `CF_HOST=${ currentContext . url } ` ,
159
+ 'DOCKER_SOCKET_PATH=/var/run/docker.sock' ,
160
+ 'NO_EXT_MONITOR=true' ,
161
+ ] ,
162
+ Hostconfig : {
163
+ Binds : [
164
+ '/var/run/docker.sock:/var/run/docker.sock' ,
165
+ ] ,
166
+ } ,
167
+ } , injectedOpts , _customizer ) , ( err , data ) => {
168
+ cleanupActions . forEach ( ( action ) => {
169
+ try {
170
+ action ( ) ;
171
+ } catch ( error ) {
172
+ console . error ( err ) ;
173
+ }
174
+ } ) ;
175
+ if ( err ) {
176
+ return console . error ( err ) ;
177
+ }
178
+ process . exit ( data . StatusCode ) ;
179
+ } ) . on ( 'stream' , ( stream ) => {
180
+ stream . on ( 'data' , ( chunk ) => {
181
+ const line = chunk . toString ( ) ;
182
+ const include = line . match ( regex ) ;
183
+ if ( include ) {
184
+ const workflowId = include [ 0 ] . substring ( 2 , include [ 0 ] . length - 2 ) ;
185
+ log . showWorkflowLogs ( workflowId , true )
186
+ . then ( ( ) => Promise . resolve ( ) ) ;
187
+ }
188
+ } ) ;
189
+ } ) ;
190
+ } else {
191
+ console . log ( err ) ;
192
+ process . exit ( 1 ) ;
193
+ }
194
+ }
195
+ function onProgress ( ) {
196
+ stream . pipe ( process . stdout ) ;
197
+ }
198
+ } ) ;
199
+ } else {
200
+ const executionRequests = [ ] ;
201
+ const executionRequestTemplate = {
202
+ pipelineName,
203
+ options : {
204
+ noCache,
205
+ resetVolume,
206
+ branch,
207
+ sha,
208
+ enableNotifications,
209
+ userYamlDescriptor,
210
+ } ,
211
+ } ;
212
+
213
+ if ( variablesFromFile ) {
214
+ _ . forEach ( variablesFromFile , ( variables ) => {
215
+ const request = _ . cloneDeep ( executionRequestTemplate ) ;
216
+ request . options . variables = variables ;
217
+ executionRequests . push ( request ) ;
218
+ } ) ;
219
+ } else {
220
+ const variables = prepareKeyValueFromCLIEnvOption ( argv . variable ) ;
221
+ const request = _ . cloneDeep ( executionRequestTemplate ) ;
222
+ request . options . variables = variables ;
223
+ request . options . contexts = contexts ;
224
+ executionRequests . push ( request ) ;
225
+ }
226
+
227
+ _ . forEach ( executionRequests , async ( { pipelineName, options } ) => {
228
+ let workflowId ;
229
+ workflowId = await pipeline . runPipelineByName ( pipelineName , options ) ;
230
+
231
+ if ( executionRequests . length === 1 ) {
232
+ if ( argv . detach ) {
233
+ console . log ( workflowId ) ;
234
+ } else {
235
+ await log . showWorkflowLogs ( workflowId , true ) ;
236
+ const workflowInstance = await workflow . getWorkflowById ( workflowId ) ;
237
+ switch ( workflowInstance . getStatus ( ) ) {
238
+ case 'success' :
239
+ process . exit ( 0 ) ;
240
+ break ;
241
+ case 'error' :
242
+ process . exit ( 1 ) ;
243
+ break ;
244
+ case 'terminated' :
245
+ process . exit ( 2 ) ;
246
+ break ;
247
+ default :
248
+ process . exit ( 100 ) ;
249
+ break ;
250
+ }
251
+ }
252
+ } else {
253
+ console . log ( workflowId ) ;
254
+ }
255
+ } ) ;
256
+ }
107
257
} ,
108
258
} ) ;
109
259
0 commit comments