Repository navigation
114 lines (102 loc) · 3.85 KB
/
Copy pathdeploy-github-pages.yml
File metadata and controls
114 lines (102 loc) · 3.85 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
name: Deploy to GitHub Pages
on:
push:
branches: [main]
paths:
- 'packages/frontend/**'
- 'packages/shared/**'
- 'pnpm-lock.yaml'
- '.github/workflows/deploy-github-pages.yml'
workflow_dispatch:
permissions:
contents: read
pages: write
id-token: write
concurrency:
group: 'pages'
cancel-in-progress: true
env:
NODE_VERSION: '24.19.0'
PNPM_VERSION: '11.21.0'
jobs:
build:
name: Build for GitHub Pages
runs-on: ubuntu-latest
timeout-minutes: 20
steps:
- name: Checkout repository
uses: actions/checkout@v5
- name: Setup pnpm + Node + install
uses: ./.github/actions/setup-node-pnpm
with:
node-version: ${{ env.NODE_VERSION }}
pnpm-version: ${{ env.PNPM_VERSION }}
build-shared: 'true'
# The demo build reads its flags from the committed `packages/frontend/.env.demo`.
# It is the only supported way to ship a build with mocks enabled: a production
# build refuses to run with VITE_USE_MOCK_API=true (guard in vite.config.ts), so
# this workflow never hand-writes a production env file.
- name: Build frontend (demo mode)
run: pnpm --filter=@scrumooth/frontend run build:demo
- name: Inject Cloudflare Web Analytics
if: vars.CF_ANALYTICS_TOKEN != ''
shell: node {0}
env:
CF_TOKEN: ${{ vars.CF_ANALYTICS_TOKEN }}
run: |
const fs = require('fs');
const path = './packages/frontend/dist/index.html';
const html = fs.readFileSync(path, 'utf8');
const snippet = `<script defer src="https://static.cloudflareinsights.com/beacon.min.js" data-cf-beacon='{"token": "${process.env.CF_TOKEN}"}'></script>`;
if (html.includes(snippet)) {
console.log('Cloudflare Analytics already injected, skipping');
} else {
const updated = html.replace('</head>', snippet + '</head>');
if (updated === html) {
console.error('ERROR: </head> not found in index.html');
process.exit(1);
}
fs.writeFileSync(path, updated);
console.log('Cloudflare Analytics injected successfully');
}
- name: Add security headers
run: |
cd packages/frontend/dist
cat > _headers << 'EOF'
/*
X-Frame-Options: DENY
X-Content-Type-Options: nosniff
Referrer-Policy: strict-origin-when-cross-origin
Permissions-Policy: accelerometer=(), camera=(), geolocation=(), gyroscope=(), magnetometer=(), microphone=(), payment=(), usb=()
/assets/*
Cache-Control: public, max-age=31536000, immutable
*.html
Cache-Control: no-cache
EOF
- name: Upload artifact
uses: actions/upload-pages-artifact@v5
with:
path: './packages/frontend/dist'
deploy:
name: Deploy to GitHub Pages
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
runs-on: ubuntu-latest
needs: build
steps:
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v5
- name: Summary
run: |
echo "### GitHub Pages Deployment Complete" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "**URL:** ${{ steps.deployment.outputs.page_url }}" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "**Configuration:**" >> $GITHUB_STEP_SUMMARY
echo "- Mock API: Enabled" >> $GITHUB_STEP_SUMMARY
echo "- Backend: Not required (using mock data)" >> $GITHUB_STEP_SUMMARY
echo "- SPA Routing: Configured" >> $GITHUB_STEP_SUMMARY
echo "- Security Headers: Applied" >> $GITHUB_STEP_SUMMARY
echo "- Cloudflare Analytics: Injected" >> $GITHUB_STEP_SUMMARY