Commit Graph

14 Commits

Author SHA1 Message Date
a21790d58d [CLAUDE] CICD: rollback npm junction cache (giữ path filter), fix #111 fail tsc not found
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 3m0s
Run #111 (commit 29eb5d9) FAIL với `'tsc' is not recognized` ở step Build fe-admin.
Symptoms confusing:
- VPS check: cache dir C:\npm-cache-erp\ chưa có (cold)
- Log: KHÔNG có Write-Host "cache MISS" hay "added 239 packages"
- Timing: 1.6s từ end-of-BE-build → start-of-fe-admin-build (impossible cho npm install 49s)
- Test gate (Domain 54 + Infra 17) PASS nên không phải code regression

Khả năng cao: junction Move-Item disrupted node_modules .bin/ structure HOẶC
act_runner PowerShell stream capture có quirk với cache MISS branch. Cần debug
riêng — không nên block deploy chính.

Decision:
- Rollback npm cache logic về fresh install như cũ (49s + 33s)
- GIỮ path filter on:push:paths-ignore (đây mới là win lớn nhất — 100% saving cho MD-only commit)
- Document gotcha cho session sau (sẽ thử robocopy thay vì junction, hoặc dùng act_runner cache server local)

Path filter behavior (giữ lại):
- Commit chỉ docs/MD/skill/gitignore → SKIP CI hoàn toàn (~196s/commit saved)
- Commit code OR cùng commit có code+docs → vẫn trigger (đúng)

Verify dotnet test local: 71 pass / 1s (BE không thay đổi).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-29 18:34:04 +07:00
29eb5d99a0 [CLAUDE] CICD: path filter docs-only + npm junction cache (Option C optimize ~2/3 deploy time)
Some checks failed
Deploy SOLUTION_ERP / build-deploy (push) Failing after 59s
Optimize CI/CD theo Option C bàn trong chat:

==== Path filter (saving 100% time cho commit MD-only) ====
on: push: paths-ignore mới — skip CI khi commit chỉ docs/skill/MD/gitignore.
- 'docs/**'
- '**/*.md'
- '.claude/skills/**'
- '.gitignore'
- 'scripts/**.md'

Commit 'Docs: chốt session' và similar sẽ KHÔNG trigger workflow → save 196s/commit.
Nếu cùng commit thay đổi cả MD + code → vẫn trigger (đúng behavior expected).
Workflow file `.gitea/workflows/**` chính NÓ thì không trong paths-ignore →
vẫn trigger khi sửa CI config (an toàn).

==== npm junction cache (saving ~70-80s code commit) ====
Replace Build fe-admin + fe-user steps với cache-aware version.

Strategy:
- Cache key = SHA256(package.json) 16-char prefix → đổi deps = miss → fresh
- Cache stored: C:\npm-cache-erp\<app>\<hash>\node_modules (ngoài workspace)
- Junction `fe-admin\node_modules → cache` (instant, không file copy)
- Lần đầu (cold): 49s + 33s = 82s (như cũ)
- Lần sau (warm): mklink instant + skip npm install → ~3s + 3s = 6s (saving ~76s)

Safety:
- Trước Deploy: convert junction → nothing (cmd /c rmdir /q chỉ remove ref,
  không follow target). Tránh trường hợp act_runner cleanup workspace
  follow junction + delete cache.
- Pruning: keep top 5 cache per app (~250MB × 5 × 2 = 2.5GB max disk usage).
  Stale evicted FIFO theo LastWriteTime DESC.

Vite 8 rolldown native binding gotcha (#20) vẫn respect: cache install trên
runner Windows nên rolldown binding match → reuse được.

==== Expected ====
- Commit MD-only: 0s CI (skip hoàn toàn)
- Commit code lần đầu sau cache miss (vd npm update): ~3min (như cũ)
- Commit code thường (cache hit): ~120s = 2 phút (giảm 38%)

Verify dotnet test local: 71 pass / 2s (BE không thay đổi).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-29 18:24:09 +07:00
14b7d18ecc [CLAUDE] CICD: bỏ uses: actions/* — manual git checkout từ Gitea (fix #108/#109 fail)
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 3m16s
Vấn đề persistent (run #108#109 đều fail trong 21-22s):
  Get "https://github.com/actions/checkout/info/refs?service=git-upload-pack":
    dial tcp 20.205.243.166:443: connectex: connection failed/timeout

act_runner v0.2.13 mỗi run đều `git fetch` actions/checkout từ github.com
để check update — VPS network → github.com TCP timeout 21s liên tục →
toàn job fail TRƯỚC khi tới test gate.

Fix: thay actions ngoài bằng native shell, eliminate github.com dependency.

- Replace `uses: actions/checkout@v4` → manual `git init` + `git fetch`
  từ Gitea internal network (luôn ổn định, không qua public internet)
  - Auth: github.token (act_runner cũng dùng tên này) — tự sẵn per job
  - Fetch by ref (branch) thay vì SHA, depth=30 đủ buffer nếu main commit
    thêm trong lúc job pickup
  - Checkout đúng commit SHA của event push
  - Log 1-line để confirm checkout đúng

- Replace `uses: actions/upload-artifact@v4` (cũng phụ thuộc github.com)
  → step "List test results" local. TRX file vẫn save trong workspace
  test-results/, đọc qua runner workspace nếu cần debug.

Test gate giữ nguyên (Domain + Infra). dotnet test local 71 pass / 2s.

Long-term option (nếu Gitea Actions thêm hỗ trợ): config `github_mirror`
trong gitea-runner config.yaml để mirror github.com → Gitea internal,
hoặc pre-cache actions/* repos vào runner cache dir.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-29 16:21:12 +07:00
df5988b7a9 [CLAUDE] Tests Phase 2: Code generator format + sequence tests (SQLite in-memory)
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 3m16s
Phase 2 — chống regression code generator. 17 test mới integration với
DB thật (SQLite in-memory) tổng cộng 71 test pass < 3 giây.

Test project:
- tests/SolutionErp.Infrastructure.Tests/ (xUnit + FluentAssertions + EF SQLite 10)
- ProjectReference SolutionErp.Infrastructure (transitively get Application + Domain)
- Added vào SolutionErp.slnx

Test fixtures:
- Common/SqliteDbFixture.cs:
  - SQLite ":memory:" + shared connection + EnsureCreated() từ DbContext model
  - TestApplicationDbContext subclass — override OnModelCreating replace
    'nvarchar(max)' → 'TEXT' (SQLite không support max keyword)
  - FixedDateTime stub IDateTime cho deterministic year boundary test

Test files:
- Services/ContractCodeGeneratorTests.cs (10 test):
  - Format per ContractType (5 type × Project scope) — RG-001 spec
  - Framework HĐ (NguyenTacNCC + NguyenTacDV) → year scope thay vì project
  - Sequence increment per prefix (3 calls → /01, /02, /03)
  - Different prefixes (project / supplier) → independent sequences
  - Year change (2026 → 2027) → reset sequence vì prefix khác
  - PersistsSequenceRow LastSeq verification
- Services/PurchaseEvaluationCodeGeneratorTests.cs (7 test):
  - Format A/B (DuyetNcc → 'A', DuyetNccPhuongAn → 'B')
  - Seq là 3-digit padded (001..012)
  - Type A và B sequence độc lập trong cùng năm
  - Year boundary reset cả A và B

CI gate update (.gitea/workflows/deploy.yml):
- Step "Run integration tests (Infrastructure)" thêm sau Domain tests
- TRX log saved riêng (infra-tests.trx)
- Cả 2 step đều exit non-zero → no deploy

Verify local:
- dotnet test SolutionErp.slnx → Total tests: 71 (54 Domain + 17 Infra) / Passed: 71 / 2.1s
- dotnet build SolutionErp.slnx → 0 error

Phase 3+ pending:
- Application handler tests (CQRS) với EF InMemory hoặc SQLite (~1 ngày)
- API smoke tests qua WebApplicationFactory (~0.5 ngày)
- FE Vitest cho lib utility (~0.5 ngày)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-29 13:29:06 +07:00
d3f9346840 [CLAUDE] Tests Phase 1: Domain unit tests + CI gate (xUnit + FluentAssertions)
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 3m25s
Phase 1 (MVP) — chống regression Workflow state machine. 54 test pure
function (no DB / IO), all pass < 7 giây.

Test project:
- tests/SolutionErp.Domain.Tests/ (xUnit 2.9.3 + FluentAssertions 7.2 — pin trước v8 commercial license)
- ProjectReference SolutionErp.Domain
- Added vào SolutionErp.slnx folder /tests/

Test files:
- Contracts/WorkflowPolicyTests.cs (~17 test):
  - Standard policy 9-phase: role transitions, CCM check, BOD signing, terminal
  - SkipCcm policy 7-phase: bypass CCM verify, no DangKiemTraCCM transition
  - Registry: DefaultPolicyName per ContractType (7 type), bypass flag override
  - FromDefinition versioned: build từ ordered steps + reject path + TuChoi auto-add + UserKindApprover populate UserTransitions
- PurchaseEvaluations/PurchaseEvaluationPolicyTests.cs (~17 test):
  - NccOnly (A) 3-step: skip ChoDuAn + ChoCEODuyetPA, CCM đẩy thẳng CEO duyệt NCC
  - NccWithPlan (B) 5-step: có ChoDuAn (PM) + ChoCEODuyetPA (Director) trước
  - Reject path cả 2 quy trình về DangSoanThao
  - Registry mapping per PEType
- Budgets/BudgetPolicyTests.cs (~13 test):
  - Default 3-step (Drafter→CCM→CEO) role guard
  - Reject paths về DangSoanThao
  - DaDuyet + TuChoi terminal (no NextPhases)
  - SLA spec 5d/3d/2d cho 3 phase đầu

CI gate (.gitea/workflows/deploy.yml):
- Step "Run unit tests (Domain)" thêm TRƯỚC build/publish/deploy
- Test fail (LASTEXITCODE != 0) → exit → KHÔNG deploy
- TRX log saved + upload artifact (continue-on-error nếu Gitea runner thiếu actions/upload-artifact)

Verify local:
- dotnet test tests/SolutionErp.Domain.Tests → Total tests: 54 / Passed: 54 / 6.4s
- dotnet build SolutionErp.slnx (full solution incl. test project) → 0 error

Phase 2-5 pending (xem plan ở chat):
- Code generator atomic concurrency tests (Infra)
- DbInitializer reconcile drift tests (Infra)
- Application handler smoke tests (CQRS) với EF InMemory
- API smoke tests qua WebApplicationFactory
- FE Vitest cho lib utility (queryMatches, fmtMoney)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-29 13:19:15 +07:00
66c1a5c170 [CLAUDE] Rebrand: 3 domain huypham.vn → solutions.com.vn + migrate script
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 2m52s
User request: anh trỏ 3 subdomain mới về VPS IP 103.124.94.38:
  - api.huypham.vn        → api.solutions.com.vn
  - admin.huypham.vn      → admin.solutions.com.vn
  - user.huypham.vn       → eoffice.solutions.com.vn

Verified DNS: cả 3 resolve 103.124.94.38 ✓

Update 17 file repo:
FE (4): fe-admin/.env.production + fe-user/.env.production
        (VITE_API_BASE_URL → https://api.solutions.com.vn)
        fe-admin/src/lib/{api,realtime}.ts + fe-user equivalents (comment)
BE (1): appsettings.Production.json.example — CORS AllowedOrigins
CI/CD (1): .gitea/workflows/deploy.yml — smoke test URL
Scripts (3): setup-iis-sites (DomainApi/Admin/User), setup-ssl (3 host),
             deploy-all (verify curls)
Docs (5): STATUS, HANDOFF, PROJECT-MAP, vps-setup, gotchas
Skill (1): iis-deploy-runbook — 3 site table + description
Email admin@huypham.vn giữ nguyên (Let's Encrypt contact — không phải
domain serve).

Thêm scripts/migrate-domains.ps1 — 1-shot VPS migration:
  1. Pre-flight: resolve DNS 3 domain → verify IP VPS khớp
  2. Add HTTP binding mới cho 3 IIS site (giữ binding cũ làm fallback)
  3. Run win-acme xin 3 cert Let's Encrypt qua HTTP-01 challenge
     (auto add HTTPS binding + http→https redirect)
  4. Verify /health/live + /health/ready + 2 FE endpoint
  5. (Optional -RemoveOld) xóa binding huypham.vn sau verify OK
Rollback: nếu fail, binding cũ vẫn active → site serve qua huypham.vn.

Anh chạy trên VPS:
  cd C:\solution-erp\scripts  ;  .\migrate-domains.ps1
  # Sau 1-2 ngày verify stable:
  .\migrate-domains.ps1 -RemoveOld -SkipCert
2026-04-24 09:43:05 +07:00
290936a0ca [CLAUDE] CICD+FE-Admin+FE-User: deploy pool-state guard + SlaTimer component
Some checks failed
Deploy SOLUTION_ERP / build-deploy (push) Has been cancelled
CICD: check app pool state before Stop-WebAppPool (idempotent).

FE: new SlaTimer component with color-coded countdown (emerald/amber/red)
and progress bar. Two variants:
- inline: used in list tables (Inbox, Contracts list x2, MyContracts)
- full: used in ContractDetail card with progress bar + deadline timestamp

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-21 15:04:44 +07:00
b40da1e726 [CLAUDE] CICD: read appsettings template from source workspace (not publish output)
Some checks failed
Deploy SOLUTION_ERP / build-deploy (push) Failing after 2m22s
2026-04-21 14:58:51 +07:00
5709092e08 [CLAUDE] CICD: fresh node_modules per build (Vite 8 rolldown native binding platform resolve)
Some checks failed
Deploy SOLUTION_ERP / build-deploy (push) Failing after 2m38s
2026-04-21 14:53:16 +07:00
519ba85f22 [CLAUDE] CICD: use npm install (not ci) to resolve Vite 8 rolldown native binding on Windows
Some checks failed
Deploy SOLUTION_ERP / build-deploy (push) Failing after 1m0s
2026-04-21 14:46:37 +07:00
489a0054fa [CLAUDE] CICD: drop GITHUB_PATH step (UTF-16 NUL issue) - PATH already set via NSSM
Some checks failed
Deploy SOLUTION_ERP / build-deploy (push) Failing after 1m12s
2026-04-21 14:40:14 +07:00
57a027501a [CLAUDE] CICD: use powershell (5.1) instead of pwsh (7) - not installed on VPS
Some checks are pending
Deploy SOLUTION_ERP / build-deploy (push) Waiting to run
2026-04-21 14:31:35 +07:00
ccfcfb4907 [CLAUDE] CICD: rewrite workflow for local deploy on self-hosted runner
Some checks failed
Deploy SOLUTION_ERP / build-deploy (push) Failing after 5s
VPS runner has only windows-latest label (no ubuntu) and lives on the
same VPS as IIS, so WinRM + multi-job artifact handoff is unnecessary.

Changes:
- Single build-deploy job on windows-latest self-hosted
- Uses pre-installed Node 20 and .NET 10 SDK (avoids 500MB setup-*
  downloads per run)
- Deploys directly to C:\inetpub\solution-erp\ — no WinRM
- appsettings.Production.json rendered from template via secrets
  (ConvertFrom-Json + ConvertTo-Json keeps JSON structure intact)
- Fixed site name mismatch: SolutionErp-Api (was SolutionErpApi)
- Removed IIS_HOST/USER/PASSWORD secrets — no longer needed
- Added smoke test step hitting https://api.huypham.vn/health/live

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-21 14:25:02 +07:00
f3fb3fd565 [CLAUDE] Phase5 prep: production infra + deploy scripts + 4 guides + FE refresh token
Backend production infra:
- Packages: Serilog.Sinks.File, HealthChecks.EntityFrameworkCore (RateLimiting built-in .NET 10)
- appsettings.Production.json MOI: placeholder __SET_VIA_SECRETS__, AllowedOrigins, Serilog File sink rolling daily retention 30d, RateLimit config
- appsettings.json + Development.json: them Serilog WriteTo Console
- Program.cs REWRITE:
  - Serilog ReadFrom.Configuration (prod file / dev console)
  - Rate limiter: policy auth-login 5/min/IP (AuthController.Login) + GlobalLimiter 300/min/IP
  - Health checks: /health/live liveness (empty predicate) + /health/ready DB probe (AddDbContextCheck)
  - HSTS production 1 year
  - CORS origins from config AllowedOrigins (default dev 2 localhost)
- AuthController.Login gắn [EnableRateLimiting("auth-login")]

Deploy scripts:
- scripts/deploy-iis.ps1: stop pool → backup current → clean+extract artifact → start pool → health check loop 30s timeout → rollback instruction if fail
- scripts/backup-sql.ps1: BACKUP DATABASE voi INIT+COMPRESSION+CHECKSUM + retention 30d auto cleanup
- .gitea/workflows/deploy.yml MOI: 4 job build BE (Windows) + build 2 FE (Ubuntu, pin .nvmrc 20) + deploy-iis qua WinRM PSSession (secrets IIS_HOST/USER/PASSWORD/JWT_SECRET/DB_CONNECTION)

Docs guides MOI (4 file):
- deployment-iis.md: prereqs (IIS features, Hosting Bundle, SQL, WinRM) + setup lan dau (app pool, 3 site, HTTPS win-acme, user-secrets) + deploy hang ngay (CI/CD + manual) + rollback + monitoring + troubleshooting + SPA web.config sample
- cicd.md: pipeline overview 4 job, secrets setup, runner Windows+Ubuntu, branch strategy, build optimizations, common CI/CD issues
- security-checklist.md: OWASP top 10 2021 mapping voi status + pre go-live checklist + incident response
- runbook.md: daily ops (health/logs), restart/rollback, DB backup/restore/migration revert, user management (reset password, unlock, disable), monitoring (CPU/disk/connection pool), deployment checklist, common gotcha

Frontend refresh token (ca 2 app fe-admin + fe-user):
- lib/api.ts REWRITE: them REFRESH_KEY, axios response interceptor 401 → POST /auth/refresh → retry request goc. Queue pattern cho nhieu request song song chi 1 refresh call chay. Skip retry /auth/login + /auth/refresh tranh infinite loop. _retry flag tren original config.
- contexts/AuthContext.tsx: luu+xoa REFRESH_KEY trong login/logout

E2E verified:
- GET /health/live → 200 Healthy
- GET /health/ready → 200 Healthy (DB probe)
- Rate limit flood 7 POST /auth/login → #1-5 HTTP 400 (cred sai) + #6-7 HTTP 429 Too Many Requests 
- TS check fe-admin + fe-user → pass
- dotnet build → 0 errors

Docs updates:
- docs/STATUS.md: Phase 5 prep done, next Phase 5 deploy production + Phase 5.1 security hardening, cumulative stats 8 commits
- docs/HANDOFF.md: phase table them Phase 5 prep row, file tree update voi guides + scripts + workflows, git state commit 8
- docs/changelog/migration-todos.md: tick Phase 5 prep items (12 items done) + Phase 5 deploy items remaining + Phase 5.1 security hardening list
- docs/changelog/sessions/2026-04-21-1530-phase5-prep.md: session log chi tiet

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-21 12:57:12 +07:00