@@ -15,6 +15,7 @@ import { Operation } from './operation/operation';
15
15
import { Task } from './operation/task' ;
16
16
import { ResourceConfig } from '../config/resource-config' ;
17
17
import { OperationConfig } from '../config/operation-config' ;
18
+ import { TaskArgData } from '../config/types' ;
18
19
import { octokitAuth } from '../utility/probot/octokit' ;
19
20
20
21
export class Service {
@@ -26,6 +27,11 @@ export class Service {
26
27
27
28
private _app : Probot ;
28
29
30
+ // Map<eventName, Map<taskName, returnValue>>
31
+ private _outputs : Map < string , Map < string , any > > ;
32
+
33
+ private readonly subPattern = / \$ \{ \{ \s * ( .* ?) \s * \} \} / ;
34
+
29
35
constructor ( name : string ) {
30
36
this . _name = name ;
31
37
}
@@ -55,6 +61,7 @@ export class Service {
55
61
this . _resource = await resConfigObj . initResource ( ) ;
56
62
const opConfigObj = new OperationConfig ( operationConfigPath ) ;
57
63
this . _operation = await opConfigObj . initOperation ( ) ;
64
+ this . _outputs = new Map < string , any > ( ) ;
58
65
this . _registerEvents ( ) ;
59
66
}
60
67
@@ -63,35 +70,73 @@ export class Service {
63
70
await promise ; // Make sure tasks are completed in sequential orders
64
71
65
72
const callPath = await realpath ( `./bin/call/${ task . callName } .js` ) ;
66
- const { callFunc } = task ;
67
- const { callArgs } = task ;
73
+ const { name, callFunc, callArgs } = task ;
68
74
69
- console . log ( `[${ event } ]: Verify call lib: ${ callPath } ` ) ;
75
+ console . log ( `[${ event } ]: Start call now: ${ name } ` ) ;
76
+ console . log ( `[${ event } ]: Check call lib: ${ callPath } ` ) ;
70
77
try {
71
78
await access ( callPath ) ;
72
79
} catch ( e ) {
73
80
console . error ( `ERROR: ${ e } ` ) ;
74
81
}
75
82
76
83
const callStack = await import ( callPath ) ;
84
+ const callArgsSub = await this . _outputsSubstitution ( { ...callArgs } , event ) ;
85
+
77
86
if ( callFunc === 'default' ) {
78
87
console . log ( `[${ event } ]: Call default function: [${ callStack . default . name } ]` ) ;
79
- await callStack . default ( this . app , context , this . resource , { ...callArgs } ) ;
88
+ const resultDefault = await callStack . default ( this . app , context , this . resource , { ...callArgsSub } ) ;
89
+ this . _outputs . get ( event ) ?. set ( name , resultDefault ) ;
90
+ console . log ( this . _outputs . get ( event ) ) ;
80
91
} else {
81
92
console . log ( callStack ) ;
82
93
const callFuncCustom = callStack [ callFunc ] ;
83
94
console . log ( `[${ event } ]: Call custom function: [${ callFuncCustom . name } ]` ) ;
84
95
if ( ! ( typeof callFuncCustom === 'function' ) ) {
85
96
throw new Error ( `[${ event } ]: ${ callFuncCustom } is not a function, please verify in ${ callPath } ` ) ;
86
97
}
87
- await callFuncCustom ( this . app , context , this . resource , { ...callArgs } ) ;
98
+ this . _outputs . get ( event ) ?. set ( name , await callFuncCustom ( this . app , context , this . resource , { ...callArgsSub } ) ) ;
88
99
}
89
100
} , Promise . resolve ( ) ) ;
90
101
}
91
102
103
+ private async _outputsSubstitution ( callArgs : TaskArgData , event : string ) : Promise < TaskArgData > {
104
+ console . log ( `[${ event } ]: Call with args:` ) ;
105
+
106
+ const callArgsTemp = callArgs ;
107
+ const argEntries = Object . entries ( callArgsTemp ) ;
108
+
109
+ await Promise . all (
110
+ argEntries . map ( async ( [ argName , argValue ] ) => {
111
+ console . log ( `[${ event } ]: args: ${ argName } : ${ argValue } ` ) ;
112
+
113
+ // Overwrite callArgsTemp if user choose to substitute value with outputs from previous task ${{ outputs.<TaskName>#<TaskOrder> }}
114
+ if ( Array . isArray ( argValue ) ) {
115
+ // string[]
116
+ callArgsTemp [ argName ] = await Promise . all ( argValue . map ( async ( argValueItem ) => this . _matchSubPattern ( argValueItem as string , event ) ) ) ;
117
+ } else {
118
+ // string
119
+ callArgsTemp [ argName ] = await this . _matchSubPattern ( argValue as string , event ) ;
120
+ }
121
+ } ) ,
122
+ ) ;
123
+ return callArgsTemp ;
124
+ }
125
+
126
+ private async _matchSubPattern ( callArgsValue : string , event : string ) : Promise < string > {
127
+ const match = callArgsValue . match ( this . subPattern ) ;
128
+ if ( match ) {
129
+ // If user substitution pattern ${{ outputs.<TaskName>#<TaskOrder> }} found in operation config
130
+ // Return substituion value based on return value saved in outputs
131
+ const outputMatch = this . _outputs . get ( event ) ?. get ( match [ 1 ] . replace ( 'outputs.' , '' ) ) ;
132
+ console . log ( `StrSub: ${ callArgsValue } , Match: ${ match [ 1 ] } , Output: ${ outputMatch } ` ) ;
133
+ return outputMatch ;
134
+ }
135
+ return callArgsValue ;
136
+ }
137
+
92
138
private async _registerEvents ( ) : Promise < void > {
93
- const { events } = this . operation ;
94
- const { tasks } = this . operation ;
139
+ const { events, tasks } = this . operation ;
95
140
console . log ( `Evaluate events: [${ events } ]` ) ;
96
141
if ( ! events ) {
97
142
throw new Error ( 'No events defined in the operation!' ) ;
@@ -102,6 +147,7 @@ export class Service {
102
147
103
148
events . forEach ( ( event ) => {
104
149
console . log ( `Register event: "${ event } "` ) ;
150
+ this . _outputs . set ( event , new Map < string , any > ( ) ) ;
105
151
if ( event === 'all' ) {
106
152
console . warn ( 'WARNING! All events will be listened based on the config!' ) ;
107
153
this . _app . onAny ( async ( context ) => {
0 commit comments