-
Notifications
You must be signed in to change notification settings - Fork 0
feat: add composite actions, enhanced governance, and GitHub Issue reports #7
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 1 commit
b239275
d83bc29
5ea0394
fd965c9
a494e5d
b98ffb2
6570f77
86835e7
60cf8e3
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,30 @@ | ||
| name: Security Scan | ||
| description: Run SAST and SCA security scans | ||
|
|
||
| inputs: | ||
| scan-path: | ||
| description: Path to scan | ||
| required: false | ||
| default: "." | ||
|
|
||
| runs: | ||
| using: composite | ||
| steps: | ||
| - name: Run Semgrep SAST | ||
| uses: semgrep/semgrep-action@713efdd345f3035192eaa63f56867b88e63e4e5d # v1.0.0 | ||
| with: | ||
| config: auto | ||
|
|
||
| - name: Run Trivy vulnerability scanner | ||
| uses: aquasecurity/trivy-action@18f2510ee396bbf400402947e7f3b01483832965 # v0.31.0 | ||
| with: | ||
| scan-type: fs | ||
| scan-ref: ${{ inputs.scan-path }} | ||
| format: sarif | ||
| output: trivy-results.sarif | ||
|
|
||
| - name: Upload Trivy results to GitHub Security | ||
| uses: github/codeql-action/upload-sarif@ff0a06e83cb2de871e5a09832bc6a81e7276941f # v3.28.18 | ||
| if: always() | ||
| with: | ||
| sarif_file: trivy-results.sarif |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,46 @@ | ||
| name: Sync Repository Settings | ||
| description: Compare and apply GitHub settings across all repos against a baseline | ||
|
|
||
| inputs: | ||
| mode: | ||
| description: "Run mode: --dry-run or --apply" | ||
| required: true | ||
| default: "--dry-run" | ||
| github_token: | ||
| description: PAT with repo and admin scopes | ||
| required: true | ||
|
|
||
| outputs: | ||
| report_file: | ||
| description: Path to the generated report | ||
| value: ${{ steps.sync.outputs.report_file }} | ||
| total_repos: | ||
| description: Number of repos scanned | ||
| value: ${{ steps.parse.outputs.total_repos }} | ||
| compliant: | ||
| description: Number of compliant repos | ||
| value: ${{ steps.parse.outputs.compliant }} | ||
| drift: | ||
| description: Number of repos with drift | ||
| value: ${{ steps.parse.outputs.drift }} | ||
| has_drift: | ||
| description: Whether any drift was detected | ||
| value: ${{ steps.parse.outputs.has_drift }} | ||
|
|
||
| runs: | ||
| using: composite | ||
| steps: | ||
| - name: Run settings sync | ||
| id: sync | ||
| shell: bash | ||
| env: | ||
| GH_TOKEN: ${{ inputs.github_token }} | ||
| REPORT_FILE: reports/sync-report.md | ||
| run: | | ||
| ./scripts/sync-repo-settings.sh "${{ inputs.mode }}" | ||
| echo "report_file=reports/sync-report.md" >> "$GITHUB_OUTPUT" | ||
|
|
||
| - name: Parse report | ||
| id: parse | ||
| shell: bash | ||
| run: ./scripts/generate-report.sh reports/sync-report.md | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,36 @@ | ||
| name: Update Pre-commit Hooks Composite Action | ||
| description: Updates pre-commit hook versions and creates a PR | ||
|
|
||
| inputs: | ||
| github_token: | ||
| description: GitHub token for creating PRs | ||
| required: true | ||
|
|
||
| runs: | ||
| using: composite | ||
| steps: | ||
| - name: Set up Python | ||
| uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0 | ||
| with: | ||
| python-version: "3.x" | ||
|
|
||
| - name: Install pre-commit | ||
| shell: bash | ||
| run: pip install pre-commit | ||
|
|
||
| - name: Update hooks | ||
| shell: bash | ||
| run: pre-commit autoupdate | ||
|
|
||
| - name: Create Pull Request | ||
| uses: peter-evans/create-pull-request@271a8d0340265f705b14b6d32b9829c1cb33d45e # v7.0.8 | ||
| with: | ||
| token: ${{ inputs.github_token }} | ||
| commit-message: "chore: update pre-commit hook versions" | ||
| title: "chore: update pre-commit hook versions" | ||
| body: | | ||
| Automated update of pre-commit hook versions. | ||
|
|
||
| Review the changes to `.pre-commit-config.yaml` and merge if CI passes. | ||
| branch: chore/update-pre-commit-hooks | ||
| delete-branch: true |
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -79,6 +79,22 @@ jobs: | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| fi | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| done | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| - name: Validate baseline schema | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| run: | | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ERRORS=0 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| for section in repo_settings security branch_protection labels required_files; do | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if ! jq -e ".$section" config/baseline.json > /dev/null 2>&1; then | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| echo "ERROR: Missing section '$section' in baseline.json" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ERRORS=$((ERRORS + 1)) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| else | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| echo "OK: section '$section' present" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| fi | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| done | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if [ "$ERRORS" -gt 0 ]; then | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| echo "ERROR: baseline.json schema validation failed" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| exit 1 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| fi | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+90
to
+110
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This only checks section presence, not the baseline schema. Lines 85-91 will still pass if Suggested jq-based validation - name: Validate baseline schema
run: |
- ERRORS=0
- for section in repo_settings security branch_protection labels required_files; do
- if ! jq -e ".$section" config/baseline.json > /dev/null 2>&1; then
- echo "ERROR: Missing section '$section' in baseline.json"
- ERRORS=$((ERRORS + 1))
- else
- echo "OK: section '$section' present"
- fi
- done
- if [ "$ERRORS" -gt 0 ]; then
- echo "ERROR: baseline.json schema validation failed"
- exit 1
- fi
+ jq -e '
+ (.repo_settings | type == "object") and
+ (.security | type == "object") and
+ (.security.vulnerability_alerts | type == "boolean") and
+ (.branch_protection | type == "object") and
+ (.required_files | type == "array") and
+ (.labels | type == "array") and
+ ([.labels[] | (.name | type == "string")
+ and (.color | type == "string" and test("^[0-9A-Fa-f]{6}$"))
+ and (.description | type == "string")] | all)
+ ' config/baseline.json >/dev/null || {
+ echo "ERROR: baseline.json schema validation failed"
+ exit 1
+ }As per coding guidelines, "Confirm the JSON structure aligns with the baseline schema validated by quality checks (Validate baseline schema step) and used by per-repo drift/metadata checks." 📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| actions-security: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| name: Actions Security | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| runs-on: ubuntu-latest | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
${{ inputs.mode }}is directly interpolated into therun:shell command, which is a script injection risk. Although the current caller constrains this input to achoicetype with fixed values, the composite action itself doesn't validate the input. If reused by another workflow that passes untrusted input, this could allow arbitrary command execution.Pass the input via an environment variable instead (e.g.,
env: MODE: ${{ inputs.mode }}), and reference it as"$MODE"in the script. This follows the recommended GitHub Actions security practice of never using${{ }}expressions directly inrun:blocks.