From 59972f518278cd86c0b28aa1aa1ded45d030f88a Mon Sep 17 00:00:00 2001 From: Adam Moussa <166072409+amoussa1229@users.noreply.github.com> Date: Thu, 14 May 2026 18:31:08 -0400 Subject: [PATCH] Add lightweight conventions check to CI workflows Validates README exists, .env in .gitignore, arm64 architecture, and log retention in synthesized templates. Runs by default, opt-out via run-conventions-check: false. --- .github/workflows/ci-python-sam.yaml | 50 ++++++++++++++++++++++++ .github/workflows/ci-typescript-cdk.yaml | 50 ++++++++++++++++++++++++ 2 files changed, 100 insertions(+) diff --git a/.github/workflows/ci-python-sam.yaml b/.github/workflows/ci-python-sam.yaml index 47578dc..d64faf7 100644 --- a/.github/workflows/ci-python-sam.yaml +++ b/.github/workflows/ci-python-sam.yaml @@ -35,6 +35,10 @@ on: description: "Node.js version for CDK CLI" type: string default: "24" + run-conventions-check: + description: "Run lightweight conventions audit" + type: boolean + default: true jobs: ci: @@ -81,6 +85,52 @@ jobs: working-directory: ${{ inputs.cdk-dir }} run: npx -y cdk synth --quiet + - name: Conventions check + if: ${{ inputs.run-conventions-check }} + run: | + errors=0 + warn() { echo "::warning::$1"; } + fail() { echo "::error::$1"; errors=$((errors + 1)); } + + # README must exist + if [[ ! -f README.md ]]; then + fail "Missing README.md" + fi + + # .gitignore must cover .env + if [[ -f .gitignore ]]; then + if ! grep -qE '^\\.env$|^\\.env\\b' .gitignore; then + fail ".gitignore does not include .env" + fi + else + fail "Missing .gitignore" + fi + + # SAM: check template for non-arm64 and missing log retention + TEMPLATE="${{ inputs.sam-template }}" + if [[ -f "$TEMPLATE" ]]; then + if grep -qi 'x86_64' "$TEMPLATE" 2>/dev/null; then + fail "SAM template: Lambda using x86_64 instead of arm64" + fi + if grep -qi 'AWS::Serverless::Function' "$TEMPLATE" 2>/dev/null; then + if ! grep -qi 'RetentionInDays\|AWS::Logs::LogGroup' "$TEMPLATE" 2>/dev/null; then + warn "SAM template: Lambda found but no explicit log retention" + fi + fi + # Check for secrets in environment variables + if grep -qiE '(API_KEY|SECRET|TOKEN|PASSWORD|WEBHOOK)' "$TEMPLATE" 2>/dev/null; then + if grep -A5 'Environment:' "$TEMPLATE" | grep -qiE '(API_KEY|SECRET|TOKEN|PASSWORD|WEBHOOK)' 2>/dev/null; then + fail "SAM template: possible secret in Lambda environment variables — use Secrets Manager" + fi + fi + fi + + if [[ $errors -gt 0 ]]; then + echo "Conventions check failed with $errors error(s)." + exit 1 + fi + echo "Conventions check passed." + - name: Setup SAM CLI if: ${{ inputs.run-sam-validate }} uses: aws-actions/setup-sam@v2 diff --git a/.github/workflows/ci-typescript-cdk.yaml b/.github/workflows/ci-typescript-cdk.yaml index 8e5a855..7048973 100644 --- a/.github/workflows/ci-typescript-cdk.yaml +++ b/.github/workflows/ci-typescript-cdk.yaml @@ -27,6 +27,10 @@ on: description: "Enable QEMU for cross-platform Docker builds (arm64 on x86 runners)" type: boolean default: false + run-conventions-check: + description: "Run lightweight conventions audit" + type: boolean + default: true run-sam-validate: description: "Run sam validate --lint (for Node.js SAM repos)" type: boolean @@ -70,6 +74,52 @@ jobs: if: ${{ inputs.run-cdk-synth }} run: npx cdk synth --quiet + - name: Conventions check + if: ${{ inputs.run-conventions-check }} + run: | + errors=0 + warn() { echo "::warning::$1"; } + fail() { echo "::error::$1"; errors=$((errors + 1)); } + + # README must exist + if [[ ! -f README.md ]]; then + fail "Missing README.md" + fi + + # .gitignore must cover .env + if [[ -f .gitignore ]]; then + if ! grep -qE '^\\.env$|^\\.env\\b' .gitignore; then + fail ".gitignore does not include .env" + fi + else + fail "Missing .gitignore" + fi + + # CDK: check synth output for non-arm64 Lambdas and missing log retention + if [[ -d cdk.out ]]; then + for tmpl in cdk.out/*.template.json; do + [[ -f "$tmpl" ]] || continue + + # Check for x86_64 Lambdas + if grep -q '"Architectures".*x86_64' "$tmpl" 2>/dev/null; then + fail "$(basename "$tmpl"): Lambda using x86_64 instead of arm64" + fi + + # Check Lambdas exist but no log retention set + if grep -q '"AWS::Lambda::Function"' "$tmpl" 2>/dev/null; then + if ! grep -q '"AWS::Logs::LogGroup"' "$tmpl" 2>/dev/null; then + warn "$(basename "$tmpl"): Lambda found but no explicit LogGroup with retention" + fi + fi + done + fi + + if [[ $errors -gt 0 ]]; then + echo "Conventions check failed with $errors error(s)." + exit 1 + fi + echo "Conventions check passed." + - name: Setup SAM CLI if: ${{ inputs.run-sam-validate }} uses: aws-actions/setup-sam@v2