Skip to content

Commit 1a07d04

Browse files
authored
Merge pull request #109 from OpenSesame/fix_call_from_other_repos
Fix call from other repos
2 parents 608b310 + 8014e3e commit 1a07d04

19 files changed

Lines changed: 345 additions & 176 deletions

File tree

.github/actions/TEMPLATE/README_TEMPLATE.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ Basic usage example:
5252
```yaml
5353
- name: Name for step
5454
id: <step-id>
55-
uses: ./.github/actions/<action-name>
55+
uses: OpenSesame/core-github-actions/.github/actions/<action-name>@actions/<action-name>/vX.Y.Z
5656
with:
5757
<input-name>: <value>
5858
```

.github/actions/pr-open-check/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ permissions:
5353
```yaml
5454
- name: Check for open PR
5555
id: pr_check
56-
uses: ./.github/actions/pr-check-open
56+
uses: OpenSesame/core-github-actions/.github/actions/pr-open-check@actions/pr-open-check/2.0.0
5757
with:
5858
github-token: ${{ secrets.GITHUB_TOKEN }}
5959
commit-identifier: ${{ github.sha }}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
# Changelog for run-semgrep Composite Action
2+
3+
All notable changes to the run-semgrep composite GitHub Action will be documented in this file.
4+
5+
## 1.0.0 - Initial Release
6+
7+
### Added
8+
9+
- Initial release of the reusable composite action for running Semgrep scans
10+
- Inputs are passed via environment variables
11+
- Support running on both push and pull_request events
12+
- Standardizes baseline resolution for diff scans
13+
- Outputs include scan summary, config summary, scan status, and finding counts
14+
- Designed to integrate with reviewdog for annotations
Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
# Run Semgrep Action
2+
3+
## 🧭 Summary
4+
5+
Runs a Semgrep scan normalizing the baseline for diff scans depending on push vs PR context. Outputs scan results and summaries for downstream steps.
6+
7+
## Scope/Limitations
8+
9+
- Supports both push and pull request events.
10+
- Requires Semgrep to be installed and available in the runner environment.
11+
- Expects environment variables for configuration (see below).
12+
13+
## 🔒 Permissions
14+
15+
The following GHA permissions are required to use this step:
16+
17+
```yaml
18+
permissions:
19+
contents: read
20+
```
21+
22+
## Dependencies
23+
24+
- `semgrep` — must be installed in the runner environment.
25+
- `https` — standard Node.js module for API requests included in default action runners
26+
- `reviewdog` — for annotation output (optional, for downstream steps).
27+
28+
## ⚙️ Inputs
29+
30+
This action is environment-driven. The following environment variables are required:
31+
32+
| Name | Required | Description |
33+
| ------------------- | -------- | ------------------------------------------------------------------------------------------- |
34+
| `HAS_PR` | ✅ | Whether the current context has an associated PR (true/false) |
35+
| `PR_NUMBER` | ❌ | PR number if applicable |
36+
| `PR_URL` | ❌ | PR URL if applicable |
37+
| `INPUT_BASELINE` | ✅ | Baseline ref to use for diffing (e.g., origin/main) |
38+
| `GITHUB_EVENT_NAME` | ✅ | GitHub provided environment variable for event name (e.g., push, pull_request) |
39+
| `GITHUB_REF_NAME` | ✅ | GitHub provided environment variable for the branch or tag name that triggered the workflow |
40+
| `GITHUB_BASE_REF` | ❌ | GitHub provided environment variable for the base ref of a PR (if applicable) |
41+
| `GITHUB_REPOSITORY` | ✅ | GitHub provided environment variable for the repository (e.g., owner/repo) |
42+
| `GITHUB_TOKEN` | ✅ | GitHub token for API access |
43+
| `SCAN_MODE` | ✅ | 'diff' or 'full' scan mode |
44+
| `SEMGREP_CONFIG` | ✅ | Semgrep ruleset(s) to use |
45+
| `SEMGREP_TARGETS` | ✅ | Targets to scan (default: current directory) |
46+
| `FAIL_LEVEL` | ✅ | Severity level to fail on (e.g., ERROR, WARNING) |
47+
| `EXTRA_ARGS` | ❌ | Additional arguments to pass to Semgrep |
48+
49+
## 📤 Outputs
50+
51+
Along with writing files for reviewdog annotations and inputs, this action provides the following outputs:
52+
53+
| Name | Description |
54+
| -------------------- | --------------------------------------------------- |
55+
| `normalizedBaseline` | The resolved baseline ref |
56+
| `scanSummary` | Summary of findings in markdown format |
57+
| `configSummary` | Summary of scan config in markdown format |
58+
| `scanStatus` | 'success' or 'failure' based on findings/fail level |
59+
| `totalFindings` | Total number of findings |
60+
| `numErrors` | Number of ERROR severity findings |
61+
| `numWarnings` | Number of WARNING severity findings |
62+
| `numInfo` | Number of INFO severity findings |
63+
64+
## 🚀 Usage
65+
66+
Basic usage example:
67+
68+
```yaml
69+
- name: Run Semgrep
70+
id: semgrep
71+
uses: OpenSesame/core-github-actions/.github/actions/run-semgrep@actions/run-semgrep/1.0.0
72+
env:
73+
HAS_PR: ${{ env.HAS_PR }}
74+
INPUT_BASELINE: ${{ env.INPUT_BASELINE }}
75+
GITHUB_EVENT_NAME: ${{ github.event_name }}
76+
GITHUB_REF_NAME: ${{ github.ref_name }}
77+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
78+
GITHUB_REPOSITORY: ${{ github.repository }}
79+
SEMGREP_CONFIG: 'p/default'
80+
SEMGREP_TARGETS: '.'
81+
SCAN_MODE: 'full'
82+
FAIL_LEVEL: 'error'
83+
EXTRA_ARGS: ''
84+
```
85+
86+
Example outputs:
87+
88+
```yaml
89+
steps.semgrep.outputs.scanStatus
90+
steps.semgrep.outputs.totalFindings
91+
```
92+
93+
Example usage of outputs in later steps:
94+
95+
```yaml
96+
if: steps.semgrep.outputs.scanStatus == 'failure'
97+
run: echo "Semgrep scan failed at or above threshold."
98+
```
99+
100+
## 🧠 Notes
101+
102+
- This action writes a file for reviewdog annotations (`reviewdog_input.txt`).
103+
- Unit tests for the script are included in `run-semgrep.unit.test.js` (not used by the action, but kept for maintainability).
104+
105+
## Versioning
106+
107+
This action uses namespaced tags for versioning and is tracked in the CHANGELOG.
108+
109+
```text
110+
actions/run-semgrep/vX.Y.Z
111+
```
112+
113+
See the repository's versioning documentation for details on how tags are validated and created.
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
name: 'Run Semgrep'
2+
description: 'Run a Semgrep scan and output results for reviewdog and future steps'
3+
outputs:
4+
normalizedBaseline:
5+
description: 'The resolved baseline ref used for reviewdog annotations'
6+
value: ${{ steps.run-semgrep.outputs.normalizedBaseline }}
7+
scanSummary:
8+
description: 'Markdown summary of the Semgrep scan results'
9+
value: ${{ steps.run-semgrep.outputs.scanSummary }}
10+
configSummary:
11+
description: 'Markdown summary of the Semgrep configuration used'
12+
value: ${{ steps.run-semgrep.outputs.configSummary }}
13+
scanStatus:
14+
description: 'success/failure based on findings and input fail level'
15+
value: ${{ steps.run-semgrep.outputs.scanStatus }}
16+
totalFindings:
17+
description: 'Total number of findings from the Semgrep scan'
18+
value: ${{ steps.run-semgrep.outputs.totalFindings }}
19+
numErrors:
20+
description: 'Number of findings at error severity level'
21+
value: ${{ steps.run-semgrep.outputs.numErrors }}
22+
numWarnings:
23+
description: 'Number of findings at warning severity level'
24+
value: ${{ steps.run-semgrep.outputs.numWarnings }}
25+
numInfos:
26+
description: 'Number of findings at info severity level'
27+
value: ${{ steps.run-semgrep.outputs.numInfos }}
28+
29+
runs:
30+
using: composite
31+
steps:
32+
- name: Run Semgrep Scan
33+
id: run-semgrep
34+
shell: bash
35+
run: node ${{ github.action_path }}/run-semgrep.js

scripts/gha-lib/run-semgrep.js renamed to .github/actions/run-semgrep/run-semgrep.js

Lines changed: 43 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -1,61 +1,51 @@
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-
351
const { spawnSync } = require('child_process');
362
const fs = require('fs');
37-
const fetch = require('node-fetch');
38-
const { validateEnvVar } = require('../utils/env-helpers');
3+
const https = require('https');
394

405
const SEMGREP_RESULTS_FILE_NAME = 'semgrep_results.json';
416
const 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+
330327
module.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

Comments
 (0)