Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
64 changes: 64 additions & 0 deletions .github/actions/create-github-issue/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
name: "Create Vulnerability Issue"
description: "Creates a GitHub issue if CRITICAL/HIGH vulnerabilities are found in the scan report"

inputs:
report_path:
description: "Path to the vulnerability report file"
required: true
package_name:
description: "Name of the package being released"
required: true
package_version:
description: "Version of the package being released"
required: true
release_branch:
description: "Release branch name"
required: true
labels:
description: "Labels to apply to the created issue"
required: false
default: "security"
vuln_art_url:
description: "URL to the vulnerability report artifact"
required: false

runs:
using: "composite"
steps:
- name: Check vulnerabilities in report
id: check_vulns
shell: bash
run: |
set -euo pipefail
REPORT="${{ inputs.report_path }}"

if grep -qE "CRITICAL|HIGH" "$REPORT"; then
echo "found=true" >> "$GITHUB_OUTPUT"
else
echo "found=false" >> "$GITHUB_OUTPUT"
fi

- name: Create GitHub Issue
if: steps.check_vulns.outputs.found == 'true'
shell: bash
env:
GH_TOKEN: ${{ github.token }}
run: |
TITLE="🔒 Security vulnerabilities in ${{ inputs.package_name }}@${{ inputs.package_version }}"
BODY=$(cat <<EOF
The vulnerability scan for \`${{ inputs.package_name }}@${{ inputs.package_version }}\` on branch \`${{ inputs.release_branch }}\` has detected **CRITICAL/HIGH** vulnerabilities.

**Release Branch:** \`${{ inputs.release_branch }}\`
**Package Version:** \`${{ inputs.package_version }}\`

Please review the attached vulnerability report and take necessary action. URL of the vulnerability report ${{ inputs.vuln_art_url }}.

---
_This issue was automatically generated by the Release Pipeline._
EOF
)

gh issue create \
--title "$TITLE" \
--body "$BODY" \
--label "${{ inputs.labels }}"
19 changes: 19 additions & 0 deletions .github/actions/create-vuln-issue.b/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# Create Vulnerability Issue (local composite action)

Creates a GitHub Issue **iff** the given vulnerability report file is **non-empty**.

## Inputs
- `report_path` (required): Path to the vulnerability report, e.g. `vuln-report.txt`.
- `package_name` (required)
- `package_version` (required)
- `release_branch` (required)
- `title_prefix` (optional, default: "Security vulnerabilities detected")
- `labels` (optional, comma-separated, default: "security,automated")
- `artifact_name` (optional): If provided, the action will link to the matching run artifact.

## Permissions
Job must grant:
```yaml
permissions:
contents: read
issues: write
105 changes: 105 additions & 0 deletions .github/actions/create-vuln-issue.b/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
name: "Create Vulnerability Issue (Inline)"
description: "Creates a GitHub issue only if vuln-report.txt contains CRITICAL/HIGH findings, inlining the report."
branding:
icon: alert-triangle
color: red

inputs:
report_path:
description: "Path to vulnerability report (e.g., vuln-report.txt)"
required: true
package_name:
description: "Package name for context"
required: false
default: ""
package_version:
description: "Package version for context"
required: false
default: ""
release_branch:
description: "Release branch for context"
required: false
default: ""
title_prefix:
description: "Issue title prefix"
required: false
default: "Security vulnerabilities detected"
labels:
description: "Comma-separated labels to apply to the issue"
required: false
default: "security,automated,trivy"

runs:
using: "composite"
steps:
- name: Inspect report for CRITICAL/HIGH
id: scan
shell: bash
run: |
set -euo pipefail
FILE="${{ inputs.report_path }}"

if [[ ! -f "$FILE" ]]; then
echo "has_findings=false" >> "$GITHUB_OUTPUT"
echo "❎ Report not found at $FILE. Skipping issue creation."
exit 0
fi

if ! [[ -s "$FILE" ]]; then
echo "has_findings=false" >> "$GITHUB_OUTPUT"
echo "✅ Report exists but is empty. Skipping issue creation."
exit 0
fi

# Look for CRITICAL or HIGH (case-insensitive, whole word)
if grep -Eqi '\b(CRITICAL|HIGH)\b' "$FILE"; then
echo "has_findings=true" >> "$GITHUB_OUTPUT"

# Escape backticks so the code block renders correctly in Markdown
REPORT_ESCAPED=$(sed 's/`/\\`/g' "$FILE")

{
echo "VULN_BODY<<'EOF_VULN'"
echo "$REPORT_ESCAPED"
echo "EOF_VULN"
} >> "$GITHUB_ENV"
else
echo "has_findings=false" >> "$GITHUB_OUTPUT"
echo "✅ No CRITICAL/HIGH findings in $FILE. Skipping issue creation."
fi

- name: Create GitHub issue with inline report
if: steps.scan.outputs.has_findings == 'true'
uses: actions/github-script@v7
with:
github-token: ${{ github.token }}
script: |
const labelsCsv = `${{ inputs.labels }}`.trim();
const labels = labelsCsv ? labelsCsv.split(',').map(s => s.trim()).filter(Boolean) : [];

const pkg = `${{ inputs.package_name }}` || '(unknown package)';
const version = `${{ inputs.package_version }}` || '(unknown version)';
const branch = `${{ inputs.release_branch }}` || '(unknown branch)';
const runUrl = `https://github.com/${context.repo.owner}/${context.repo.repo}/actions/runs/${process.env.GITHUB_RUN_ID}`;
const report = process.env.VULN_BODY || '(no report content)';

const title = `${{ inputs.title_prefix }} in ${pkg}@${ver}`;
const body =
`Automated scan detected **CRITICAL/HIGH** vulnerabilities.\n\n` +
`**Package:** ${pkg}\n` +
`**Version:** ${version}\n` +
`**Release branch:** ${branch}\n` +
`**Workflow run:** ${runUrl}\n\n` +
`<details><summary>Trivy Report (table)</summary>\n\n` +
'```\n' + report + '\n```\n\n' +
`</details>\n`;

const { data: issue } = await github.rest.issues.create({
owner: context.repo.owner,
repo: context.repo.repo,
title,
body,
labels
});

core.info(`✅ Issue created: ${issue.html_url}`);
Loading
Loading