Skip to content
This repository was archived by the owner on Jan 1, 2026. It is now read-only.

Commit f2c6b1c

Browse files
committed
feat: add scripts for OpenAPI sync, Firebase emulator management, linting, security scanning, and map updates
- Implemented `check-openapi-sync.ts` to ensure OpenAPI specs are in sync with backend code. - Created `emulator-wrapper.ts` to manage Firebase emulator lifecycle and cleanup debug logs. - Added `lint-all.ts` to run multiple linting tasks across the project. - Introduced `security-scan.ts` for auditing vulnerabilities in project dependencies. - Developed `update-maps-from-tarkovdev.ts` to fetch and update fallback maps from tarkov.dev.
1 parent d51ebe7 commit f2c6b1c

308 files changed

Lines changed: 21012 additions & 11096 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/enforced-ci.yml

Lines changed: 327 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,327 @@
1+
name: Enforced CI Pipeline
2+
3+
on:
4+
pull_request:
5+
branches: [main, master, develop]
6+
push:
7+
branches: [main, master, develop]
8+
9+
# Principle of least privilege: only grant necessary permissions
10+
permissions:
11+
contents: read # Read repository contents for checkout
12+
actions: write # Upload test artifacts and coverage reports
13+
pull-requests: write # Comment on PRs with results
14+
15+
env:
16+
NODE_VERSION: '22'
17+
# Fail fast on any job failure
18+
FAIL_FAST: true
19+
20+
jobs:
21+
# === PRE-REQUISITE CHECKS ===
22+
lint-and-format:
23+
name: Lint & Format Check
24+
runs-on: ubuntu-latest
25+
26+
steps:
27+
- name: Checkout code
28+
uses: actions/checkout@v4
29+
30+
- name: Setup Node.js
31+
uses: actions/setup-node@v4
32+
with:
33+
node-version: ${{ env.NODE_VERSION }}
34+
cache: 'npm'
35+
36+
- name: Install dependencies
37+
run: npm ci
38+
39+
- name: Run linting
40+
run: npm run lint
41+
42+
- name: Check formatting
43+
run: npm run format:check
44+
45+
- name: Block raw useProgressStore usage
46+
run: |
47+
ALLOWLIST='(stores/progress\.ts|composables/useProgressQueries\.ts|composables/livedata\.ts|types/.*)'
48+
if grep -RIn --include='*.{ts,tsx,vue}' 'useProgressStore\(' frontend | grep -Ev "$ALLOWLIST"; then
49+
echo 'Direct useProgressStore detected outside allowlist';
50+
exit 1;
51+
fi
52+
53+
# === SECURITY SCANS ===
54+
security-audit:
55+
name: Security Audit
56+
runs-on: ubuntu-latest
57+
58+
steps:
59+
- name: Checkout code
60+
uses: actions/checkout@v4
61+
62+
- name: Setup Node.js
63+
uses: actions/setup-node@v4
64+
with:
65+
node-version: ${{ env.NODE_VERSION }}
66+
cache: 'npm'
67+
68+
- name: Install dependencies
69+
run: npm ci
70+
71+
- name: Run comprehensive security scan
72+
run: npm run security:scan
73+
74+
- name: Check license compliance
75+
run: |
76+
npx license-checker --summary
77+
if npx license-checker --summary | grep -E 'GPL-3.0|AGPL|LGPL'; then
78+
echo "⚠️ Found copyleft licenses that require review"
79+
npx license-checker --summary
80+
exit 1
81+
fi
82+
83+
# === FRONTEND TESTING ===
84+
frontend-tests:
85+
name: Frontend Tests
86+
runs-on: ubuntu-latest
87+
needs: [lint-and-format, security-audit]
88+
89+
strategy:
90+
matrix:
91+
type: [unit, coverage]
92+
fail-fast: ${{ env.FAIL_FAST }}
93+
94+
steps:
95+
- name: Checkout code
96+
uses: actions/checkout@v4
97+
98+
- name: Setup Node.js
99+
uses: actions/setup-node@v4
100+
with:
101+
node-version: ${{ env.NODE_VERSION }}
102+
cache: 'npm'
103+
cache-dependency-path: frontend/package-lock.json
104+
105+
- name: Install frontend dependencies
106+
working-directory: ./frontend
107+
run: npm ci
108+
109+
- name: Run unit tests
110+
if: matrix.type == 'unit'
111+
working-directory: ./frontend
112+
run: npm run test:run
113+
114+
- name: Run tests with coverage
115+
if: matrix.type == 'coverage'
116+
working-directory: ./frontend
117+
run: npm run test:coverage
118+
119+
- name: Run type checking
120+
working-directory: ./frontend
121+
run: npm run type-check
122+
123+
- name: Upload coverage reports
124+
if: matrix.type == 'coverage'
125+
uses: actions/upload-artifact@v4
126+
with:
127+
name: frontend-coverage
128+
path: frontend/coverage/
129+
retention-days: 30
130+
131+
- name: Enforce bundle size
132+
working-directory: ./frontend
133+
run: |
134+
npm run build
135+
SIZE=$(node -e "const fs=require('fs');const files=fs.readdirSync('dist/assets').filter(f=>f.startsWith('index-')&&f.endsWith('.js'));if(!files[0]){console.error('No index file found');process.exit(1);}console.log(fs.statSync('dist/assets/'+files[0]).size);")
136+
if [ "$SIZE" -gt 512000 ]; then
137+
echo "Bundle exceeds 500kb (actual: $SIZE bytes)";
138+
exit 1;
139+
fi
140+
141+
# === FUNCTIONS TESTING ===
142+
functions-tests:
143+
name: Functions Tests
144+
runs-on: ubuntu-latest
145+
needs: [lint-and-format, security-audit]
146+
147+
strategy:
148+
matrix:
149+
type: [unit, coverage]
150+
fail-fast: ${{ env.FAIL_FAST }}
151+
152+
steps:
153+
- name: Checkout code
154+
uses: actions/checkout@v4
155+
156+
- name: Setup Node.js
157+
uses: actions/setup-node@v4
158+
with:
159+
node-version: ${{ env.NODE_VERSION }}
160+
cache: 'npm'
161+
cache-dependency-path: functions/package-lock.json
162+
163+
- name: Install functions dependencies
164+
run: npm ci --workspace functions
165+
166+
- name: Run unit tests
167+
if: matrix.type == 'unit'
168+
run: npm test --workspace functions
169+
170+
- name: Run tests with coverage
171+
if: matrix.type == 'coverage'
172+
run: npm run test:coverage --workspace functions
173+
174+
- name: Type checking
175+
run: npm run type-check --workspace functions
176+
177+
- name: Upload coverage reports
178+
if: matrix.type == 'coverage'
179+
uses: actions/upload-artifact@v4
180+
with:
181+
name: functions-coverage
182+
path: functions/coverage/
183+
retention-days: 30
184+
185+
# === INTEGRATION AND BUILD ===
186+
build-and-integration:
187+
name: Build & Integration
188+
runs-on: ubuntu-latest
189+
needs: [frontend-tests, functions-tests]
190+
191+
steps:
192+
- name: Checkout code
193+
uses: actions/checkout@v4
194+
195+
- name: Setup Node.js
196+
uses: actions/setup-node@v4
197+
with:
198+
node-version: ${{ env.NODE_VERSION }}
199+
cache: 'npm'
200+
201+
- name: Install all dependencies
202+
run: npm ci
203+
204+
- name: Build functions
205+
run: npm run build:functions
206+
207+
- name: Build frontend
208+
run: npm run build:frontend
209+
210+
- name: Check OpenAPI documentation sync
211+
run: npm run docs:check
212+
213+
- name: Generate full OpenAPI docs
214+
run: npm run docs:generate
215+
216+
- name: Upload OpenAPI spec
217+
uses: actions/upload-artifact@v4
218+
with:
219+
name: openapi-spec
220+
path: frontend/public/api/openapi.json
221+
retention-days: 30
222+
223+
# === E2E TESTING (Limited to pushes) ===
224+
e2e-tests:
225+
name: E2E Tests
226+
runs-on: ubuntu-latest
227+
needs: build-and-integration
228+
if: github.event_name == 'push' && (github.ref == 'refs/heads/main' || github.ref == 'refs/heads/master' || github.ref == 'refs/heads/develop')
229+
230+
steps:
231+
- name: Checkout code
232+
uses: actions/checkout@v4
233+
234+
- name: Setup Node.js
235+
uses: actions/setup-node@v4
236+
with:
237+
node-version: ${{ env.NODE_VERSION }}
238+
cache: 'npm'
239+
cache-dependency-path: frontend/package-lock.json
240+
241+
- name: Install frontend dependencies
242+
working-directory: ./frontend
243+
run: npm ci
244+
245+
- name: Install Playwright Browsers
246+
working-directory: ./frontend
247+
run: npx playwright install --with-deps
248+
249+
- name: Build frontend
250+
working-directory: ./frontend
251+
run: npm run build
252+
253+
- name: Run E2E tests
254+
working-directory: ./frontend
255+
run: npm run test:e2e
256+
env:
257+
CI: true
258+
259+
- name: Upload Playwright Report
260+
uses: actions/upload-artifact@v4
261+
if: failure()
262+
with:
263+
name: playwright-report
264+
path: frontend/playwright-report/
265+
retention-days: 30
266+
267+
# === RESULTS SUMMARY ===
268+
results-summary:
269+
name: Results Summary
270+
runs-on: ubuntu-latest
271+
needs: [lint-and-format, security-audit, frontend-tests, functions-tests, build-and-integration, e2e-tests]
272+
if: always()
273+
274+
steps:
275+
- name: Download all artifacts
276+
uses: actions/download-artifact@v4
277+
278+
- name: Create PR comment
279+
if: github.event_name == 'pull_request'
280+
uses: actions/github-script@v7
281+
with:
282+
script: |
283+
const { data: jobs } = await github.rest.actions.listJobsForWorkflowRun({
284+
owner: context.repo.owner,
285+
repo: context.repo.repo,
286+
run_id: context.runId,
287+
});
288+
289+
const results = jobs.jobs.map(job => ({
290+
name: job.name,
291+
conclusion: job.conclusion,
292+
url: job.html_url
293+
}));
294+
295+
const statusEmoji = {
296+
success: '✅',
297+
failure: '❌',
298+
cancelled: '⏹️',
299+
skipped: '⏭️'
300+
};
301+
302+
const summary = results.map(r =>
303+
`${statusEmoji[r.conclusion] || '❓'} **${r.name}**: ${r.conclusion?.toUpperCase() || 'UNKNOWN'}`
304+
).join('\n');
305+
306+
const comment = `## 🚦 CI Pipeline Results\n\n${summary}\n\n[View full details](${context.payload.repository.html_url}/actions/runs/${context.runId})`;
307+
308+
await github.rest.issues.createComment({
309+
issue_number: context.issue.number,
310+
owner: context.repo.owner,
311+
repo: context.repo.repo,
312+
body: comment
313+
});
314+
315+
- name: Overall status check
316+
run: |
317+
# This job will fail if any required job failed
318+
if [ "${{ needs.lint-and-format.result }}" != "success" ] || \
319+
[ "${{ needs.security-audit.result }}" != "success" ] || \
320+
[ "${{ needs.frontend-tests.result }}" != "success" ] || \
321+
[ "${{ needs.functions-tests.result }}" != "success" ] || \
322+
[ "${{ needs.build-and-integration.result }}" != "success" ]; then
323+
echo "❌ CI Pipeline Failed"
324+
exit 1
325+
else
326+
echo "✅ CI Pipeline Passed"
327+
fi

0 commit comments

Comments
 (0)