@malamute/ai-rules 1.0.0 → 1.3.0
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/README.md +272 -121
- package/bin/cli.js +5 -2
- package/configs/_shared/CLAUDE.md +52 -149
- package/configs/_shared/rules/conventions/documentation.md +324 -0
- package/configs/_shared/rules/conventions/git.md +265 -0
- package/configs/_shared/rules/conventions/npm.md +80 -0
- package/configs/_shared/{.claude/rules → rules/conventions}/performance.md +1 -1
- package/configs/_shared/rules/conventions/principles.md +334 -0
- package/configs/_shared/rules/devops/ci-cd.md +262 -0
- package/configs/_shared/rules/devops/docker.md +275 -0
- package/configs/_shared/rules/devops/nx.md +194 -0
- package/configs/_shared/rules/domain/backend/api-design.md +203 -0
- package/configs/_shared/rules/lang/csharp/async.md +220 -0
- package/configs/_shared/rules/lang/csharp/csharp.md +314 -0
- package/configs/_shared/rules/lang/csharp/linq.md +210 -0
- package/configs/_shared/rules/lang/python/async.md +337 -0
- package/configs/_shared/rules/lang/python/celery.md +476 -0
- package/configs/_shared/rules/lang/python/config.md +339 -0
- package/configs/{python/.claude/rules → _shared/rules/lang/python}/database/sqlalchemy.md +6 -1
- package/configs/_shared/rules/lang/python/deployment.md +523 -0
- package/configs/_shared/rules/lang/python/error-handling.md +330 -0
- package/configs/_shared/rules/lang/python/migrations.md +421 -0
- package/configs/_shared/rules/lang/python/python.md +172 -0
- package/configs/_shared/rules/lang/python/repository.md +383 -0
- package/configs/{python/.claude/rules → _shared/rules/lang/python}/testing.md +2 -69
- package/configs/_shared/rules/lang/typescript/async.md +447 -0
- package/configs/_shared/rules/lang/typescript/generics.md +356 -0
- package/configs/_shared/rules/lang/typescript/typescript.md +212 -0
- package/configs/_shared/rules/quality/error-handling.md +48 -0
- package/configs/_shared/rules/quality/logging.md +45 -0
- package/configs/_shared/rules/quality/observability.md +240 -0
- package/configs/_shared/rules/quality/testing-patterns.md +65 -0
- package/configs/_shared/rules/security/secrets-management.md +222 -0
- package/configs/_shared/skills/analysis/explore/SKILL.md +257 -0
- package/configs/_shared/skills/analysis/security-audit/SKILL.md +184 -0
- package/configs/_shared/skills/dev/api-endpoint/SKILL.md +126 -0
- package/configs/_shared/{.claude/commands/generate-tests.md → skills/dev/generate-tests/SKILL.md} +6 -0
- package/configs/_shared/{.claude/commands/fix-issue.md → skills/git/fix-issue/SKILL.md} +6 -0
- package/configs/_shared/{.claude/commands/review-pr.md → skills/git/review-pr/SKILL.md} +6 -0
- package/configs/_shared/skills/infra/deploy/SKILL.md +139 -0
- package/configs/_shared/skills/infra/docker/SKILL.md +95 -0
- package/configs/_shared/skills/infra/migration/SKILL.md +158 -0
- package/configs/_shared/skills/nx/nx-affected/SKILL.md +72 -0
- package/configs/_shared/skills/nx/nx-lib/SKILL.md +375 -0
- package/configs/angular/CLAUDE.md +24 -216
- package/configs/angular/{.claude/rules → rules/core}/components.md +69 -15
- package/configs/angular/rules/core/resource.md +285 -0
- package/configs/angular/rules/core/signals.md +323 -0
- package/configs/angular/rules/http.md +338 -0
- package/configs/angular/rules/routing.md +291 -0
- package/configs/angular/rules/ssr.md +312 -0
- package/configs/angular/rules/state/signal-store.md +408 -0
- package/configs/angular/{.claude/rules → rules/state}/state.md +2 -2
- package/configs/angular/{.claude/rules → rules}/testing.md +7 -7
- package/configs/angular/rules/ui/aria.md +422 -0
- package/configs/angular/rules/ui/forms.md +424 -0
- package/configs/angular/rules/ui/pipes-directives.md +335 -0
- package/configs/angular/{.claude/settings.json → settings.json} +3 -0
- package/configs/dotnet/CLAUDE.md +53 -286
- package/configs/dotnet/rules/background-services.md +552 -0
- package/configs/dotnet/rules/configuration.md +426 -0
- package/configs/dotnet/rules/ddd.md +447 -0
- package/configs/dotnet/rules/dependency-injection.md +343 -0
- package/configs/dotnet/rules/mediatr.md +320 -0
- package/configs/dotnet/rules/middleware.md +489 -0
- package/configs/dotnet/rules/result-pattern.md +363 -0
- package/configs/dotnet/rules/validation.md +388 -0
- package/configs/dotnet/settings.json +29 -0
- package/configs/fastapi/CLAUDE.md +144 -0
- package/configs/fastapi/rules/background-tasks.md +254 -0
- package/configs/fastapi/rules/dependencies.md +170 -0
- package/configs/{python/.claude → fastapi}/rules/fastapi.md +61 -1
- package/configs/fastapi/rules/lifespan.md +274 -0
- package/configs/fastapi/rules/middleware.md +229 -0
- package/configs/fastapi/rules/pydantic.md +433 -0
- package/configs/fastapi/rules/responses.md +251 -0
- package/configs/fastapi/rules/routers.md +202 -0
- package/configs/fastapi/rules/security.md +222 -0
- package/configs/fastapi/rules/testing.md +251 -0
- package/configs/fastapi/rules/websockets.md +298 -0
- package/configs/fastapi/settings.json +35 -0
- package/configs/flask/CLAUDE.md +166 -0
- package/configs/flask/rules/blueprints.md +208 -0
- package/configs/flask/rules/cli.md +285 -0
- package/configs/flask/rules/configuration.md +281 -0
- package/configs/flask/rules/context.md +238 -0
- package/configs/flask/rules/error-handlers.md +278 -0
- package/configs/flask/rules/extensions.md +278 -0
- package/configs/flask/rules/flask.md +171 -0
- package/configs/flask/rules/marshmallow.md +206 -0
- package/configs/flask/rules/security.md +267 -0
- package/configs/flask/rules/testing.md +284 -0
- package/configs/flask/settings.json +35 -0
- package/configs/nestjs/CLAUDE.md +57 -215
- package/configs/nestjs/rules/common-patterns.md +300 -0
- package/configs/nestjs/rules/filters.md +376 -0
- package/configs/nestjs/rules/interceptors.md +317 -0
- package/configs/nestjs/rules/middleware.md +321 -0
- package/configs/nestjs/{.claude/rules → rules}/modules.md +26 -0
- package/configs/nestjs/rules/pipes.md +351 -0
- package/configs/nestjs/rules/websockets.md +451 -0
- package/configs/nestjs/settings.json +31 -0
- package/configs/nextjs/CLAUDE.md +69 -331
- package/configs/nextjs/rules/api-routes.md +358 -0
- package/configs/nextjs/rules/authentication.md +355 -0
- package/configs/nextjs/{.claude/rules → rules}/components.md +52 -0
- package/configs/nextjs/rules/data-fetching.md +249 -0
- package/configs/nextjs/rules/database.md +400 -0
- package/configs/nextjs/rules/middleware.md +303 -0
- package/configs/nextjs/rules/routing.md +324 -0
- package/configs/nextjs/rules/seo.md +350 -0
- package/configs/nextjs/rules/server-actions.md +353 -0
- package/configs/nextjs/{.claude/rules → rules}/state/zustand.md +6 -6
- package/configs/nextjs/{.claude/settings.json → settings.json} +7 -0
- package/package.json +24 -9
- package/src/cli.js +218 -0
- package/src/config.js +63 -0
- package/src/index.js +4 -0
- package/src/installer.js +414 -0
- package/src/merge.js +109 -0
- package/src/tech-config.json +45 -0
- package/src/utils.js +88 -0
- package/configs/dotnet/.claude/settings.json +0 -9
- package/configs/nestjs/.claude/settings.json +0 -15
- package/configs/python/.claude/rules/flask.md +0 -332
- package/configs/python/.claude/settings.json +0 -18
- package/configs/python/CLAUDE.md +0 -273
- package/src/install.js +0 -315
- /package/configs/_shared/{.claude/rules → rules/domain/frontend}/accessibility.md +0 -0
- /package/configs/_shared/{.claude/rules → rules/security}/security.md +0 -0
- /package/configs/_shared/{.claude/skills → skills/dev}/debug/SKILL.md +0 -0
- /package/configs/_shared/{.claude/skills → skills/dev}/learning/SKILL.md +0 -0
- /package/configs/_shared/{.claude/skills → skills/dev}/spec/SKILL.md +0 -0
- /package/configs/_shared/{.claude/skills → skills/git}/review/SKILL.md +0 -0
- /package/configs/dotnet/{.claude/rules → rules}/api.md +0 -0
- /package/configs/dotnet/{.claude/rules → rules}/architecture.md +0 -0
- /package/configs/dotnet/{.claude/rules → rules}/database/efcore.md +0 -0
- /package/configs/dotnet/{.claude/rules → rules}/testing.md +0 -0
- /package/configs/nestjs/{.claude/rules → rules}/auth.md +0 -0
- /package/configs/nestjs/{.claude/rules → rules}/database/prisma.md +0 -0
- /package/configs/nestjs/{.claude/rules → rules}/database/typeorm.md +0 -0
- /package/configs/nestjs/{.claude/rules → rules}/testing.md +0 -0
- /package/configs/nestjs/{.claude/rules → rules}/validation.md +0 -0
- /package/configs/nextjs/{.claude/rules → rules}/state/redux-toolkit.md +0 -0
- /package/configs/nextjs/{.claude/rules → rules}/testing.md +0 -0
|
@@ -0,0 +1,262 @@
|
|
|
1
|
+
---
|
|
2
|
+
paths:
|
|
3
|
+
- ".github/workflows/**"
|
|
4
|
+
- ".gitlab-ci.yml"
|
|
5
|
+
- "azure-pipelines.yml"
|
|
6
|
+
- "Jenkinsfile"
|
|
7
|
+
- ".circleci/**"
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
# CI/CD Best Practices
|
|
11
|
+
|
|
12
|
+
## Pipeline Principles
|
|
13
|
+
|
|
14
|
+
- **Fast feedback**: Run quick checks first (lint, type-check)
|
|
15
|
+
- **Fail fast**: Stop pipeline on first failure
|
|
16
|
+
- **Parallelization**: Run independent jobs in parallel
|
|
17
|
+
- **Caching**: Cache dependencies between runs
|
|
18
|
+
- **Artifacts**: Pass build outputs between jobs
|
|
19
|
+
|
|
20
|
+
## GitHub Actions
|
|
21
|
+
|
|
22
|
+
### Basic Pipeline
|
|
23
|
+
|
|
24
|
+
```yaml
|
|
25
|
+
# .github/workflows/ci.yml
|
|
26
|
+
name: CI
|
|
27
|
+
|
|
28
|
+
on:
|
|
29
|
+
push:
|
|
30
|
+
branches: [main, develop]
|
|
31
|
+
pull_request:
|
|
32
|
+
branches: [main]
|
|
33
|
+
|
|
34
|
+
concurrency:
|
|
35
|
+
group: ${{ github.workflow }}-${{ github.ref }}
|
|
36
|
+
cancel-in-progress: true
|
|
37
|
+
|
|
38
|
+
jobs:
|
|
39
|
+
lint:
|
|
40
|
+
runs-on: ubuntu-latest
|
|
41
|
+
steps:
|
|
42
|
+
- uses: actions/checkout@v4
|
|
43
|
+
- uses: actions/setup-node@v4
|
|
44
|
+
with:
|
|
45
|
+
node-version: '20'
|
|
46
|
+
cache: 'npm'
|
|
47
|
+
- run: npm ci
|
|
48
|
+
- run: npm run lint
|
|
49
|
+
|
|
50
|
+
test:
|
|
51
|
+
runs-on: ubuntu-latest
|
|
52
|
+
needs: lint
|
|
53
|
+
steps:
|
|
54
|
+
- uses: actions/checkout@v4
|
|
55
|
+
- uses: actions/setup-node@v4
|
|
56
|
+
with:
|
|
57
|
+
node-version: '20'
|
|
58
|
+
cache: 'npm'
|
|
59
|
+
- run: npm ci
|
|
60
|
+
- run: npm test -- --coverage
|
|
61
|
+
- uses: codecov/codecov-action@v3
|
|
62
|
+
|
|
63
|
+
build:
|
|
64
|
+
runs-on: ubuntu-latest
|
|
65
|
+
needs: test
|
|
66
|
+
steps:
|
|
67
|
+
- uses: actions/checkout@v4
|
|
68
|
+
- uses: actions/setup-node@v4
|
|
69
|
+
with:
|
|
70
|
+
node-version: '20'
|
|
71
|
+
cache: 'npm'
|
|
72
|
+
- run: npm ci
|
|
73
|
+
- run: npm run build
|
|
74
|
+
- uses: actions/upload-artifact@v4
|
|
75
|
+
with:
|
|
76
|
+
name: build
|
|
77
|
+
path: dist/
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
### Nx Monorepo Pipeline
|
|
81
|
+
|
|
82
|
+
```yaml
|
|
83
|
+
name: CI (Nx)
|
|
84
|
+
|
|
85
|
+
on:
|
|
86
|
+
push:
|
|
87
|
+
branches: [main]
|
|
88
|
+
pull_request:
|
|
89
|
+
|
|
90
|
+
jobs:
|
|
91
|
+
main:
|
|
92
|
+
runs-on: ubuntu-latest
|
|
93
|
+
steps:
|
|
94
|
+
- uses: actions/checkout@v4
|
|
95
|
+
with:
|
|
96
|
+
fetch-depth: 0
|
|
97
|
+
|
|
98
|
+
- uses: actions/setup-node@v4
|
|
99
|
+
with:
|
|
100
|
+
node-version: '20'
|
|
101
|
+
cache: 'npm'
|
|
102
|
+
|
|
103
|
+
- run: npm ci
|
|
104
|
+
|
|
105
|
+
- uses: nrwl/nx-set-shas@v4
|
|
106
|
+
|
|
107
|
+
# Run affected commands
|
|
108
|
+
- run: npx nx affected -t lint --parallel=3
|
|
109
|
+
- run: npx nx affected -t test --parallel=3 --coverage
|
|
110
|
+
- run: npx nx affected -t build --parallel=3
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
### Deploy Pipeline
|
|
114
|
+
|
|
115
|
+
```yaml
|
|
116
|
+
# .github/workflows/deploy.yml
|
|
117
|
+
name: Deploy
|
|
118
|
+
|
|
119
|
+
on:
|
|
120
|
+
push:
|
|
121
|
+
branches: [main]
|
|
122
|
+
|
|
123
|
+
jobs:
|
|
124
|
+
deploy:
|
|
125
|
+
runs-on: ubuntu-latest
|
|
126
|
+
environment: production
|
|
127
|
+
steps:
|
|
128
|
+
- uses: actions/checkout@v4
|
|
129
|
+
|
|
130
|
+
- name: Build Docker image
|
|
131
|
+
run: |
|
|
132
|
+
docker build -t myapp:${{ github.sha }} .
|
|
133
|
+
|
|
134
|
+
- name: Login to Registry
|
|
135
|
+
uses: docker/login-action@v3
|
|
136
|
+
with:
|
|
137
|
+
registry: ghcr.io
|
|
138
|
+
username: ${{ github.actor }}
|
|
139
|
+
password: ${{ secrets.GITHUB_TOKEN }}
|
|
140
|
+
|
|
141
|
+
- name: Push image
|
|
142
|
+
run: |
|
|
143
|
+
docker tag myapp:${{ github.sha }} ghcr.io/${{ github.repository }}:${{ github.sha }}
|
|
144
|
+
docker tag myapp:${{ github.sha }} ghcr.io/${{ github.repository }}:latest
|
|
145
|
+
docker push ghcr.io/${{ github.repository }} --all-tags
|
|
146
|
+
|
|
147
|
+
- name: Deploy to production
|
|
148
|
+
run: |
|
|
149
|
+
# kubectl, ssh, or cloud CLI deployment
|
|
150
|
+
echo "Deploying ${{ github.sha }}"
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
## Branch Protection
|
|
154
|
+
|
|
155
|
+
Configure in GitHub Settings:
|
|
156
|
+
|
|
157
|
+
- Require PR reviews before merging
|
|
158
|
+
- Require status checks (CI must pass)
|
|
159
|
+
- Require branches to be up to date
|
|
160
|
+
- Enforce linear history (squash or rebase)
|
|
161
|
+
- Restrict force pushes
|
|
162
|
+
|
|
163
|
+
## Secrets Management
|
|
164
|
+
|
|
165
|
+
```yaml
|
|
166
|
+
# Reference secrets (never hardcode!)
|
|
167
|
+
env:
|
|
168
|
+
DATABASE_URL: ${{ secrets.DATABASE_URL }}
|
|
169
|
+
API_KEY: ${{ secrets.API_KEY }}
|
|
170
|
+
|
|
171
|
+
# Use environments for different configs
|
|
172
|
+
jobs:
|
|
173
|
+
deploy:
|
|
174
|
+
environment: production # Uses production secrets
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
## Caching Strategies
|
|
178
|
+
|
|
179
|
+
```yaml
|
|
180
|
+
# Node.js
|
|
181
|
+
- uses: actions/setup-node@v4
|
|
182
|
+
with:
|
|
183
|
+
cache: 'npm' # Built-in caching
|
|
184
|
+
|
|
185
|
+
# Custom cache
|
|
186
|
+
- uses: actions/cache@v4
|
|
187
|
+
with:
|
|
188
|
+
path: |
|
|
189
|
+
~/.npm
|
|
190
|
+
node_modules
|
|
191
|
+
key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
|
|
192
|
+
restore-keys: |
|
|
193
|
+
${{ runner.os }}-node-
|
|
194
|
+
|
|
195
|
+
# Docker layer caching
|
|
196
|
+
- uses: docker/build-push-action@v5
|
|
197
|
+
with:
|
|
198
|
+
cache-from: type=gha
|
|
199
|
+
cache-to: type=gha,mode=max
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
## Matrix Builds
|
|
203
|
+
|
|
204
|
+
```yaml
|
|
205
|
+
jobs:
|
|
206
|
+
test:
|
|
207
|
+
strategy:
|
|
208
|
+
matrix:
|
|
209
|
+
node: [18, 20, 22]
|
|
210
|
+
os: [ubuntu-latest, windows-latest]
|
|
211
|
+
runs-on: ${{ matrix.os }}
|
|
212
|
+
steps:
|
|
213
|
+
- uses: actions/setup-node@v4
|
|
214
|
+
with:
|
|
215
|
+
node-version: ${{ matrix.node }}
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
## Release Automation
|
|
219
|
+
|
|
220
|
+
```yaml
|
|
221
|
+
# .github/workflows/release.yml
|
|
222
|
+
name: Release
|
|
223
|
+
|
|
224
|
+
on:
|
|
225
|
+
push:
|
|
226
|
+
tags:
|
|
227
|
+
- 'v*'
|
|
228
|
+
|
|
229
|
+
jobs:
|
|
230
|
+
release:
|
|
231
|
+
runs-on: ubuntu-latest
|
|
232
|
+
steps:
|
|
233
|
+
- uses: actions/checkout@v4
|
|
234
|
+
|
|
235
|
+
- name: Create Release
|
|
236
|
+
uses: softprops/action-gh-release@v1
|
|
237
|
+
with:
|
|
238
|
+
generate_release_notes: true
|
|
239
|
+
files: |
|
|
240
|
+
dist/*.zip
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
## Quality Gates
|
|
244
|
+
|
|
245
|
+
| Check | Tool | Threshold |
|
|
246
|
+
|-------|------|-----------|
|
|
247
|
+
| Lint | ESLint/Ruff | 0 errors |
|
|
248
|
+
| Type check | TypeScript/mypy | 0 errors |
|
|
249
|
+
| Unit tests | Jest/pytest | 100% pass |
|
|
250
|
+
| Coverage | Codecov | ≥80% |
|
|
251
|
+
| Security | Snyk/Dependabot | 0 critical |
|
|
252
|
+
| Build | Framework CLI | Success |
|
|
253
|
+
|
|
254
|
+
## Anti-patterns
|
|
255
|
+
|
|
256
|
+
- Running all tests on every commit (use affected)
|
|
257
|
+
- Not caching dependencies
|
|
258
|
+
- Hardcoding secrets
|
|
259
|
+
- Not using concurrency limits
|
|
260
|
+
- Deploying without approval gates
|
|
261
|
+
- Missing rollback strategy
|
|
262
|
+
- No artifact retention policy
|
|
@@ -0,0 +1,275 @@
|
|
|
1
|
+
---
|
|
2
|
+
paths:
|
|
3
|
+
- "**/Dockerfile"
|
|
4
|
+
- "**/docker-compose*.yml"
|
|
5
|
+
- "**/.dockerignore"
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Docker Best Practices
|
|
9
|
+
|
|
10
|
+
## Dockerfile Principles
|
|
11
|
+
|
|
12
|
+
### Multi-stage Builds
|
|
13
|
+
|
|
14
|
+
Always use multi-stage builds to minimize image size:
|
|
15
|
+
|
|
16
|
+
```dockerfile
|
|
17
|
+
# Stage 1: Build
|
|
18
|
+
FROM node:20-alpine AS builder
|
|
19
|
+
WORKDIR /app
|
|
20
|
+
COPY package*.json ./
|
|
21
|
+
RUN npm ci
|
|
22
|
+
COPY . .
|
|
23
|
+
RUN npm run build
|
|
24
|
+
|
|
25
|
+
# Stage 2: Production
|
|
26
|
+
FROM node:20-alpine AS runner
|
|
27
|
+
WORKDIR /app
|
|
28
|
+
ENV NODE_ENV=production
|
|
29
|
+
COPY --from=builder /app/dist ./dist
|
|
30
|
+
COPY --from=builder /app/node_modules ./node_modules
|
|
31
|
+
USER node
|
|
32
|
+
EXPOSE 3000
|
|
33
|
+
CMD ["node", "dist/main.js"]
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
### Layer Optimization
|
|
37
|
+
|
|
38
|
+
Order from least to most frequently changed:
|
|
39
|
+
|
|
40
|
+
```dockerfile
|
|
41
|
+
# 1. Base image (rarely changes)
|
|
42
|
+
FROM node:20-alpine
|
|
43
|
+
|
|
44
|
+
# 2. System dependencies (rarely changes)
|
|
45
|
+
RUN apk add --no-cache dumb-init
|
|
46
|
+
|
|
47
|
+
# 3. App dependencies (changes with package.json)
|
|
48
|
+
WORKDIR /app
|
|
49
|
+
COPY package*.json ./
|
|
50
|
+
RUN npm ci --only=production
|
|
51
|
+
|
|
52
|
+
# 4. App code (changes frequently)
|
|
53
|
+
COPY . .
|
|
54
|
+
|
|
55
|
+
# 5. Build (if needed)
|
|
56
|
+
RUN npm run build
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
### Security
|
|
60
|
+
|
|
61
|
+
```dockerfile
|
|
62
|
+
# Use specific version, not :latest
|
|
63
|
+
FROM node:20.10.0-alpine
|
|
64
|
+
|
|
65
|
+
# Run as non-root user
|
|
66
|
+
RUN addgroup -g 1001 appgroup && \
|
|
67
|
+
adduser -u 1001 -G appgroup -s /bin/sh -D appuser
|
|
68
|
+
USER appuser
|
|
69
|
+
|
|
70
|
+
# Don't expose unnecessary ports
|
|
71
|
+
EXPOSE 3000
|
|
72
|
+
|
|
73
|
+
# Use read-only filesystem where possible
|
|
74
|
+
# (set in docker-compose or runtime)
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
## .dockerignore
|
|
78
|
+
|
|
79
|
+
Always include:
|
|
80
|
+
|
|
81
|
+
```
|
|
82
|
+
node_modules
|
|
83
|
+
npm-debug.log
|
|
84
|
+
.git
|
|
85
|
+
.gitignore
|
|
86
|
+
.env
|
|
87
|
+
.env.*
|
|
88
|
+
*.md
|
|
89
|
+
.vscode
|
|
90
|
+
.idea
|
|
91
|
+
coverage
|
|
92
|
+
dist
|
|
93
|
+
.nx
|
|
94
|
+
tmp
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
## Docker Compose
|
|
98
|
+
|
|
99
|
+
### Development
|
|
100
|
+
|
|
101
|
+
```yaml
|
|
102
|
+
# docker-compose.yml
|
|
103
|
+
services:
|
|
104
|
+
app:
|
|
105
|
+
build:
|
|
106
|
+
context: .
|
|
107
|
+
dockerfile: Dockerfile
|
|
108
|
+
target: development
|
|
109
|
+
volumes:
|
|
110
|
+
- .:/app
|
|
111
|
+
- /app/node_modules # Prevent overwriting
|
|
112
|
+
ports:
|
|
113
|
+
- "3000:3000"
|
|
114
|
+
environment:
|
|
115
|
+
- NODE_ENV=development
|
|
116
|
+
depends_on:
|
|
117
|
+
- db
|
|
118
|
+
- redis
|
|
119
|
+
|
|
120
|
+
db:
|
|
121
|
+
image: postgres:16-alpine
|
|
122
|
+
environment:
|
|
123
|
+
POSTGRES_USER: dev
|
|
124
|
+
POSTGRES_PASSWORD: dev
|
|
125
|
+
POSTGRES_DB: app_dev
|
|
126
|
+
volumes:
|
|
127
|
+
- postgres_data:/var/lib/postgresql/data
|
|
128
|
+
ports:
|
|
129
|
+
- "5432:5432"
|
|
130
|
+
|
|
131
|
+
redis:
|
|
132
|
+
image: redis:7-alpine
|
|
133
|
+
ports:
|
|
134
|
+
- "6379:6379"
|
|
135
|
+
|
|
136
|
+
volumes:
|
|
137
|
+
postgres_data:
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
### Production
|
|
141
|
+
|
|
142
|
+
```yaml
|
|
143
|
+
# docker-compose.prod.yml
|
|
144
|
+
services:
|
|
145
|
+
app:
|
|
146
|
+
build:
|
|
147
|
+
context: .
|
|
148
|
+
dockerfile: Dockerfile
|
|
149
|
+
target: production
|
|
150
|
+
restart: unless-stopped
|
|
151
|
+
read_only: true
|
|
152
|
+
security_opt:
|
|
153
|
+
- no-new-privileges:true
|
|
154
|
+
environment:
|
|
155
|
+
- NODE_ENV=production
|
|
156
|
+
healthcheck:
|
|
157
|
+
test: ["CMD", "curl", "-f", "http://localhost:3000/health"]
|
|
158
|
+
interval: 30s
|
|
159
|
+
timeout: 10s
|
|
160
|
+
retries: 3
|
|
161
|
+
start_period: 40s
|
|
162
|
+
deploy:
|
|
163
|
+
resources:
|
|
164
|
+
limits:
|
|
165
|
+
cpus: '1'
|
|
166
|
+
memory: 512M
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
## Framework-Specific Patterns
|
|
170
|
+
|
|
171
|
+
### Node.js / NestJS / Next.js
|
|
172
|
+
|
|
173
|
+
```dockerfile
|
|
174
|
+
FROM node:20-alpine AS base
|
|
175
|
+
RUN apk add --no-cache libc6-compat
|
|
176
|
+
WORKDIR /app
|
|
177
|
+
|
|
178
|
+
FROM base AS deps
|
|
179
|
+
COPY package*.json ./
|
|
180
|
+
RUN npm ci
|
|
181
|
+
|
|
182
|
+
FROM base AS builder
|
|
183
|
+
COPY --from=deps /app/node_modules ./node_modules
|
|
184
|
+
COPY . .
|
|
185
|
+
RUN npm run build
|
|
186
|
+
|
|
187
|
+
FROM base AS runner
|
|
188
|
+
ENV NODE_ENV=production
|
|
189
|
+
RUN addgroup --system --gid 1001 nodejs
|
|
190
|
+
RUN adduser --system --uid 1001 app
|
|
191
|
+
COPY --from=builder --chown=app:nodejs /app/dist ./dist
|
|
192
|
+
COPY --from=builder --chown=app:nodejs /app/node_modules ./node_modules
|
|
193
|
+
USER app
|
|
194
|
+
EXPOSE 3000
|
|
195
|
+
CMD ["node", "dist/main.js"]
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
### Python / FastAPI
|
|
199
|
+
|
|
200
|
+
```dockerfile
|
|
201
|
+
FROM python:3.12-slim AS base
|
|
202
|
+
ENV PYTHONDONTWRITEBYTECODE=1 \
|
|
203
|
+
PYTHONUNBUFFERED=1 \
|
|
204
|
+
PIP_NO_CACHE_DIR=1
|
|
205
|
+
|
|
206
|
+
FROM base AS builder
|
|
207
|
+
RUN pip install poetry
|
|
208
|
+
WORKDIR /app
|
|
209
|
+
COPY pyproject.toml poetry.lock ./
|
|
210
|
+
RUN poetry export -f requirements.txt --output requirements.txt
|
|
211
|
+
|
|
212
|
+
FROM base AS runner
|
|
213
|
+
WORKDIR /app
|
|
214
|
+
COPY --from=builder /app/requirements.txt .
|
|
215
|
+
RUN pip install -r requirements.txt
|
|
216
|
+
COPY . .
|
|
217
|
+
RUN useradd -m appuser && chown -R appuser:appuser /app
|
|
218
|
+
USER appuser
|
|
219
|
+
EXPOSE 8000
|
|
220
|
+
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
### .NET
|
|
224
|
+
|
|
225
|
+
```dockerfile
|
|
226
|
+
FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build
|
|
227
|
+
WORKDIR /src
|
|
228
|
+
COPY *.csproj ./
|
|
229
|
+
RUN dotnet restore
|
|
230
|
+
COPY . .
|
|
231
|
+
RUN dotnet publish -c Release -o /app/publish
|
|
232
|
+
|
|
233
|
+
FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS runtime
|
|
234
|
+
WORKDIR /app
|
|
235
|
+
COPY --from=build /app/publish .
|
|
236
|
+
RUN useradd -m appuser && chown -R appuser:appuser /app
|
|
237
|
+
USER appuser
|
|
238
|
+
EXPOSE 8080
|
|
239
|
+
ENTRYPOINT ["dotnet", "App.dll"]
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
## Health Checks
|
|
243
|
+
|
|
244
|
+
Always implement health endpoints:
|
|
245
|
+
|
|
246
|
+
```dockerfile
|
|
247
|
+
HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \
|
|
248
|
+
CMD curl -f http://localhost:3000/health || exit 1
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
## Environment Variables
|
|
252
|
+
|
|
253
|
+
```dockerfile
|
|
254
|
+
# Build-time args
|
|
255
|
+
ARG NODE_ENV=production
|
|
256
|
+
ARG APP_VERSION
|
|
257
|
+
|
|
258
|
+
# Runtime environment
|
|
259
|
+
ENV NODE_ENV=${NODE_ENV} \
|
|
260
|
+
APP_VERSION=${APP_VERSION}
|
|
261
|
+
|
|
262
|
+
# Never put secrets in Dockerfile!
|
|
263
|
+
# Use: docker run -e SECRET=xxx or docker-compose with env_file
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
## Anti-patterns
|
|
267
|
+
|
|
268
|
+
- Using `:latest` tag
|
|
269
|
+
- Running as root
|
|
270
|
+
- Copying entire context before installing deps
|
|
271
|
+
- Not using multi-stage builds
|
|
272
|
+
- Hardcoding secrets in Dockerfile
|
|
273
|
+
- Not setting resource limits
|
|
274
|
+
- Missing health checks
|
|
275
|
+
- Not using .dockerignore
|
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
---
|
|
2
|
+
paths:
|
|
3
|
+
- "libs/**/*"
|
|
4
|
+
- "apps/**/*"
|
|
5
|
+
- "nx.json"
|
|
6
|
+
- "project.json"
|
|
7
|
+
- "*.ts"
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
# Nx Monorepo Rules
|
|
11
|
+
|
|
12
|
+
## Project Structure
|
|
13
|
+
|
|
14
|
+
```
|
|
15
|
+
workspace/
|
|
16
|
+
├── apps/ # Deployable applications
|
|
17
|
+
│ ├── web/ # Main app
|
|
18
|
+
│ └── web-e2e/ # E2E tests
|
|
19
|
+
├── libs/ # Reusable libraries
|
|
20
|
+
│ ├── shared/ # Cross-domain (ui, util)
|
|
21
|
+
│ └── [domain]/ # Domain-specific
|
|
22
|
+
│ ├── feature-*/ # Smart components, pages
|
|
23
|
+
│ ├── ui-*/ # Dumb/presentational components
|
|
24
|
+
│ ├── data-access-*/ # State, API services
|
|
25
|
+
│ └── util-*/ # Pure functions, helpers
|
|
26
|
+
├── nx.json
|
|
27
|
+
└── tsconfig.base.json
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
## Library Types
|
|
31
|
+
|
|
32
|
+
| Type | Purpose | Can Import |
|
|
33
|
+
|------|---------|------------|
|
|
34
|
+
| `feature` | Smart components, routing, pages | ui, data-access, util |
|
|
35
|
+
| `ui` | Presentational components | util only |
|
|
36
|
+
| `data-access` | State management, API calls | util only |
|
|
37
|
+
| `util` | Pure functions, types, constants | util only |
|
|
38
|
+
|
|
39
|
+
## Naming Convention
|
|
40
|
+
|
|
41
|
+
```
|
|
42
|
+
libs/[scope]/[type]-[name]
|
|
43
|
+
|
|
44
|
+
# Examples
|
|
45
|
+
libs/users/feature-list # User list page
|
|
46
|
+
libs/users/ui-avatar # Avatar component
|
|
47
|
+
libs/users/data-access # User state/API
|
|
48
|
+
libs/users/util-permissions # Permission helpers
|
|
49
|
+
libs/shared/ui-button # Shared button
|
|
50
|
+
libs/shared/util-format # Format utilities
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
## Tags & Boundaries
|
|
54
|
+
|
|
55
|
+
### nx.json
|
|
56
|
+
|
|
57
|
+
```json
|
|
58
|
+
{
|
|
59
|
+
"targetDefaults": {
|
|
60
|
+
"build": { "dependsOn": ["^build"] },
|
|
61
|
+
"test": { "dependsOn": ["build"] }
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
### project.json tags
|
|
67
|
+
|
|
68
|
+
```json
|
|
69
|
+
{
|
|
70
|
+
"tags": ["scope:users", "type:feature"]
|
|
71
|
+
}
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
### .eslintrc.json boundaries
|
|
75
|
+
|
|
76
|
+
```json
|
|
77
|
+
{
|
|
78
|
+
"rules": {
|
|
79
|
+
"@nx/enforce-module-boundaries": [
|
|
80
|
+
"error",
|
|
81
|
+
{
|
|
82
|
+
"depConstraints": [
|
|
83
|
+
{ "sourceTag": "type:feature", "onlyDependOnLibsWithTags": ["type:ui", "type:data-access", "type:util"] },
|
|
84
|
+
{ "sourceTag": "type:ui", "onlyDependOnLibsWithTags": ["type:util"] },
|
|
85
|
+
{ "sourceTag": "type:data-access", "onlyDependOnLibsWithTags": ["type:util"] },
|
|
86
|
+
{ "sourceTag": "type:util", "onlyDependOnLibsWithTags": ["type:util"] },
|
|
87
|
+
{ "sourceTag": "scope:shared", "onlyDependOnLibsWithTags": ["scope:shared"] },
|
|
88
|
+
{ "sourceTag": "scope:users", "onlyDependOnLibsWithTags": ["scope:users", "scope:shared"] }
|
|
89
|
+
]
|
|
90
|
+
}
|
|
91
|
+
]
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
## Dependency Flow
|
|
97
|
+
|
|
98
|
+
```
|
|
99
|
+
┌─────────────────────────────────────────────┐
|
|
100
|
+
│ apps/ │
|
|
101
|
+
│ (can import any lib) │
|
|
102
|
+
└─────────────────────────────────────────────┘
|
|
103
|
+
│
|
|
104
|
+
▼
|
|
105
|
+
┌─────────────────────────────────────────────┐
|
|
106
|
+
│ feature libs │
|
|
107
|
+
│ (pages, smart components, routing) │
|
|
108
|
+
└─────────────────────────────────────────────┘
|
|
109
|
+
│ │
|
|
110
|
+
▼ ▼
|
|
111
|
+
┌──────────────────┐ ┌──────────────────┐
|
|
112
|
+
│ ui libs │ │ data-access │
|
|
113
|
+
│ (presentational)│ │ (state, API) │
|
|
114
|
+
└──────────────────┘ └──────────────────┘
|
|
115
|
+
│ │
|
|
116
|
+
└───────┬────────┘
|
|
117
|
+
▼
|
|
118
|
+
┌─────────────────────────────────────────────┐
|
|
119
|
+
│ util libs │
|
|
120
|
+
│ (pure functions, types, constants) │
|
|
121
|
+
└─────────────────────────────────────────────┘
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
## Commands Reference
|
|
125
|
+
|
|
126
|
+
| Command | Description |
|
|
127
|
+
|---------|-------------|
|
|
128
|
+
| `nx affected -t test` | Test affected projects |
|
|
129
|
+
| `nx affected -t build` | Build affected projects |
|
|
130
|
+
| `nx affected -t lint` | Lint affected projects |
|
|
131
|
+
| `nx run-many -t test --all` | Test all projects |
|
|
132
|
+
| `nx graph` | Visualize dependency graph |
|
|
133
|
+
| `nx reset` | Clear cache |
|
|
134
|
+
|
|
135
|
+
## Generator Commands
|
|
136
|
+
|
|
137
|
+
| Command | Description |
|
|
138
|
+
|---------|-------------|
|
|
139
|
+
| `nx g @nx/angular:lib [name]` | Generate Angular library |
|
|
140
|
+
| `nx g @nx/angular:component [name]` | Generate component |
|
|
141
|
+
| `nx g @nx/angular:service [name]` | Generate service |
|
|
142
|
+
| `nx g remove [name]` | Remove project |
|
|
143
|
+
| `nx g move --project [name] [dest]` | Move project |
|
|
144
|
+
|
|
145
|
+
## Import Paths
|
|
146
|
+
|
|
147
|
+
Always use workspace paths, never relative imports across libs:
|
|
148
|
+
|
|
149
|
+
```typescript
|
|
150
|
+
// GOOD - workspace path
|
|
151
|
+
import { UserService } from '@myorg/users/data-access';
|
|
152
|
+
import { ButtonComponent } from '@myorg/shared/ui-button';
|
|
153
|
+
|
|
154
|
+
// BAD - relative cross-lib import
|
|
155
|
+
import { UserService } from '../../../users/data-access/src';
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
## Anti-patterns
|
|
159
|
+
|
|
160
|
+
- Never import from `apps/` into `libs/`
|
|
161
|
+
- Never create circular dependencies between libs
|
|
162
|
+
- Never import `feature` into `ui` or `data-access`
|
|
163
|
+
- Never import domain-specific into `shared/` scope
|
|
164
|
+
- Never skip the public API (`index.ts`)
|
|
165
|
+
|
|
166
|
+
## Caching
|
|
167
|
+
|
|
168
|
+
Nx caches build/test results. To leverage:
|
|
169
|
+
|
|
170
|
+
```json
|
|
171
|
+
// nx.json
|
|
172
|
+
{
|
|
173
|
+
"tasksRunnerOptions": {
|
|
174
|
+
"default": {
|
|
175
|
+
"runner": "nx/tasks-runners/default",
|
|
176
|
+
"options": {
|
|
177
|
+
"cacheableOperations": ["build", "lint", "test", "e2e"]
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
## Affected Commands
|
|
185
|
+
|
|
186
|
+
Always use `affected` in CI:
|
|
187
|
+
|
|
188
|
+
```bash
|
|
189
|
+
# Only test what changed
|
|
190
|
+
nx affected -t test --base=main --head=HEAD
|
|
191
|
+
|
|
192
|
+
# Only build what changed
|
|
193
|
+
nx affected -t build --base=main --head=HEAD
|
|
194
|
+
```
|