Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
103 changes: 66 additions & 37 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,38 @@ name: CI/CD Pipeline
on:
push:
branches: [ main, develop ]
paths:
- 'backend/**'
- 'frontend/**'
- 'src/**'
- 'tests/**'
- 'infra/**'
- 'scripts/**'
- 'docker/**'
- 'docker-compose*.yml'
- 'pyproject.toml'
- 'uv.lock'
- 'go.mod'
- 'go.sum'
- 'package.json'
- 'bun.lock'
pull_request:
branches: [ main, develop ]
paths:
- 'backend/**'
- 'frontend/**'
- 'src/**'
- 'tests/**'
- 'infra/**'
- 'scripts/**'
- 'docker/**'
- 'docker-compose*.yml'
- 'pyproject.toml'
- 'uv.lock'
- 'go.mod'
- 'go.sum'
- 'package.json'
- 'bun.lock'
release:
types: [ published ]

Expand Down Expand Up @@ -722,44 +752,41 @@ jobs:
# Extract coverage from vitest output or coverage-final.json
if [ -f "coverage/coverage-final.json" ]; then
node << 'EOF'
const fs = require('fs');
const coverage = JSON.parse(fs.readFileSync('coverage/coverage-final.json', 'utf8'));

// Calculate per-file coverage
const fileCoverage = {};
let totalLines = 0, coveredLines = 0;

Object.entries(coverage).forEach(([file, stats]) => {
if (stats.l) {
const lines = Object.values(stats.l);
const covered = lines.filter(v => v > 0).length;
const total = lines.length;
if (total > 0) {
fileCoverage[file] = Math.round((covered / total) * 100 * 100) / 100;
totalLines += total;
coveredLines += covered;
}
const fs = require('fs');
const coverage = JSON.parse(fs.readFileSync('coverage/coverage-final.json', 'utf8'));

const fileCoverage = {};
let totalLines = 0;
let coveredLines = 0;

Object.entries(coverage).forEach(([file, stats]) => {
if (stats.l) {
const lines = Object.values(stats.l);
const covered = lines.filter((v) => v > 0).length;
const total = lines.length;
if (total > 0) {
fileCoverage[file] = Math.round((covered / total) * 100 * 100) / 100;
totalLines += total;
coveredLines += covered;
}
}
});

let output = '';
Object.entries(fileCoverage)
.sort(([a], [b]) => a.localeCompare(b))
.forEach(([file, cov]) => {
output += `${file}|${cov}\n`;
});
fs.writeFileSync('coverage-by-file.txt', output);

// Write simple format for comparison
const fs2 = require('fs');
let output = '';
Object.entries(fileCoverage)
.sort(([a], [b]) => a.localeCompare(b))
.forEach(([file, cov]) => {
output += `${file}|${cov}\n`;
});
fs2.writeFileSync('coverage-by-file.txt', output);

// Write summary
if (totalLines > 0) {
const totalCov = Math.round((coveredLines / totalLines) * 100 * 100) / 100;
fs2.appendFileSync('coverage-by-file.txt', `TOTAL|${totalCov}\n`);
}
if (totalLines > 0) {
const totalCov = Math.round((coveredLines / totalLines) * 100 * 100) / 100;
fs.appendFileSync('coverage-by-file.txt', `TOTAL|${totalCov}\n`);
}

console.log('Frontend coverage data extracted');
EOF
console.log('Frontend coverage data extracted');
EOF
else
echo "Warning: coverage-final.json not found"
fi
Expand Down Expand Up @@ -1414,24 +1441,26 @@ jobs:
name: IaC Deploy (Pulumi dev)
runs-on: ubuntu-latest
needs: [docker-build]
# Only run when a Pulumi access token is configured; otherwise skip gracefully.
if: ${{ secrets.PULUMI_ACCESS_TOKEN != '' }}

permissions:
contents: read
env:
PULUMI_ACCESS_TOKEN: ${{ secrets.PULUMI_ACCESS_TOKEN }}

steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Install Pulumi Node.js dependencies
if: env.PULUMI_ACCESS_TOKEN != ''
working-directory: infra
run: bun install

- name: Pulumi up (dev)
if: env.PULUMI_ACCESS_TOKEN != ''
uses: pulumi/actions@v5
env:
PULUMI_ACCESS_TOKEN: ${{ secrets.PULUMI_ACCESS_TOKEN }}
PULUMI_ACCESS_TOKEN: ${{ env.PULUMI_ACCESS_TOKEN }}
Comment on lines +1417 to +1433
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🧹 Nitpick | 🔵 Trivial

Redundant step-level env for PULUMI_ACCESS_TOKEN.

Since PULUMI_ACCESS_TOKEN is already exposed at the job level (lines 1417-1418), steps inherit it automatically. The inner env: on the Pulumi step that re-exports ${{ env.PULUMI_ACCESS_TOKEN }} is redundant and can be removed to reduce surface area. The step-level if: env.PULUMI_ACCESS_TOKEN != '' gating itself is fine (the env context is available in step-level if).

♻️ Proposed simplification
     - name: Pulumi up (dev)
       if: env.PULUMI_ACCESS_TOKEN != ''
       uses: pulumi/actions@v5
-      env:
-        PULUMI_ACCESS_TOKEN: ${{ env.PULUMI_ACCESS_TOKEN }}
       with:
         command: up
         stack-name: dev
         work-dir: infra
         comment-on-pr: false
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/ci.yml around lines 1417 - 1433, The step-level env that
re-exports PULUMI_ACCESS_TOKEN is redundant because the job-level env already
exposes it; remove the inner env block from the "Pulumi up (dev)" step (the step
using pulumi/actions@v5) while keeping the existing step-level if:
env.PULUMI_ACCESS_TOKEN != '' gating intact so the step still only runs when the
token is present.

with:
command: up
stack-name: dev
Expand Down
27 changes: 26 additions & 1 deletion .github/workflows/contracts.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,34 @@ name: Contracts & SDKs
on:
pull_request:
branches: [main, develop]
paths:
- 'backend/**'
- 'frontend/**'
- 'contracts/**'
- 'scripts/**'
- 'openapi/**'
- 'buf.yaml'
- 'buf.gen.yaml'
- 'go.mod'
- 'go.sum'
- 'pyproject.toml'
- 'uv.lock'
- 'bun.lock'
push:
branches: [main, develop]
paths:
- 'backend/**'
- 'frontend/**'
- 'contracts/**'
- 'scripts/**'
- 'openapi/**'
- 'buf.yaml'
- 'buf.gen.yaml'
- 'go.mod'
- 'go.sum'
- 'pyproject.toml'
- 'uv.lock'
- 'bun.lock'

jobs:
contracts:
Expand Down Expand Up @@ -35,7 +61,6 @@ jobs:
uses: actions/setup-python@v5
with:
cache: 'pip'
with:
python-version: '3.12'

- name: Cache uv dependencies
Expand Down
25 changes: 18 additions & 7 deletions .github/workflows/test-validation.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,22 @@ name: Comprehensive Test Validation
on:
push:
branches: [main, develop]
paths:
- 'backend/**'
- 'frontend/**'
- 'Makefile'
- 'package.json'
- 'bun.lock'
- 'uv.lock'
pull_request:
branches: [main, develop]
paths:
- 'backend/**'
- 'frontend/**'
- 'Makefile'
- 'package.json'
- 'bun.lock'
- 'uv.lock'

jobs:
setup-test-users:
Expand All @@ -16,7 +30,6 @@ jobs:
- uses: actions/setup-node@v4
with:
cache: 'npm'
with:
node-version: '20'

- uses: actions/setup-go@v4
Expand All @@ -40,7 +53,6 @@ jobs:
- uses: actions/setup-node@v4
with:
cache: 'npm'
with:
node-version: '20'

- name: Install bun
Expand Down Expand Up @@ -81,7 +93,6 @@ jobs:
- uses: actions/setup-node@v4
with:
cache: 'npm'
with:
node-version: '20'

- name: Install bun
Expand Down Expand Up @@ -204,10 +215,10 @@ jobs:

| Suite | Status |
|-------|--------|
| Frontend E2E (Playwright) | ${{ job.test-frontend-e2e.status }} |
| Frontend API (Vitest) | ${{ job.test-frontend-api.status }} |
| Backend Go | ${{ job.test-backend-go.status }} |
| Backend Python | ${{ job.test-backend-python.status }} |
| Frontend E2E (Playwright) | ${{ needs.test-frontend-e2e.result }} |
| Frontend API (Vitest) | ${{ needs.test-frontend-api.result }} |
| Backend Go | ${{ needs.test-backend-go.result }} |
| Backend Python | ${{ needs.test-backend-python.result }} |

## Artifacts

Expand Down
Loading