@@ -57,9 +57,7 @@ async function run() {
5757 const intermediates = core . getInput ( "intermediates" ) . split ( " " ) ;
5858 const key = core . getInput ( "key" ) ;
5959 let outfile = core . getInput ( "outfile" ) ;
60- outfile = outfile
61- ? outfile
62- : path . join ( os . tmpdir ( ) , step + "-attestation.json" ) ;
60+ outfile = outfile ? outfile : path . join ( os . tmpdir ( ) , step + "-attestation.json" ) ;
6361 const productExcludeGlob = core . getInput ( "product-exclude-glob" ) ;
6462 const productIncludeGlob = core . getInput ( "product-include-glob" ) ;
6563 const spiffeSocket = core . getInput ( "spiffe-socket" ) ;
@@ -107,40 +105,21 @@ async function run() {
107105
108106 for ( const gitOID of gitOIDs ) {
109107 console . log ( "Extracted GitOID:" , gitOID ) ;
110-
111- // Print the GitOID to the output
112108 core . setOutput ( "git_oid" , gitOID ) ;
113-
114- // Construct the artifact URL using Archivista server and GitOID
115109 const artifactURL = `${ archivistaServer } /download/${ gitOID } ` ;
116-
117- // Add Job Summary with Markdown content
118110 const summaryHeader = `
119111## Attestations Created
120112| Step | Attestors Run | Attestation GitOID
121113| --- | --- | --- |
122114` ;
123-
124- // Try to access the step summary file
125115 try {
126116 if ( process . env . GITHUB_STEP_SUMMARY ) {
127- // Read the contents of the file
128- const summaryFile = fs . readFileSync ( process . env . GITHUB_STEP_SUMMARY , {
129- encoding : "utf-8" ,
130- } ) ;
131-
132- // Check if the file contains the header
117+ const summaryFile = fs . readFileSync ( process . env . GITHUB_STEP_SUMMARY , { encoding : "utf-8" } ) ;
133118 const headerExists = summaryFile . includes ( summaryHeader . trim ( ) ) ;
134-
135- // If the header does not exist, append it to the file
136119 if ( ! headerExists ) {
137120 fs . appendFileSync ( process . env . GITHUB_STEP_SUMMARY , summaryHeader ) ;
138121 }
139-
140- // Construct the table row for the current step
141122 const tableRow = `| ${ step } | ${ attestations . join ( ", " ) } | [${ gitOID } ](${ artifactURL } ) |\n` ;
142-
143- // Append the table row to the file
144123 fs . appendFileSync ( process . env . GITHUB_STEP_SUMMARY , tableRow ) ;
145124 }
146125 } catch ( error ) {
@@ -155,102 +134,63 @@ async function run() {
155134 }
156135}
157136
158- // Download and install Witness
159137async function downloadWitness ( version , installDir ) {
160- // Check if Witness is already in the tool cache
161138 let witnessPath = tc . find ( "witness" , version ) ;
162139 console . log ( "Cached Witness Path: " + witnessPath ) ;
163-
164140 if ( ! witnessPath ) {
165141 console . log ( "Witness not found in cache, downloading now" ) ;
166142 let witnessTar ;
167-
168- // Determine the OS-specific download URL
169143 if ( process . platform === "win32" ) {
170144 witnessTar = await tc . downloadTool (
171- "https://github.com/in-toto/witness/releases/download/v" +
172- version +
173- "/witness_" +
174- version +
175- "_windows_amd64.tar.gz"
145+ "https://github.com/in-toto/witness/releases/download/v" + version + "/witness_" + version + "_windows_amd64.tar.gz"
176146 ) ;
177147 } else if ( process . platform === "darwin" ) {
178148 witnessTar = await tc . downloadTool (
179- "https://github.com/in-toto/witness/releases/download/v" +
180- version +
181- "/witness_" +
182- version +
183- "_darwin_amd64.tar.gz"
149+ "https://github.com/in-toto/witness/releases/download/v" + version + "/witness_" + version + "_darwin_amd64.tar.gz"
184150 ) ;
185151 } else {
186152 witnessTar = await tc . downloadTool (
187- "https://github.com/in-toto/witness/releases/download/v" +
188- version +
189- "/witness_" +
190- version +
191- "_linux_amd64.tar.gz"
153+ "https://github.com/in-toto/witness/releases/download/v" + version + "/witness_" + version + "_linux_amd64.tar.gz"
192154 ) ;
193155 }
194-
195- // Create the install directory if it doesn't exist
196156 if ( ! fs . existsSync ( installDir ) ) {
197157 console . log ( "Creating witness install directory at " + installDir ) ;
198158 fs . mkdirSync ( installDir , { recursive : true } ) ;
199159 }
200-
201- // Extract and cache Witness
202160 console . log ( "Extracting witness at: " + installDir ) ;
203161 witnessPath = await tc . extractTar ( witnessTar , installDir ) ;
204-
205162 const cachedPath = await tc . cacheFile (
206163 path . join ( witnessPath , "witness" ) ,
207164 "witness" ,
208165 "witness" ,
209166 version
210167 ) ;
211168 console . log ( "Witness cached at: " + cachedPath ) ;
212-
213169 witnessPath = cachedPath ;
214170 }
215-
216- // Add Witness to the PATH
217171 core . addPath ( witnessPath ) ;
218172 return witnessPath ;
219173}
220174
221- // Download and extract a GitHub Action
222175async function downloadAndExtractAction ( actionRef ) {
223- // Parse action-ref (expects format: owner/repo@ref)
224176 const [ repo , ref ] = parseActionRef ( actionRef ) ;
225177 core . info ( `Parsed repo: ${ repo } , ref: ${ ref } ` ) ;
226-
227- // Construct URL for the repository zip archive
228- // Use proper URL format for GitHub archives (handle both branches and tags)
229178 const isTag = ! ref . includes ( '/' ) ;
230179 const zipUrl = isTag
231180 ? `https://github.com/${ repo } /archive/refs/tags/${ ref } .zip`
232181 : `https://github.com/${ repo } /archive/refs/heads/${ ref } .zip` ;
233-
234182 core . info ( `Downloading action from: ${ zipUrl } ` ) ;
235-
236- // Create a temporary directory for extraction
237183 const tempDir = fs . mkdtempSync ( path . join ( os . tmpdir ( ) , "nested-action-" ) ) ;
238-
239184 try {
240- // Download and extract the zip archive
241185 const response = await axios ( {
242186 url : zipUrl ,
243187 method : "GET" ,
244188 responseType : "stream" ,
245- validateStatus : function ( status ) {
246- return status >= 200 && status < 300 ; // Default
247- } ,
248- maxRedirects : 5 // Handle redirects
189+ validateStatus : function ( status ) { return status >= 200 && status < 300 ; } ,
190+ maxRedirects : 5
249191 } ) ;
250-
251192 await new Promise ( ( resolve , reject ) => {
252- response . data
253- . pipe ( unzipper . Extract ( { path : tempDir } ) )
193+ response . data . pipe ( unzipper . Extract ( { path : tempDir } ) )
254194 . on ( "close" , resolve )
255195 . on ( "error" , reject ) ;
256196 } ) ;
@@ -259,21 +199,17 @@ async function downloadAndExtractAction(actionRef) {
259199 if ( error . response ) {
260200 core . error ( `Download failed with status ${ error . response . status } ` ) ;
261201 if ( isTag ) {
262- // Try alternative URL format if first attempt failed
263202 core . info ( "Attempting alternative download URL for branches..." ) ;
264203 const altZipUrl = `https://github.com/${ repo } /archive/refs/heads/${ ref } .zip` ;
265204 core . info ( `Trying alternative URL: ${ altZipUrl } ` ) ;
266-
267205 const altResponse = await axios ( {
268206 url : altZipUrl ,
269207 method : "GET" ,
270208 responseType : "stream" ,
271209 maxRedirects : 5
272210 } ) ;
273-
274211 await new Promise ( ( resolve , reject ) => {
275- altResponse . data
276- . pipe ( unzipper . Extract ( { path : tempDir } ) )
212+ altResponse . data . pipe ( unzipper . Extract ( { path : tempDir } ) )
277213 . on ( "close" , resolve )
278214 . on ( "error" , reject ) ;
279215 } ) ;
@@ -285,30 +221,22 @@ async function downloadAndExtractAction(actionRef) {
285221 throw error ;
286222 }
287223 }
288-
289- // List contents of the temp directory for diagnostic purposes
290224 core . debug ( `Temporary directory contents: ${ fs . readdirSync ( tempDir ) . join ( ', ' ) } ` ) ;
291-
292- // GitHub archives typically extract to a folder named "repo-ref"
293225 const repoName = repo . split ( "/" ) [ 1 ] ;
294226 const extractedFolder = path . join ( tempDir , `${ repoName } -${ ref } ` ) ;
295227 if ( ! fs . existsSync ( extractedFolder ) ) {
296- // If default folder name doesn't exist, try finding based on content
297228 const tempContents = fs . readdirSync ( tempDir ) ;
298229 if ( tempContents . length === 1 && fs . lstatSync ( path . join ( tempDir , tempContents [ 0 ] ) ) . isDirectory ( ) ) {
299- // If there's only one directory, use that one
300230 const alternateFolder = path . join ( tempDir , tempContents [ 0 ] ) ;
301231 core . info ( `Using alternative extracted folder: ${ alternateFolder } ` ) ;
302232 return alternateFolder ;
303233 } else {
304234 throw new Error ( `Extracted folder ${ extractedFolder } not found and could not determine alternative.` ) ;
305235 }
306236 }
307-
308237 return extractedFolder ;
309238}
310239
311- // Run an action with Witness
312240async function runActionWithWitness ( actionDir , witnessOptions ) {
313241 let {
314242 step,
@@ -335,13 +263,9 @@ async function runActionWithWitness(actionDir, witnessOptions) {
335263 mavenPOM,
336264 } = witnessOptions ;
337265
338- // Read action.yml from the downloaded action
339266 const actionYmlPath = path . join ( actionDir , "action.yml" ) ;
340- // Some actions use action.yaml instead of action.yml
341267 const actionYamlPath = path . join ( actionDir , "action.yaml" ) ;
342-
343268 let actionConfig ;
344-
345269 if ( fs . existsSync ( actionYmlPath ) ) {
346270 actionConfig = yaml . load ( fs . readFileSync ( actionYmlPath , "utf8" ) ) ;
347271 } else if ( fs . existsSync ( actionYamlPath ) ) {
@@ -356,36 +280,30 @@ async function runActionWithWitness(actionDir, witnessOptions) {
356280 }
357281 core . info ( `Nested action entry point: ${ entryPoint } ` ) ;
358282
359- // Construct full path to the nested action's entry file
360283 const entryFile = path . join ( actionDir , entryPoint ) ;
361284 if ( ! fs . existsSync ( entryFile ) ) {
362285 throw new Error ( `Entry file ${ entryFile } does not exist.` ) ;
363286 }
364287
365- // Optionally, install dependencies if package.json exists
366288 const pkgJsonPath = path . join ( actionDir , "package.json" ) ;
367289 if ( fs . existsSync ( pkgJsonPath ) ) {
368290 core . info ( "Installing dependencies for nested action..." ) ;
369291 await exec . exec ( "npm" , [ "install" ] , { cwd : actionDir } ) ;
370292 }
371293
372- // Instead of filtering, pass all environment variables to the nested action
373294 const envVars = { ...process . env } ;
374-
375295 // For testing, force the nested action to see a value for INPUT_WHO_TO_GREET
376296 envVars [ "INPUT_WHO_TO_GREET" ] = envVars [ "INPUT_WHO_TO_GREET" ] || "Sigstore" ;
377297 core . info ( `For testing, setting INPUT_WHO_TO_GREET to: ${ envVars [ "INPUT_WHO_TO_GREET" ] } ` ) ;
378298
379299 // Build the witness run command
380300 const cmd = [ "run" ] ;
381-
382301 if ( enableSigstore ) {
383302 fulcio = fulcio || "https://fulcio.sigstore.dev" ;
384303 fulcioOidcClientId = fulcioOidcClientId || "sigstore" ;
385304 fulcioOidcIssuer = fulcioOidcIssuer || "https://oauth2.sigstore.dev/auth" ;
386305 timestampServers = "https://freetsa.org/tsr " + timestampServers ;
387306 }
388-
389307 if ( attestations . length ) {
390308 attestations . forEach ( ( attestation ) => {
391309 attestation = attestation . trim ( ) ;
@@ -394,21 +312,17 @@ async function runActionWithWitness(actionDir, witnessOptions) {
394312 }
395313 } ) ;
396314 }
397-
398315 if ( exportLink ) cmd . push ( `--attestor-link-export` ) ;
399316 if ( exportSBOM ) cmd . push ( `--attestor-sbom-export` ) ;
400317 if ( exportSLSA ) cmd . push ( `--attestor-slsa-export` ) ;
401-
402318 if ( mavenPOM ) cmd . push ( `--attestor-maven-pom-path=${ mavenPOM } ` ) ;
403-
404319 if ( certificate ) cmd . push ( `--certificate=${ certificate } ` ) ;
405320 if ( enableArchivista ) cmd . push ( `--enable-archivista=${ enableArchivista } ` ) ;
406321 if ( archivistaServer ) cmd . push ( `--archivista-server=${ archivistaServer } ` ) ;
407322 if ( fulcio ) cmd . push ( `--signer-fulcio-url=${ fulcio } ` ) ;
408323 if ( fulcioOidcClientId ) cmd . push ( `--signer-fulcio-oidc-client-id=${ fulcioOidcClientId } ` ) ;
409324 if ( fulcioOidcIssuer ) cmd . push ( `--signer-fulcio-oidc-issuer=${ fulcioOidcIssuer } ` ) ;
410325 if ( fulcioToken ) cmd . push ( `--signer-fulcio-token=${ fulcioToken } ` ) ;
411-
412326 if ( intermediates . length ) {
413327 intermediates . forEach ( ( intermediate ) => {
414328 intermediate = intermediate . trim ( ) ;
@@ -417,13 +331,11 @@ async function runActionWithWitness(actionDir, witnessOptions) {
417331 }
418332 } ) ;
419333 }
420-
421334 if ( key ) cmd . push ( `--key=${ key } ` ) ;
422335 if ( productExcludeGlob ) cmd . push ( `--attestor-product-exclude-glob=${ productExcludeGlob } ` ) ;
423336 if ( productIncludeGlob ) cmd . push ( `--attestor-product-include-glob=${ productIncludeGlob } ` ) ;
424337 if ( spiffeSocket ) cmd . push ( `--spiffe-socket=${ spiffeSocket } ` ) ;
425338 if ( step ) cmd . push ( `-s=${ step } ` ) ;
426-
427339 if ( timestampServers ) {
428340 const timestampServerValues = timestampServers . split ( " " ) ;
429341 timestampServerValues . forEach ( ( timestampServer ) => {
@@ -433,39 +345,27 @@ async function runActionWithWitness(actionDir, witnessOptions) {
433345 }
434346 } ) ;
435347 }
436-
437348 if ( trace ) cmd . push ( `--trace=${ trace } ` ) ;
438349 if ( outfile ) cmd . push ( `--outfile=${ outfile } ` ) ;
439350
440- // Prepare the command to run the action
441- const nodeCmd = 'node ' ;
442- const nodeArgs = [ entryFile ] ;
443-
444- // Build the base command string from witness arguments
445- const baseCommand = [ " witness" , ... cmd , "--" , nodeCmd , ... nodeArgs ] . join ( " " ) ;
351+ // Instead of invoking node directly, run a shell command that exports the variable before running node
352+ const newNodeCmd = 'sh ' ;
353+ const newNodeArgs = [ '-c' , `export INPUT_WHO_TO_GREET= ${ envVars [ "INPUT_WHO_TO_GREET" ] } && node ${ entryFile } ` ] ;
354+ const runArray = [ "witness" , ... cmd , "--" , newNodeCmd , ... newNodeArgs ] ;
355+ const commandString = runArray . join ( " " ) ;
356+ core . info ( `Running witness command: ${ commandString } ` ) ;
446357
447- // For testing, explicitly prepend the environment assignment for INPUT_WHO_TO_GREET
448- const prefixedCommand = `INPUT_WHO_TO_GREET=${ envVars [ "INPUT_WHO_TO_GREET" ] } ${ baseCommand } ` ;
449- core . info ( `Running witness command: ${ prefixedCommand } ` ) ;
450-
451- // Set up options for execution
452358 const execOptions = {
453359 cwd : actionDir ,
454360 env : envVars ,
455361 listeners : {
456- stdout : ( data ) => {
457- process . stdout . write ( data . toString ( ) ) ;
458- } ,
459- stderr : ( data ) => {
460- process . stderr . write ( data . toString ( ) ) ;
461- }
362+ stdout : ( data ) => { process . stdout . write ( data . toString ( ) ) ; } ,
363+ stderr : ( data ) => { process . stderr . write ( data . toString ( ) ) ; }
462364 }
463365 } ;
464366
465- // Execute and capture output
466367 let output = '' ;
467-
468- await exec . exec ( 'sh' , [ '-c' , prefixedCommand ] , {
368+ await exec . exec ( 'sh' , [ '-c' , commandString ] , {
469369 ...execOptions ,
470370 listeners : {
471371 ...execOptions . listeners ,
@@ -485,11 +385,9 @@ async function runActionWithWitness(actionDir, witnessOptions) {
485385 return output ;
486386}
487387
488- // Extract GitOIDs from witness output
489388function extractDesiredGitOIDs ( output ) {
490389 const lines = output . split ( "\n" ) ;
491390 const desiredSubstring = "Stored in archivista as " ;
492-
493391 const matchArray = [ ] ;
494392 console . log ( "Looking for GitOID in the output" ) ;
495393 for ( const line of lines ) {
@@ -503,7 +401,6 @@ function extractDesiredGitOIDs(output) {
503401 }
504402 }
505403 }
506-
507404 return matchArray ;
508405}
509406
@@ -518,15 +415,13 @@ function parseActionRef(refString) {
518415run ( )
519416 . then ( ( ) => {
520417 core . debug ( 'Action wrapper completed successfully' ) ;
521- // Force exit to ensure we don't hang
522418 setTimeout ( ( ) => {
523419 core . debug ( 'Forcing process exit to prevent hanging' ) ;
524420 process . exit ( 0 ) ;
525421 } , 500 ) ;
526422 } )
527423 . catch ( error => {
528424 core . setFailed ( `Action wrapper failed: ${ error . message } ` ) ;
529- // Force exit to ensure we don't hang
530425 setTimeout ( ( ) => {
531426 core . debug ( 'Forcing process exit to prevent hanging' ) ;
532427 process . exit ( 1 ) ;
0 commit comments