Implement Sprint 1 stories: collections, RBAC, audit logging, load testing
Complete 6 Sprint 1 stories for Epic 1 web migration infrastructure. Portfolio Collection: - Add 7 fields: title, slug, url, image, description, websiteType, tags - Configure R2 storage and authenticated access control Categories Collection: - Add nameEn, order, textColor, backgroundColor fields - Add color picker UI configuration Posts Collection: - Add excerpt with 200 char limit and ogImage for social sharing - Add showInFooter checkbox and status select (draft/review/published) Role-Based Access Control: - Add role field to Users collection (admin/editor) - Create adminOnly and authenticated access functions - Apply access rules to Portfolio, Categories, Posts, Users collections Audit Logging System (NFR9): - Create Audit collection with timestamps for 90-day retention - Add auditLogger utility for login/logout/content change tracking - Add auditChange and auditGlobalChange hooks to all collections and globals - Add cleanupAuditLogs job with 90-day retention policy Load Testing Framework (NFR4): - Add k6 load testing with 3 scripts: public-browsing, admin-operations, api-performance - Configure targets: p95 < 500ms, error rate < 1%, 100 concurrent users - Add verification script and comprehensive documentation Other Changes: - Remove unused Form blocks - Add Header/Footer audit hooks - Regenerate Payload TypeScript types
This commit is contained in:
154
apps/backend/tests/k6/.github-workflow-example.yml
Normal file
154
apps/backend/tests/k6/.github-workflow-example.yml
Normal file
@@ -0,0 +1,154 @@
|
||||
# K6 Load Testing - GitHub Actions Workflow Example
|
||||
# Copy this to .github/workflows/load-tests.yml
|
||||
|
||||
name: Load Tests
|
||||
|
||||
on:
|
||||
# Run daily at 2 AM UTC
|
||||
schedule:
|
||||
- cron: '0 2 * * *'
|
||||
|
||||
# Run on demand
|
||||
workflow_dispatch:
|
||||
|
||||
# Run after deployment to staging
|
||||
workflow_run:
|
||||
workflows: ["Deploy to Staging"]
|
||||
types:
|
||||
- completed
|
||||
|
||||
jobs:
|
||||
public-browsing:
|
||||
name: Public Browsing (100 users)
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup k6
|
||||
run: |
|
||||
curl https://github.com/grafana/k6/releases/download/v0.51.0/k6-v0.51.0-linux-amd64.tar.gz -L | tar xvz
|
||||
sudo mv k6-v0.51.0-linux-amd64/k6 /usr/local/bin/
|
||||
|
||||
- name: Wait for server
|
||||
run: |
|
||||
echo "Waiting for server to be ready..."
|
||||
timeout 60 bash -c 'until curl -sSf ${{ vars.STAGING_URL }} > /dev/null; do sleep 2; done'
|
||||
echo "Server is ready!"
|
||||
|
||||
- name: Run Public Browsing Test
|
||||
run: |
|
||||
k6 run \
|
||||
--env BASE_URL=${{ vars.STAGING_URL }} \
|
||||
--out json=public-browsing-results.json \
|
||||
apps/backend/tests/k6/public-browsing.js
|
||||
|
||||
- name: Upload Results
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: public-browsing-results
|
||||
path: public-browsing-results.json
|
||||
retention-days: 30
|
||||
|
||||
api-performance:
|
||||
name: API Performance (50 users)
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup k6
|
||||
run: |
|
||||
curl https://github.com/grafana/k6/releases/download/v0.51.0/k6-v0.51.0-linux-amd64.tar.gz -L | tar xvz
|
||||
sudo mv k6-v0.51.0-linux-amd64/k6 /usr/local/bin/
|
||||
|
||||
- name: Run API Performance Test
|
||||
run: |
|
||||
k6 run \
|
||||
--env BASE_URL=${{ vars.STAGING_URL }} \
|
||||
--out json=api-performance-results.json \
|
||||
apps/backend/tests/k6/api-performance.js
|
||||
|
||||
- name: Upload Results
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: api-performance-results
|
||||
path: api-performance-results.json
|
||||
retention-days: 30
|
||||
|
||||
admin-operations:
|
||||
name: Admin Operations (20 users)
|
||||
runs-on: ubuntu-latest
|
||||
# Only run on manual trigger or schedule, not on every deployment
|
||||
if: github.event_name == 'schedule' || github.event_name == 'workflow_dispatch'
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup k6
|
||||
run: |
|
||||
curl https://github.com/grafana/k6/releases/download/v0.51.0/k6-v0.51.0-linux-amd64.tar.gz -L | tar xvz
|
||||
sudo mv k6-v0.51.0-linux-amd64/k6 /usr/local/bin/
|
||||
|
||||
- name: Run Admin Operations Test
|
||||
run: |
|
||||
k6 run \
|
||||
--env BASE_URL=${{ vars.STAGING_URL }} \
|
||||
--env ADMIN_EMAIL=${{ secrets.TEST_ADMIN_EMAIL }} \
|
||||
--env ADMIN_PASSWORD=${{ secrets.TEST_ADMIN_PASSWORD }} \
|
||||
--out json=admin-operations-results.json \
|
||||
apps/backend/tests/k6/admin-operations.js
|
||||
env:
|
||||
# Don't log passwords
|
||||
K6_NO_LOG_USAGE: true
|
||||
|
||||
- name: Upload Results
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: admin-operations-results
|
||||
path: admin-operations-results.json
|
||||
retention-days: 30
|
||||
|
||||
# Optional: Generate and publish HTML reports
|
||||
generate-reports:
|
||||
name: Generate HTML Reports
|
||||
needs: [public-browsing, api-performance]
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Download Results
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
path: results
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: '20'
|
||||
|
||||
- name: Install k6-reporter
|
||||
run: npm install -g k6-reporter
|
||||
|
||||
- name: Generate Reports
|
||||
run: |
|
||||
mkdir -p reports
|
||||
k6-reporter results/public-browsing-results/public-browsing-results.json --output reports/public-browsing.html
|
||||
k6-reporter results/api-performance-results/api-performance-results.json --output reports/api-performance.html
|
||||
|
||||
- name: Upload Reports
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: html-reports
|
||||
path: reports/
|
||||
retention-days: 30
|
||||
|
||||
- name: Comment PR with Results
|
||||
if: github.event_name == 'pull_request'
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
const fs = require('fs');
|
||||
const publicReport = fs.readFileSync('reports/public-browsing.html', 'utf8');
|
||||
// Add comment to PR with summary...
|
||||
Reference in New Issue
Block a user