forgedev 1.4.0 → 1.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/chainproof-bridge.js +9 -2
- package/src/ci-mode.js +3 -4
- package/src/composer.js +228 -242
- package/src/doctor-checks-chainproof.js +14 -11
- package/src/doctor-checks.js +3 -19
- package/src/index.js +6 -34
- package/src/recommender.js +319 -319
- package/src/uat-generator.js +105 -93
- package/src/utils.js +245 -214
- package/templates/auth/jwt-custom/backend/app/api/auth.py.template +39 -45
- package/templates/auth/jwt-custom/backend/app/core/security.py.template +44 -37
- package/templates/backend/express/package.json.template +35 -33
- package/templates/backend/express/src/lib/prisma.ts.template +32 -0
- package/templates/backend/express/src/routes/health.ts.template +35 -27
- package/templates/backend/fastapi/backend/app/main.py.template +67 -60
- package/templates/backend/fastapi/backend/requirements.txt.template +18 -16
- package/templates/backend/hono/package.json.template +33 -31
- package/templates/backend/hono/src/lib/prisma.ts.template +32 -0
- package/templates/backend/hono/src/routes/health.ts.template +38 -27
- package/templates/base/.gitignore.template +32 -32
- package/templates/claude-code/commands/workflows.md +52 -52
- package/templates/database/prisma-postgres/prisma/schema.prisma.template +19 -18
- package/templates/database/sqlalchemy-postgres/backend/alembic/env.py.template +39 -40
- package/templates/database/sqlalchemy-postgres/backend/alembic.ini.template +38 -36
- package/templates/database/sqlalchemy-postgres/backend/app/db/session.py.template +50 -48
- package/templates/frontend/nextjs/package.json.template +45 -43
- package/templates/frontend/remix/package.json.template +41 -39
- package/templates/infra/docker/.dockerignore.template +16 -0
- package/templates/infra/docker-compose/docker-compose.yml.template +22 -19
- package/templates/infra/github-actions/.github/workflows/ci.yml.template +61 -52
- package/templates/infra/k8s/k8s/deployment.yml.template +70 -70
- package/templates/infra/k8s/k8s/hpa.yml.template +24 -24
- package/templates/infra/k8s/k8s/ingress.yml.template +26 -26
- package/templates/infra/k8s/k8s/kustomization.yml.template +13 -13
- package/templates/infra/k8s/k8s/namespace.yml.template +4 -4
- package/templates/infra/k8s/k8s/networkpolicy.yml.template +41 -41
- package/templates/infra/k8s/k8s/secrets.yml.template +10 -10
- package/templates/infra/k8s/k8s/service.yml.template +15 -15
- package/templates/testing/load/k6/README.md.template +48 -48
- package/templates/testing/load/k6/load-test.js.template +57 -57
|
@@ -1,52 +1,61 @@
|
|
|
1
|
-
name: CI
|
|
2
|
-
|
|
3
|
-
on:
|
|
4
|
-
push:
|
|
5
|
-
branches: [main]
|
|
6
|
-
pull_request:
|
|
7
|
-
branches: [main]
|
|
8
|
-
|
|
9
|
-
jobs:
|
|
10
|
-
lint-and-test:
|
|
11
|
-
runs-on: ubuntu-latest
|
|
12
|
-
|
|
13
|
-
services:
|
|
14
|
-
postgres:
|
|
15
|
-
image: postgres:17-alpine
|
|
16
|
-
env:
|
|
17
|
-
POSTGRES_DB: {{PROJECT_NAME_SNAKE}}
|
|
18
|
-
POSTGRES_USER: postgres
|
|
19
|
-
POSTGRES_PASSWORD: postgres
|
|
20
|
-
ports:
|
|
21
|
-
- 5432:5432
|
|
22
|
-
options: >-
|
|
23
|
-
--health-cmd pg_isready
|
|
24
|
-
--health-interval 10s
|
|
25
|
-
--health-timeout 5s
|
|
26
|
-
--health-retries 5
|
|
27
|
-
|
|
28
|
-
steps:
|
|
29
|
-
- uses: actions/checkout@v4
|
|
30
|
-
|
|
31
|
-
- name: Setup Node.js
|
|
32
|
-
uses: actions/setup-node@v4
|
|
33
|
-
with:
|
|
34
|
-
node-version: '22'
|
|
35
|
-
cache: 'npm'
|
|
36
|
-
|
|
37
|
-
- name: Install dependencies
|
|
38
|
-
run: npm ci
|
|
39
|
-
|
|
40
|
-
- name: Lint
|
|
41
|
-
run: {{LINT_COMMAND}}
|
|
42
|
-
|
|
43
|
-
- name: Type check
|
|
44
|
-
run: {{TYPE_CHECK_COMMAND}}
|
|
45
|
-
|
|
46
|
-
- name: Build
|
|
47
|
-
run: {{BUILD_COMMAND}}
|
|
48
|
-
|
|
49
|
-
- name: Test
|
|
50
|
-
run: {{TEST_COMMAND}}
|
|
51
|
-
env:
|
|
52
|
-
DATABASE_URL: postgresql://postgres:postgres@localhost:5432/{{PROJECT_NAME_SNAKE}}
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
pull_request:
|
|
7
|
+
branches: [main]
|
|
8
|
+
|
|
9
|
+
jobs:
|
|
10
|
+
lint-and-test:
|
|
11
|
+
runs-on: ubuntu-latest
|
|
12
|
+
|
|
13
|
+
services:
|
|
14
|
+
postgres:
|
|
15
|
+
image: postgres:17-alpine
|
|
16
|
+
env:
|
|
17
|
+
POSTGRES_DB: {{PROJECT_NAME_SNAKE}}
|
|
18
|
+
POSTGRES_USER: postgres
|
|
19
|
+
POSTGRES_PASSWORD: postgres
|
|
20
|
+
ports:
|
|
21
|
+
- 5432:5432
|
|
22
|
+
options: >-
|
|
23
|
+
--health-cmd pg_isready
|
|
24
|
+
--health-interval 10s
|
|
25
|
+
--health-timeout 5s
|
|
26
|
+
--health-retries 5
|
|
27
|
+
|
|
28
|
+
steps:
|
|
29
|
+
- uses: actions/checkout@v4
|
|
30
|
+
|
|
31
|
+
- name: Setup Node.js
|
|
32
|
+
uses: actions/setup-node@v4
|
|
33
|
+
with:
|
|
34
|
+
node-version: '22'
|
|
35
|
+
cache: 'npm'
|
|
36
|
+
|
|
37
|
+
- name: Install dependencies
|
|
38
|
+
run: npm ci
|
|
39
|
+
|
|
40
|
+
- name: Lint
|
|
41
|
+
run: {{LINT_COMMAND}}
|
|
42
|
+
|
|
43
|
+
- name: Type check
|
|
44
|
+
run: {{TYPE_CHECK_COMMAND}}
|
|
45
|
+
|
|
46
|
+
- name: Build
|
|
47
|
+
run: {{BUILD_COMMAND}}
|
|
48
|
+
|
|
49
|
+
- name: Test
|
|
50
|
+
run: {{TEST_COMMAND}}
|
|
51
|
+
env:
|
|
52
|
+
DATABASE_URL: postgresql://postgres:postgres@localhost:5432/{{PROJECT_NAME_SNAKE}}
|
|
53
|
+
|
|
54
|
+
- name: Security audit (npm)
|
|
55
|
+
run: npm audit --audit-level=high
|
|
56
|
+
continue-on-error: true
|
|
57
|
+
|
|
58
|
+
- name: Security audit (pip)
|
|
59
|
+
if: hashFiles('**/requirements.txt') != ''
|
|
60
|
+
run: pip install pip-audit && pip-audit -r requirements.txt
|
|
61
|
+
continue-on-error: true
|
|
@@ -1,70 +1,70 @@
|
|
|
1
|
-
apiVersion: apps/v1
|
|
2
|
-
kind: Deployment
|
|
3
|
-
metadata:
|
|
4
|
-
name: {{PROJECT_NAME}}
|
|
5
|
-
labels:
|
|
6
|
-
app: {{PROJECT_NAME}}
|
|
7
|
-
spec:
|
|
8
|
-
replicas: 2
|
|
9
|
-
selector:
|
|
10
|
-
matchLabels:
|
|
11
|
-
app: {{PROJECT_NAME}}
|
|
12
|
-
template:
|
|
13
|
-
metadata:
|
|
14
|
-
labels:
|
|
15
|
-
app: {{PROJECT_NAME}}
|
|
16
|
-
spec:
|
|
17
|
-
automountServiceAccountToken: false
|
|
18
|
-
securityContext:
|
|
19
|
-
runAsNonRoot: true
|
|
20
|
-
runAsUser: 1000
|
|
21
|
-
fsGroup: 1000
|
|
22
|
-
containers:
|
|
23
|
-
- name: {{PROJECT_NAME}}
|
|
24
|
-
image: {{PROJECT_NAME}}:{{IMAGE_TAG}} # Update to match your CI-built image tag
|
|
25
|
-
imagePullPolicy: IfNotPresent
|
|
26
|
-
ports:
|
|
27
|
-
- containerPort: {{APP_PORT}}
|
|
28
|
-
env:
|
|
29
|
-
- name: PORT
|
|
30
|
-
value: "{{APP_PORT}}"
|
|
31
|
-
- name: DATABASE_URL
|
|
32
|
-
valueFrom:
|
|
33
|
-
secretKeyRef:
|
|
34
|
-
name: {{PROJECT_NAME}}-secrets
|
|
35
|
-
key: database-url
|
|
36
|
-
securityContext:
|
|
37
|
-
allowPrivilegeEscalation: false
|
|
38
|
-
readOnlyRootFilesystem: true
|
|
39
|
-
capabilities:
|
|
40
|
-
drop: ["ALL"]
|
|
41
|
-
volumeMounts:
|
|
42
|
-
- name: tmp
|
|
43
|
-
mountPath: /tmp
|
|
44
|
-
livenessProbe:
|
|
45
|
-
httpGet:
|
|
46
|
-
path: /health
|
|
47
|
-
port: {{APP_PORT}}
|
|
48
|
-
initialDelaySeconds: 10
|
|
49
|
-
periodSeconds: 15
|
|
50
|
-
timeoutSeconds: 5
|
|
51
|
-
failureThreshold: 3
|
|
52
|
-
readinessProbe:
|
|
53
|
-
httpGet:
|
|
54
|
-
path: /healthz
|
|
55
|
-
port: {{APP_PORT}}
|
|
56
|
-
initialDelaySeconds: 5
|
|
57
|
-
periodSeconds: 10
|
|
58
|
-
timeoutSeconds: 5
|
|
59
|
-
failureThreshold: 3
|
|
60
|
-
resources:
|
|
61
|
-
requests:
|
|
62
|
-
cpu: 100m
|
|
63
|
-
memory: 128Mi
|
|
64
|
-
limits:
|
|
65
|
-
cpu: 500m
|
|
66
|
-
memory: 512Mi
|
|
67
|
-
volumes:
|
|
68
|
-
- name: tmp
|
|
69
|
-
emptyDir: {}
|
|
70
|
-
terminationGracePeriodSeconds: 30
|
|
1
|
+
apiVersion: apps/v1
|
|
2
|
+
kind: Deployment
|
|
3
|
+
metadata:
|
|
4
|
+
name: {{PROJECT_NAME}}
|
|
5
|
+
labels:
|
|
6
|
+
app: {{PROJECT_NAME}}
|
|
7
|
+
spec:
|
|
8
|
+
replicas: 2
|
|
9
|
+
selector:
|
|
10
|
+
matchLabels:
|
|
11
|
+
app: {{PROJECT_NAME}}
|
|
12
|
+
template:
|
|
13
|
+
metadata:
|
|
14
|
+
labels:
|
|
15
|
+
app: {{PROJECT_NAME}}
|
|
16
|
+
spec:
|
|
17
|
+
automountServiceAccountToken: false
|
|
18
|
+
securityContext:
|
|
19
|
+
runAsNonRoot: true
|
|
20
|
+
runAsUser: 1000
|
|
21
|
+
fsGroup: 1000
|
|
22
|
+
containers:
|
|
23
|
+
- name: {{PROJECT_NAME}}
|
|
24
|
+
image: {{PROJECT_NAME}}:{{IMAGE_TAG}} # Update to match your CI-built image tag
|
|
25
|
+
imagePullPolicy: IfNotPresent
|
|
26
|
+
ports:
|
|
27
|
+
- containerPort: {{APP_PORT}}
|
|
28
|
+
env:
|
|
29
|
+
- name: PORT
|
|
30
|
+
value: "{{APP_PORT}}"
|
|
31
|
+
- name: DATABASE_URL
|
|
32
|
+
valueFrom:
|
|
33
|
+
secretKeyRef:
|
|
34
|
+
name: {{PROJECT_NAME}}-secrets
|
|
35
|
+
key: database-url
|
|
36
|
+
securityContext:
|
|
37
|
+
allowPrivilegeEscalation: false
|
|
38
|
+
readOnlyRootFilesystem: true
|
|
39
|
+
capabilities:
|
|
40
|
+
drop: ["ALL"]
|
|
41
|
+
volumeMounts:
|
|
42
|
+
- name: tmp
|
|
43
|
+
mountPath: /tmp
|
|
44
|
+
livenessProbe:
|
|
45
|
+
httpGet:
|
|
46
|
+
path: /health
|
|
47
|
+
port: {{APP_PORT}}
|
|
48
|
+
initialDelaySeconds: 10
|
|
49
|
+
periodSeconds: 15
|
|
50
|
+
timeoutSeconds: 5
|
|
51
|
+
failureThreshold: 3
|
|
52
|
+
readinessProbe:
|
|
53
|
+
httpGet:
|
|
54
|
+
path: /healthz
|
|
55
|
+
port: {{APP_PORT}}
|
|
56
|
+
initialDelaySeconds: 5
|
|
57
|
+
periodSeconds: 10
|
|
58
|
+
timeoutSeconds: 5
|
|
59
|
+
failureThreshold: 3
|
|
60
|
+
resources:
|
|
61
|
+
requests:
|
|
62
|
+
cpu: 100m
|
|
63
|
+
memory: 128Mi
|
|
64
|
+
limits:
|
|
65
|
+
cpu: 500m
|
|
66
|
+
memory: 512Mi
|
|
67
|
+
volumes:
|
|
68
|
+
- name: tmp
|
|
69
|
+
emptyDir: {}
|
|
70
|
+
terminationGracePeriodSeconds: 30
|
|
@@ -1,24 +1,24 @@
|
|
|
1
|
-
apiVersion: autoscaling/v2
|
|
2
|
-
kind: HorizontalPodAutoscaler
|
|
3
|
-
metadata:
|
|
4
|
-
name: {{PROJECT_NAME}}
|
|
5
|
-
spec:
|
|
6
|
-
scaleTargetRef:
|
|
7
|
-
apiVersion: apps/v1
|
|
8
|
-
kind: Deployment
|
|
9
|
-
name: {{PROJECT_NAME}}
|
|
10
|
-
minReplicas: 2
|
|
11
|
-
maxReplicas: 10
|
|
12
|
-
metrics:
|
|
13
|
-
- type: Resource
|
|
14
|
-
resource:
|
|
15
|
-
name: cpu
|
|
16
|
-
target:
|
|
17
|
-
type: Utilization
|
|
18
|
-
averageUtilization: 70
|
|
19
|
-
- type: Resource
|
|
20
|
-
resource:
|
|
21
|
-
name: memory
|
|
22
|
-
target:
|
|
23
|
-
type: Utilization
|
|
24
|
-
averageUtilization: 80
|
|
1
|
+
apiVersion: autoscaling/v2
|
|
2
|
+
kind: HorizontalPodAutoscaler
|
|
3
|
+
metadata:
|
|
4
|
+
name: {{PROJECT_NAME}}
|
|
5
|
+
spec:
|
|
6
|
+
scaleTargetRef:
|
|
7
|
+
apiVersion: apps/v1
|
|
8
|
+
kind: Deployment
|
|
9
|
+
name: {{PROJECT_NAME}}
|
|
10
|
+
minReplicas: 2
|
|
11
|
+
maxReplicas: 10
|
|
12
|
+
metrics:
|
|
13
|
+
- type: Resource
|
|
14
|
+
resource:
|
|
15
|
+
name: cpu
|
|
16
|
+
target:
|
|
17
|
+
type: Utilization
|
|
18
|
+
averageUtilization: 70
|
|
19
|
+
- type: Resource
|
|
20
|
+
resource:
|
|
21
|
+
name: memory
|
|
22
|
+
target:
|
|
23
|
+
type: Utilization
|
|
24
|
+
averageUtilization: 80
|
|
@@ -1,26 +1,26 @@
|
|
|
1
|
-
apiVersion: networking.k8s.io/v1
|
|
2
|
-
kind: Ingress
|
|
3
|
-
metadata:
|
|
4
|
-
name: {{PROJECT_NAME}}
|
|
5
|
-
annotations:
|
|
6
|
-
nginx.ingress.kubernetes.io/ssl-redirect: "true"
|
|
7
|
-
nginx.ingress.kubernetes.io/proxy-body-size: "10m"
|
|
8
|
-
nginx.ingress.kubernetes.io/limit-rps: "10"
|
|
9
|
-
nginx.ingress.kubernetes.io/limit-connections: "5"
|
|
10
|
-
spec:
|
|
11
|
-
ingressClassName: nginx
|
|
12
|
-
rules:
|
|
13
|
-
- host: {{PROJECT_NAME}}.example.com
|
|
14
|
-
http:
|
|
15
|
-
paths:
|
|
16
|
-
- path: /
|
|
17
|
-
pathType: Prefix
|
|
18
|
-
backend:
|
|
19
|
-
service:
|
|
20
|
-
name: {{PROJECT_NAME}}
|
|
21
|
-
port:
|
|
22
|
-
number: 80
|
|
23
|
-
tls:
|
|
24
|
-
- hosts:
|
|
25
|
-
- {{PROJECT_NAME}}.example.com
|
|
26
|
-
secretName: {{PROJECT_NAME}}-tls
|
|
1
|
+
apiVersion: networking.k8s.io/v1
|
|
2
|
+
kind: Ingress
|
|
3
|
+
metadata:
|
|
4
|
+
name: {{PROJECT_NAME}}
|
|
5
|
+
annotations:
|
|
6
|
+
nginx.ingress.kubernetes.io/ssl-redirect: "true"
|
|
7
|
+
nginx.ingress.kubernetes.io/proxy-body-size: "10m"
|
|
8
|
+
nginx.ingress.kubernetes.io/limit-rps: "10"
|
|
9
|
+
nginx.ingress.kubernetes.io/limit-connections: "5"
|
|
10
|
+
spec:
|
|
11
|
+
ingressClassName: nginx
|
|
12
|
+
rules:
|
|
13
|
+
- host: {{PROJECT_NAME}}.example.com
|
|
14
|
+
http:
|
|
15
|
+
paths:
|
|
16
|
+
- path: /
|
|
17
|
+
pathType: Prefix
|
|
18
|
+
backend:
|
|
19
|
+
service:
|
|
20
|
+
name: {{PROJECT_NAME}}
|
|
21
|
+
port:
|
|
22
|
+
number: 80
|
|
23
|
+
tls:
|
|
24
|
+
- hosts:
|
|
25
|
+
- {{PROJECT_NAME}}.example.com
|
|
26
|
+
secretName: {{PROJECT_NAME}}-tls
|
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
apiVersion: kustomize.config.k8s.io/v1beta1
|
|
2
|
-
kind: Kustomization
|
|
3
|
-
|
|
4
|
-
namespace: {{PROJECT_NAME}}
|
|
5
|
-
|
|
6
|
-
resources:
|
|
7
|
-
- namespace.yml
|
|
8
|
-
- deployment.yml
|
|
9
|
-
- service.yml
|
|
10
|
-
- ingress.yml
|
|
11
|
-
- secrets.yml
|
|
12
|
-
- hpa.yml
|
|
13
|
-
- networkpolicy.yml
|
|
1
|
+
apiVersion: kustomize.config.k8s.io/v1beta1
|
|
2
|
+
kind: Kustomization
|
|
3
|
+
|
|
4
|
+
namespace: {{PROJECT_NAME}}
|
|
5
|
+
|
|
6
|
+
resources:
|
|
7
|
+
- namespace.yml
|
|
8
|
+
- deployment.yml
|
|
9
|
+
- service.yml
|
|
10
|
+
- ingress.yml
|
|
11
|
+
- secrets.yml
|
|
12
|
+
- hpa.yml
|
|
13
|
+
- networkpolicy.yml
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
apiVersion: v1
|
|
2
|
-
kind: Namespace
|
|
3
|
-
metadata:
|
|
4
|
-
name: {{PROJECT_NAME}}
|
|
1
|
+
apiVersion: v1
|
|
2
|
+
kind: Namespace
|
|
3
|
+
metadata:
|
|
4
|
+
name: {{PROJECT_NAME}}
|
|
@@ -1,41 +1,41 @@
|
|
|
1
|
-
apiVersion: networking.k8s.io/v1
|
|
2
|
-
kind: NetworkPolicy
|
|
3
|
-
metadata:
|
|
4
|
-
name: {{PROJECT_NAME}}
|
|
5
|
-
spec:
|
|
6
|
-
podSelector:
|
|
7
|
-
matchLabels:
|
|
8
|
-
app: {{PROJECT_NAME}}
|
|
9
|
-
policyTypes:
|
|
10
|
-
- Ingress
|
|
11
|
-
- Egress
|
|
12
|
-
ingress:
|
|
13
|
-
- from:
|
|
14
|
-
- namespaceSelector:
|
|
15
|
-
matchLabels:
|
|
16
|
-
kubernetes.io/metadata.name: ingress-nginx
|
|
17
|
-
ports:
|
|
18
|
-
- port: {{APP_PORT}}
|
|
19
|
-
egress:
|
|
20
|
-
# Database
|
|
21
|
-
- to:
|
|
22
|
-
- podSelector:
|
|
23
|
-
matchLabels:
|
|
24
|
-
app: postgres
|
|
25
|
-
ports:
|
|
26
|
-
- port: 5432
|
|
27
|
-
# DNS (UDP + TCP for large responses)
|
|
28
|
-
- to:
|
|
29
|
-
- namespaceSelector:
|
|
30
|
-
matchLabels:
|
|
31
|
-
kubernetes.io/metadata.name: kube-system
|
|
32
|
-
ports:
|
|
33
|
-
- port: 53
|
|
34
|
-
protocol: UDP
|
|
35
|
-
- port: 53
|
|
36
|
-
protocol: TCP
|
|
37
|
-
# Uncomment to allow outbound HTTPS (external APIs, OAuth, webhooks)
|
|
38
|
-
# - to: []
|
|
39
|
-
# ports:
|
|
40
|
-
# - port: 443
|
|
41
|
-
# protocol: TCP
|
|
1
|
+
apiVersion: networking.k8s.io/v1
|
|
2
|
+
kind: NetworkPolicy
|
|
3
|
+
metadata:
|
|
4
|
+
name: {{PROJECT_NAME}}
|
|
5
|
+
spec:
|
|
6
|
+
podSelector:
|
|
7
|
+
matchLabels:
|
|
8
|
+
app: {{PROJECT_NAME}}
|
|
9
|
+
policyTypes:
|
|
10
|
+
- Ingress
|
|
11
|
+
- Egress
|
|
12
|
+
ingress:
|
|
13
|
+
- from:
|
|
14
|
+
- namespaceSelector:
|
|
15
|
+
matchLabels:
|
|
16
|
+
kubernetes.io/metadata.name: ingress-nginx
|
|
17
|
+
ports:
|
|
18
|
+
- port: {{APP_PORT}}
|
|
19
|
+
egress:
|
|
20
|
+
# Database
|
|
21
|
+
- to:
|
|
22
|
+
- podSelector:
|
|
23
|
+
matchLabels:
|
|
24
|
+
app: postgres
|
|
25
|
+
ports:
|
|
26
|
+
- port: 5432
|
|
27
|
+
# DNS (UDP + TCP for large responses)
|
|
28
|
+
- to:
|
|
29
|
+
- namespaceSelector:
|
|
30
|
+
matchLabels:
|
|
31
|
+
kubernetes.io/metadata.name: kube-system
|
|
32
|
+
ports:
|
|
33
|
+
- port: 53
|
|
34
|
+
protocol: UDP
|
|
35
|
+
- port: 53
|
|
36
|
+
protocol: TCP
|
|
37
|
+
# Uncomment to allow outbound HTTPS (external APIs, OAuth, webhooks)
|
|
38
|
+
# - to: []
|
|
39
|
+
# ports:
|
|
40
|
+
# - port: 443
|
|
41
|
+
# protocol: TCP
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
apiVersion: v1
|
|
2
|
-
kind: Secret
|
|
3
|
-
metadata:
|
|
4
|
-
name: {{PROJECT_NAME}}-secrets
|
|
5
|
-
type: Opaque
|
|
6
|
-
stringData:
|
|
7
|
-
# IMPORTANT: Replace these placeholder values before deploying.
|
|
8
|
-
# In production, use sealed-secrets, external-secrets, or your cloud provider's secret manager.
|
|
9
|
-
# Do NOT commit real credentials to version control.
|
|
10
|
-
database-url: "postgresql://USER:CHANGE_ME_BEFORE_DEPLOY@postgres:5432/{{PROJECT_NAME_SNAKE}}"
|
|
1
|
+
apiVersion: v1
|
|
2
|
+
kind: Secret
|
|
3
|
+
metadata:
|
|
4
|
+
name: {{PROJECT_NAME}}-secrets
|
|
5
|
+
type: Opaque
|
|
6
|
+
stringData:
|
|
7
|
+
# IMPORTANT: Replace these placeholder values before deploying.
|
|
8
|
+
# In production, use sealed-secrets, external-secrets, or your cloud provider's secret manager.
|
|
9
|
+
# Do NOT commit real credentials to version control.
|
|
10
|
+
database-url: "postgresql://USER:CHANGE_ME_BEFORE_DEPLOY@postgres:5432/{{PROJECT_NAME_SNAKE}}?sslmode=require"
|
|
@@ -1,15 +1,15 @@
|
|
|
1
|
-
apiVersion: v1
|
|
2
|
-
kind: Service
|
|
3
|
-
metadata:
|
|
4
|
-
name: {{PROJECT_NAME}}
|
|
5
|
-
labels:
|
|
6
|
-
app: {{PROJECT_NAME}}
|
|
7
|
-
spec:
|
|
8
|
-
type: ClusterIP
|
|
9
|
-
selector:
|
|
10
|
-
app: {{PROJECT_NAME}}
|
|
11
|
-
ports:
|
|
12
|
-
- name: http
|
|
13
|
-
port: 80
|
|
14
|
-
targetPort: {{APP_PORT}}
|
|
15
|
-
protocol: TCP
|
|
1
|
+
apiVersion: v1
|
|
2
|
+
kind: Service
|
|
3
|
+
metadata:
|
|
4
|
+
name: {{PROJECT_NAME}}
|
|
5
|
+
labels:
|
|
6
|
+
app: {{PROJECT_NAME}}
|
|
7
|
+
spec:
|
|
8
|
+
type: ClusterIP
|
|
9
|
+
selector:
|
|
10
|
+
app: {{PROJECT_NAME}}
|
|
11
|
+
ports:
|
|
12
|
+
- name: http
|
|
13
|
+
port: 80
|
|
14
|
+
targetPort: {{APP_PORT}}
|
|
15
|
+
protocol: TCP
|
|
@@ -1,48 +1,48 @@
|
|
|
1
|
-
# Load Testing — {{PROJECT_NAME_PASCAL}}
|
|
2
|
-
|
|
3
|
-
Uses [k6](https://k6.io/) for load testing.
|
|
4
|
-
|
|
5
|
-
## Setup
|
|
6
|
-
|
|
7
|
-
```bash
|
|
8
|
-
# macOS
|
|
9
|
-
brew install k6
|
|
10
|
-
|
|
11
|
-
# Windows (scoop)
|
|
12
|
-
scoop install k6
|
|
13
|
-
|
|
14
|
-
# Docker (no install)
|
|
15
|
-
docker run --rm -i grafana/k6 run - <load-test.js
|
|
16
|
-
```
|
|
17
|
-
|
|
18
|
-
## Run
|
|
19
|
-
|
|
20
|
-
```bash
|
|
21
|
-
# Smoke test (quick, single request)
|
|
22
|
-
k6 run --vus 1 --iterations 1 k6/load-test.js
|
|
23
|
-
|
|
24
|
-
# Full load test against local server
|
|
25
|
-
k6 run k6/load-test.js
|
|
26
|
-
|
|
27
|
-
# Against staging
|
|
28
|
-
k6 run -e BASE_URL=https://staging.example.com k6/load-test.js
|
|
29
|
-
```
|
|
30
|
-
|
|
31
|
-
## Thresholds
|
|
32
|
-
|
|
33
|
-
| Metric | Threshold | Meaning |
|
|
34
|
-
|--------|-----------|---------|
|
|
35
|
-
| `http_req_duration p(95)` | < 500ms | 95th percentile response time |
|
|
36
|
-
| `http_req_duration p(99)` | < 1.5s | 99th percentile response time |
|
|
37
|
-
| `http_req_failed` | < 1% | Error rate |
|
|
38
|
-
| `checks` | > 99% | Assertion pass rate |
|
|
39
|
-
|
|
40
|
-
## CI Integration
|
|
41
|
-
|
|
42
|
-
Add to your CI pipeline after deployment:
|
|
43
|
-
|
|
44
|
-
```yaml
|
|
45
|
-
- name: Load test
|
|
46
|
-
run: |
|
|
47
|
-
k6 run -e BASE_URL=${{ secrets.STAGING_URL }} k6/load-test.js
|
|
48
|
-
```
|
|
1
|
+
# Load Testing — {{PROJECT_NAME_PASCAL}}
|
|
2
|
+
|
|
3
|
+
Uses [k6](https://k6.io/) for load testing.
|
|
4
|
+
|
|
5
|
+
## Setup
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
# macOS
|
|
9
|
+
brew install k6
|
|
10
|
+
|
|
11
|
+
# Windows (scoop)
|
|
12
|
+
scoop install k6
|
|
13
|
+
|
|
14
|
+
# Docker (no install)
|
|
15
|
+
docker run --rm -i grafana/k6 run - <load-test.js
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## Run
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
# Smoke test (quick, single request)
|
|
22
|
+
k6 run --vus 1 --iterations 1 k6/load-test.js
|
|
23
|
+
|
|
24
|
+
# Full load test against local server
|
|
25
|
+
k6 run k6/load-test.js
|
|
26
|
+
|
|
27
|
+
# Against staging
|
|
28
|
+
k6 run -e BASE_URL=https://staging.example.com k6/load-test.js
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
## Thresholds
|
|
32
|
+
|
|
33
|
+
| Metric | Threshold | Meaning |
|
|
34
|
+
|--------|-----------|---------|
|
|
35
|
+
| `http_req_duration p(95)` | < 500ms | 95th percentile response time |
|
|
36
|
+
| `http_req_duration p(99)` | < 1.5s | 99th percentile response time |
|
|
37
|
+
| `http_req_failed` | < 1% | Error rate |
|
|
38
|
+
| `checks` | > 99% | Assertion pass rate |
|
|
39
|
+
|
|
40
|
+
## CI Integration
|
|
41
|
+
|
|
42
|
+
Add to your CI pipeline after deployment:
|
|
43
|
+
|
|
44
|
+
```yaml
|
|
45
|
+
- name: Load test
|
|
46
|
+
run: |
|
|
47
|
+
k6 run -e BASE_URL=${{ secrets.STAGING_URL }} k6/load-test.js
|
|
48
|
+
```
|