Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
291fe2c
Epic 10: Planning & Weekly Queue (Stories 10.1–10.5)
don-petry Mar 30, 2026
107c31b
Fix Epic 10 review: align client GraphQL with schema, add coverage
github-actions[bot] May 6, 2026
01b6679
Epic 11 + 12: Media Pipeline & Notifications (Stories 11.1–12.5) (#37)
don-petry May 12, 2026
231a367
trigger: dev-lead workflow execution via synchronize event
claude Jun 4, 2026
0d01aa8
fix(bot): address bot feedback [skip ci-relay]
donpetry-bot Jun 8, 2026
ded1ac8
fix(bot): address bot feedback [skip ci-relay]
donpetry-bot Jun 8, 2026
062c3c8
fix(bot): address bot feedback [skip ci-relay]
donpetry-bot Jun 8, 2026
f99424f
test: add coverage for plan screen and weekly queue hooks
donpetry-bot Jul 15, 2026
74109f5
test: add coverage for planning GraphQL documents
donpetry-bot Jul 15, 2026
ce481c6
test: enhance coverage for planning features (plan screen, homepage, …
donpetry-bot Jul 15, 2026
ad21724
fix(bot): address bot feedback [skip ci-relay]
donpetry-bot Jul 15, 2026
acf7bca
fix(coverage): move test files to __tests__/ for proper jest discovery
donpetry-bot Jul 15, 2026
0909430
fix(coverage): configure jest to discover tests and generate proper c…
donpetry-bot Jul 15, 2026
49e2d24
fix(bot): address bot feedback [skip ci-relay]
donpetry-bot Jul 15, 2026
95cca20
fix(coverage): add inspection GraphQL tests and exclude __tests__ fro…
donpetry-bot Jul 15, 2026
e36467d
fix(coverage): improve SonarCloud coverage configuration and add veri…
donpetry-bot Jul 15, 2026
0c5755e
fix(ci): add Go coverage and SonarCloud result reporting
don-petry Oct 3, 2026
b8ee65d
fix(bot): address bot feedback [skip ci-relay]
don-petry Oct 3, 2026
4c8b719
fix(sonarcloud): restore .github exclusion to prevent coverage dilution
don-petry Oct 4, 2026
b8f4bab
fix(jest): correct setupFilesAfterEnv configuration for proper test e…
don-petry Oct 4, 2026
dfdb494
fix(sonarcloud): remove --ignore-scripts to allow proper Jest setup d…
don-petry Oct 4, 2026
44c31e1
fix(jest): use CommonJS require for jest-native setup compatibility
don-petry Oct 4, 2026
49cc576
fix(reviews): address review comments [skip ci-relay]
don-petry Oct 9, 2026
c9bf4ab
fix(reviews): address review comments [skip ci-relay]
don-petry Oct 9, 2026
40cc95c
fix(reviews): address review comments [skip ci-relay]
don-petry Oct 10, 2026
00b6139
fix(reviews): keep CI emulator env from being inlined into jest trans…
don-petry Oct 10, 2026
7eb9efa
test(coverage): add missing test cases for hooks, screens, and error …
don-petry Oct 10, 2026
d00159c
fix(reliability): improve error handling in query/mutation hooks
don-petry Oct 10, 2026
626e6d9
test(coverage): add comprehensive edge case and component tests
don-petry Oct 10, 2026
5bcfb46
fix(reviews): repair failing homepage, context-card and plan-screen t…
don-petry Oct 10, 2026
9772ba8
test(coverage): add missing test coverage for hooks and GraphQL opera…
don-petry Oct 10, 2026
143351e
fix(reviews): repair failing hook and staleness tests breaking CI
don-petry Oct 10, 2026
4bedbff
fix(reliability): extract error handling helpers and add comprehensiv…
don-petry Oct 10, 2026
d060809
test(coverage): add comprehensive edge case tests for hooks and screens
don-petry Oct 10, 2026
c747545
fix(reviews): align ensureData operation names with hook tests
don-petry Oct 11, 2026
61134c7
fix(reliability): add defensive data validation and error test coverage
don-petry Oct 11, 2026
2f55823
fix(reviews): align defer-task no-data test with ensureData operation…
don-petry Oct 11, 2026
a399e89
test(coverage): add comprehensive tests for notification GraphQL, sto…
don-petry Oct 11, 2026
58d04ee
fix(reviews): repair failing mobile tests blocking SonarCloud
don-petry Oct 11, 2026
e906ff5
fix(test-coverage): replace dynamic require with static imports in un…
don-petry Oct 11, 2026
c3a78ab
fix(test-coverage): replace dynamic require in homepage tests with st…
don-petry Oct 11, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
138 changes: 76 additions & 62 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,9 @@ jobs:
typescript:
name: TypeScript
runs-on: ubuntu-latest
timeout-minutes: 15
env:
# Firebase Emulator config for tests — no real credentials needed
EXPO_PUBLIC_FIREBASE_USE_EMULATOR: 'true'
EXPO_PUBLIC_FIREBASE_USE_EMULATOR: "true"
EXPO_PUBLIC_FIREBASE_PROJECT_ID: broodly-dev
steps:
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
Expand All @@ -34,7 +34,7 @@ jobs:
- run: pnpm install --frozen-lockfile

- name: Format check
run: pnpm run format:check
run: pnpm -w run format:check

- name: Lint
run: pnpm run lint
Expand All @@ -50,65 +50,27 @@ jobs:
exit 1
fi

- name: Test
- name: Test with coverage
# Coverage (lcov + text-summary) is configured in apps/mobile/jest.config.js.
# Passing CLI flags here forwards a literal `--` through nested pnpm, making
# jest treat the flags as test-path patterns (0 matches → exit 1).
run: pnpm run test
continue-on-error: false

mobile-build:
name: Mobile Build
runs-on: ubuntu-latest
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
needs: [typescript]
steps:
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4

- uses: pnpm/action-setup@f40ffcd9367d9f12939873eb1018b921a783ffaa # v4

- uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4
- name: Upload test artifacts on failure
if: failure()
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
with:
node-version: 20
cache: pnpm

- run: pnpm install --frozen-lockfile

- name: Generate .env from secrets
working-directory: apps/mobile
env:
EXPO_PUBLIC_FIREBASE_API_KEY: ${{ secrets.EXPO_PUBLIC_FIREBASE_API_KEY }}
EXPO_PUBLIC_FIREBASE_AUTH_DOMAIN: ${{ secrets.EXPO_PUBLIC_FIREBASE_AUTH_DOMAIN }}
EXPO_PUBLIC_FIREBASE_PROJECT_ID: ${{ secrets.EXPO_PUBLIC_FIREBASE_PROJECT_ID }}
EXPO_PUBLIC_FIREBASE_STORAGE_BUCKET: ${{ secrets.EXPO_PUBLIC_FIREBASE_STORAGE_BUCKET }}
EXPO_PUBLIC_FIREBASE_MESSAGING_SENDER_ID: ${{ secrets.EXPO_PUBLIC_FIREBASE_MESSAGING_SENDER_ID }}
EXPO_PUBLIC_FIREBASE_APP_ID: ${{ secrets.EXPO_PUBLIC_FIREBASE_APP_ID }}
EXPO_PUBLIC_API_URL: ${{ secrets.EXPO_PUBLIC_API_URL }}
run: |
cat > .env << 'ENVEOF'
EXPO_PUBLIC_FIREBASE_USE_EMULATOR=false
ENVEOF
echo "EXPO_PUBLIC_FIREBASE_API_KEY=${EXPO_PUBLIC_FIREBASE_API_KEY}" >> .env
echo "EXPO_PUBLIC_FIREBASE_AUTH_DOMAIN=${EXPO_PUBLIC_FIREBASE_AUTH_DOMAIN}" >> .env
echo "EXPO_PUBLIC_FIREBASE_PROJECT_ID=${EXPO_PUBLIC_FIREBASE_PROJECT_ID}" >> .env
echo "EXPO_PUBLIC_FIREBASE_STORAGE_BUCKET=${EXPO_PUBLIC_FIREBASE_STORAGE_BUCKET}" >> .env
echo "EXPO_PUBLIC_FIREBASE_MESSAGING_SENDER_ID=${EXPO_PUBLIC_FIREBASE_MESSAGING_SENDER_ID}" >> .env
echo "EXPO_PUBLIC_FIREBASE_APP_ID=${EXPO_PUBLIC_FIREBASE_APP_ID}" >> .env
echo "EXPO_PUBLIC_API_URL=${EXPO_PUBLIC_API_URL}" >> .env

- name: Inject native Firebase config (Android)
if: env.GOOGLE_SERVICES_JSON != ''
working-directory: apps/mobile
env:
GOOGLE_SERVICES_JSON: ${{ secrets.GOOGLE_SERVICES_JSON }}
run: echo "${GOOGLE_SERVICES_JSON}" | base64 -d > google-services.json

- name: Inject native Firebase config (iOS)
if: env.GOOGLE_SERVICE_INFO_PLIST != ''
working-directory: apps/mobile
env:
GOOGLE_SERVICE_INFO_PLIST: ${{ secrets.GOOGLE_SERVICE_INFO_PLIST }}
run: echo "${GOOGLE_SERVICE_INFO_PLIST}" | base64 -d > GoogleService-Info.plist
name: ts-test-results
path: |
apps/mobile/coverage/
test-results/
retention-days: 14

go:
name: Go
runs-on: ubuntu-latest
timeout-minutes: 15
defaults:
run:
working-directory: apps/api
Expand All @@ -129,7 +91,7 @@ jobs:
working-directory: apps/api

- name: Unit tests
run: go test -short -race -coverprofile=coverage.out ./...
run: go test -short -race -coverprofile=coverage.out -timeout=5m ./...

- name: Check coverage threshold
run: |
Expand All @@ -142,10 +104,12 @@ jobs:
fi

- name: Upload coverage
if: always()
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
with:
name: go-coverage
path: apps/api/coverage.out
retention-days: 14

- name: Migration guard
shell: bash
Expand All @@ -164,7 +128,6 @@ jobs:

errors=0

# Collect sequence numbers and validate naming
declare -A up_files
declare -A down_files
sequences=()
Expand Down Expand Up @@ -192,10 +155,8 @@ jobs:
fi
done

# Sort sequences
IFS=$'\n' sorted=($(sort <<<"${sequences[*]}")); unset IFS

# Check each sequence has both up and down
for seq in "${sorted[@]}"; do
if [ -z "${up_files[$seq]}" ]; then
echo "ERROR: Migration $seq is missing an .up.sql file"
Expand All @@ -207,7 +168,6 @@ jobs:
fi
done

# Check sequences are sequential (no gaps)
prev=""
for seq in "${sorted[@]}"; do
if [ -n "$prev" ]; then
Expand Down Expand Up @@ -236,6 +196,7 @@ jobs:
go-integration:
name: Go Integration Tests
runs-on: ubuntu-latest
timeout-minutes: 15
needs: go
defaults:
run:
Expand All @@ -249,5 +210,58 @@ jobs:
cache-dependency-path: apps/api/go.sum

- name: Integration tests (testcontainers)
run: go test -race -count=1 -run TestIntegration ./internal/repository/
timeout-minutes: 10
run: go test -race -count=1 -timeout=10m -run TestIntegration ./internal/repository/

mobile-build:
name: Mobile Build
runs-on: ubuntu-latest
timeout-minutes: 20
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
needs: [typescript]
steps:
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4

- uses: pnpm/action-setup@f40ffcd9367d9f12939873eb1018b921a783ffaa # v4

- uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4
with:
node-version: 20
cache: pnpm

- run: pnpm install --frozen-lockfile

- name: Generate .env from secrets
working-directory: apps/mobile
env:
EXPO_PUBLIC_FIREBASE_API_KEY: ${{ secrets.EXPO_PUBLIC_FIREBASE_API_KEY }}
EXPO_PUBLIC_FIREBASE_AUTH_DOMAIN: ${{ secrets.EXPO_PUBLIC_FIREBASE_AUTH_DOMAIN }}
EXPO_PUBLIC_FIREBASE_PROJECT_ID: ${{ secrets.EXPO_PUBLIC_FIREBASE_PROJECT_ID }}
EXPO_PUBLIC_FIREBASE_STORAGE_BUCKET: ${{ secrets.EXPO_PUBLIC_FIREBASE_STORAGE_BUCKET }}
EXPO_PUBLIC_FIREBASE_MESSAGING_SENDER_ID: ${{ secrets.EXPO_PUBLIC_FIREBASE_MESSAGING_SENDER_ID }}
EXPO_PUBLIC_FIREBASE_APP_ID: ${{ secrets.EXPO_PUBLIC_FIREBASE_APP_ID }}
EXPO_PUBLIC_API_URL: ${{ secrets.EXPO_PUBLIC_API_URL }}
run: |
cat > .env << 'ENVEOF'
EXPO_PUBLIC_FIREBASE_USE_EMULATOR=false
ENVEOF
echo "EXPO_PUBLIC_FIREBASE_API_KEY=${EXPO_PUBLIC_FIREBASE_API_KEY}" >> .env
echo "EXPO_PUBLIC_FIREBASE_AUTH_DOMAIN=${EXPO_PUBLIC_FIREBASE_AUTH_DOMAIN}" >> .env
echo "EXPO_PUBLIC_FIREBASE_PROJECT_ID=${EXPO_PUBLIC_FIREBASE_PROJECT_ID}" >> .env
echo "EXPO_PUBLIC_FIREBASE_STORAGE_BUCKET=${EXPO_PUBLIC_FIREBASE_STORAGE_BUCKET}" >> .env
echo "EXPO_PUBLIC_FIREBASE_MESSAGING_SENDER_ID=${EXPO_PUBLIC_FIREBASE_MESSAGING_SENDER_ID}" >> .env
echo "EXPO_PUBLIC_FIREBASE_APP_ID=${EXPO_PUBLIC_FIREBASE_APP_ID}" >> .env
echo "EXPO_PUBLIC_API_URL=${EXPO_PUBLIC_API_URL}" >> .env

- name: Inject native Firebase config (Android)
if: env.GOOGLE_SERVICES_JSON != ''

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In GitHub Actions, step-level env: is not populated when the step's if: condition is evaluated, so if: env.GOOGLE_SERVICES_JSON != '' (and if: env.GOOGLE_SERVICE_INFO_PLIST != '' on line 263) will always evaluate to false unless those variables are defined at the job/workflow level. In addition, mobile-build writes .env and native config files but never runs a build or bundle verification step afterward.

working-directory: apps/mobile
env:
GOOGLE_SERVICES_JSON: ${{ secrets.GOOGLE_SERVICES_JSON }}
run: echo "${GOOGLE_SERVICES_JSON}" | base64 -d > google-services.json

- name: Inject native Firebase config (iOS)
if: env.GOOGLE_SERVICE_INFO_PLIST != ''
working-directory: apps/mobile
env:
GOOGLE_SERVICE_INFO_PLIST: ${{ secrets.GOOGLE_SERVICE_INFO_PLIST }}
run: echo "${GOOGLE_SERVICE_INFO_PLIST}" | base64 -d > GoogleService-Info.plist
55 changes: 52 additions & 3 deletions .github/workflows/sonarcloud.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,25 +11,74 @@ jobs:
sonarcloud:
name: SonarCloud
runs-on: ubuntu-latest
timeout-minutes: 20
permissions:
contents: read
pull-requests: read
pull-requests: write
env:
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
EXPO_PUBLIC_FIREBASE_USE_EMULATOR: "true"
EXPO_PUBLIC_FIREBASE_PROJECT_ID: broodly-dev
steps:
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
with:
fetch-depth: 0

- uses: pnpm/action-setup@f40ffcd9367d9f12939873eb1018b921a783ffaa # v4

- uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4
with:
node-version: 20
cache: pnpm

- run: pnpm install --frozen-lockfile

- name: Generate TypeScript coverage
# Coverage (lcov + text-summary) is configured in apps/mobile/jest.config.js.
# Passing CLI flags here forwards a literal `--` through nested pnpm, making
# jest treat the flags as test-path patterns (0 matches → exit 1).
run: pnpm run test
continue-on-error: false

- name: Verify coverage file exists
run: |
if [ -f "apps/mobile/coverage/lcov.info" ]; then
echo "✓ Coverage file found"
head -5 apps/mobile/coverage/lcov.info
else
echo "✗ Coverage file NOT found at apps/mobile/coverage/lcov.info"
ls -la apps/mobile/coverage/ || echo "Coverage directory does not exist"
exit 1
fi

- name: Normalize lcov paths for monorepo
run: |
# jest runs with rootDir apps/mobile and emits SF: paths relative to it
# (e.g. SF:app/..., SF:src/...). SonarCloud scans from the repo root, so
# those paths must be prefixed to repo-root-relative form or coverage
# fails to map to any source file (reported as 0% coverage on new code).
# Only rewrite relative paths; leave any absolute SF: paths untouched.
sed -i 's|^SF:\([^/]\)|SF:apps/mobile/\1|' apps/mobile/coverage/lcov.info
echo "Normalized SF: paths (sample):"
grep -m 3 "^SF:" apps/mobile/coverage/lcov.info

- uses: actions/setup-go@40f1582b2485089dde7abd97c1529aa768e1baff # v5
with:
go-version-file: apps/api/go.mod
cache-dependency-path: apps/api/go.sum

- name: Generate Go coverage for SonarCloud
- name: Generate Go coverage
working-directory: apps/api
run: go test -coverprofile=coverage.out ./...
run: go test -short -race -coverprofile=coverage.out -timeout=5m ./...

- uses: actions/setup-java@cf277c60eb25467037889841efdb72551f06f6c3 # v4.9.1
with:
java-version: 21
distribution: temurin

- name: SonarCloud Scan
if: ${{ env.SONAR_TOKEN != '' }}
uses: SonarSource/sonarqube-scan-action@fd88b7d7ccbaefd23d8f36f73b59db7a3d246602 # v6
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
36 changes: 18 additions & 18 deletions _bmad-output/implementation-artifacts/sprint-status.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -93,26 +93,26 @@ development_status:
9-5-skill-mismatch-detection: review
epic-9-retrospective: optional

epic-10: backlog
10-1-happy-context-homepage: ready-for-dev
10-2-weekly-action-queue: ready-for-dev
10-3-task-resolution-actions: ready-for-dev
10-4-seasonal-planning-calendar: ready-for-dev
10-5-dynamic-priority-updates: ready-for-dev
epic-10: done
10-1-happy-context-homepage: review
10-2-weekly-action-queue: review
10-3-task-resolution-actions: review
10-4-seasonal-planning-calendar: review
10-5-dynamic-priority-updates: review
epic-10-retrospective: optional

epic-11: backlog
11-1-signed-url-media-upload: ready-for-dev
11-2-stt-transcription-worker: ready-for-dev
11-3-vision-ai-analysis-worker: ready-for-dev
11-4-acoustic-analysis-worker: ready-for-dev
11-5-embedding-generation-pipeline: ready-for-dev
epic-11: done
11-1-signed-url-media-upload: review
11-2-stt-transcription-worker: review
11-3-vision-ai-analysis-worker: review
11-4-acoustic-analysis-worker: review
11-5-embedding-generation-pipeline: review
epic-11-retrospective: optional

epic-12: backlog
12-1-notification-dispatch-service: ready-for-dev
12-2-notification-center-ui: ready-for-dev
12-3-notification-sensitivity-config: ready-for-dev
12-4-alert-escalation-engine: ready-for-dev
12-5-feedback-prompts: ready-for-dev
epic-12: done
12-1-notification-dispatch-service: review
12-2-notification-center-ui: review
12-3-notification-sensitivity-config: review
12-4-alert-escalation-engine: review
12-5-feedback-prompts: review
epic-12-retrospective: optional
Loading
Loading