1- /*
2- * Run Semgrep scan
3- * Normalizes baseline for diff scans depending on push vs PR context
4- *
5- * Expects the following environment variables:
6- * HAS_PR - whether the current context has an associated PR (true/false)
7- * PR_NUMBER - PR number if applicable
8- * PR_URL - PR URL if applicable
9- * INPUT_BASELINE - baseline ref to use for diffing (e.g., origin/main)
10- * GITHUB_EVENT_NAME - GitHub provided environment variable for event name (e.g., push, pull_request)
11- * GITHUB_REF - Github provided environment variable for the git ref that triggered the workflow
12- * GITHUB_REF_NAME - GitHub provided environment variable for the branch or tag name that triggered the workflow
13- * GITHUB_BASE_REF - GitHub provided environment variable for the base ref of a PR (if applicable)
14- * GITHUB_REPOSITORY - GitHub provided environment variable for the repository (e.g., owner/repo)
15- * GITHUB_TOKEN - GitHub token for API access
16- * SCAN_MODE - 'diff' or 'full' scan mode
17- * SEMGREP_CONFIG - Semgrep ruleset(s) to use
18- * SEMGREP_TARGETS - Targets to scan (default: current directory)
19- * FAIL_LEVEL - Severity level to fail on (e.g., ERROR, WARNING)
20- * EXTRA_ARGS - Additional arguments to pass to Semgrep
21- *
22- * Outputs:
23- * - Writes file for reviewdog annotations, reviewdog_input.txt
24- * - Sets GitHub Action outputs
25- * - normalizedBaseline - the resolved baseline ref
26- * - totalFindings - total number of findings
27- * - numErrors - number of ERROR severity findings
28- * - numWarnings - number of WARNING severity findings
29- * - numInfo - number of INFO severity findings
30- * - scanSummary - summary of findings in md format
31- * - configSummary - summary of scan config in md format
32- * - scanStatus - 'success' or 'failure' based on findings and fail level
33- */
34-
351const { spawnSync } = require ( 'child_process' ) ;
362const fs = require ( 'fs' ) ;
37- const fetch = require ( 'node-fetch' ) ;
38- const { validateEnvVar } = require ( '../utils/env-helpers' ) ;
3+ const https = require ( 'https' ) ;
394
405const SEMGREP_RESULTS_FILE_NAME = 'semgrep_results.json' ;
416const REVIEWDOG_INPUT_FILE_NAME = 'reviewdog_input.txt' ;
427
43- async function getPrBaseBranch ( owner , repo , branch , token ) {
8+ function getPrBaseBranch ( owner , repo , branch , token ) {
449 // Use GitHub API to find open PR for the branch and get its base branch
45- const url = `https://api.github.com/repos/${ owner } /${ repo } /pulls?state=open&head=${ owner } :${ branch } ` ;
46- const res = await fetch ( url , {
10+ const url = `/repos/${ owner } /${ repo } /pulls?state=open&head=${ owner } :${ branch } ` ;
11+ const options = {
12+ hostname : 'api.github.com' ,
13+ path : url ,
14+ method : 'GET' ,
4715 headers : {
4816 Authorization : `Bearer ${ token } ` ,
4917 Accept : 'application/vnd.github.v3+json' ,
5018 'User-Agent' : 'normalize-push-baseline-script' ,
5119 } ,
20+ } ;
21+
22+ return new Promise ( resolve => {
23+ const req = https . request ( options , res => {
24+ let data = '' ;
25+ res . on ( 'data' , chunk => {
26+ data += chunk ;
27+ } ) ;
28+ res . on ( 'end' , ( ) => {
29+ if ( res . statusCode < 200 || res . statusCode >= 300 ) {
30+ return resolve ( null ) ;
31+ }
32+ try {
33+ const prs = JSON . parse ( data ) ;
34+ if ( Array . isArray ( prs ) && prs . length > 0 && prs [ 0 ] . base && prs [ 0 ] . base . ref ) {
35+ resolve ( prs [ 0 ] . base . ref ) ;
36+ } else {
37+ resolve ( null ) ;
38+ }
39+ } catch ( _e ) {
40+ resolve ( null ) ;
41+ }
42+ } ) ;
43+ } ) ;
44+ req . on ( 'error' , _err => {
45+ resolve ( null ) ;
46+ } ) ;
47+ req . end ( ) ;
5248 } ) ;
53- if ( ! res . ok ) return null ;
54- const prs = await res . json ( ) ;
55- if ( prs . length > 0 && prs [ 0 ] . base && prs [ 0 ] . base . ref ) {
56- return prs [ 0 ] . base . ref ;
57- }
58- return null ;
5949}
6050
6151/* Normalize the baseline ref for push events in GitHub Actions.
@@ -327,6 +317,13 @@ if (require.main === module) {
327317 } ) ;
328318}
329319
320+ function validateEnvVar ( name ) {
321+ if ( ! process . env [ name ] ) {
322+ console . error ( `::error::Environment variable ${ name } is required` ) ;
323+ process . exit ( 1 ) ;
324+ }
325+ }
326+
330327module . exports = {
331328 main,
332329 getPrBaseBranch,
@@ -338,6 +335,7 @@ module.exports = {
338335 writeFindingsMarkdown,
339336 writeConfigMarkdown,
340337 evaluateScanStatus,
338+ validateEnvVar,
341339 SEMGREP_RESULTS_FILE_NAME ,
342340 REVIEWDOG_INPUT_FILE_NAME ,
343341} ;
0 commit comments