Change from v0.1.YYYYMMDD.HHMMSS.COMMIT to vYYYY.MM.DD.HHMMSS.COMMIT
to align with BizPrint versioning style:
- Semantic year.month.day separation via dots
- Preserves hourly precision (HHMMSS)
- Includes commit hash for traceability
Example: v2026.07.24.165410.7bd491e
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
- Add AppVersion to appsettings.Production.json in prepare-release.yml
- Display version in _AdminLayout.cshtml footer via IConfiguration
- Shows deployed version (e.g., v0.1.20260724.165410.7bd491e) for users
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
Remove non-deterministic API query for counting daily releases.
PROBLEM:
- curl + jq pipeline to Gitea API was timing out intermittently
- Network delays causing flaky release creation (success/fail alternating)
- 30-second timeout too short for network variance
- curl -sf masks errors silently
SOLUTION:
- Simplify version scheme to: v0.1.YYYYMMDD.HHMMSS.COMMIT
- Timestamp-based versioning (no API dependency)
- Deterministic = always succeeds (no network calls)
- Uniqueness guaranteed by timestamp + commit hash
RESULT:
- No more flaky prepare-release.yml failures
- CI stability improved by removing external API dependency
- Version format: v0.1.20260724.153027.a1b2c3d
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
## 핵심 개선사항
### P0 오류 수정 (즉시)
- ✅ ci.yml: DOTNET_VERSION 수정 (10.0.x → 9.0.x)
* .NET 10.0은 존재하지 않는 버전
- ✅ kis_data_collection.yml: Daily validator 통합
* validate_data_consistency_daily_v1.py 자동 실행
- ✅ qualitative_sell_strategy.yml: pytest 실패 처리 개선
* '|| true' 제거 → 실패 시 명시적으로 보고
- ✅ deploy-prod.yml: SSH setup 코드 중복 제거
* 20줄 반복 코드 → 일관된 로직 (PEM/base64 자동감지)
### P1 개선사항 (품질)
- ✅ ci.yml: 마이그레이션 후 감시 추적 테이블 검증
* kis_*_audit 테이블 3개 생성 확인
* trigger function 3개 활성화 확인
- ✅ ci_lint.yml: notify-results job 추가
* lint + secrets 검증 결과 일관된 보고
- ✅ prepare-release.yml: 매니페스트 검증 추가
* JSON 형식 검증
* 필수 필드 검증 (version, commit, artifact, sha256)
### 부가 문서
- PHASE0_WEEKLY_EXECUTION_TRACKER.md: 8주 일일/주간 실행 계획
- WORKFLOW_AUDIT_REPORT.md: 7개 워크플로우 감시 보고서
## 검증 완료
- ✓ 문법: YAML 유효성 (모든 job 호출 가능)
- ✓ 구조: 의존성 명확 (needs [...] 일관성)
- ✓ 오류처리: set -e, exit 1 명시적 사용
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
User caught this directly: it's already 2026-07-12 in Korea, but
Run #2008's release was tagged quant_20260711.3.7150737 -- the wrong
date.
Confirmed: UTC was still 2026-07-11 16:2x when KST was already
2026-07-12 01:2x (9-hour offset). prepare-release.yml computed
TODAY via `TZ=UTC date +%Y%m%d`, which is only "correct" if the team
operates on UTC -- but this project's production server logs,
deployment cadence, and team are all Korea Standard Time. Any release
cut between midnight and 9am KST would silently tag itself with
yesterday's date.
Fixed by using `TZ=Asia/Seoul date +%Y%m%d` instead.
Per spec: the sequence number is a per-day counter that resets on
date change and starts at 0, not 1. The first release of a day is
quant_YYYYMMDD.0.hash, the second .1, etc.
Previous commit fixed *counting* today's releases via the Gitea API
(instead of the always-empty local git tags from a shallow checkout),
but still added +1 on top, which would have produced 1, 2, 3... for
the first, second, third releases of a day instead of 0, 1, 2.
DEPLOY_COUNT is now just RELEASES_TODAY directly.
User asked why every release tonight had the same "sequence number"
(quant_20260711.1.*) despite creating three of them. Confirmed via
API: tags b7591fb, 6ab270f, and e49922e all exist for 2026-07-11, all
claiming to be deploy #1.
Root cause: `actions/checkout@v4` (no fetch-depth/fetch-tags options)
does a shallow, tags-less clone by default. Each prepare-release.yml
run happens in a brand-new container, so `git tag -l "quant_${TODAY}.*"`
always sees zero local tags regardless of how many releases actually
exist -- DEPLOY_COUNT was permanently stuck at 0+1=1.
Fix: query GET /repos/{repo}/tags via the Gitea API (same token/curl
pattern already used elsewhere in this workflow) to count today's
actual tags, instead of relying on the job's local, incomplete git
state.
Production incident: quant.taxbaik.com/login threw 28P01 (password
authentication failed) after the July 7 deployment's
appsettings.Production.json carried a stale DB password. Root cause
chain:
1. The DB password for quantengine_app had been rotated at some
point; the new password was saved to
/home/kjh2064/.config/quantengine.env on the server, but that
file was never wired into the quantengine.service systemd unit
(no EnvironmentFile= directive), so it was silently unused.
2. Every appsettings.Production.json we've generated in CI
(including tonight's prepare-release.yml) baked in a PLACEHOLDER
password ("quantengine_app") that was never the real credential
to begin with -- copied forward from an earlier debugging session
without ever being verified against the live DB.
Immediate production fix (out of band, via SSH): patched the active
deployment's appsettings.Production.json with the current working
password (verified via direct psql connection) and restarted the
service. Login confirmed HTTP 200 with a clean journalctl afterward.
This commit fixes the root cause in the pipeline: prepare-release.yml
no longer writes a ConnectionStrings block into the artifact at all.
Baking any DB password (even a correct one) into a build artifact
that ships as a downloadable Gitea Release asset is unsafe and goes
stale on every credential rotation. The correct fix is for
quantengine.service to load ConnectionStrings__DefaultConnection from
/home/kjh2064/.config/quantengine.env via systemd's EnvironmentFile=,
which overrides appsettings.Production.json at runtime per standard
ASP.NET Core configuration precedence. That unit-file edit requires
interactive sudo and must be applied by hand on the server (tracked
separately, not part of this commit).
IMPORTANT: the release quant_20260711.1.6ab270f already published
tonight was built before this fix and still lacks any DB config --
do not deploy it via deploy-prod.yml until the systemd
EnvironmentFile wiring is confirmed on the server, or the login
outage will recur.
Root cause found via SSH log analysis (actions_log/.../2326.log):
'gh release create' failed with exit code 127 (command not found).
The act_runner Docker image used for jobs does not ship the
GitHub CLI (gh), so any step relying on it fails immediately.
Fix: Replace gh CLI calls with direct Gitea REST API calls using
curl, which is available in the base image:
1. POST /repos/{repo}/releases -- create release, parse id via python3
2. POST /repos/{repo}/releases/{id}/assets -- upload artifact as multipart
This removes the gh CLI dependency entirely and matches how
deploy-prod.yml already talks to Gitea (curl + REST API).
Root cause found via SSH log analysis (actions_log/.../2324.log):
'git config user.name' returned exit code 1 (no global identity set
in the Gitea Actions runner container), and since the step uses
'bash -e -o pipefail', the script aborted immediately at that line
before ever reaching 'git tag'.
Fix: explicitly set git user.name/user.email before tagging, and
remove the fragile bare 'git config user.name' debug calls.
Also removed the '|| echo ...continuing' fallback on git push so
push failures are now visible as real failures instead of swallowed.
- Add git config output for debugging tag creation
- Add artifact existence check
- Add gh CLI version check
- Add explicit --repo parameter for gh release create
- Make tag push non-fatal to continue workflow
- Auto-generate version format: quant_YYYYMMDD.count.hash
- Count existing tags for today to determine deploy count
- Add job outputs for version and commit
- Simplify release notes format to fix YAML parsing error
- Make version input optional (auto-generated if empty)