feat: AI판정/OCR/알림톡/소셜로그인/푸시/CODEF 전체 구현 + CI SSH 전환
Deploy via SSH / remote-deploy (push) Failing after 6s
Deploy via SSH / remote-deploy (push) Failing after 6s
Backend (server/src): - services/anthropic.ts — Claude API 래퍼 (키 없으면 룰베이스 fallback) - services/ocr.ts — Naver Clova + Google Vision 듀얼 연동 + 영수증 필드 파서 - services/solapi.ts — 카카오 알림톡 HMAC 서명 + 드라이런 - services/expoPush.ts — Expo Push API 전송 - services/codef.ts — 보험 통합조회 mock + 실연동 포인트 - routes/ai.ts, ocr.ts, devices.ts, social.ts (naver/apple), alimtalk.ts, codef.ts - Prisma: PushDevice 모델 + binaryTargets linux-musl-openssl-3.0.x - Dockerfile: apk add openssl (Prisma schema engine 정상화) - api-secrets에 9개 외부 API 키 슬롯 추가 (optional) Frontend: - api/endpoints.ts: aiApi, ocrApi, deviceApi, socialApi, codefApi - services/kakao.ts — Kakao JS SDK 동적 로드 + Auth.login - services/push.ts — expo-notifications 권한/토큰 등록 + 서버 전송 - LoginScreen — 카카오/네이버/애플 버튼 (웹은 토큰 입력 fallback) - AIJudgeScreen — 실제 /ai/claim-judge 호출, source(llm/rules) 표시 - ClaimScreen — 영수증 촬영 시 자동 OCR → 병원/날짜/제목 자동 기입 - useAuthStore hydrate 시 푸시 토큰 등록 Infra: - eas.json (development/preview/production 빌드 프로필) - API_KEYS.md — 9개 외부 서비스 발급/등록 가이드 - scripts/deploy-remote.sh 개선 (sudo 정확히, traefik cp 버그 수정, API fail 시 로그 출력) - deploy/k8s/api.yaml — 외부 API 키 환경변수 매핑 (optional=true) CI/CD: - .gitea/workflows/deploy.yml → SSH 기반으로 전환 (appleboy/ssh-action으로 서버 접속 → deploy-remote.sh 실행) - 필요 Secrets: SSH_HOST, SSH_USER, SSH_PASSWORD Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
+20
-112
@@ -1,122 +1,30 @@
|
||||
name: Build & Deploy
|
||||
name: Deploy via SSH
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [master, main]
|
||||
workflow_dispatch:
|
||||
|
||||
env:
|
||||
REGISTRY: git.junggomoa.com
|
||||
WEB_IMAGE: chpark/insurance
|
||||
API_IMAGE: chpark/insurance-api
|
||||
API_BASE_URL: https://api.insurance.junggomoa.com
|
||||
|
||||
jobs:
|
||||
build-and-deploy:
|
||||
remote-deploy:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Set short SHA
|
||||
run: echo "SHORT_SHA=$(git rev-parse --short HEAD)" >> $GITHUB_ENV
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
|
||||
- name: Log in to Gitea Container Registry
|
||||
uses: docker/login-action@v3
|
||||
- name: Trigger remote deploy on server
|
||||
uses: appleboy/ssh-action@v1.0.3
|
||||
with:
|
||||
registry: ${{ env.REGISTRY }}
|
||||
username: ${{ secrets.REGISTRY_USER }}
|
||||
password: ${{ secrets.REGISTRY_TOKEN }}
|
||||
|
||||
- name: Build & push WEB image
|
||||
uses: docker/build-push-action@v5
|
||||
with:
|
||||
context: .
|
||||
file: ./Dockerfile
|
||||
build-args: |
|
||||
EXPO_PUBLIC_API_BASE=${{ env.API_BASE_URL }}
|
||||
push: true
|
||||
tags: |
|
||||
${{ env.REGISTRY }}/${{ env.WEB_IMAGE }}:latest
|
||||
${{ env.REGISTRY }}/${{ env.WEB_IMAGE }}:${{ env.SHORT_SHA }}
|
||||
cache-from: type=registry,ref=${{ env.REGISTRY }}/${{ env.WEB_IMAGE }}:buildcache
|
||||
cache-to: type=registry,ref=${{ env.REGISTRY }}/${{ env.WEB_IMAGE }}:buildcache,mode=max
|
||||
|
||||
- name: Build & push API image
|
||||
uses: docker/build-push-action@v5
|
||||
with:
|
||||
context: ./server
|
||||
file: ./server/Dockerfile
|
||||
push: true
|
||||
tags: |
|
||||
${{ env.REGISTRY }}/${{ env.API_IMAGE }}:latest
|
||||
${{ env.REGISTRY }}/${{ env.API_IMAGE }}:${{ env.SHORT_SHA }}
|
||||
cache-from: type=registry,ref=${{ env.REGISTRY }}/${{ env.API_IMAGE }}:buildcache
|
||||
cache-to: type=registry,ref=${{ env.REGISTRY }}/${{ env.API_IMAGE }}:buildcache,mode=max
|
||||
|
||||
- name: Set up kubectl
|
||||
uses: azure/setup-kubectl@v4
|
||||
with:
|
||||
version: "v1.29.0"
|
||||
|
||||
- name: Configure kubeconfig
|
||||
run: |
|
||||
mkdir -p $HOME/.kube
|
||||
echo "${{ secrets.KUBE_CONFIG }}" | base64 -d > $HOME/.kube/config
|
||||
chmod 600 $HOME/.kube/config
|
||||
|
||||
- name: Ensure namespace, registry & DB secrets
|
||||
run: |
|
||||
kubectl apply -f deploy/k8s/namespace.yaml
|
||||
|
||||
kubectl -n insurance create secret docker-registry gitea-registry \
|
||||
--docker-server=${{ env.REGISTRY }} \
|
||||
--docker-username=${{ secrets.REGISTRY_USER }} \
|
||||
--docker-password=${{ secrets.REGISTRY_TOKEN }} \
|
||||
--dry-run=client -o yaml | kubectl apply -f -
|
||||
|
||||
kubectl -n insurance create secret generic postgres-credentials \
|
||||
--from-literal=username=insurance \
|
||||
--from-literal=password='${{ secrets.POSTGRES_PASSWORD }}' \
|
||||
--dry-run=client -o yaml | kubectl apply -f -
|
||||
|
||||
kubectl -n insurance create secret generic api-secrets \
|
||||
--from-literal=jwtSecret='${{ secrets.JWT_SECRET }}' \
|
||||
--from-literal=databaseUrl="postgresql://insurance:${{ secrets.POSTGRES_PASSWORD }}@postgres:5432/insurance?schema=public" \
|
||||
--dry-run=client -o yaml | kubectl apply -f -
|
||||
|
||||
- name: Deploy Postgres
|
||||
run: kubectl apply -f deploy/k8s/postgres.yaml
|
||||
|
||||
- name: Wait for Postgres
|
||||
run: kubectl -n insurance rollout status statefulset/postgres --timeout=180s
|
||||
|
||||
- name: Deploy API
|
||||
run: |
|
||||
kubectl apply -f deploy/k8s/api.yaml
|
||||
kubectl -n insurance set image deployment/insurance-api \
|
||||
api=${{ env.REGISTRY }}/${{ env.API_IMAGE }}:${{ env.SHORT_SHA }}
|
||||
kubectl -n insurance rollout status deployment/insurance-api --timeout=240s
|
||||
|
||||
- name: Deploy Web
|
||||
run: |
|
||||
kubectl apply -f deploy/k8s/deployment.yaml
|
||||
kubectl apply -f deploy/k8s/service.yaml
|
||||
if [ "${{ secrets.INGRESS_MODE }}" = "ingressroute" ]; then
|
||||
kubectl apply -f deploy/k8s/ingressroute-traefik.yaml
|
||||
else
|
||||
kubectl apply -f deploy/k8s/ingress.yaml
|
||||
fi
|
||||
kubectl -n insurance set image deployment/insurance-web \
|
||||
web=${{ env.REGISTRY }}/${{ env.WEB_IMAGE }}:${{ env.SHORT_SHA }}
|
||||
kubectl -n insurance rollout status deployment/insurance-web --timeout=180s
|
||||
|
||||
- name: Show deployment info
|
||||
run: |
|
||||
kubectl -n insurance get deployment,statefulset,svc,ingress,pvc
|
||||
echo ""
|
||||
echo "🚀 Web: https://insurance.junggomoa.com"
|
||||
echo "🔌 API: https://api.insurance.junggomoa.com"
|
||||
host: ${{ secrets.SSH_HOST }}
|
||||
port: ${{ secrets.SSH_PORT || 22 }}
|
||||
username: ${{ secrets.SSH_USER }}
|
||||
password: ${{ secrets.SSH_PASSWORD }}
|
||||
command_timeout: 20m
|
||||
script: |
|
||||
set -e
|
||||
cd /home/chpark
|
||||
if [ ! -d insurance/.git ]; then
|
||||
git clone https://git.junggomoa.com/chpark/insurance.git
|
||||
fi
|
||||
cd insurance
|
||||
git fetch origin
|
||||
git reset --hard origin/master
|
||||
chmod +x scripts/deploy-remote.sh
|
||||
bash scripts/deploy-remote.sh
|
||||
|
||||
Reference in New Issue
Block a user