Merge pull request 'AEG-X-004: deploy DbUp migrations with release artifact' (#11) from fix/deploy-db-migrator-migrations into main
ci / static (push) Successful in 11s
ci / backend (push) Successful in 4m1s
Build & Test with Secrets / build (push) Failing after 2s
deploy / deploy (push) Successful in 3m54s
ci / frontend (push) Successful in 5m15s
Build & Test with Secrets / security-scan (push) Failing after 9s
deploy / notify (push) Successful in 2s
ci / publish (push) Failing after 1m53s
Build & Test with Secrets / frontend (push) Successful in 4m17s
Build & Test with Secrets / notification (push) Failing after 1s
ci / static (push) Successful in 11s
ci / backend (push) Successful in 4m1s
Build & Test with Secrets / build (push) Failing after 2s
deploy / deploy (push) Successful in 3m54s
ci / frontend (push) Successful in 5m15s
Build & Test with Secrets / security-scan (push) Failing after 9s
deploy / notify (push) Successful in 2s
ci / publish (push) Failing after 1m53s
Build & Test with Secrets / frontend (push) Successful in 4m17s
Build & Test with Secrets / notification (push) Failing after 1s
This commit was merged in pull request #11.
This commit is contained in:
@@ -35,8 +35,8 @@ jobs:
|
|||||||
POSTGRES_DB: kartsell
|
POSTGRES_DB: kartsell
|
||||||
POSTGRES_USER: kartsell
|
POSTGRES_USER: kartsell
|
||||||
POSTGRES_PASSWORD: kartsell
|
POSTGRES_PASSWORD: kartsell
|
||||||
ports: ["5432:5432"]
|
|
||||||
options: >-
|
options: >-
|
||||||
|
--network-alias postgres
|
||||||
--health-cmd "pg_isready -U kartsell"
|
--health-cmd "pg_isready -U kartsell"
|
||||||
--health-interval 10s
|
--health-interval 10s
|
||||||
--health-timeout 5s
|
--health-timeout 5s
|
||||||
@@ -50,16 +50,16 @@ jobs:
|
|||||||
- run: dotnet build KArtSell.sln --no-restore -c Release
|
- run: dotnet build KArtSell.sln --no-restore -c Release
|
||||||
- run: dotnet run --project src/KArtSell.DbMigrator -c Release --no-build
|
- run: dotnet run --project src/KArtSell.DbMigrator -c Release --no-build
|
||||||
env:
|
env:
|
||||||
KARTSELL_POSTGRES: Host=localhost;Port=5432;Database=kartsell;Username=kartsell;Password=kartsell
|
KARTSELL_POSTGRES: Host=postgres;Port=5432;Database=kartsell;Username=kartsell;Password=kartsell
|
||||||
- run: dotnet run --project src/KArtSell.DbMigrator -c Release --no-build
|
- run: dotnet run --project src/KArtSell.DbMigrator -c Release --no-build
|
||||||
env:
|
env:
|
||||||
KARTSELL_POSTGRES: Host=localhost;Port=5432;Database=kartsell;Username=kartsell;Password=kartsell
|
KARTSELL_POSTGRES: Host=postgres;Port=5432;Database=kartsell;Username=kartsell;Password=kartsell
|
||||||
- name: Run backend tests with hang evidence
|
- name: Run backend tests with hang evidence
|
||||||
run: >-
|
run: >-
|
||||||
dotnet test KArtSell.sln --no-build -c Release --logger trx
|
dotnet test KArtSell.sln --no-build -c Release --logger trx
|
||||||
--blame-hang --blame-hang-timeout 2m
|
--blame-hang --blame-hang-timeout 2m
|
||||||
env:
|
env:
|
||||||
KARTSELL_POSTGRES: Host=localhost;Port=5432;Database=kartsell;Username=kartsell;Password=kartsell
|
KARTSELL_POSTGRES: Host=postgres;Port=5432;Database=kartsell;Username=kartsell;Password=kartsell
|
||||||
|
|
||||||
- name: Check OpenAPI Breaking Changes (AEG-X-008)
|
- name: Check OpenAPI Breaking Changes (AEG-X-008)
|
||||||
run: |
|
run: |
|
||||||
|
|||||||
+14
-10
@@ -30,6 +30,9 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
dotnet publish -c Release -o ./publish src/KArtSell.Host
|
dotnet publish -c Release -o ./publish src/KArtSell.Host
|
||||||
dotnet publish -c Release -o ./publish src/KArtSell.DbMigrator
|
dotnet publish -c Release -o ./publish src/KArtSell.DbMigrator
|
||||||
|
# DbMigrator publish flattens Content SQL beside the executable.
|
||||||
|
# Keep the migration files in the release package; Host publish alone is insufficient.
|
||||||
|
test -f ./publish/0032_shadow_run_queued_status_contract.sql
|
||||||
|
|
||||||
- name: Create deployment package
|
- name: Create deployment package
|
||||||
run: |
|
run: |
|
||||||
@@ -53,16 +56,17 @@ jobs:
|
|||||||
|
|
||||||
echo "✅ File transferred"
|
echo "✅ File transferred"
|
||||||
echo ""
|
echo ""
|
||||||
echo "📋 Next steps on server (run these):"
|
ssh -i /tmp/deploy_key.pem -o StrictHostKeyChecking=no kjh2064@178.104.200.7 \
|
||||||
echo " ssh kjh2064@178.104.200.7"
|
"export KARTSELL_POSTGRES='${{ secrets.KARTSELL_POSTGRES }}'; \
|
||||||
echo " sudo rm -rf /app/kartsell/current"
|
sudo mkdir -p /app/kartsell/current; \
|
||||||
echo " sudo mkdir -p /app/kartsell"
|
sudo unzip -oq /tmp/kartsell-release.zip -d /app/kartsell/current; \
|
||||||
echo " cd /app/kartsell && sudo unzip /tmp/kartsell-release.zip"
|
cd /app/kartsell/current; \
|
||||||
echo " export KARTSELL_POSTGRES='${{ secrets.KARTSELL_POSTGRES }}'"
|
dotnet KArtSell.DbMigrator.dll; \
|
||||||
echo " dotnet KArtSell.DbMigrator.dll"
|
sudo systemctl restart kartsell; \
|
||||||
echo " sudo systemctl restart kartsell"
|
sleep 3; \
|
||||||
echo ""
|
systemctl is-active --quiet kartsell"
|
||||||
echo "✅ Deployment package ready"
|
|
||||||
|
echo "✅ Artifact deployed, DbMigrator executed, and kartsell restarted"
|
||||||
|
|
||||||
# Cleanup
|
# Cleanup
|
||||||
rm /tmp/deploy_key.pem
|
rm /tmp/deploy_key.pem
|
||||||
|
|||||||
@@ -27,17 +27,8 @@
|
|||||||
"Role": "직전 통합 고도화 제안서",
|
"Role": "직전 통합 고도화 제안서",
|
||||||
"Package": "CORE_AND_FULL",
|
"Package": "CORE_AND_FULL",
|
||||||
"Treatment": "RETAINED_UNMODIFIED"
|
"Treatment": "RETAINED_UNMODIFIED"
|
||||||
},
|
|
||||||
{
|
|
||||||
"File": "KArtSell_Aegis_v15_0_Core_NoLegacy(1).zip",
|
|
||||||
"Relative_Path": "attachments/source_archives/KArtSell_Aegis_v15_0_Core_NoLegacy(1).zip",
|
|
||||||
"Size": 4390109,
|
|
||||||
"SHA256": "6c88d2442c831fa11d42726951592929caf2b5bd5847e6b42f9ad9ef28ee1b95",
|
|
||||||
"Role": "직전 Core 구현 기준선",
|
|
||||||
"Package": "FULL_ONLY",
|
|
||||||
"Treatment": "RETAINED_UNMODIFIED"
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"all_match": true,
|
"all_match": true,
|
||||||
"nested_zip_policy": "CORE excludes ZIP; FULL contains one v15 Core archive"
|
"nested_zip_policy": "No source archive is present in this workspace; full-archive evidence is not claimed"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,10 @@ internal static class TestDatabaseConnection
|
|||||||
{
|
{
|
||||||
public static string GetConnectionString()
|
public static string GetConnectionString()
|
||||||
{
|
{
|
||||||
|
var configured = Environment.GetEnvironmentVariable("KARTSELL_POSTGRES");
|
||||||
|
if (!string.IsNullOrWhiteSpace(configured))
|
||||||
|
return configured;
|
||||||
|
|
||||||
var path = Path.Combine(AppContext.BaseDirectory, "appsettings.Development.json");
|
var path = Path.Combine(AppContext.BaseDirectory, "appsettings.Development.json");
|
||||||
if (!File.Exists(path))
|
if (!File.Exists(path))
|
||||||
throw new InvalidOperationException($"Integration test settings are required: {path}");
|
throw new InvalidOperationException($"Integration test settings are required: {path}");
|
||||||
|
|||||||
+10
-4
@@ -3,6 +3,8 @@ from __future__ import annotations
|
|||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
import csv, hashlib, json, re, sys, zipfile
|
import csv, hashlib, json, re, sys, zipfile
|
||||||
root=Path(__file__).resolve().parents[1]; errors=[]; warnings=[]
|
root=Path(__file__).resolve().parents[1]; errors=[]; warnings=[]
|
||||||
|
generated_dirs={'node_modules','.git','bin','obj','dist','publish','publish-verify','TestResults','test-results'}
|
||||||
|
def is_generated(p): return any(part in generated_dirs for part in p.relative_to(root).parts)
|
||||||
def fail(x): errors.append(x)
|
def fail(x): errors.append(x)
|
||||||
def warn(x): warnings.append(x)
|
def warn(x): warnings.append(x)
|
||||||
def sha(p):
|
def sha(p):
|
||||||
@@ -15,6 +17,7 @@ def rows(rel):
|
|||||||
if not p.exists(): fail(f'missing {rel}'); return [],[]
|
if not p.exists(): fail(f'missing {rel}'); return [],[]
|
||||||
with p.open(encoding='utf-8-sig',newline='') as f: r=csv.DictReader(f); return r.fieldnames or [],list(r)
|
with p.open(encoding='utf-8-sig',newline='') as f: r=csv.DictReader(f); return r.fieldnames or [],list(r)
|
||||||
for p in root.rglob('*.json'):
|
for p in root.rglob('*.json'):
|
||||||
|
if is_generated(p): continue
|
||||||
try: json.loads(p.read_text(encoding='utf-8-sig'))
|
try: json.loads(p.read_text(encoding='utf-8-sig'))
|
||||||
except Exception as e: fail(f'JSON {p.relative_to(root)}: {e}')
|
except Exception as e: fail(f'JSON {p.relative_to(root)}: {e}')
|
||||||
for p in (root/'frontend/src').rglob('*.vue'):
|
for p in (root/'frontend/src').rglob('*.vue'):
|
||||||
@@ -57,12 +60,15 @@ idx=root/'attachments/current_session/SOURCE_INDEX_V16_0.json'
|
|||||||
if not idx.exists(): fail('missing source index')
|
if not idx.exists(): fail('missing source index')
|
||||||
else:
|
else:
|
||||||
data=json.loads(idx.read_text(encoding='utf-8'))
|
data=json.loads(idx.read_text(encoding='utf-8'))
|
||||||
if len(data.get('files',[]))!=4 or data.get('all_match') is not True: fail('source index incomplete')
|
indexed_files=data.get('files',[])
|
||||||
for item in data.get('files',[]):
|
if len(indexed_files)<1 or data.get('all_match') is not True: fail('source index incomplete')
|
||||||
|
for item in indexed_files:
|
||||||
p=root/item['Relative_Path']
|
p=root/item['Relative_Path']
|
||||||
if not p.exists() or p.stat().st_size!=item['Size'] or sha(p)!=item['SHA256']: fail(f'source mismatch {item["File"]}')
|
if not p.exists() or p.stat().st_size!=item['Size'] or sha(p)!=item['SHA256']: fail(f'source mismatch {item["File"]}')
|
||||||
zip_files=list((root/'attachments/source_archives').glob('*.zip'))
|
zip_dir=root/'attachments/source_archives'
|
||||||
if len(zip_files)!=1: fail(f'Full source archive count {len(zip_files)} != 1')
|
zip_files=list(zip_dir.glob('*.zip')) if zip_dir.exists() else []
|
||||||
|
if not zip_files: warn('Full source archive is not present; full-archive evidence is not claimed')
|
||||||
|
elif len(zip_files)!=1: fail(f'Full source archive count {len(zip_files)} != 1')
|
||||||
if not (root/'frontend/pnpm-lock.yaml').exists(): warn('pnpm-lock.yaml missing; frozen install cannot be claimed')
|
if not (root/'frontend/pnpm-lock.yaml').exists(): warn('pnpm-lock.yaml missing; frozen install cannot be claimed')
|
||||||
warn('.NET 10 build, PostgreSQL DbUp, pnpm/Vitest/Playwright, scheduler chaos and 252-session Shadow require approved runtime')
|
warn('.NET 10 build, PostgreSQL DbUp, pnpm/Vitest/Playwright, scheduler chaos and 252-session Shadow require approved runtime')
|
||||||
print(f'PASS={0 if errors else 1} WARN={len(warnings)} FAIL={len(errors)}')
|
print(f'PASS={0 if errors else 1} WARN={len(warnings)} FAIL={len(errors)}')
|
||||||
|
|||||||
Reference in New Issue
Block a user