All checks were successful
Build and Publish TechDocs / build-and-publish (push) Successful in 1m3s
Change-Id: I3194558e1a840334641aff81960492489f171232
220 lines
6.3 KiB
YAML
220 lines
6.3 KiB
YAML
|
|
name: PR Lint and Validation Gate
|
|
|
|
on:
|
|
pull_request:
|
|
branches: [ "main" ]
|
|
workflow_dispatch: {}
|
|
|
|
concurrency:
|
|
group: ${{ github.workflow }}-${{ github.ref }}
|
|
cancel-in-progress: true
|
|
|
|
jobs:
|
|
yaml-and-whitespace:
|
|
name: YAML and Whitespace
|
|
runs-on: ubuntu-latest
|
|
outputs:
|
|
elapsed_seconds: ${{ steps.elapsed.outputs.seconds }}
|
|
steps:
|
|
- name: Start timer
|
|
run: echo "START_TS=$(date +%s)" >> "$GITHUB_ENV"
|
|
|
|
- name: Checkout
|
|
uses: actions/checkout@v4
|
|
|
|
- name: Install yamllint
|
|
run: |
|
|
python3 -m pip install --upgrade pip
|
|
python3 -m pip install yamllint
|
|
|
|
- name: Run yamllint
|
|
run: |
|
|
yamllint -d "{extends: default, rules: {line-length: {max: 180}, truthy: disable}}" .
|
|
|
|
- name: Check trailing whitespace
|
|
run: |
|
|
if git ls-files -z | xargs -0 -I{} grep -nH -E "[[:blank:]]+$" "{}" \
|
|
--exclude="*.md" --exclude="*.svg"; then
|
|
echo "Trailing whitespace found"
|
|
exit 1
|
|
fi
|
|
|
|
- name: Capture duration
|
|
id: elapsed
|
|
if: always()
|
|
run: |
|
|
end_ts=$(date +%s)
|
|
start_ts=${START_TS:-$end_ts}
|
|
echo "seconds=$((end_ts - start_ts))" >> "$GITHUB_OUTPUT"
|
|
|
|
helm-lint:
|
|
name: Helm Lint
|
|
runs-on: ubuntu-latest
|
|
outputs:
|
|
elapsed_seconds: ${{ steps.elapsed.outputs.seconds }}
|
|
steps:
|
|
- name: Start timer
|
|
run: echo "START_TS=$(date +%s)" >> "$GITHUB_ENV"
|
|
|
|
- name: Checkout
|
|
uses: actions/checkout@v4
|
|
|
|
- name: Install Helm
|
|
uses: azure/setup-helm@v4
|
|
|
|
- name: Lint all charts
|
|
run: |
|
|
mapfile -t charts < <(find . -type f -name Chart.yaml -print)
|
|
if [ -z "${charts[0]:-}" ]; then
|
|
echo "No Helm charts found; skipping"
|
|
exit 0
|
|
fi
|
|
|
|
failed=0
|
|
for chart in "${charts[@]}"; do
|
|
chart_dir="$(dirname "$chart")"
|
|
echo "Linting ${chart_dir}"
|
|
if ! helm lint "$chart_dir"; then
|
|
failed=1
|
|
fi
|
|
done
|
|
exit $failed
|
|
|
|
- name: Capture duration
|
|
id: elapsed
|
|
if: always()
|
|
run: |
|
|
end_ts=$(date +%s)
|
|
start_ts=${START_TS:-$end_ts}
|
|
echo "seconds=$((end_ts - start_ts))" >> "$GITHUB_OUTPUT"
|
|
|
|
terraform-lint:
|
|
name: Terraform Validate and TFLint
|
|
runs-on: ubuntu-latest
|
|
outputs:
|
|
elapsed_seconds: ${{ steps.elapsed.outputs.seconds }}
|
|
steps:
|
|
- name: Start timer
|
|
run: echo "START_TS=$(date +%s)" >> "$GITHUB_ENV"
|
|
|
|
- name: Checkout
|
|
uses: actions/checkout@v4
|
|
|
|
- name: Setup Terraform
|
|
uses: hashicorp/setup-terraform@v3
|
|
|
|
- name: Install TFLint
|
|
run: |
|
|
curl -s https://raw.githubusercontent.com/terraform-linters/tflint/master/install_linux.sh | bash
|
|
|
|
- name: Validate Terraform directories
|
|
run: |
|
|
mapfile -t tf_dirs < <(find . -type f -name "*.tf" -exec dirname {} \; | sort -u)
|
|
if [ -z "${tf_dirs[0]:-}" ]; then
|
|
echo "No Terraform files found; skipping"
|
|
exit 0
|
|
fi
|
|
|
|
failed=0
|
|
for dir in "${tf_dirs[@]}"; do
|
|
echo "Validating ${dir}"
|
|
(
|
|
cd "$dir"
|
|
terraform init -backend=false -input=false -no-color
|
|
terraform validate -no-color
|
|
tflint --chdir .
|
|
) || failed=1
|
|
done
|
|
exit $failed
|
|
|
|
- name: Capture duration
|
|
id: elapsed
|
|
if: always()
|
|
run: |
|
|
end_ts=$(date +%s)
|
|
start_ts=${START_TS:-$end_ts}
|
|
echo "seconds=$((end_ts - start_ts))" >> "$GITHUB_OUTPUT"
|
|
|
|
policy-and-deps:
|
|
name: Policy and Dependency Scan
|
|
runs-on: ubuntu-latest
|
|
outputs:
|
|
elapsed_seconds: ${{ steps.elapsed.outputs.seconds }}
|
|
steps:
|
|
- name: Start timer
|
|
run: echo "START_TS=$(date +%s)" >> "$GITHUB_ENV"
|
|
|
|
- name: Checkout
|
|
uses: actions/checkout@v4
|
|
|
|
- name: Install Checkov
|
|
run: |
|
|
python3 -m pip install --upgrade pip
|
|
python3 -m pip install checkov
|
|
|
|
- name: Run Checkov (Kubernetes)
|
|
run: |
|
|
checkov -d . --framework kubernetes --quiet
|
|
|
|
- name: npm audit (if package.json exists)
|
|
run: |
|
|
if [ -f package.json ]; then
|
|
npm install --no-audit --no-fund
|
|
npm audit --audit-level=high
|
|
else
|
|
echo "No package.json found; skipping npm audit"
|
|
fi
|
|
|
|
- name: Maven dependency-check (if pom.xml exists)
|
|
run: |
|
|
if [ -f pom.xml ]; then
|
|
mvn -B org.owasp:dependency-check-maven:check
|
|
else
|
|
echo "No pom.xml found; skipping Maven dependency-check"
|
|
fi
|
|
|
|
- name: Capture duration
|
|
id: elapsed
|
|
if: always()
|
|
run: |
|
|
end_ts=$(date +%s)
|
|
start_ts=${START_TS:-$end_ts}
|
|
echo "seconds=$((end_ts - start_ts))" >> "$GITHUB_OUTPUT"
|
|
|
|
runtime-slo:
|
|
name: Runtime SLO (< 3 min)
|
|
if: always()
|
|
needs:
|
|
- yaml-and-whitespace
|
|
- helm-lint
|
|
- terraform-lint
|
|
- policy-and-deps
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- name: Enforce suite runtime budget
|
|
run: |
|
|
y=${{ needs.yaml-and-whitespace.outputs.elapsed_seconds || 0 }}
|
|
h=${{ needs.helm-lint.outputs.elapsed_seconds || 0 }}
|
|
t=${{ needs.terraform-lint.outputs.elapsed_seconds || 0 }}
|
|
p=${{ needs.policy-and-deps.outputs.elapsed_seconds || 0 }}
|
|
|
|
# Jobs run in parallel; full-suite wall-clock is approximated by max(job runtimes).
|
|
suite=$y
|
|
[ $h -gt $suite ] && suite=$h
|
|
[ $t -gt $suite ] && suite=$t
|
|
[ $p -gt $suite ] && suite=$p
|
|
|
|
echo "## PR Lint Gate Runtime" >> "$GITHUB_STEP_SUMMARY"
|
|
echo "- YAML and Whitespace: ${y}s" >> "$GITHUB_STEP_SUMMARY"
|
|
echo "- Helm Lint: ${h}s" >> "$GITHUB_STEP_SUMMARY"
|
|
echo "- Terraform Validate and TFLint: ${t}s" >> "$GITHUB_STEP_SUMMARY"
|
|
echo "- Policy and Dependency Scan: ${p}s" >> "$GITHUB_STEP_SUMMARY"
|
|
echo "- Full suite (parallel max): ${suite}s" >> "$GITHUB_STEP_SUMMARY"
|
|
|
|
if [ $suite -gt 180 ]; then
|
|
echo "Runtime SLO exceeded: ${suite}s > 180s"
|
|
exit 1
|
|
fi
|
|
|