@mandujs/mcp 0.13.0 → 0.16.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 +6 -7
- package/package.json +3 -2
- package/src/adapters/index.ts +20 -20
- package/src/adapters/monitor-adapter.ts +100 -100
- package/src/adapters/tool-adapter.ts +88 -88
- package/src/executor/error-handler.ts +250 -250
- package/src/executor/index.ts +22 -22
- package/src/executor/tool-executor.ts +148 -148
- package/src/hooks/config-watcher.ts +174 -174
- package/src/hooks/index.ts +23 -23
- package/src/hooks/mcp-hooks.ts +227 -227
- package/src/logging/index.ts +15 -15
- package/src/logging/mcp-transport.ts +134 -134
- package/src/registry/index.ts +13 -13
- package/src/registry/mcp-tool-registry.ts +298 -298
- package/src/resources/skills/guides.ts +1136 -1136
- package/src/resources/skills/index.ts +12 -12
- package/src/resources/skills/loader.ts +218 -218
- package/src/resources/skills/mandu-composition/SKILL.md +91 -91
- package/src/resources/skills/mandu-composition/metadata.json +13 -13
- package/src/resources/skills/mandu-composition/rules/_sections.md +26 -26
- package/src/resources/skills/mandu-composition/rules/_template.md +77 -77
- package/src/resources/skills/mandu-composition/rules/comp-arch-avoid-boolean-props.md +146 -146
- package/src/resources/skills/mandu-composition/rules/comp-arch-compound-components.md +164 -164
- package/src/resources/skills/mandu-composition/rules/comp-island-event.md +161 -161
- package/src/resources/skills/mandu-composition/rules/comp-island-slot-split.md +167 -167
- package/src/resources/skills/mandu-composition/rules/comp-pattern-children.md +149 -149
- package/src/resources/skills/mandu-composition/rules/comp-state-context-interface.md +148 -148
- package/src/resources/skills/mandu-composition/rules/comp-state-lift-state.md +150 -150
- package/src/resources/skills/mandu-deployment/SKILL.md +92 -92
- package/src/resources/skills/mandu-deployment/_sections.md +41 -41
- package/src/resources/skills/mandu-deployment/_template.md +38 -38
- package/src/resources/skills/mandu-deployment/metadata.json +13 -13
- package/src/resources/skills/mandu-deployment/rules/deploy-build-bun.md +109 -109
- package/src/resources/skills/mandu-deployment/rules/deploy-build-output.md +115 -115
- package/src/resources/skills/mandu-deployment/rules/deploy-cicd-github.md +219 -219
- package/src/resources/skills/mandu-deployment/rules/deploy-docker-bun.md +150 -150
- package/src/resources/skills/mandu-deployment/rules/deploy-docker-compose.md +223 -223
- package/src/resources/skills/mandu-deployment/rules/deploy-platform-fly.md +152 -152
- package/src/resources/skills/mandu-deployment/rules/deploy-platform-render.md +179 -179
- package/src/resources/skills/mandu-deployment/rules/deploy-platform-supabase.md +323 -323
- package/src/resources/skills/mandu-deployment/rules/deploy-platform-vercel.md +140 -140
- package/src/resources/skills/mandu-fs-routes/SKILL.md +82 -82
- package/src/resources/skills/mandu-fs-routes/metadata.json +12 -12
- package/src/resources/skills/mandu-fs-routes/rules/_sections.md +36 -36
- package/src/resources/skills/mandu-fs-routes/rules/_template.md +69 -69
- package/src/resources/skills/mandu-fs-routes/rules/routes-api-methods.md +65 -65
- package/src/resources/skills/mandu-fs-routes/rules/routes-dynamic-param.md +93 -93
- package/src/resources/skills/mandu-fs-routes/rules/routes-naming-page.md +55 -55
- package/src/resources/skills/mandu-guard/SKILL.md +129 -129
- package/src/resources/skills/mandu-guard/metadata.json +12 -12
- package/src/resources/skills/mandu-guard/rules/_sections.md +36 -36
- package/src/resources/skills/mandu-guard/rules/_template.md +82 -82
- package/src/resources/skills/mandu-guard/rules/guard-config-rules.md +100 -100
- package/src/resources/skills/mandu-guard/rules/guard-layer-direction.md +76 -76
- package/src/resources/skills/mandu-guard/rules/guard-preset-mandu.md +81 -81
- package/src/resources/skills/mandu-guard/rules/guard-validate-import.md +80 -80
- package/src/resources/skills/mandu-hydration/SKILL.md +91 -91
- package/src/resources/skills/mandu-hydration/metadata.json +12 -12
- package/src/resources/skills/mandu-hydration/rules/_sections.md +31 -31
- package/src/resources/skills/mandu-hydration/rules/_template.md +72 -72
- package/src/resources/skills/mandu-hydration/rules/hydration-data-event.md +109 -109
- package/src/resources/skills/mandu-hydration/rules/hydration-directive-use-client.md +55 -55
- package/src/resources/skills/mandu-hydration/rules/hydration-island-setup.md +113 -113
- package/src/resources/skills/mandu-hydration/rules/hydration-priority-visible.md +68 -68
- package/src/resources/skills/mandu-performance/SKILL.md +85 -85
- package/src/resources/skills/mandu-performance/metadata.json +14 -14
- package/src/resources/skills/mandu-performance/rules/_sections.md +31 -31
- package/src/resources/skills/mandu-performance/rules/_template.md +64 -64
- package/src/resources/skills/mandu-performance/rules/perf-async-defer-await.md +103 -103
- package/src/resources/skills/mandu-performance/rules/perf-async-parallel.md +95 -95
- package/src/resources/skills/mandu-performance/rules/perf-bun-file.md +124 -124
- package/src/resources/skills/mandu-performance/rules/perf-bun-serve.md +125 -125
- package/src/resources/skills/mandu-performance/rules/perf-bundle-imports.md +80 -80
- package/src/resources/skills/mandu-performance/rules/perf-bundle-island-lazy.md +145 -145
- package/src/resources/skills/mandu-performance/rules/perf-cache-react.md +98 -98
- package/src/resources/skills/mandu-performance/rules/perf-render-transitions.md +154 -154
- package/src/resources/skills/mandu-security/SKILL.md +87 -87
- package/src/resources/skills/mandu-security/metadata.json +13 -13
- package/src/resources/skills/mandu-security/rules/_sections.md +31 -31
- package/src/resources/skills/mandu-security/rules/_template.md +74 -74
- package/src/resources/skills/mandu-security/rules/sec-auth-guard.md +127 -127
- package/src/resources/skills/mandu-security/rules/sec-env-management.md +133 -133
- package/src/resources/skills/mandu-security/rules/sec-input-validate.md +148 -148
- package/src/resources/skills/mandu-security/rules/sec-protect-csrf.md +146 -146
- package/src/resources/skills/mandu-security/rules/sec-protect-headers.md +138 -138
- package/src/resources/skills/mandu-slot/SKILL.md +85 -85
- package/src/resources/skills/mandu-slot/metadata.json +12 -12
- package/src/resources/skills/mandu-slot/rules/_sections.md +36 -36
- package/src/resources/skills/mandu-slot/rules/_template.md +63 -63
- package/src/resources/skills/mandu-slot/rules/slot-basic-structure.md +38 -38
- package/src/resources/skills/mandu-slot/rules/slot-ctx-response.md +56 -56
- package/src/resources/skills/mandu-slot/rules/slot-guard-auth.md +59 -59
- package/src/resources/skills/mandu-slot/rules/slot-http-methods.md +64 -64
- package/src/resources/skills/mandu-styling/SKILL.md +154 -154
- package/src/resources/skills/mandu-styling/_sections.md +43 -43
- package/src/resources/skills/mandu-styling/_template.md +32 -32
- package/src/resources/skills/mandu-styling/metadata.json +15 -15
- package/src/resources/skills/mandu-styling/rules/style-component-compound.md +235 -235
- package/src/resources/skills/mandu-styling/rules/style-component-slots.md +255 -255
- package/src/resources/skills/mandu-styling/rules/style-component-tokens.md +205 -205
- package/src/resources/skills/mandu-styling/rules/style-island-animations.md +272 -272
- package/src/resources/skills/mandu-styling/rules/style-island-scoping.md +167 -167
- package/src/resources/skills/mandu-styling/rules/style-island-variants.md +221 -221
- package/src/resources/skills/mandu-styling/rules/style-perf-critical.md +209 -209
- package/src/resources/skills/mandu-styling/rules/style-perf-purge.md +192 -192
- package/src/resources/skills/mandu-styling/rules/style-setup-modules.md +162 -162
- package/src/resources/skills/mandu-styling/rules/style-setup-panda.md +164 -164
- package/src/resources/skills/mandu-styling/rules/style-setup-tailwind.md +170 -170
- package/src/resources/skills/mandu-styling/rules/style-tailwind-v4-gotchas.md +179 -179
- package/src/resources/skills/mandu-styling/rules/style-theme-darkmode.md +229 -229
- package/src/resources/skills/mandu-testing/SKILL.md +99 -99
- package/src/resources/skills/mandu-testing/metadata.json +13 -13
- package/src/resources/skills/mandu-testing/rules/_sections.md +26 -26
- package/src/resources/skills/mandu-testing/rules/_template.md +65 -65
- package/src/resources/skills/mandu-testing/rules/test-component-island.md +195 -195
- package/src/resources/skills/mandu-testing/rules/test-e2e-playwright.md +196 -196
- package/src/resources/skills/mandu-testing/rules/test-mock-fetch.md +219 -219
- package/src/resources/skills/mandu-testing/rules/test-slot-unit.md +192 -192
- package/src/resources/skills/mandu-ui/SKILL.md +117 -117
- package/src/resources/skills/mandu-ui/_sections.md +23 -23
- package/src/resources/skills/mandu-ui/_template.md +32 -32
- package/src/resources/skills/mandu-ui/metadata.json +13 -13
- package/src/resources/skills/mandu-ui/rules/ui-accessibility-aria.md +232 -232
- package/src/resources/skills/mandu-ui/rules/ui-accessibility-focus.md +238 -238
- package/src/resources/skills/mandu-ui/rules/ui-composition-patterns.md +259 -259
- package/src/resources/skills/mandu-ui/rules/ui-island-integration.md +258 -258
- package/src/resources/skills/mandu-ui/rules/ui-radix-patterns.md +213 -213
- package/src/resources/skills/mandu-ui/rules/ui-shadcn-setup.md +209 -209
- package/src/resources/skills/recipes.ts +932 -932
- package/src/tools/ate.ts +129 -0
- package/src/tools/index.ts +4 -1
- package/src/tools/project.ts +334 -334
- package/src/tools/runtime.ts +497 -497
- package/src/tools/seo.ts +417 -417
- package/src/utils/withWarnings.ts +83 -83
|
@@ -1,115 +1,115 @@
|
|
|
1
|
-
---
|
|
2
|
-
title: Build Output Configuration
|
|
3
|
-
impact: HIGH
|
|
4
|
-
impactDescription: Affects bundle size and load performance
|
|
5
|
-
tags: deployment, build, output, optimization
|
|
6
|
-
---
|
|
7
|
-
|
|
8
|
-
## Build Output Configuration
|
|
9
|
-
|
|
10
|
-
**Impact: HIGH (Affects bundle size and load performance)**
|
|
11
|
-
|
|
12
|
-
빌드 출력을 최적화하여 번들 크기를 줄이고 로딩 성능을 개선하세요.
|
|
13
|
-
|
|
14
|
-
**디렉토리 구조:**
|
|
15
|
-
|
|
16
|
-
```
|
|
17
|
-
dist/
|
|
18
|
-
├── server.js # 서버 엔트리포인트
|
|
19
|
-
├── public/
|
|
20
|
-
│ ├── islands/ # Island 컴포넌트 청크
|
|
21
|
-
│ │ ├── counter-abc123.js
|
|
22
|
-
│ │ └── form-def456.js
|
|
23
|
-
│ ├── shared/ # 공유 청크
|
|
24
|
-
│ │ └── react-vendor-xyz789.js
|
|
25
|
-
│ └── assets/ # 정적 자산
|
|
26
|
-
│ ├── styles.css
|
|
27
|
-
│ └── images/
|
|
28
|
-
└── server.js.map # 소스맵 (프로덕션 디버깅용)
|
|
29
|
-
```
|
|
30
|
-
|
|
31
|
-
**청크 분할 설정:**
|
|
32
|
-
|
|
33
|
-
```typescript
|
|
34
|
-
// scripts/build.ts
|
|
35
|
-
await Bun.build({
|
|
36
|
-
entrypoints: ["./app/**/client.tsx"],
|
|
37
|
-
outdir: "./dist/public/islands",
|
|
38
|
-
target: "browser",
|
|
39
|
-
splitting: true, // 공유 코드 자동 분리
|
|
40
|
-
minify: true,
|
|
41
|
-
naming: {
|
|
42
|
-
chunk: "[name]-[hash].js",
|
|
43
|
-
entry: "[name]-[hash].js",
|
|
44
|
-
asset: "[name]-[hash][ext]",
|
|
45
|
-
},
|
|
46
|
-
});
|
|
47
|
-
```
|
|
48
|
-
|
|
49
|
-
## 정적 자산 처리
|
|
50
|
-
|
|
51
|
-
```typescript
|
|
52
|
-
// 정적 파일 복사
|
|
53
|
-
import { $ } from "bun";
|
|
54
|
-
|
|
55
|
-
// public 폴더 복사
|
|
56
|
-
await $`cp -r public/* dist/public/`;
|
|
57
|
-
|
|
58
|
-
// CSS 최적화 (optional)
|
|
59
|
-
await $`bunx lightningcss --minify public/styles.css -o dist/public/styles.css`;
|
|
60
|
-
```
|
|
61
|
-
|
|
62
|
-
## Gzip/Brotli 압축
|
|
63
|
-
|
|
64
|
-
```typescript
|
|
65
|
-
// 프로덕션 서버에서 압축
|
|
66
|
-
import { gzipSync } from "bun";
|
|
67
|
-
|
|
68
|
-
// 또는 빌드 시 사전 압축
|
|
69
|
-
import { $ } from "bun";
|
|
70
|
-
|
|
71
|
-
const files = await Array.fromAsync(
|
|
72
|
-
new Bun.Glob("dist/public/**/*.{js,css}").scan()
|
|
73
|
-
);
|
|
74
|
-
|
|
75
|
-
for (const file of files) {
|
|
76
|
-
const content = await Bun.file(file).arrayBuffer();
|
|
77
|
-
await Bun.write(`${file}.gz`, gzipSync(new Uint8Array(content)));
|
|
78
|
-
}
|
|
79
|
-
```
|
|
80
|
-
|
|
81
|
-
## 빌드 매니페스트
|
|
82
|
-
|
|
83
|
-
```typescript
|
|
84
|
-
// 빌드 후 매니페스트 생성
|
|
85
|
-
const manifest = {
|
|
86
|
-
version: process.env.BUILD_VERSION || Date.now().toString(),
|
|
87
|
-
files: {},
|
|
88
|
-
};
|
|
89
|
-
|
|
90
|
-
const files = await Array.fromAsync(
|
|
91
|
-
new Bun.Glob("dist/public/**/*").scan()
|
|
92
|
-
);
|
|
93
|
-
|
|
94
|
-
for (const file of files) {
|
|
95
|
-
const hash = Bun.hash(await Bun.file(file).arrayBuffer());
|
|
96
|
-
manifest.files[file] = hash.toString(16);
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
await Bun.write("dist/manifest.json", JSON.stringify(manifest, null, 2));
|
|
100
|
-
```
|
|
101
|
-
|
|
102
|
-
## 번들 크기 모니터링
|
|
103
|
-
|
|
104
|
-
```bash
|
|
105
|
-
# 번들 크기 리포트
|
|
106
|
-
bun run scripts/bundle-size.ts
|
|
107
|
-
|
|
108
|
-
# CI에서 크기 제한 체크
|
|
109
|
-
if [ $(du -sb dist/public | cut -f1) -gt 1048576 ]; then
|
|
110
|
-
echo "Bundle size exceeds 1MB limit"
|
|
111
|
-
exit 1
|
|
112
|
-
fi
|
|
113
|
-
```
|
|
114
|
-
|
|
115
|
-
Reference: [Bun Build Naming](https://bun.sh/docs/bundler#naming)
|
|
1
|
+
---
|
|
2
|
+
title: Build Output Configuration
|
|
3
|
+
impact: HIGH
|
|
4
|
+
impactDescription: Affects bundle size and load performance
|
|
5
|
+
tags: deployment, build, output, optimization
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## Build Output Configuration
|
|
9
|
+
|
|
10
|
+
**Impact: HIGH (Affects bundle size and load performance)**
|
|
11
|
+
|
|
12
|
+
빌드 출력을 최적화하여 번들 크기를 줄이고 로딩 성능을 개선하세요.
|
|
13
|
+
|
|
14
|
+
**디렉토리 구조:**
|
|
15
|
+
|
|
16
|
+
```
|
|
17
|
+
dist/
|
|
18
|
+
├── server.js # 서버 엔트리포인트
|
|
19
|
+
├── public/
|
|
20
|
+
│ ├── islands/ # Island 컴포넌트 청크
|
|
21
|
+
│ │ ├── counter-abc123.js
|
|
22
|
+
│ │ └── form-def456.js
|
|
23
|
+
│ ├── shared/ # 공유 청크
|
|
24
|
+
│ │ └── react-vendor-xyz789.js
|
|
25
|
+
│ └── assets/ # 정적 자산
|
|
26
|
+
│ ├── styles.css
|
|
27
|
+
│ └── images/
|
|
28
|
+
└── server.js.map # 소스맵 (프로덕션 디버깅용)
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
**청크 분할 설정:**
|
|
32
|
+
|
|
33
|
+
```typescript
|
|
34
|
+
// scripts/build.ts
|
|
35
|
+
await Bun.build({
|
|
36
|
+
entrypoints: ["./app/**/client.tsx"],
|
|
37
|
+
outdir: "./dist/public/islands",
|
|
38
|
+
target: "browser",
|
|
39
|
+
splitting: true, // 공유 코드 자동 분리
|
|
40
|
+
minify: true,
|
|
41
|
+
naming: {
|
|
42
|
+
chunk: "[name]-[hash].js",
|
|
43
|
+
entry: "[name]-[hash].js",
|
|
44
|
+
asset: "[name]-[hash][ext]",
|
|
45
|
+
},
|
|
46
|
+
});
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
## 정적 자산 처리
|
|
50
|
+
|
|
51
|
+
```typescript
|
|
52
|
+
// 정적 파일 복사
|
|
53
|
+
import { $ } from "bun";
|
|
54
|
+
|
|
55
|
+
// public 폴더 복사
|
|
56
|
+
await $`cp -r public/* dist/public/`;
|
|
57
|
+
|
|
58
|
+
// CSS 최적화 (optional)
|
|
59
|
+
await $`bunx lightningcss --minify public/styles.css -o dist/public/styles.css`;
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
## Gzip/Brotli 압축
|
|
63
|
+
|
|
64
|
+
```typescript
|
|
65
|
+
// 프로덕션 서버에서 압축
|
|
66
|
+
import { gzipSync } from "bun";
|
|
67
|
+
|
|
68
|
+
// 또는 빌드 시 사전 압축
|
|
69
|
+
import { $ } from "bun";
|
|
70
|
+
|
|
71
|
+
const files = await Array.fromAsync(
|
|
72
|
+
new Bun.Glob("dist/public/**/*.{js,css}").scan()
|
|
73
|
+
);
|
|
74
|
+
|
|
75
|
+
for (const file of files) {
|
|
76
|
+
const content = await Bun.file(file).arrayBuffer();
|
|
77
|
+
await Bun.write(`${file}.gz`, gzipSync(new Uint8Array(content)));
|
|
78
|
+
}
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
## 빌드 매니페스트
|
|
82
|
+
|
|
83
|
+
```typescript
|
|
84
|
+
// 빌드 후 매니페스트 생성
|
|
85
|
+
const manifest = {
|
|
86
|
+
version: process.env.BUILD_VERSION || Date.now().toString(),
|
|
87
|
+
files: {},
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
const files = await Array.fromAsync(
|
|
91
|
+
new Bun.Glob("dist/public/**/*").scan()
|
|
92
|
+
);
|
|
93
|
+
|
|
94
|
+
for (const file of files) {
|
|
95
|
+
const hash = Bun.hash(await Bun.file(file).arrayBuffer());
|
|
96
|
+
manifest.files[file] = hash.toString(16);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
await Bun.write("dist/manifest.json", JSON.stringify(manifest, null, 2));
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
## 번들 크기 모니터링
|
|
103
|
+
|
|
104
|
+
```bash
|
|
105
|
+
# 번들 크기 리포트
|
|
106
|
+
bun run scripts/bundle-size.ts
|
|
107
|
+
|
|
108
|
+
# CI에서 크기 제한 체크
|
|
109
|
+
if [ $(du -sb dist/public | cut -f1) -gt 1048576 ]; then
|
|
110
|
+
echo "Bundle size exceeds 1MB limit"
|
|
111
|
+
exit 1
|
|
112
|
+
fi
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
Reference: [Bun Build Naming](https://bun.sh/docs/bundler#naming)
|
|
@@ -1,219 +1,219 @@
|
|
|
1
|
-
---
|
|
2
|
-
title: GitHub Actions CI/CD
|
|
3
|
-
impact: HIGH
|
|
4
|
-
impactDescription: Automates testing and deployment pipeline
|
|
5
|
-
tags: deployment, cicd, github, automation
|
|
6
|
-
---
|
|
7
|
-
|
|
8
|
-
## GitHub Actions CI/CD
|
|
9
|
-
|
|
10
|
-
**Impact: HIGH (Automates testing and deployment pipeline)**
|
|
11
|
-
|
|
12
|
-
GitHub Actions를 사용하여 테스트, 빌드, 배포를 자동화하세요.
|
|
13
|
-
|
|
14
|
-
**.github/workflows/ci.yml:**
|
|
15
|
-
|
|
16
|
-
```yaml
|
|
17
|
-
name: CI
|
|
18
|
-
|
|
19
|
-
on:
|
|
20
|
-
push:
|
|
21
|
-
branches: [main, develop]
|
|
22
|
-
pull_request:
|
|
23
|
-
branches: [main]
|
|
24
|
-
|
|
25
|
-
jobs:
|
|
26
|
-
test:
|
|
27
|
-
runs-on: ubuntu-latest
|
|
28
|
-
|
|
29
|
-
steps:
|
|
30
|
-
- uses: actions/checkout@v4
|
|
31
|
-
|
|
32
|
-
- name: Setup Bun
|
|
33
|
-
uses: oven-sh/setup-bun@v1
|
|
34
|
-
with:
|
|
35
|
-
bun-version: latest
|
|
36
|
-
|
|
37
|
-
- name: Install dependencies
|
|
38
|
-
run: bun install --frozen-lockfile
|
|
39
|
-
|
|
40
|
-
- name: Type check
|
|
41
|
-
run: bun run typecheck
|
|
42
|
-
|
|
43
|
-
- name: Lint
|
|
44
|
-
run: bun run lint
|
|
45
|
-
|
|
46
|
-
- name: Test
|
|
47
|
-
run: bun test --coverage
|
|
48
|
-
|
|
49
|
-
- name: Upload coverage
|
|
50
|
-
uses: codecov/codecov-action@v3
|
|
51
|
-
with:
|
|
52
|
-
files: ./coverage/lcov.info
|
|
53
|
-
|
|
54
|
-
build:
|
|
55
|
-
runs-on: ubuntu-latest
|
|
56
|
-
needs: test
|
|
57
|
-
|
|
58
|
-
steps:
|
|
59
|
-
- uses: actions/checkout@v4
|
|
60
|
-
|
|
61
|
-
- name: Setup Bun
|
|
62
|
-
uses: oven-sh/setup-bun@v1
|
|
63
|
-
|
|
64
|
-
- name: Install dependencies
|
|
65
|
-
run: bun install --frozen-lockfile
|
|
66
|
-
|
|
67
|
-
- name: Build
|
|
68
|
-
run: bun run build
|
|
69
|
-
|
|
70
|
-
- name: Upload artifacts
|
|
71
|
-
uses: actions/upload-artifact@v4
|
|
72
|
-
with:
|
|
73
|
-
name: dist
|
|
74
|
-
path: dist/
|
|
75
|
-
```
|
|
76
|
-
|
|
77
|
-
## 배포 워크플로우
|
|
78
|
-
|
|
79
|
-
```yaml
|
|
80
|
-
# .github/workflows/deploy.yml
|
|
81
|
-
name: Deploy
|
|
82
|
-
|
|
83
|
-
on:
|
|
84
|
-
push:
|
|
85
|
-
branches: [main]
|
|
86
|
-
|
|
87
|
-
jobs:
|
|
88
|
-
deploy-render:
|
|
89
|
-
runs-on: ubuntu-latest
|
|
90
|
-
if: github.ref == 'refs/heads/main'
|
|
91
|
-
|
|
92
|
-
steps:
|
|
93
|
-
- name: Deploy to Render
|
|
94
|
-
uses: johnbeynon/render-deploy-action@v0.0.8
|
|
95
|
-
with:
|
|
96
|
-
service-id: ${{ secrets.RENDER_SERVICE_ID }}
|
|
97
|
-
api-key: ${{ secrets.RENDER_API_KEY }}
|
|
98
|
-
|
|
99
|
-
deploy-fly:
|
|
100
|
-
runs-on: ubuntu-latest
|
|
101
|
-
if: github.ref == 'refs/heads/main'
|
|
102
|
-
|
|
103
|
-
steps:
|
|
104
|
-
- uses: actions/checkout@v4
|
|
105
|
-
|
|
106
|
-
- name: Setup Fly
|
|
107
|
-
uses: superfly/flyctl-actions/setup-flyctl@master
|
|
108
|
-
|
|
109
|
-
- name: Deploy to Fly.io
|
|
110
|
-
run: flyctl deploy --remote-only
|
|
111
|
-
env:
|
|
112
|
-
FLY_API_TOKEN: ${{ secrets.FLY_API_TOKEN }}
|
|
113
|
-
```
|
|
114
|
-
|
|
115
|
-
## Docker 이미지 빌드 & 푸시
|
|
116
|
-
|
|
117
|
-
```yaml
|
|
118
|
-
# .github/workflows/docker.yml
|
|
119
|
-
name: Docker
|
|
120
|
-
|
|
121
|
-
on:
|
|
122
|
-
push:
|
|
123
|
-
branches: [main]
|
|
124
|
-
tags: ['v*']
|
|
125
|
-
|
|
126
|
-
jobs:
|
|
127
|
-
docker:
|
|
128
|
-
runs-on: ubuntu-latest
|
|
129
|
-
|
|
130
|
-
steps:
|
|
131
|
-
- uses: actions/checkout@v4
|
|
132
|
-
|
|
133
|
-
- name: Set up Docker Buildx
|
|
134
|
-
uses: docker/setup-buildx-action@v3
|
|
135
|
-
|
|
136
|
-
- name: Login to GitHub Container Registry
|
|
137
|
-
uses: docker/login-action@v3
|
|
138
|
-
with:
|
|
139
|
-
registry: ghcr.io
|
|
140
|
-
username: ${{ github.actor }}
|
|
141
|
-
password: ${{ secrets.GITHUB_TOKEN }}
|
|
142
|
-
|
|
143
|
-
- name: Extract metadata
|
|
144
|
-
id: meta
|
|
145
|
-
uses: docker/metadata-action@v5
|
|
146
|
-
with:
|
|
147
|
-
images: ghcr.io/${{ github.repository }}
|
|
148
|
-
tags: |
|
|
149
|
-
type=ref,event=branch
|
|
150
|
-
type=semver,pattern={{version}}
|
|
151
|
-
type=sha,prefix=
|
|
152
|
-
|
|
153
|
-
- name: Build and push
|
|
154
|
-
uses: docker/build-push-action@v5
|
|
155
|
-
with:
|
|
156
|
-
context: .
|
|
157
|
-
push: true
|
|
158
|
-
tags: ${{ steps.meta.outputs.tags }}
|
|
159
|
-
cache-from: type=gha
|
|
160
|
-
cache-to: type=gha,mode=max
|
|
161
|
-
```
|
|
162
|
-
|
|
163
|
-
## E2E 테스트 (Playwright)
|
|
164
|
-
|
|
165
|
-
```yaml
|
|
166
|
-
e2e:
|
|
167
|
-
runs-on: ubuntu-latest
|
|
168
|
-
needs: build
|
|
169
|
-
|
|
170
|
-
steps:
|
|
171
|
-
- uses: actions/checkout@v4
|
|
172
|
-
|
|
173
|
-
- name: Setup Bun
|
|
174
|
-
uses: oven-sh/setup-bun@v1
|
|
175
|
-
|
|
176
|
-
- name: Install dependencies
|
|
177
|
-
run: bun install --frozen-lockfile
|
|
178
|
-
|
|
179
|
-
- name: Install Playwright browsers
|
|
180
|
-
run: bunx playwright install --with-deps
|
|
181
|
-
|
|
182
|
-
- name: Run E2E tests
|
|
183
|
-
run: bunx playwright test
|
|
184
|
-
|
|
185
|
-
- name: Upload test results
|
|
186
|
-
if: always()
|
|
187
|
-
uses: actions/upload-artifact@v4
|
|
188
|
-
with:
|
|
189
|
-
name: playwright-report
|
|
190
|
-
path: playwright-report/
|
|
191
|
-
```
|
|
192
|
-
|
|
193
|
-
## 환경별 배포
|
|
194
|
-
|
|
195
|
-
```yaml
|
|
196
|
-
jobs:
|
|
197
|
-
deploy:
|
|
198
|
-
runs-on: ubuntu-latest
|
|
199
|
-
environment: ${{ github.ref == 'refs/heads/main' && 'production' || 'staging' }}
|
|
200
|
-
|
|
201
|
-
steps:
|
|
202
|
-
- name: Deploy
|
|
203
|
-
run: |
|
|
204
|
-
echo "Deploying to ${{ github.ref == 'refs/heads/main' && 'production' || 'staging' }}"
|
|
205
|
-
env:
|
|
206
|
-
API_URL: ${{ secrets.API_URL }}
|
|
207
|
-
```
|
|
208
|
-
|
|
209
|
-
## 시크릿 설정
|
|
210
|
-
|
|
211
|
-
```bash
|
|
212
|
-
# GitHub CLI로 시크릿 설정
|
|
213
|
-
gh secret set RENDER_API_KEY --body "rnd_xxx"
|
|
214
|
-
gh secret set RENDER_SERVICE_ID --body "srv_xxx"
|
|
215
|
-
gh secret set FLY_API_TOKEN --body "xxx"
|
|
216
|
-
gh secret set DATABASE_URL --body "postgresql://..."
|
|
217
|
-
```
|
|
218
|
-
|
|
219
|
-
Reference: [GitHub Actions Documentation](https://docs.github.com/en/actions)
|
|
1
|
+
---
|
|
2
|
+
title: GitHub Actions CI/CD
|
|
3
|
+
impact: HIGH
|
|
4
|
+
impactDescription: Automates testing and deployment pipeline
|
|
5
|
+
tags: deployment, cicd, github, automation
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## GitHub Actions CI/CD
|
|
9
|
+
|
|
10
|
+
**Impact: HIGH (Automates testing and deployment pipeline)**
|
|
11
|
+
|
|
12
|
+
GitHub Actions를 사용하여 테스트, 빌드, 배포를 자동화하세요.
|
|
13
|
+
|
|
14
|
+
**.github/workflows/ci.yml:**
|
|
15
|
+
|
|
16
|
+
```yaml
|
|
17
|
+
name: CI
|
|
18
|
+
|
|
19
|
+
on:
|
|
20
|
+
push:
|
|
21
|
+
branches: [main, develop]
|
|
22
|
+
pull_request:
|
|
23
|
+
branches: [main]
|
|
24
|
+
|
|
25
|
+
jobs:
|
|
26
|
+
test:
|
|
27
|
+
runs-on: ubuntu-latest
|
|
28
|
+
|
|
29
|
+
steps:
|
|
30
|
+
- uses: actions/checkout@v4
|
|
31
|
+
|
|
32
|
+
- name: Setup Bun
|
|
33
|
+
uses: oven-sh/setup-bun@v1
|
|
34
|
+
with:
|
|
35
|
+
bun-version: latest
|
|
36
|
+
|
|
37
|
+
- name: Install dependencies
|
|
38
|
+
run: bun install --frozen-lockfile
|
|
39
|
+
|
|
40
|
+
- name: Type check
|
|
41
|
+
run: bun run typecheck
|
|
42
|
+
|
|
43
|
+
- name: Lint
|
|
44
|
+
run: bun run lint
|
|
45
|
+
|
|
46
|
+
- name: Test
|
|
47
|
+
run: bun test --coverage
|
|
48
|
+
|
|
49
|
+
- name: Upload coverage
|
|
50
|
+
uses: codecov/codecov-action@v3
|
|
51
|
+
with:
|
|
52
|
+
files: ./coverage/lcov.info
|
|
53
|
+
|
|
54
|
+
build:
|
|
55
|
+
runs-on: ubuntu-latest
|
|
56
|
+
needs: test
|
|
57
|
+
|
|
58
|
+
steps:
|
|
59
|
+
- uses: actions/checkout@v4
|
|
60
|
+
|
|
61
|
+
- name: Setup Bun
|
|
62
|
+
uses: oven-sh/setup-bun@v1
|
|
63
|
+
|
|
64
|
+
- name: Install dependencies
|
|
65
|
+
run: bun install --frozen-lockfile
|
|
66
|
+
|
|
67
|
+
- name: Build
|
|
68
|
+
run: bun run build
|
|
69
|
+
|
|
70
|
+
- name: Upload artifacts
|
|
71
|
+
uses: actions/upload-artifact@v4
|
|
72
|
+
with:
|
|
73
|
+
name: dist
|
|
74
|
+
path: dist/
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
## 배포 워크플로우
|
|
78
|
+
|
|
79
|
+
```yaml
|
|
80
|
+
# .github/workflows/deploy.yml
|
|
81
|
+
name: Deploy
|
|
82
|
+
|
|
83
|
+
on:
|
|
84
|
+
push:
|
|
85
|
+
branches: [main]
|
|
86
|
+
|
|
87
|
+
jobs:
|
|
88
|
+
deploy-render:
|
|
89
|
+
runs-on: ubuntu-latest
|
|
90
|
+
if: github.ref == 'refs/heads/main'
|
|
91
|
+
|
|
92
|
+
steps:
|
|
93
|
+
- name: Deploy to Render
|
|
94
|
+
uses: johnbeynon/render-deploy-action@v0.0.8
|
|
95
|
+
with:
|
|
96
|
+
service-id: ${{ secrets.RENDER_SERVICE_ID }}
|
|
97
|
+
api-key: ${{ secrets.RENDER_API_KEY }}
|
|
98
|
+
|
|
99
|
+
deploy-fly:
|
|
100
|
+
runs-on: ubuntu-latest
|
|
101
|
+
if: github.ref == 'refs/heads/main'
|
|
102
|
+
|
|
103
|
+
steps:
|
|
104
|
+
- uses: actions/checkout@v4
|
|
105
|
+
|
|
106
|
+
- name: Setup Fly
|
|
107
|
+
uses: superfly/flyctl-actions/setup-flyctl@master
|
|
108
|
+
|
|
109
|
+
- name: Deploy to Fly.io
|
|
110
|
+
run: flyctl deploy --remote-only
|
|
111
|
+
env:
|
|
112
|
+
FLY_API_TOKEN: ${{ secrets.FLY_API_TOKEN }}
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
## Docker 이미지 빌드 & 푸시
|
|
116
|
+
|
|
117
|
+
```yaml
|
|
118
|
+
# .github/workflows/docker.yml
|
|
119
|
+
name: Docker
|
|
120
|
+
|
|
121
|
+
on:
|
|
122
|
+
push:
|
|
123
|
+
branches: [main]
|
|
124
|
+
tags: ['v*']
|
|
125
|
+
|
|
126
|
+
jobs:
|
|
127
|
+
docker:
|
|
128
|
+
runs-on: ubuntu-latest
|
|
129
|
+
|
|
130
|
+
steps:
|
|
131
|
+
- uses: actions/checkout@v4
|
|
132
|
+
|
|
133
|
+
- name: Set up Docker Buildx
|
|
134
|
+
uses: docker/setup-buildx-action@v3
|
|
135
|
+
|
|
136
|
+
- name: Login to GitHub Container Registry
|
|
137
|
+
uses: docker/login-action@v3
|
|
138
|
+
with:
|
|
139
|
+
registry: ghcr.io
|
|
140
|
+
username: ${{ github.actor }}
|
|
141
|
+
password: ${{ secrets.GITHUB_TOKEN }}
|
|
142
|
+
|
|
143
|
+
- name: Extract metadata
|
|
144
|
+
id: meta
|
|
145
|
+
uses: docker/metadata-action@v5
|
|
146
|
+
with:
|
|
147
|
+
images: ghcr.io/${{ github.repository }}
|
|
148
|
+
tags: |
|
|
149
|
+
type=ref,event=branch
|
|
150
|
+
type=semver,pattern={{version}}
|
|
151
|
+
type=sha,prefix=
|
|
152
|
+
|
|
153
|
+
- name: Build and push
|
|
154
|
+
uses: docker/build-push-action@v5
|
|
155
|
+
with:
|
|
156
|
+
context: .
|
|
157
|
+
push: true
|
|
158
|
+
tags: ${{ steps.meta.outputs.tags }}
|
|
159
|
+
cache-from: type=gha
|
|
160
|
+
cache-to: type=gha,mode=max
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
## E2E 테스트 (Playwright)
|
|
164
|
+
|
|
165
|
+
```yaml
|
|
166
|
+
e2e:
|
|
167
|
+
runs-on: ubuntu-latest
|
|
168
|
+
needs: build
|
|
169
|
+
|
|
170
|
+
steps:
|
|
171
|
+
- uses: actions/checkout@v4
|
|
172
|
+
|
|
173
|
+
- name: Setup Bun
|
|
174
|
+
uses: oven-sh/setup-bun@v1
|
|
175
|
+
|
|
176
|
+
- name: Install dependencies
|
|
177
|
+
run: bun install --frozen-lockfile
|
|
178
|
+
|
|
179
|
+
- name: Install Playwright browsers
|
|
180
|
+
run: bunx playwright install --with-deps
|
|
181
|
+
|
|
182
|
+
- name: Run E2E tests
|
|
183
|
+
run: bunx playwright test
|
|
184
|
+
|
|
185
|
+
- name: Upload test results
|
|
186
|
+
if: always()
|
|
187
|
+
uses: actions/upload-artifact@v4
|
|
188
|
+
with:
|
|
189
|
+
name: playwright-report
|
|
190
|
+
path: playwright-report/
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
## 환경별 배포
|
|
194
|
+
|
|
195
|
+
```yaml
|
|
196
|
+
jobs:
|
|
197
|
+
deploy:
|
|
198
|
+
runs-on: ubuntu-latest
|
|
199
|
+
environment: ${{ github.ref == 'refs/heads/main' && 'production' || 'staging' }}
|
|
200
|
+
|
|
201
|
+
steps:
|
|
202
|
+
- name: Deploy
|
|
203
|
+
run: |
|
|
204
|
+
echo "Deploying to ${{ github.ref == 'refs/heads/main' && 'production' || 'staging' }}"
|
|
205
|
+
env:
|
|
206
|
+
API_URL: ${{ secrets.API_URL }}
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
## 시크릿 설정
|
|
210
|
+
|
|
211
|
+
```bash
|
|
212
|
+
# GitHub CLI로 시크릿 설정
|
|
213
|
+
gh secret set RENDER_API_KEY --body "rnd_xxx"
|
|
214
|
+
gh secret set RENDER_SERVICE_ID --body "srv_xxx"
|
|
215
|
+
gh secret set FLY_API_TOKEN --body "xxx"
|
|
216
|
+
gh secret set DATABASE_URL --body "postgresql://..."
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
Reference: [GitHub Actions Documentation](https://docs.github.com/en/actions)
|