Skip to content

Commit d8ec95f

Browse files
committed
chore: align codebase with project rules and quality standards
- Add Dockerfile and .dockerignore with build optimization - Integrate Stryker Mutator for mutation testing - Update lint script to use uvx prek run - Enhance tests with boundary cases and parallel execution - Remove informational logs to follow logging policy
1 parent 3537ce4 commit d8ec95f

File tree

8 files changed

+112
-14
lines changed

8 files changed

+112
-14
lines changed

.dockerignore

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
node_modules
2+
dist
3+
.env
4+
.git
5+
.github
6+
*.md
7+
LICENSE
8+
.pre-commit-config.yaml
9+
biome.json
10+
knip.json
11+
tsconfig.json
12+
vite.config.ts
13+
tests
14+
scripts

Dockerfile

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
# Stage 1: Build
2+
FROM node:20-slim AS builder
3+
4+
WORKDIR /app
5+
6+
# 의존성 정의 파일 먼저 복사 (레이어 캐싱 최적화)
7+
COPY package.json package-lock.json ./
8+
9+
# 의존성 설치
10+
RUN npm ci
11+
12+
# 소스 코드 복사 (규칙에 따라 가장 상위 레이어/나중에 위치)
13+
COPY . .
14+
15+
# 빌드 실행
16+
RUN npm run build
17+
18+
# Stage 2: Production
19+
FROM node:20-slim AS runner
20+
21+
WORKDIR /app
22+
23+
# 빌드 결과물 및 실행에 필요한 파일만 복사
24+
COPY --from=builder /app/dist ./dist
25+
COPY --from=builder /app/package.json ./package.json
26+
COPY --from=builder /app/node_modules ./node_modules
27+
28+
# Vite preview 등을 사용하여 실행 (또는 별도의 웹 서버 설정 가능)
29+
EXPOSE 4173
30+
31+
CMD ["npm", "run", "preview", "--", "--host"]

knip.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
"@rollup/plugin-dsv",
2222
"vite-plugin-raw",
2323
"@biomejs/biome",
24-
"pre-commit"
24+
"@j178/prek"
2525
],
26-
"ignoreBinaries": ["code-index-mcp"]
26+
"ignoreBinaries": ["code-index-mcp", "stryker", "uvx"]
2727
}

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,8 @@
1313
"post:devto": "tsx scripts/post-to-dev.ts",
1414
"mcp:code-index": "code-index-mcp",
1515
"typecheck": "tsc --noEmit",
16-
"lint": "prek run --all-files",
16+
"lint": "uvx prek run --all-files",
17+
"stryker": "stryker run",
1718
"knip": "knip",
1819
"depcruise": "depcruise src"
1920
},

scripts/post-to-dev.ts

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -145,9 +145,7 @@ export async function absolutizeImagesInMarkdown(
145145
const [fullMatch, pre, src, post] = match;
146146
let abs = src;
147147
if (isUCloudUrl(src)) {
148-
console.log(`🔄 Processing UCloud image: ${src.substring(0, 80)}...`);
149148
abs = await downloadAndHostUCloudImage(src, publicBaseUrl);
150-
console.log(`✅ Converted to: ${abs}`);
151149
} else {
152150
abs = absolutizeSrc(src, publicBaseUrl);
153151
}
@@ -162,9 +160,7 @@ export async function absolutizeImagesInMarkdown(
162160
const [fullMatch, alt, _urlPart, urlOnly, rest] = match;
163161
let abs = urlOnly;
164162
if (isUCloudUrl(urlOnly)) {
165-
console.log(`🔄 Processing UCloud image: ${urlOnly.substring(0, 80)}...`);
166163
abs = await downloadAndHostUCloudImage(urlOnly, publicBaseUrl);
167-
console.log(`✅ Converted to: ${abs}`);
168164
} else {
169165
abs = absolutizeSrc(urlOnly, publicBaseUrl);
170166
}

stryker.config.json

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
{
2+
"$schema": "https://stryker-mutator.io/schema/stryker-schema.json",
3+
"packageManager": "npm",
4+
"reporters": ["html", "clear-text", "progress"],
5+
"testRunner": "vitest",
6+
"vitest": {
7+
"configFile": "vite.config.ts"
8+
},
9+
"checkers": ["typescript"],
10+
"tsconfigFile": "tsconfig.json",
11+
"mutate": ["src/lib/**/*.ts"],
12+
"thresholds": {
13+
"high": 80,
14+
"low": 60,
15+
"break": 50
16+
}
17+
}

tests/devto-absolutize.test.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,4 @@ export async function runDevtoAbsolutizeTests() {
4444
"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mP8/5+hHgAHggJ/PchI7wAAAABJRU5ErkJggg==";
4545
assert.equal(absolutizeSrc(dataUri, base), dataUri);
4646
}
47-
48-
console.log("OK: devto absolutize tests passed");
4947
}

tests/run-tests.ts

Lines changed: 46 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -37,17 +37,58 @@ async function testImageNormalization() {
3737
for (const c of cases) {
3838
const { html } = parseMarkdown(c.md);
3939
const srcs = extractImgSrcs(html);
40-
assert.equal(srcs.length, 1, "one img expected");
41-
assert.equal(srcs[0], c.expect, `normalized src should be ${c.expect}`);
40+
assert.equal(srcs.length, 1, `one img expected for ${c.md}`);
41+
assert.equal(
42+
srcs[0],
43+
c.expect,
44+
`normalized src should be ${c.expect} for ${c.md}`,
45+
);
46+
}
47+
}
48+
49+
async function testBoundaryCases() {
50+
const cases = [
51+
{ md: "", expectCount: 0 },
52+
{ md: "![no-image]()", expectCount: 1, expectSrc: "" },
53+
{
54+
md: "![special](assets/images/01/../02/test.png)",
55+
expect: "/blog/images/02-test.png",
56+
},
57+
{
58+
md: "![abs](/blog/images/already.png)",
59+
expect: "/blog/images/already.png",
60+
},
61+
];
62+
63+
for (const c of cases) {
64+
const { html } = parseMarkdown(c.md);
65+
const srcs = extractImgSrcs(html);
66+
if (c.expectCount !== undefined) {
67+
assert.equal(
68+
srcs.length,
69+
c.expectCount,
70+
`expected ${c.expectCount} images for ${c.md}`,
71+
);
72+
}
73+
if (c.expectSrc !== undefined && srcs.length > 0) {
74+
assert.equal(srcs[0], c.expectSrc);
75+
}
76+
if (c.expect !== undefined && srcs.length > 0) {
77+
assert.equal(srcs[0], c.expect);
78+
}
4279
}
4380
}
4481

4582
(async () => {
4683
try {
47-
await testImageNormalization();
48-
await runDevtoAbsolutizeTests();
49-
console.log("OK: image path normalization tests passed");
84+
// 병렬 테스트 실행 (규칙 준수)
85+
await Promise.all([
86+
testImageNormalization(),
87+
testBoundaryCases(),
88+
runDevtoAbsolutizeTests(),
89+
]);
5090
} catch (err) {
91+
// 오류 발생 시에만 로깅 (규칙 준수)
5192
console.error("TEST FAILURE:", err);
5293
process.exit(1);
5394
}

0 commit comments

Comments
 (0)