@@ -454,6 +454,26 @@ export default class Maestro extends BaseProvider<MaestroOptions> {
454454 // If we have a single directory, use it as base; otherwise use common ancestor or flatten
455455 const baseDir = baseDirs . length === 1 ? baseDirs [ 0 ] : undefined ;
456456
457+ // Discover dependencies (addMedia, runScript, runFlow, etc.) for all flow files
458+ // This ensures referenced files are included even when individual YAML files are passed
459+ const allFilesSet = new Set ( allFlowFiles . map ( ( f ) => path . resolve ( f ) ) ) ;
460+ for ( const flowFile of [ ...allFlowFiles ] ) {
461+ const ext = path . extname ( flowFile ) . toLowerCase ( ) ;
462+ if ( ext === '.yaml' || ext === '.yml' ) {
463+ const deps = await this . discoverDependencies (
464+ flowFile ,
465+ baseDir || path . dirname ( flowFile ) ,
466+ ) ;
467+ for ( const dep of deps ) {
468+ const resolved = path . resolve ( dep ) ;
469+ if ( ! allFilesSet . has ( resolved ) ) {
470+ allFilesSet . add ( resolved ) ;
471+ allFlowFiles . push ( dep ) ;
472+ }
473+ }
474+ }
475+ }
476+
457477 if ( ! this . options . quiet ) {
458478 this . logIncludedFiles ( allFlowFiles , baseDir ) ;
459479
@@ -918,19 +938,12 @@ export default class Maestro extends BaseProvider<MaestroOptions> {
918938 if ( typeof value === 'string' ) {
919939 if ( this . looksLikePath ( value ) ) {
920940 const resolvedPath = path . resolve ( path . dirname ( flowFile ) , value ) ;
921- // Check if the file is in included files OR exists on disk
922941 if ( ! includedFiles . has ( resolvedPath ) ) {
923- try {
924- await fs . promises . access ( resolvedPath ) ;
925- // File exists on disk but won't be included - also warn
926- } catch {
927- // File doesn't exist
928- missingReferences . push ( {
929- flowFile,
930- referencedFile : value ,
931- resolvedPath,
932- } ) ;
933- }
942+ missingReferences . push ( {
943+ flowFile,
944+ referencedFile : value ,
945+ resolvedPath,
946+ } ) ;
934947 }
935948 }
936949 } else if ( Array . isArray ( value ) ) {
@@ -958,15 +971,11 @@ export default class Maestro extends BaseProvider<MaestroOptions> {
958971 if ( typeof scriptFile === 'string' ) {
959972 const resolved = path . resolve ( path . dirname ( flowFile ) , scriptFile ) ;
960973 if ( ! includedFiles . has ( resolved ) ) {
961- try {
962- await fs . promises . access ( resolved ) ;
963- } catch {
964- missingReferences . push ( {
965- flowFile,
966- referencedFile : scriptFile ,
967- resolvedPath : resolved ,
968- } ) ;
969- }
974+ missingReferences . push ( {
975+ flowFile,
976+ referencedFile : scriptFile ,
977+ resolvedPath : resolved ,
978+ } ) ;
970979 }
971980 }
972981 // Don't recurse into runScript - it only has file, env, when (no nested file refs)
@@ -983,15 +992,11 @@ export default class Maestro extends BaseProvider<MaestroOptions> {
983992 if ( typeof flowRef === 'string' ) {
984993 const resolved = path . resolve ( path . dirname ( flowFile ) , flowRef ) ;
985994 if ( ! includedFiles . has ( resolved ) ) {
986- try {
987- await fs . promises . access ( resolved ) ;
988- } catch {
989- missingReferences . push ( {
990- flowFile,
991- referencedFile : flowRef ,
992- resolvedPath : resolved ,
993- } ) ;
994- }
995+ missingReferences . push ( {
996+ flowFile,
997+ referencedFile : flowRef ,
998+ resolvedPath : resolved ,
999+ } ) ;
9951000 }
9961001 }
9971002 // Only recurse into 'commands' if present (for inline commands)
@@ -1021,15 +1026,11 @@ export default class Maestro extends BaseProvider<MaestroOptions> {
10211026 if ( typeof mediaFile === 'string' ) {
10221027 const resolved = path . resolve ( path . dirname ( flowFile ) , mediaFile ) ;
10231028 if ( ! includedFiles . has ( resolved ) ) {
1024- try {
1025- await fs . promises . access ( resolved ) ;
1026- } catch {
1027- missingReferences . push ( {
1028- flowFile,
1029- referencedFile : mediaFile ,
1030- resolvedPath : resolved ,
1031- } ) ;
1032- }
1029+ missingReferences . push ( {
1030+ flowFile,
1031+ referencedFile : mediaFile ,
1032+ resolvedPath : resolved ,
1033+ } ) ;
10331034 }
10341035 }
10351036 }
@@ -1040,15 +1041,11 @@ export default class Maestro extends BaseProvider<MaestroOptions> {
10401041 handledKeys . add ( 'file' ) ;
10411042 const resolved = path . resolve ( path . dirname ( flowFile ) , obj . file ) ;
10421043 if ( ! includedFiles . has ( resolved ) ) {
1043- try {
1044- await fs . promises . access ( resolved ) ;
1045- } catch {
1046- missingReferences . push ( {
1047- flowFile,
1048- referencedFile : obj . file ,
1049- resolvedPath : resolved ,
1050- } ) ;
1051- }
1044+ missingReferences . push ( {
1045+ flowFile,
1046+ referencedFile : obj . file ,
1047+ resolvedPath : resolved ,
1048+ } ) ;
10521049 }
10531050 }
10541051
@@ -1113,8 +1110,9 @@ export default class Maestro extends BaseProvider<MaestroOptions> {
11131110
11141111 private logIncludedFiles ( files : string [ ] , baseDir ?: string ) : void {
11151112 // Get relative paths for display
1113+ const effectiveBase = baseDir || this . computeCommonDirectory ( files ) ;
11161114 const relativePaths = files
1117- . map ( ( f ) => ( baseDir ? path . relative ( baseDir , f ) : path . basename ( f ) ) )
1115+ . map ( ( f ) => path . relative ( effectiveBase , f ) )
11181116 . sort ( ) ;
11191117
11201118 // Group by file type
@@ -1179,21 +1177,43 @@ export default class Maestro extends BaseProvider<MaestroOptions> {
11791177
11801178 archive . pipe ( output ) ;
11811179
1180+ // Compute effective base directory for archive paths
1181+ const effectiveBase = baseDir || this . computeCommonDirectory ( files ) ;
1182+
11821183 for ( const file of files ) {
1183- // Determine the name in the archive
1184- let archiveName : string ;
1185- if ( baseDir ) {
1186- archiveName = path . relative ( baseDir , file ) ;
1187- } else {
1188- archiveName = path . basename ( file ) ;
1189- }
1184+ const archiveName = path . relative ( effectiveBase , file ) ;
11901185 archive . file ( file , { name : archiveName } ) ;
11911186 }
11921187
11931188 archive . finalize ( ) ;
11941189 } ) ;
11951190 }
11961191
1192+ /**
1193+ * Compute the common parent directory of all files
1194+ */
1195+ private computeCommonDirectory ( files : string [ ] ) : string {
1196+ if ( files . length === 0 ) return process . cwd ( ) ;
1197+ if ( files . length === 1 ) return path . dirname ( files [ 0 ] ) ;
1198+
1199+ const dirs = files . map ( ( f ) => path . dirname ( path . resolve ( f ) ) ) ;
1200+ const parts = dirs [ 0 ] . split ( path . sep ) ;
1201+ let commonLength = parts . length ;
1202+
1203+ for ( let i = 1 ; i < dirs . length ; i ++ ) {
1204+ const dirParts = dirs [ i ] . split ( path . sep ) ;
1205+ commonLength = Math . min ( commonLength , dirParts . length ) ;
1206+ for ( let j = 0 ; j < commonLength ; j ++ ) {
1207+ if ( parts [ j ] !== dirParts [ j ] ) {
1208+ commonLength = j ;
1209+ break ;
1210+ }
1211+ }
1212+ }
1213+
1214+ return parts . slice ( 0 , commonLength ) . join ( path . sep ) || path . sep ;
1215+ }
1216+
11971217 private async runTests ( ) {
11981218 try {
11991219 const capabilities = this . options . getCapabilities ( this . detectedPlatform ) ;
@@ -1272,6 +1292,11 @@ export default class Maestro extends BaseProvider<MaestroOptions> {
12721292 // Check for version update notification
12731293 const latestVersion = response . headers ?. [ 'x-testingbotctl-version' ] ;
12741294 utils . checkForUpdate ( latestVersion ) ;
1295+
1296+ if ( this . options . debug ) {
1297+ logger . debug ( `API response: ${ JSON . stringify ( response . data , null , 2 ) } ` ) ;
1298+ }
1299+
12751300 return response . data ;
12761301 } ) ;
12771302 } catch ( error ) {
0 commit comments