11import { Octokit } from "@octokit/rest" ;
22import fs from "fs" ;
33import AdmZip from "adm-zip" ;
4+ import { log } from "console" ;
45
56// Initialize Octokit with a personal access token
67const octokit = new Octokit ( {
78 auth : process . env . GITHUB_TOKEN , // Set your GitHub token in an environment variable
89 baseUrl : process . env . GITHUB_BASE_URL // Set the GitHub base URL, e.g. for Enterprise Server, in an env var
910} ) ;
1011
12+ function searchForActionsLines ( entry , actionRegex ) {
13+ const logContent = entry . getData ( ) . toString ( "utf8" ) ; // Extract file content as a string
14+ const logLines = logContent . split ( "\n" ) ;
15+ const actions = [ ] ;
16+
17+ for ( const line of logLines ) {
18+ const data = line . split ( " " ) . slice ( 1 ) . join ( " " ) ;
19+ if ( data == undefined ) {
20+ continue ;
21+ }
22+ if ( data . startsWith ( "Download action repository '" ) ) {
23+ const match = actionRegex . exec ( data ) ;
24+ if ( match ) {
25+ const action = match [ 1 ] ;
26+ const sha = match [ 2 ] ;
27+
28+ const [ repo , version ] = action . split ( "@" ) ;
29+ actions . push ( [ repo , version , sha ] ) ;
30+ }
31+ }
32+ }
33+
34+ return actions ;
35+ }
36+
37+ function searchForSetUpJob ( logEntries , actionRegex ) {
38+ let foundSetUpJob = false ;
39+ const actions = [ ] ;
40+
41+ // Iterate through each file in the zip
42+ for ( const entry of logEntries ) {
43+ if ( ! entry . isDirectory ) {
44+ const fileName = entry . entryName ; // Get the file name
45+ if ( fileName === undefined ) {
46+ continue ;
47+ }
48+ // get the base name of the file
49+ const baseName = fileName . split ( "/" ) . pop ( ) ;
50+ if ( baseName == "1_Set up job.txt" ) {
51+ foundSetUpJob = true ;
52+ actions . push ( ...searchForActionsLines ( entry , actionRegex ) ) ;
53+ }
54+ }
55+ }
56+
57+ return [ foundSetUpJob , actions ] ;
58+ }
59+
60+ function searchForTopLevelLog ( logEntries , actionRegex ) {
61+ const actions = [ ] ;
62+
63+ // Iterate through each file in the zip
64+ for ( const entry of logEntries ) {
65+ if ( ! entry . isDirectory ) {
66+ const fileName = entry . entryName ; // Get the file name
67+ console . log ( fileName ) ;
68+ if ( fileName !== undefined && fileName . startsWith ( "0_" ) ) {
69+ actions . push ( ...searchForActionsLines ( entry , actionRegex ) ) ;
70+ }
71+ }
72+ }
73+
74+ return actions ;
75+ }
76+
1177// Helper function to extract Actions used from workflow logs
1278async function extractActionsFromLogs ( logUrl ) {
1379 try {
@@ -23,29 +89,14 @@ async function extractActionsFromLogs(logUrl) {
2389 const logEntries = zip . getEntries ( ) ; // Get all entries in the zip file
2490
2591 // Download action repository 'actions/checkout@v4' (SHA:11bd71901bbe5b1630ceea73d27597364c9af683)
26- const actionRegex = / D o w n l o a d a c t i o n r e p o s i t o r y ' ( .+ ?) ' \( S H A : ( .+ ?) \) / g;
27- const actions = [ ] ;
92+ const actionRegex = / D o w n l o a d a c t i o n r e p o s i t o r y ' ( .+ ?) ' \( S H A : ( .+ ?) \) / ;
2893
29- // Iterate through each file in the zip
30- for ( const entry of logEntries ) {
31- if ( ! entry . isDirectory ) {
32- const fileName = entry . entryName ; // Get the file name
33- // get the base name of the file
34- const baseName = fileName . split ( "/" ) . pop ( ) ;
35- if ( baseName == "1_Set up job.txt" ) {
36- const logContent = entry . getData ( ) . toString ( "utf8" ) ; // Extract file content as a string
37- let match ;
38- // Extract actions from the log content
39- while ( match = actionRegex . exec ( logContent ) ) {
40- const action = match [ 1 ] ;
41- const sha = match [ 2 ] ;
94+ const [ success , actions ] = searchForSetUpJob ( logEntries , actionRegex ) ;
95+
96+ if ( ! success ) {
97+ actions . push ( ...searchForTopLevelLog ( logEntries , actionRegex ) ) ;
98+ }
4299
43- const [ repo , version ] = action . split ( "@" ) ;
44- actions . push ( [ repo , version , sha ] ) ;
45- }
46- }
47- }
48- }
49100 return actions ;
50101
51102 } catch ( error ) {
0 commit comments