99
1010const Inspector = ( ( ) => {
1111
12+ /**
13+ * Helper: Mirrors the GitHub Actions backend logic.
14+ * Detects if the ZIP has a single root directory.
15+ */
16+ function _getSingleRoot ( zipFiles ) {
17+ const topLevelEntries = new Set ( ) ;
18+ Object . keys ( zipFiles ) . forEach ( path => {
19+ const topLevel = path . split ( '/' ) [ 0 ] ;
20+ if ( topLevel ) topLevelEntries . add ( topLevel ) ;
21+ } ) ;
22+
23+ if ( topLevelEntries . size === 1 ) {
24+ const root = Array . from ( topLevelEntries ) [ 0 ] ;
25+ // Ensure it's actually a directory
26+ if ( zipFiles [ root + '/' ] ) return root + '/' ;
27+ }
28+ return null ;
29+ }
30+
1231 /**
1332 * Inspect a ZIP file and return its contents analysis.
1433 * @param {File|Blob } file
@@ -26,19 +45,26 @@ const Inspector = (() => {
2645 const files = [ ] ;
2746 const workflowFiles = [ ] ;
2847 let totalSize = 0 ;
48+
49+ const rootToFlatten = _getSingleRoot ( zip . files ) ;
2950
3051 zip . forEach ( ( relativePath , entry ) => {
3152 if ( entry . dir ) return ;
3253
3354 const size = entry . _data ?. uncompressedSize || 0 ;
3455 totalSize += size ;
3556
57+ // Adjust path if the backend will flatten it
58+ let actualPath = relativePath ;
59+ if ( rootToFlatten && actualPath . startsWith ( rootToFlatten ) ) {
60+ actualPath = actualPath . substring ( rootToFlatten . length ) ;
61+ }
62+
3663 const info = {
37- path : relativePath ,
38- name : relativePath . split ( '/' ) . pop ( ) ,
64+ path : actualPath ,
65+ name : actualPath . split ( '/' ) . pop ( ) ,
3966 size,
40- // FIX: Removed strict start anchor (^) to allow root folders
41- isWorkflow : / (?: ^ | \/ ) \. g i t h u b \/ w o r k f l o w s \/ .* \. y a ? m l $ / i. test ( relativePath ) ,
67+ isWorkflow : / ^ \. g i t h u b \/ w o r k f l o w s \/ .* \. y a ? m l $ / i. test ( actualPath ) ,
4268 } ;
4369
4470 files . push ( info ) ;
@@ -104,13 +130,20 @@ const Inspector = (() => {
104130
105131 const zip = await JSZip . loadAsync ( file ) ;
106132 const results = [ ] ;
133+ const rootToFlatten = _getSingleRoot ( zip . files ) ;
107134
108135 for ( const [ path , entry ] of Object . entries ( zip . files ) ) {
109136 if ( entry . dir ) continue ;
110- // FIX: Removed strict start anchor (^) to allow root folders
111- if ( / (?: ^ | \/ ) \. g i t h u b \/ w o r k f l o w s \/ .* \. y a ? m l $ / i. test ( path ) ) {
137+
138+ // Adjust path if the backend will flatten it
139+ let actualPath = path ;
140+ if ( rootToFlatten && actualPath . startsWith ( rootToFlatten ) ) {
141+ actualPath = actualPath . substring ( rootToFlatten . length ) ;
142+ }
143+
144+ if ( / ^ \. g i t h u b \/ w o r k f l o w s \/ .* \. y a ? m l $ / i. test ( actualPath ) ) {
112145 const content = await entry . async ( 'base64' ) ;
113- results . push ( { path, contentBase64 : content } ) ;
146+ results . push ( { path : actualPath , contentBase64 : content } ) ;
114147 }
115148 }
116149
0 commit comments