feat(ci): add Flutter CI/CD pipeline for Forgejo Actions (Stage 4C)

Add Forgejo Actions workflows for automated Flutter validation on PRs:

- flutter-analyze.yml: runs dart analyze --fatal-infos on all 8 packages/apps

- flutter-test.yml: runs flutter test per package with pass/fail reporting

- Aggregate test result summary table in workflow output

- Workflows trigger on PRs to main and all non-main branch pushes

- Uses ghcr.io/cirruslabs/flutter:stable container image

Populate tools/ directory with CI helper scripts:

- run_all_tests.sh: local test runner with optional --analyze flag

- README.md: documents scripts and CI workflow inventory

Validated locally:

- dart analyze: all 8 packages/apps clean (no issues)

- core: 20/20 tests passed

- design_system: 41/41 tests passed

- feature_wordpress: 294/294 tests passed

- kell_web: 24/24 tests passed

- Total: 379/379 tests passed
This commit is contained in:
Mike Kell 2026-05-22 10:09:42 -04:00
parent 0a0abc2c3d
commit b00072474b
4 changed files with 395 additions and 0 deletions

View File

@ -0,0 +1,77 @@
name: Flutter Analyze
on:
pull_request:
branches:
- main
push:
branches:
- "**"
- "!main"
jobs:
analyze:
name: Dart Analyze
runs-on: ubuntu-latest
container:
image: ghcr.io/cirruslabs/flutter:stable
defaults:
run:
working-directory: kell_creations_apps
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Install dependencies — core
run: cd packages/core && flutter pub get
- name: Install dependencies — design_system
run: cd packages/design_system && flutter pub get
- name: Install dependencies — feature_wordpress
run: cd packages/feature_wordpress && flutter pub get
- name: Install dependencies — feature_inventory
run: cd packages/feature_inventory && flutter pub get
- name: Install dependencies — feature_orders
run: cd packages/feature_orders && flutter pub get
- name: Install dependencies — feature_policy
run: cd packages/feature_policy && flutter pub get
- name: Install dependencies — kell_web
run: cd apps/kell_web && flutter pub get
- name: Install dependencies — kell_mobile
run: cd apps/kell_mobile && flutter pub get
- name: Analyze — core
run: cd packages/core && dart analyze --fatal-infos
- name: Analyze — design_system
run: cd packages/design_system && dart analyze --fatal-infos
- name: Analyze — feature_wordpress
run: cd packages/feature_wordpress && dart analyze --fatal-infos
- name: Analyze — feature_inventory
run: cd packages/feature_inventory && dart analyze --fatal-infos
- name: Analyze — feature_orders
run: cd packages/feature_orders && dart analyze --fatal-infos
- name: Analyze — feature_policy
run: cd packages/feature_policy && dart analyze --fatal-infos
- name: Analyze — kell_web
run: cd apps/kell_web && dart analyze --fatal-infos
- name: Analyze — kell_mobile
run: cd apps/kell_mobile && dart analyze --fatal-infos
- name: Summary
if: always()
run: echo "✅ Dart analyze completed for all packages and apps"

View File

@ -0,0 +1,127 @@
name: Flutter Test
on:
pull_request:
branches:
- main
push:
branches:
- "**"
- "!main"
jobs:
test:
name: Flutter Tests
runs-on: ubuntu-latest
container:
image: ghcr.io/cirruslabs/flutter:stable
defaults:
run:
working-directory: kell_creations_apps
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Install dependencies — core
run: cd packages/core && flutter pub get
- name: Install dependencies — design_system
run: cd packages/design_system && flutter pub get
- name: Install dependencies — feature_wordpress
run: cd packages/feature_wordpress && flutter pub get
- name: Install dependencies — kell_web
run: cd apps/kell_web && flutter pub get
- name: Test — core
run: |
cd packages/core
flutter test --reporter expanded 2>&1 | tee test_output.txt
echo ""
echo "=== core test summary ==="
TOTAL=$(grep -cE '^\s*✓' test_output.txt || echo "0")
FAILED=$(grep -cE '^\s*✗' test_output.txt || echo "0")
echo " Passed: $TOTAL"
echo " Failed: $FAILED"
# Fail the step if any tests failed
if [ "$FAILED" -gt 0 ]; then exit 1; fi
- name: Test — design_system
run: |
cd packages/design_system
flutter test --reporter expanded 2>&1 | tee test_output.txt
echo ""
echo "=== design_system test summary ==="
TOTAL=$(grep -cE '^\s*✓' test_output.txt || echo "0")
FAILED=$(grep -cE '^\s*✗' test_output.txt || echo "0")
echo " Passed: $TOTAL"
echo " Failed: $FAILED"
if [ "$FAILED" -gt 0 ]; then exit 1; fi
- name: Test — feature_wordpress
run: |
cd packages/feature_wordpress
flutter test --reporter expanded 2>&1 | tee test_output.txt
echo ""
echo "=== feature_wordpress test summary ==="
TOTAL=$(grep -cE '^\s*✓' test_output.txt || echo "0")
FAILED=$(grep -cE '^\s*✗' test_output.txt || echo "0")
echo " Passed: $TOTAL"
echo " Failed: $FAILED"
if [ "$FAILED" -gt 0 ]; then exit 1; fi
- name: Test — kell_web
run: |
cd apps/kell_web
flutter test --reporter expanded 2>&1 | tee test_output.txt
echo ""
echo "=== kell_web test summary ==="
TOTAL=$(grep -cE '^\s*✓' test_output.txt || echo "0")
FAILED=$(grep -cE '^\s*✗' test_output.txt || echo "0")
echo " Passed: $TOTAL"
echo " Failed: $FAILED"
if [ "$FAILED" -gt 0 ]; then exit 1; fi
- name: Aggregate test report
if: always()
run: |
echo ""
echo "╔══════════════════════════════════════╗"
echo "║ Flutter Test Results Summary ║"
echo "╠══════════════════════════════════════╣"
echo "║ Package Pass Fail ║"
echo "╠══════════════════════════════════════╣"
TOTAL_PASS=0
TOTAL_FAIL=0
for pkg in packages/core packages/design_system packages/feature_wordpress apps/kell_web; do
NAME=$(basename "$pkg")
OUTPUT="$pkg/test_output.txt"
if [ -f "$OUTPUT" ]; then
PASS=$(grep -cE '^\s*✓' "$OUTPUT" || echo "0")
FAIL=$(grep -cE '^\s*✗' "$OUTPUT" || echo "0")
else
PASS="—"
FAIL="—"
fi
printf "║ %-20s %-7s %-7s ║\n" "$NAME" "$PASS" "$FAIL"
if [ "$PASS" != "—" ]; then TOTAL_PASS=$((TOTAL_PASS + PASS)); fi
if [ "$FAIL" != "—" ]; then TOTAL_FAIL=$((TOTAL_FAIL + FAIL)); fi
done
echo "╠══════════════════════════════════════╣"
printf "║ %-20s %-7s %-7s ║\n" "TOTAL" "$TOTAL_PASS" "$TOTAL_FAIL"
echo "╚══════════════════════════════════════╝"
if [ "$TOTAL_FAIL" -gt 0 ]; then
echo ""
echo "❌ Some tests failed. See individual package results above."
exit 1
else
echo ""
echo "✅ All $TOTAL_PASS tests passed across all packages."
fi

View File

@ -0,0 +1,44 @@
# Tools
CI/CD helper scripts for the Kell Creations Flutter monorepo.
## Scripts
### `run_all_tests.sh`
Runs `flutter test` across all testable packages and apps, producing a per-package pass/fail summary.
**Usage:**
```bash
# From kell_creations_apps/ directory
./tools/run_all_tests.sh # Run tests only
./tools/run_all_tests.sh --analyze # Run dart analyze + tests
```
**What it does:**
1. Installs dependencies (`flutter pub get`) for all packages and apps.
2. Optionally runs `dart analyze --fatal-infos` on each package/app.
3. Runs `flutter test --reporter expanded` for packages with tests.
4. Prints an aggregate pass/fail summary table.
**Adding new packages:**
When a new package gains tests, add its path to the `TESTABLE` array in the script. For packages that should be analyzed but have no tests yet, add to the `ANALYZABLE` array only.
**Exit codes:**
- `0` — all tests passed (and analyze clean, if `--analyze` was used)
- `1` — one or more failures detected
## CI Workflows
The corresponding Forgejo Actions workflows live in `.forgejo/workflows/`:
| Workflow | Trigger | Purpose |
| --------------------- | ----------------- | -------------------------------------------- |
| `flutter-analyze.yml` | PRs and branches | Runs `dart analyze` on all packages and apps |
| `flutter-test.yml` | PRs and branches | Runs `flutter test` with result reporting |
| `validate-docs.yml` | Non-main branches | Validates MkDocs documentation build |
| `publish-docs.yml` | Push to main | Publishes documentation to docs host |

View File

@ -0,0 +1,147 @@
#!/usr/bin/env bash
# ──────────────────────────────────────────────────────────────────────
# run_all_tests.sh — Run flutter test for all testable packages and apps
#
# Usage:
# ./tools/run_all_tests.sh # Run from kell_creations_apps/
# ./tools/run_all_tests.sh --analyze # Also run dart analyze first
#
# Exit codes:
# 0 — all tests passed (and analyze clean, if requested)
# 1 — one or more failures
# ──────────────────────────────────────────────────────────────────────
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
ROOT_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
# Packages/apps with tests (add new ones here as they gain tests)
TESTABLE=(
packages/core
packages/design_system
packages/feature_wordpress
apps/kell_web
)
# All packages/apps to analyze (includes those without tests)
ANALYZABLE=(
packages/core
packages/design_system
packages/feature_wordpress
packages/feature_inventory
packages/feature_orders
packages/feature_policy
apps/kell_web
apps/kell_mobile
)
RUN_ANALYZE=false
if [[ "${1:-}" == "--analyze" ]]; then
RUN_ANALYZE=true
fi
OVERALL_EXIT=0
# ── Dependency install ───────────────────────────────────────────────
echo ""
echo "══════════════════════════════════════"
echo " Installing dependencies"
echo "══════════════════════════════════════"
for pkg in "${ANALYZABLE[@]}"; do
echo "$pkg"
(cd "$ROOT_DIR/$pkg" && flutter pub get --no-example) > /dev/null 2>&1
done
# ── Analyze (optional) ──────────────────────────────────────────────
if $RUN_ANALYZE; then
echo ""
echo "══════════════════════════════════════"
echo " Running dart analyze"
echo "══════════════════════════════════════"
ANALYZE_FAILURES=()
for pkg in "${ANALYZABLE[@]}"; do
NAME=$(basename "$pkg")
printf " %-25s" "$NAME"
if (cd "$ROOT_DIR/$pkg" && dart analyze --fatal-infos) > /dev/null 2>&1; then
echo "✅ clean"
else
echo "❌ issues found"
ANALYZE_FAILURES+=("$NAME")
OVERALL_EXIT=1
fi
done
if [ ${#ANALYZE_FAILURES[@]} -gt 0 ]; then
echo ""
echo " ❌ Analyze failures: ${ANALYZE_FAILURES[*]}"
else
echo ""
echo " ✅ All packages analyze clean"
fi
fi
# ── Tests ────────────────────────────────────────────────────────────
echo ""
echo "══════════════════════════════════════"
echo " Running flutter test"
echo "══════════════════════════════════════"
declare -A RESULTS_PASS
declare -A RESULTS_FAIL
TEST_FAILURES=()
for pkg in "${TESTABLE[@]}"; do
NAME=$(basename "$pkg")
echo ""
echo " ── $NAME ──"
TMPFILE=$(mktemp)
if (cd "$ROOT_DIR/$pkg" && flutter test --reporter expanded 2>&1) | tee "$TMPFILE"; then
: # tests passed
else
TEST_FAILURES+=("$NAME")
OVERALL_EXIT=1
fi
PASS=$(grep -cE '^\s*✓' "$TMPFILE" 2>/dev/null || echo "0")
FAIL=$(grep -cE '^\s*✗' "$TMPFILE" 2>/dev/null || echo "0")
RESULTS_PASS[$NAME]=$PASS
RESULTS_FAIL[$NAME]=$FAIL
rm -f "$TMPFILE"
done
# ── Summary ──────────────────────────────────────────────────────────
echo ""
echo "╔══════════════════════════════════════╗"
echo "║ Flutter Test Results Summary ║"
echo "╠══════════════════════════════════════╣"
echo "║ Package Pass Fail ║"
echo "╠══════════════════════════════════════╣"
TOTAL_PASS=0
TOTAL_FAIL=0
for pkg in "${TESTABLE[@]}"; do
NAME=$(basename "$pkg")
P=${RESULTS_PASS[$NAME]:-0}
F=${RESULTS_FAIL[$NAME]:-0}
printf "║ %-20s %-7s %-7s ║\n" "$NAME" "$P" "$F"
TOTAL_PASS=$((TOTAL_PASS + P))
TOTAL_FAIL=$((TOTAL_FAIL + F))
done
echo "╠══════════════════════════════════════╣"
printf "║ %-20s %-7s %-7s ║\n" "TOTAL" "$TOTAL_PASS" "$TOTAL_FAIL"
echo "╚══════════════════════════════════════╝"
if [ $OVERALL_EXIT -ne 0 ]; then
echo ""
echo "❌ Failures detected. See details above."
else
echo ""
echo "✅ All $TOTAL_PASS tests passed across all packages."
fi
exit $OVERALL_EXIT