ci/workflows: add build automation, release pipeline, and branch protection rules #8
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Mandatory PR Checks | |
| # Runs all mandatory quality gates on every PR targeting `develop`. | |
| # These checks must pass before a PR is eligible for human review. | |
| # Configure these as required status checks in the branch protection settings. | |
| on: | |
| pull_request: | |
| branches: | |
| - develop | |
| types: | |
| - opened | |
| - reopened | |
| - synchronize | |
| - edited | |
| permissions: | |
| contents: read | |
| jobs: | |
| # ── 1. Detect prohibited file changes ───────────────────────────────────── | |
| check-prohibited-files: | |
| name: Check for Prohibited File Changes | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4 | |
| with: | |
| fetch-depth: 0 | |
| persist-credentials: false | |
| - name: Detect changes to protected files | |
| env: | |
| BASE_SHA: ${{ github.event.pull_request.base.sha }} | |
| HEAD_SHA: ${{ github.event.pull_request.head.sha }} | |
| run: | | |
| PROHIBITED_PATTERNS=( | |
| "^LICENSE" | |
| "^\.github/workflows/" | |
| "^SECURITY\.md" | |
| ) | |
| CHANGED_FILES=$(git diff --name-only "$BASE_SHA" "$HEAD_SHA") | |
| echo "Changed files:" | |
| echo "$CHANGED_FILES" | |
| VIOLATIONS=0 | |
| for pattern in "${PROHIBITED_PATTERNS[@]}"; do | |
| MATCHES=$(echo "$CHANGED_FILES" | grep -E "$pattern" || true) | |
| if [ -n "$MATCHES" ]; then | |
| echo "::warning::The following protected file(s) were modified — a maintainer must review:" | |
| echo "$MATCHES" | while read -r f; do echo " • $f"; done | |
| VIOLATIONS=$((VIOLATIONS + 1)) | |
| fi | |
| done | |
| if [ "$VIOLATIONS" -gt 0 ]; then | |
| echo "::warning::This PR modifies one or more protected files. A maintainer must review before merging." | |
| else | |
| echo "No prohibited file changes detected — OK" | |
| fi | |
| # ── 2. Check PR size (lines changed) ────────────────────────────────────── | |
| check-pr-size: | |
| name: Check PR Size | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4 | |
| with: | |
| fetch-depth: 0 | |
| persist-credentials: false | |
| - name: Warn on large PRs | |
| env: | |
| BASE_SHA: ${{ github.event.pull_request.base.sha }} | |
| HEAD_SHA: ${{ github.event.pull_request.head.sha }} | |
| run: | | |
| MAX_LINES=1500 | |
| CHANGED=$(git diff --stat "$BASE_SHA" "$HEAD_SHA" | tail -1) | |
| INSERTIONS=$(git diff --numstat "$BASE_SHA" "$HEAD_SHA" | awk '{sum += $1} END {print sum+0}') | |
| DELETIONS=$(git diff --numstat "$BASE_SHA" "$HEAD_SHA" | awk '{sum += $2} END {print sum+0}') | |
| TOTAL=$((INSERTIONS + DELETIONS)) | |
| echo "Lines added : $INSERTIONS" | |
| echo "Lines removed : $DELETIONS" | |
| echo "Total changes : $TOTAL" | |
| if [ "$TOTAL" -gt "$MAX_LINES" ]; then | |
| echo "::warning::This PR changes $TOTAL lines (threshold: $MAX_LINES)." | |
| echo "::warning::Consider splitting it into smaller, focused PRs for easier review." | |
| else | |
| echo "PR size is within the recommended limit — OK" | |
| fi | |
| # ── 3. Detect leftover conflict markers ─────────────────────────────────── | |
| check-no-conflict-markers: | |
| name: No Conflict Markers | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4 | |
| with: | |
| ref: ${{ github.event.pull_request.head.sha }} | |
| persist-credentials: false | |
| - name: Scan for unresolved conflict markers | |
| run: | | |
| MARKERS=$(grep -rn --include="*.c" --include="*.h" --include="*.sh" \ | |
| --include="*.md" --include="*.yml" --include="*.yaml" \ | |
| -E "^(<{7}|>{7}|={7}|\|{7}) " . || true) | |
| if [ -n "$MARKERS" ]; then | |
| echo "::error::Unresolved merge conflict markers found:" | |
| echo "$MARKERS" | |
| exit 1 | |
| fi | |
| echo "No conflict markers found — OK" | |
| # ── 4. Summary gate ─────────────────────────────────────────────────────── | |
| mandatory-checks-gate: | |
| name: All Mandatory PR Checks Passed | |
| runs-on: ubuntu-latest | |
| needs: | |
| - check-prohibited-files | |
| - check-pr-size | |
| - check-no-conflict-markers | |
| steps: | |
| - name: All checks passed | |
| run: | | |
| echo "All mandatory PR checks passed. Ready for maintainer review." |