fix: stop committing generated frontend build output (wwwroot rehash noise)

Root cause (CURRENT_ROADMAP.md item #3): wwwroot/assets/* and
wwwroot/index.html under KArtSell.Host are 100% Vite build output (no
hand-authored files in there) but were committed to git. Every local
dotnet build re-triggers pnpm build via the BuildFrontend MSBuild
target, which produces new content-hashed filenames even when no
frontend source changed, and the old hashed files were never cleaned
up (4 of the 6 committed asset files were already orphaned/unreferenced
before this fix, confirmed by diffing wwwroot/index.html's script/link
tags against what was actually on disk).

Investigated whether the committed output was load-bearing for
deployment before picking a fix:
- .gitea/workflows/deploy.yml (the real production deploy path) already
  wipes wwwroot and rebuilds it fresh from pnpm build on every deploy,
  so the committed files were never actually used there.
- .gitea/workflows/ci.yml's `publish` job (Gitea Release zip) was the
  only place actually depending on the committed wwwroot contents,
  since it runs `dotnet publish` without ever building the frontend.

Given that, committing the hashed output was pure architectural
mistake with no deployment benefit, and the smaller/more correct fix
is to stop tracking it rather than bolt MSBuild Inputs/Outputs
incrementality onto the BuildFrontend target (which would also be
fragile: git checkouts/worktrees can normalize file mtimes in ways
that defeat timestamp-based up-to-date checks).

Fix:
- .gitignore: ignore src/KArtSell.Host/wwwroot/assets/ and
  wwwroot/index.html (generated by BuildFrontend target locally and by
  deploy.yml in production).
- git rm --cached the 7 previously-tracked generated files.
- ci.yml publish job: add the same pnpm install/build + wipe-and-copy
  step deploy.yml already uses, so the release zip still ships a real
  frontend build instead of losing it now that git no longer carries it.
- Left the BuildFrontend MSBuild target itself unchanged (still runs
  pnpm build on every local `dotnet build`) since re-running it is no
  longer a problem now that its output isn't tracked.

Verified (not just asserted):
- `dotnet build KArtSell.sln -c Release` run twice in a row: `git
  status`/`git diff --stat` identical after both runs (only the 9
  intentional lines in .gitignore/ci.yml), even though wwwroot/assets
  on disk got fresh hashed filenames both times.
- Reverted to pre-fix state and ran a single `dotnet build` with zero
  source changes: reproduced the bug exactly as described -
  wwwroot/index.html showed a 13-line diff and 2 new untracked hash
  files appeared, with the old stale ones left behind. Then restored
  the fix and re-verified the two-consecutive-build check above.
- `cd frontend && pnpm install --frozen-lockfile && pnpm typecheck &&
  pnpm build` all pass cleanly on their own.
- `dotnet test tests/KArtSell.ModelOperations.UnitTests` still 54/54
  passing after the build changes.

Separate, out-of-scope finding recorded in CURRENT_ROADMAP.md: ~130
frontend/src/**/*.js files compiled from .ts/.vue siblings (plus
tsconfig.tsbuildinfo, vite.config.js) are also committed and also
regenerate on every `pnpm build` via `vue-tsc -b`, because
tsconfig.json has no `noEmit: true`. Same class of problem, not fixed
here to keep this PR to one goal.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-08 12:55:43 +09:00
parent b86e6fee2c
commit 769d188701
10 changed files with 27 additions and 9911 deletions
+19
View File
@@ -100,6 +100,25 @@ jobs:
- uses: actions/setup-dotnet@v4
with:
dotnet-version: '10.0.x'
- uses: pnpm/action-setup@v4
with:
version: 10
- uses: actions/setup-node@v4
with:
node-version: 22
cache: pnpm
cache-dependency-path: frontend/pnpm-lock.yaml
- name: Build frontend into Host static assets
# wwwroot/assets and wwwroot/index.html are gitignored build output (see
# CURRENT_ROADMAP.md item #3) -- this release zip must build them fresh,
# the same way .gitea/workflows/deploy.yml does for production.
run: |
pnpm install --frozen-lockfile
pnpm build
find ../src/KArtSell.Host/wwwroot -mindepth 1 -delete
cp -R dist/. ../src/KArtSell.Host/wwwroot/
working-directory: frontend
- name: Publish Release Build
run: |
+6
View File
@@ -3,6 +3,12 @@
frontend/node_modules/
frontend/dist/
frontend/.env.local
# Vite build output copied into the Host's wwwroot by KArtSell.Host.csproj's
# BuildFrontend target (local dev) and by .gitea/workflows/deploy.yml (production).
# Content-hashed filenames change on every rebuild even with no source changes,
# so this must never be committed -- see CURRENT_ROADMAP.md item #3.
src/KArtSell.Host/wwwroot/assets/
src/KArtSell.Host/wwwroot/index.html
frontend/test-results/
.playwright/
TestResults/
+2 -1
View File
@@ -10,7 +10,8 @@
1. **VS 번호 체계 충돌:** `docs/CURRENT/CATALOGS/WBS_MASTER.csv`(원 계획)와 실제 구현/`WBS_PROGRESS_TRACKER.csv`(실행 트래커) 사이에 VS-03/VS-04/VS-12/VS-14 번호가 서로 다른 기능을 가리키는 충돌이 있습니다. 이번 세션에서 발견했고, 사용자 결정에 따라 **기존 트래커 번호를 유지**하고 충돌 사실만 각 행에 명시했습니다. 근본 해결(재번호 부여 또는 WBS_MASTER 공식 대체)은 아직 미결정입니다.
2. **DbUp 마이그레이션 테스트 DB 권한 문제:** `kartsell` DB 사용자가 `kartsell_migration_test` 데이터베이스의 소유자가 아니어서 `DbUpMigrationTests`(12건)가 로컬에서 실패합니다. 코드 문제가 아니라 DBA 조치(소유권 부여)가 필요합니다.
3. **frontend 빌드 산출물 재해시:** `dotnet build`를 실행할 때마다 `pnpm build`가 재실행되어 `wwwroot/assets/*` 해시 파일명이 바뀌고 git에 불필요한 변경이 쌓이는 구조적 문제가 있습니다 (아직 미해결).
3. **[해결됨 2026-08-08] frontend 빌드 산출물 재해시:** `dotnet build`를 실행할 때마다 `pnpm build`가 재실행되어 `wwwroot/assets/*` 해시 파일명이 바뀌고 git에 불필요한 변경이 쌓이는 구조적 문제가 있습니다. **근본 원인:** `wwwroot/assets/*`, `wwwroot/index.html`은 100% Vite 생성 산출물(수작업 파일 없음)인데도 git에 커밋되어 있었고, 재빌드마다 콘텐츠 해시가 바뀌어 stale 파일이 삭제되지 않고 계속 누적됨(실제로 6개 커밋 파일 중 4개가 이미 orphan 상태였음이 확인됨). 조사 결과 `.gitea/workflows/deploy.yml`(실제 프로덕션 배포)은 이미 매 배포마다 `wwwroot`를 지우고 새로 빌드하므로 커밋된 산출물이 배포에 전혀 쓰이지 않았음 — 유일하게 의존하던 곳은 `.gitea/workflows/ci.yml``publish`(Gitea Release zip 생성) 잡뿐이었음. **조치:** `wwwroot/assets/`, `wwwroot/index.html``.gitignore`에 추가하고 `git rm --cached`로 추적 해제했으며, `ci.yml``publish` 잡에 `deploy.yml`과 동일한 패턴(pnpm install → build → wwwroot 비우고 복사)을 추가해 release zip도 신선한 산출물을 갖도록 함. MSBuild의 `BuildFrontend` 타겟(로컬 `dotnet build` 시 항상 pnpm build 재실행)은 변경하지 않음 — 산출물이 더 이상 git 추적 대상이 아니므로 재실행 자체는 더 이상 문제가 아님. **검증:** `dotnet build KArtSell.sln -c Release`를 연속 2회 실행해 `git status`가 두 번 모두 동일(무관 변경 없음)함을 확인했고, 수정 전 코드로 되돌려 동일한 무변경 빌드를 1회 실행하면 `wwwroot/index.html`이 13줄 diff로 수정되고 신규 해시 파일 2개가 untracked로 생기는 것을 재현해 대조 확인함.
- **별도 발견(미해결, 범위 밖):** `frontend/src/**/*.vue.js`, `frontend/src/features/*/api.js` 등 TS 소스 옆에 나란히 존재하는 `.js` 파일(약 130개)과 `frontend/tsconfig.tsbuildinfo`, `frontend/vite.config.js`도 전부 git에 커밋되어 있고, `pnpm build`(`vue-tsc -b`)를 실행할 때마다 매번 재생성되어 같은 종류의 불필요한 diff를 만듭니다. 근본 원인은 `frontend/tsconfig.json``"noEmit": true`가 없어 `vue-tsc -b`(프로젝트 빌드 모드, `outDir` 미지정)가 소스 옆에 컴파일 결과를 그대로 방출하기 때문입니다(`pnpm typecheck`가 쓰는 `vue-tsc --noEmit`은 문제없음). 이번 PR 범위(`wwwroot/assets` 재해시)와는 별개의 구조적 문제라 이번에는 손대지 않았습니다.
---
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
-13
View File
@@ -1,13 +0,0 @@
<!doctype html>
<html lang="ko">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>K-ArtSell</title>
<script type="module" crossorigin src="/assets/index-BWcFQ8l5.js"></script>
<link rel="stylesheet" crossorigin href="/assets/index-0LVfl5hP.css">
</head>
<body>
<div id="app"></div>
</body>
</html>