This repository was archived by the owner on Jul 13, 2026. It is now read-only.
Description I used cast init and select the 2 then generate
[Invalid workflow file: .github/workflows/devsecops.yml#L163](https://github.com/castops/tests/actions/runs/23688702679/workflow)
You have an error in your yaml syntax on line 163
here are the devsecops.yml
# CAST — DevSecOps Pipeline for Node.js
# https://github.com/castops/cast
#
# Includes:
# 1. Secrets Detection — Gitleaks
# 2. SAST — Semgrep
# 3. SCA — npm audit
# 4. Container Security — Trivy (skipped if no Dockerfile)
# 5. Code Quality — ESLint
# 6. Security Gate — conftest policy evaluation on SARIF findings
name: CAST DevSecOps
on:
push:
branches: [main, master]
pull_request:
branches: [main, master]
workflow_dispatch:
permissions:
contents: read
security-events: write # required for SARIF upload to GitHub Security tab
actions: read
jobs:
# ── 1. Secrets Detection ───────────────────────────────────────────────────
secrets:
name: Secrets Detection
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0 # full history so Gitleaks can scan all commits
- name: Gitleaks
uses: gitleaks/gitleaks-action@v2
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN } }
# ── 2. SAST ────────────────────────────────────────────────────────────────
sast:
name: SAST
runs-on: ubuntu-latest
container:
image: semgrep/semgrep
steps:
- uses: actions/checkout@v4
- name: Semgrep scan
run: semgrep ci --sarif --output=semgrep.sarif || true
env:
SEMGREP_APP_TOKEN: ${{ secrets.SEMGREP_APP_TOKEN } }
- name: Upload to GitHub Security tab
uses: github/codeql-action/upload-sarif@v3
if: always ()
with:
sarif_file: semgrep.sarif
- name: Upload SARIF artifact
uses: actions/upload-artifact@v4
if: always ()
with:
name: cast-sarif-sast
path: semgrep.sarif
# ── 3. SCA — Dependency Audit ──────────────────────────────────────────────
sca:
name: SCA
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: " lts/*"
cache: npm
- name: Install dependencies
run: npm ci --prefer-offline
- name: npm audit
run: npm audit --audit-level=high
# ── 4. Container Security ──────────────────────────────────────────────────
container:
name: Container Security
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Check for Dockerfile
id: check_dockerfile
run: |
if [ -f Dockerfile ]; then
echo " found=true" >> $GITHUB_OUTPUT
else
echo " No Dockerfile found — skipping container scan"
echo " found=false" >> $GITHUB_OUTPUT
fi
- name: Build image
if: steps.check_dockerfile.outputs.found == ' true'
run: docker build -t cast-scan:${{ github.sha } } .
- name: Trivy scan
if: steps.check_dockerfile.outputs.found == ' true'
uses: aquasecurity/trivy-action@master
with:
image-ref: cast-scan:${{ github.sha } }
format: sarif
output: trivy.sarif
severity: CRITICAL,HIGH
exit-code: " 0" # gate handles blocking, not trivy directly
- name: Upload to GitHub Security tab
if: steps.check_dockerfile.outputs.found == ' true'
uses: github/codeql-action/upload-sarif@v3
with:
sarif_file: trivy.sarif
- name: Upload SARIF artifact
if: steps.check_dockerfile.outputs.found == ' true'
uses: actions/upload-artifact@v4
with:
name: cast-sarif-container
path: trivy.sarif
# ── 5. Code Quality ────────────────────────────────────────────────────────
quality:
name: Code Quality
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: " lts/*"
cache: npm
- name: Install dependencies
run: npm ci --prefer-offline
- name: ESLint
run: npx eslint . --ext .js,.jsx,.ts,.tsx --max-warnings 0
# ── 6. Security Gate ───────────────────────────────────────────────────────
gate:
name: Security Gate
runs-on: ubuntu-latest
needs: [secrets, sast, sca, container, quality]
if: always ()
steps:
- uses: actions/checkout@v4
- name: Download SARIF results
uses: actions/download-artifact@v4
with:
pattern: cast-sarif-*
path: sarif-results/
merge-multiple: true
continue-on-error: true
- name: Install conftest
run: |
curl -fsSL -o conftest.tar.gz \
https://github.com/open-policy-agent/conftest/releases/download/v0.50.0/conftest_0.50.0_Linux_x86_64.tar.gz
tar xzf conftest.tar.gz conftest
chmod +x conftest && sudo mv conftest /usr/local/bin/
- name: Write default policy
run: |
# Use local policy/ directory if present; otherwise write the built-in default.
# For strict/permissive mode, copy the desired .rego from:
# https://github.com/castops/cast/tree/main/policy
if [ ! -d policy ] || [ -z " $( ls -A policy/* .rego 2> /dev/null) " ]; then
mkdir -p policy
cat > policy/active.rego << 'REGO '
package main
import future.keywords.if
import future.keywords.in
deny[msg] if {
run := input.runs[_]
result := run.results[_]
result.level == "error"
tool := run.tool.driver.name
msg := sprintf("[CRITICAL] %s — %s (rule: %s)", [tool, result.message.text, result.ruleId])
}
REGO
fi
- name: Evaluate policy
run: |
GATE_FAILED=0
# Run conftest on any SARIF files collected
if compgen -G " sarif-results/*.sarif" > /dev/null 2>&1 ; then
conftest test sarif-results/* .sarif --policy policy/ \
|| GATE_FAILED=1
fi
# Check job results for non-SARIF tools
if [[ " ${{ needs.secrets.result } }" == " failure" ]]; then
echo " ❌ Secrets Detection failed"
GATE_FAILED=1
fi
if [[ " ${{ needs.sca.result } }" == " failure" ]]; then
echo " ❌ SCA (npm audit) failed"
GATE_FAILED=1
fi
if [ " $GATE_FAILED " -eq 1 ]; then
echo " ❌ Security gate blocked merge"
exit 1
fi
echo " ✅ All security checks passed — safe to merge" Reactions are currently unavailable
I used
cast initand select the 2 then generate[Invalid workflow file: .github/workflows/devsecops.yml#L163](https://github.com/castops/tests/actions/runs/23688702679/workflow) You have an error in your yaml syntax on line 163here are the devsecops.yml