chore(release): reconcile v0.1.1 with main #4
@@ -0,0 +1,103 @@
|
|||||||
|
schema: gitea-agent/release/v1
|
||||||
|
|
||||||
|
version:
|
||||||
|
sources:
|
||||||
|
- path: pyproject.toml
|
||||||
|
format: toml
|
||||||
|
selector: project.version
|
||||||
|
- path: jarca_ledger_mcp/__init__.py
|
||||||
|
format: python-assignment
|
||||||
|
selector: __version__
|
||||||
|
lockfiles:
|
||||||
|
- path: uv.lock
|
||||||
|
package: jarca-ledger-mcp
|
||||||
|
tag_template: "v{version}"
|
||||||
|
|
||||||
|
prepare:
|
||||||
|
runtime:
|
||||||
|
python: "3.12"
|
||||||
|
commands:
|
||||||
|
- name: sync
|
||||||
|
argv: [uv, sync, --python, "3.12", --frozen, --extra, dev, --extra, dashboard]
|
||||||
|
- name: lint
|
||||||
|
argv: [uv, run, ruff, check, .]
|
||||||
|
- name: test
|
||||||
|
argv: [uv, run, pytest]
|
||||||
|
- name: dashboard-http-smoke
|
||||||
|
argv: [uv, run, python, scripts/ci_dashboard_http_smoke.py, --host, 127.0.0.1, --port, "18501", --timeout, "45"]
|
||||||
|
- name: db-safety-smoke
|
||||||
|
argv: [uv, run, python, scripts/ci_db_safety_smoke.py, --timeout, "45"]
|
||||||
|
|
||||||
|
artifacts:
|
||||||
|
- type: container
|
||||||
|
name: jarca-ledger-mcp
|
||||||
|
platform: linux/arm64
|
||||||
|
|
||||||
|
build:
|
||||||
|
adapter: docker-buildx
|
||||||
|
context: .
|
||||||
|
dockerfile: Dockerfile
|
||||||
|
pull: true
|
||||||
|
local_tag_template: "jarca-ledger-mcp:release-{commit}"
|
||||||
|
labels:
|
||||||
|
org.opencontainers.image.source: "https://gitea.jsfamily.quest/jsfamily/jarca-ledger-mcp"
|
||||||
|
org.opencontainers.image.revision: "{commit}"
|
||||||
|
org.opencontainers.image.version: "{version}"
|
||||||
|
|
||||||
|
smoke:
|
||||||
|
- type: image-platform
|
||||||
|
expected_os: linux
|
||||||
|
expected_architecture: arm64
|
||||||
|
- type: container-command
|
||||||
|
environment:
|
||||||
|
JARCA_LEDGER_DB_PATH: /tmp/ledger.sqlite3
|
||||||
|
argv:
|
||||||
|
- python
|
||||||
|
- -c
|
||||||
|
- >-
|
||||||
|
import platform; from jarca_ledger_mcp import service;
|
||||||
|
result = service.health_check();
|
||||||
|
assert platform.machine() == "aarch64";
|
||||||
|
assert result["success"], result
|
||||||
|
- type: container-health
|
||||||
|
name_template: "jarca-mcp-{run_id}"
|
||||||
|
command: default
|
||||||
|
expected: healthy
|
||||||
|
timeout_seconds: 90
|
||||||
|
- type: container-http
|
||||||
|
name_template: "jarca-dashboard-{run_id}"
|
||||||
|
command:
|
||||||
|
- python
|
||||||
|
- -m
|
||||||
|
- streamlit
|
||||||
|
- run
|
||||||
|
- dashboard/app.py
|
||||||
|
- --server.address
|
||||||
|
- 0.0.0.0
|
||||||
|
- --server.port
|
||||||
|
- "8501"
|
||||||
|
- --server.headless
|
||||||
|
- "true"
|
||||||
|
- --browser.gatherUsageStats
|
||||||
|
- "false"
|
||||||
|
container_port: 8501
|
||||||
|
path: /_stcore/health
|
||||||
|
expected_status: 200
|
||||||
|
expected_body: ok
|
||||||
|
timeout_seconds: 90
|
||||||
|
|
||||||
|
publish:
|
||||||
|
adapter: gitea-container-registry
|
||||||
|
registry: gitea.jsfamily.quest
|
||||||
|
repository: jsfamily/jarca-ledger-mcp
|
||||||
|
credentials:
|
||||||
|
username: authenticated-gitea-login
|
||||||
|
token_env: GITEA_TOKEN
|
||||||
|
tags:
|
||||||
|
- "{tag}"
|
||||||
|
- "sha-{commit}"
|
||||||
|
overwrite: false
|
||||||
|
verify:
|
||||||
|
- digest
|
||||||
|
- platform
|
||||||
|
- org.opencontainers.image.revision
|
||||||
@@ -1,134 +0,0 @@
|
|||||||
name: Verify and publish ARM64 image
|
|
||||||
|
|
||||||
on:
|
|
||||||
pull_request:
|
|
||||||
paths:
|
|
||||||
- Dockerfile
|
|
||||||
- .dockerignore
|
|
||||||
- pyproject.toml
|
|
||||||
- uv.lock
|
|
||||||
- jarca_ledger_mcp/**
|
|
||||||
- dashboard/**
|
|
||||||
- .github/workflows/publish-image.yml
|
|
||||||
push:
|
|
||||||
tags:
|
|
||||||
- "v*"
|
|
||||||
workflow_dispatch:
|
|
||||||
|
|
||||||
permissions:
|
|
||||||
contents: read
|
|
||||||
|
|
||||||
concurrency:
|
|
||||||
group: image-${{ github.workflow }}-${{ github.ref }}
|
|
||||||
cancel-in-progress: true
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
verify-arm64:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- uses: docker/setup-qemu-action@v3
|
|
||||||
with:
|
|
||||||
platforms: arm64
|
|
||||||
|
|
||||||
- uses: docker/setup-buildx-action@v3
|
|
||||||
|
|
||||||
- name: Build ARM64 verification image
|
|
||||||
uses: docker/build-push-action@v6
|
|
||||||
with:
|
|
||||||
context: .
|
|
||||||
platforms: linux/arm64
|
|
||||||
load: true
|
|
||||||
push: false
|
|
||||||
tags: jarca-ledger-mcp:arm64-verify
|
|
||||||
cache-from: type=gha,scope=jarca-ledger-arm64
|
|
||||||
cache-to: type=gha,mode=max,scope=jarca-ledger-arm64
|
|
||||||
|
|
||||||
- name: Verify image platform, imports, and SQLite
|
|
||||||
run: |
|
|
||||||
set -euo pipefail
|
|
||||||
test "$(docker image inspect jarca-ledger-mcp:arm64-verify --format '{{.Architecture}}')" = arm64
|
|
||||||
docker run --rm --platform linux/arm64 \
|
|
||||||
-e JARCA_LEDGER_DB_PATH=/tmp/ledger.sqlite3 \
|
|
||||||
jarca-ledger-mcp:arm64-verify \
|
|
||||||
python -c 'import platform, cryptography, numpy, pandas, pyarrow, pymupdf; from jarca_ledger_mcp import service; result=service.health_check(); assert platform.machine() == "aarch64"; assert result["success"], result; print(result["schema_version"])'
|
|
||||||
|
|
||||||
- name: Verify MCP and Dashboard startup
|
|
||||||
run: |
|
|
||||||
set -euo pipefail
|
|
||||||
trap 'docker rm -f jarca-mcp-smoke jarca-dashboard-smoke >/dev/null 2>&1 || true' EXIT
|
|
||||||
|
|
||||||
docker run -d --name jarca-mcp-smoke --platform linux/arm64 \
|
|
||||||
jarca-ledger-mcp:arm64-verify
|
|
||||||
for _ in $(seq 1 60); do
|
|
||||||
status=$(docker inspect --format '{{.State.Health.Status}}' jarca-mcp-smoke)
|
|
||||||
test "$status" = healthy && break
|
|
||||||
test "$status" = unhealthy && { docker logs jarca-mcp-smoke; exit 1; }
|
|
||||||
sleep 1
|
|
||||||
done
|
|
||||||
test "$(docker inspect --format '{{.State.Health.Status}}' jarca-mcp-smoke)" = healthy
|
|
||||||
|
|
||||||
docker run -d --name jarca-dashboard-smoke --platform linux/arm64 \
|
|
||||||
-p 127.0.0.1::8501 jarca-ledger-mcp:arm64-verify \
|
|
||||||
python -m streamlit run dashboard/app.py \
|
|
||||||
--server.address 0.0.0.0 --server.port 8501 \
|
|
||||||
--server.headless true --browser.gatherUsageStats false
|
|
||||||
port=$(docker port jarca-dashboard-smoke 8501/tcp | sed 's/.*://')
|
|
||||||
code=000
|
|
||||||
for _ in $(seq 1 90); do
|
|
||||||
code=$(curl -sS -o /tmp/dashboard-health -w '%{http_code}' \
|
|
||||||
"http://127.0.0.1:${port}/_stcore/health" || true)
|
|
||||||
test "$code" = 200 && break
|
|
||||||
sleep 1
|
|
||||||
done
|
|
||||||
test "$code" = 200
|
|
||||||
test "$(tr -d '\n' < /tmp/dashboard-health)" = ok
|
|
||||||
|
|
||||||
publish:
|
|
||||||
if: startsWith(github.ref, 'refs/tags/v')
|
|
||||||
needs: verify-arm64
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
permissions:
|
|
||||||
contents: read
|
|
||||||
packages: write
|
|
||||||
outputs:
|
|
||||||
digest: ${{ steps.build.outputs.digest }}
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- uses: docker/setup-qemu-action@v3
|
|
||||||
with:
|
|
||||||
platforms: arm64
|
|
||||||
|
|
||||||
- uses: docker/setup-buildx-action@v3
|
|
||||||
|
|
||||||
- name: Log in to GHCR
|
|
||||||
uses: docker/login-action@v3
|
|
||||||
with:
|
|
||||||
registry: ghcr.io
|
|
||||||
username: ${{ github.actor }}
|
|
||||||
password: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
|
|
||||||
- name: Build and publish immutable ARM64 image
|
|
||||||
id: build
|
|
||||||
uses: docker/build-push-action@v6
|
|
||||||
with:
|
|
||||||
context: .
|
|
||||||
platforms: linux/arm64
|
|
||||||
push: true
|
|
||||||
tags: |
|
|
||||||
ghcr.io/genichin/jarca-ledger-mcp:${{ github.ref_name }}
|
|
||||||
ghcr.io/genichin/jarca-ledger-mcp:sha-${{ github.sha }}
|
|
||||||
labels: |
|
|
||||||
org.opencontainers.image.source=${{ github.server_url }}/${{ github.repository }}
|
|
||||||
org.opencontainers.image.revision=${{ github.sha }}
|
|
||||||
org.opencontainers.image.version=${{ github.ref_name }}
|
|
||||||
cache-from: type=gha,scope=jarca-ledger-arm64
|
|
||||||
cache-to: type=gha,mode=max,scope=jarca-ledger-arm64
|
|
||||||
provenance: mode=max
|
|
||||||
sbom: true
|
|
||||||
|
|
||||||
- name: Report published digest
|
|
||||||
run: |
|
|
||||||
echo "ghcr.io/genichin/jarca-ledger-mcp:${GITHUB_REF_NAME}@${{ steps.build.outputs.digest }}"
|
|
||||||
@@ -90,11 +90,11 @@ Deployment: jarca-ledger (replicas: 1)
|
|||||||
- MCP와 frontend는 목적별 Kubernetes Service로 분리합니다. MCP는 `8000`, frontend는 `8501`을 대상으로 합니다.
|
- MCP와 frontend는 목적별 Kubernetes Service로 분리합니다. MCP는 `8000`, frontend는 `8501`을 대상으로 합니다.
|
||||||
- 외부 공개가 필요하면 일반적으로 frontend Service만 Ingress 또는 NodePort에 연결하고, MCP Service는 필요한 범위에서만 노출합니다.
|
- 외부 공개가 필요하면 일반적으로 frontend Service만 Ingress 또는 NodePort에 연결하고, MCP Service는 필요한 범위에서만 노출합니다.
|
||||||
- ARM64 worker에서만 실행하도록 Pod의 `nodeSelector` 또는 node affinity를 설정합니다.
|
- ARM64 worker에서만 실행하도록 Pod의 `nodeSelector` 또는 node affinity를 설정합니다.
|
||||||
- 배포 이미지는 가변 태그 대신 검증된 GHCR digest로 고정합니다.
|
- 배포 이미지는 가변 태그 대신 검증된 `gitea.jsfamily.quest/jsfamily/jarca-ledger-mcp` Gitea Container Registry digest로 고정합니다.
|
||||||
|
|
||||||
Streamlit이 SQLite에 직접 접근하지 않고 MCP/API만 호출하도록 변경하거나 네트워크 DB로 전환한 뒤에는 MCP와 frontend를 각각 독립 Deployment로 분리할 수 있습니다.
|
Streamlit이 SQLite에 직접 접근하지 않고 MCP/API만 호출하도록 변경하거나 네트워크 DB로 전환한 뒤에는 MCP와 frontend를 각각 독립 Deployment로 분리할 수 있습니다.
|
||||||
|
|
||||||
로컬 `docker-compose.yml`도 동일한 애플리케이션 이미지를 두 컨테이너로 실행하는 구조입니다. 현재 Compose 설정은 로컬에서 빌드한 `jarca-ledger:latest`를 사용하며, MCP는 호스트 `8000` 포트로, Streamlit은 호스트 `40059`에서 컨테이너 `8501` 포트로 연결됩니다. Compose 실행 전 host environment 또는 안전한 `.env` 전달 경계에 두 Dashboard credential 변수를 설정해야 하며 누락 시 Compose가 시작을 거부합니다. GHCR 릴리즈를 배포할 때는 두 서비스의 `image`를 검증된 동일 digest로 지정해야 합니다.
|
로컬 `docker-compose.yml`도 동일한 애플리케이션 이미지를 두 컨테이너로 실행하는 구조입니다. 현재 Compose 설정은 로컬에서 빌드한 `jarca-ledger:latest`를 사용하며, MCP는 호스트 `8000` 포트로, Streamlit은 호스트 `40059`에서 컨테이너 `8501` 포트로 연결됩니다. Compose 실행 전 host environment 또는 안전한 `.env` 전달 경계에 두 Dashboard credential 변수를 설정해야 하며 누락 시 Compose가 시작을 거부합니다. Gitea Container Registry 릴리즈를 배포할 때는 두 서비스의 `image`를 검증된 동일 `gitea.jsfamily.quest/jsfamily/jarca-ledger-mcp` digest로 지정해야 합니다.
|
||||||
|
|
||||||
## 주요 도구
|
## 주요 도구
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
"""Jarca Ledger MCP server."""
|
"""Jarca Ledger MCP server."""
|
||||||
|
|
||||||
__version__ = "0.1.0"
|
__version__ = "0.1.1"
|
||||||
|
|||||||
+1
-1
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|||||||
|
|
||||||
[project]
|
[project]
|
||||||
name = "jarca-ledger-mcp"
|
name = "jarca-ledger-mcp"
|
||||||
version = "0.1.0"
|
version = "0.1.1"
|
||||||
description = "Jarca household ledger MCP server for transactions, accounts, budgets, cashflow, and investable cashflow analysis"
|
description = "Jarca household ledger MCP server for transactions, accounts, budgets, cashflow, and investable cashflow analysis"
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
requires-python = ">=3.11"
|
requires-python = ">=3.11"
|
||||||
|
|||||||
@@ -469,7 +469,7 @@ wheels = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "jarca-ledger-mcp"
|
name = "jarca-ledger-mcp"
|
||||||
version = "0.1.0"
|
version = "0.1.1"
|
||||||
source = { editable = "." }
|
source = { editable = "." }
|
||||||
dependencies = [
|
dependencies = [
|
||||||
{ name = "mcp" },
|
{ name = "mcp" },
|
||||||
|
|||||||
Reference in New Issue
Block a user