CD: เพิ่ม workflow uat.yml deploy เครื่อง UAT — mirror build.yml ทุกอย่าง เปลี่ยนตัวเดียว: DEPLOY_HOST อ่านจาก vars.SSH_UAT_DEPLOY_HOST ใหม่ (ตั้งเพิ่มใน Forgejo ก่อนใช้ ไม่งั้น deploy job SSH ไป string ว่าง) — trigger tag v*.*.* เดิม (push tag เดียว deploy Test + UAT พร้อมกัน), registry/image เดิม push :v* และ :latest ซ้ำกัน (commit เดียวกัน เนื้อหาเหมือน ไม่ชนกัน), SSH user/port/password ชุดเดิม, script ~/repo/replace-env.sh + deploy.sh เดิม (เครื่อง UAT ต้องมีไฟล์สองตัวนี้ + รับ credentials เดิม), Discord webhook/Web URL ตัวเดิม — เปลี่ยนเฉพาะข้อความ workflow/job/notification เป็น "UAT" ให้แยก notification สองเครื่องได้
Co-Authored-By: Claude Code <noreply@anthropic.com>
This commit is contained in:
parent
6940b3870d
commit
2f260e0f3b
1 changed files with 249 additions and 0 deletions
249
.forgejo/workflows/uat.yml
Normal file
249
.forgejo/workflows/uat.yml
Normal file
|
|
@ -0,0 +1,249 @@
|
|||
name: Deploy eCourt Note Web to UAT Server
|
||||
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- "v*.*.*"
|
||||
workflow_dispatch:
|
||||
|
||||
env:
|
||||
# Container Registry
|
||||
REGISTRY_URL: ${{ vars.CONTAINER_REGISTRY }}
|
||||
REGISTRY_USERNAME: ${{ vars.CONTAINER_REGISTRY_USERNAME }}
|
||||
REGISTRY_PASSWORD: ${{ secrets.CONTAINER_REGISTRY_PASSWORD }}
|
||||
|
||||
# Docker Image
|
||||
WEB_IMAGE_NAME: chamomind/ecourt-note
|
||||
IMAGE_TAG: ${{ github.ref_name }}
|
||||
|
||||
# SSH Deployment — ต่างจาก build.yml ตัวเดียว: ชี้เครื่อง UAT (ตั้ง vars.SSH_UAT_DEPLOY_HOST เพิ่มใน Forgejo)
|
||||
DEPLOY_HOST: ${{ vars.SSH_UAT_DEPLOY_HOST }}
|
||||
DEPLOY_USER: ${{ vars.SSH_DEPLOY_USER }}
|
||||
|
||||
# Notifications
|
||||
DISCORD_WEBHOOK_URL: ${{ vars.DISCORD_WEBHOOK_URL }}
|
||||
NEXT_PUBLIC_APP_URL: ${{ vars.NEXT_PUBLIC_APP_URL }}
|
||||
|
||||
jobs:
|
||||
validate-schema:
|
||||
name: Validate Database Schema (Drizzle)
|
||||
runs-on: ubuntu-latest
|
||||
if: startsWith(github.ref, 'refs/tags/')
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Verify tag is on dev branch
|
||||
run: |
|
||||
echo "======================================================"
|
||||
echo "Verifying tag is pushed to dev branch"
|
||||
echo "======================================================"
|
||||
echo "Tag: ${{ github.ref_name }}"
|
||||
echo "Commit: ${{ github.sha }}"
|
||||
|
||||
# Fetch dev branch
|
||||
git fetch origin dev
|
||||
|
||||
# Check if the tag's commit is on dev branch
|
||||
if git branch -r --contains ${{ github.sha }} | grep -q "origin/dev"; then
|
||||
echo "✅ Tag is on dev branch"
|
||||
echo "test_branch=true" >> $GITHUB_ENV
|
||||
else
|
||||
echo "❌ Tag is NOT on dev branch"
|
||||
echo "This workflow only triggers for tags pushed to dev branch"
|
||||
echo ""
|
||||
echo "Current branches containing this commit:"
|
||||
git branch -r --contains ${{ github.sha }}
|
||||
exit 1
|
||||
fi
|
||||
|
||||
- name: Check for schema changes
|
||||
id: schema-check
|
||||
run: |
|
||||
# โปรเจกต์นี้ใช้ Drizzle (drizzle-kit push) ไม่มีโฟลเดอร์ migrations — ดูการเปลี่ยนแปลงที่ db/schema.ts
|
||||
if git diff --name-only origin/dev...HEAD | grep -qE "^db/schema\.ts$"; then
|
||||
echo "has_schema_changes=true" >> $GITHUB_OUTPUT
|
||||
echo "✅ Schema changes detected"
|
||||
else
|
||||
echo "has_schema_changes=false" >> $GITHUB_OUTPUT
|
||||
echo "ℹ️ No schema changes"
|
||||
fi
|
||||
|
||||
- name: Schema change summary
|
||||
if: steps.schema-check.outputs.has_schema_changes == 'true'
|
||||
run: |
|
||||
echo "=== Schema Change Summary ==="
|
||||
echo ""
|
||||
echo "Database schema (db/schema.ts) has been modified in this deployment."
|
||||
echo "This project uses Drizzle push (no migration files)."
|
||||
echo ""
|
||||
echo "⚠️ REMINDERS:"
|
||||
echo " 1. Run 'npx drizzle-kit push' on the target database (staging first)"
|
||||
echo " 2. Monitor logs after deployment"
|
||||
echo ""
|
||||
echo "📚 Reference: README.md / docs/PLAN.md §3"
|
||||
|
||||
build:
|
||||
name: Build Web Docker Image
|
||||
runs-on: ubuntu-latest
|
||||
needs: validate-schema
|
||||
if: startsWith(github.ref, 'refs/tags/')
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Log in to Container Registry
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: ${{ env.REGISTRY_URL }}
|
||||
username: ${{ env.REGISTRY_USERNAME }}
|
||||
password: ${{ env.REGISTRY_PASSWORD }}
|
||||
|
||||
- name: Build Docker image (no buildx)
|
||||
run: |
|
||||
# Build using standard docker build (not buildx)
|
||||
git reset --hard HEAD
|
||||
cd ${{ github.workspace }}
|
||||
docker build \
|
||||
--no-cache \
|
||||
--pull \
|
||||
--file ./docker/web.Dockerfile \
|
||||
--tag ${{ env.REGISTRY_URL }}/${{ env.WEB_IMAGE_NAME }}:${{ env.IMAGE_TAG }} \
|
||||
--tag ${{ env.REGISTRY_URL }}/${{ env.WEB_IMAGE_NAME }}:latest \
|
||||
.
|
||||
|
||||
echo "✅ Build successful!"
|
||||
docker images | grep ${{ env.WEB_IMAGE_NAME }}
|
||||
|
||||
- name: Push Docker image
|
||||
run: |
|
||||
docker push ${{ env.REGISTRY_URL }}/${{ env.WEB_IMAGE_NAME }}:${{ env.IMAGE_TAG }}
|
||||
docker push ${{ env.REGISTRY_URL }}/${{ env.WEB_IMAGE_NAME }}:latest
|
||||
echo "✅ Image pushed to registry"
|
||||
|
||||
- name: Test image can run
|
||||
run: |
|
||||
# Quick test that image can start
|
||||
docker run --rm ${{ env.REGISTRY_URL }}/${{ env.WEB_IMAGE_NAME }}:${{ env.IMAGE_TAG }} node --version
|
||||
|
||||
deploy:
|
||||
name: Deploy eCourt Note Web to UAT Server
|
||||
runs-on: ubuntu-latest
|
||||
needs: build
|
||||
if: startsWith(github.ref, 'refs/tags/')
|
||||
steps:
|
||||
- name: Deploy web on UAT server
|
||||
uses: appleboy/ssh-action@v1.2.1
|
||||
with:
|
||||
host: ${{ env.DEPLOY_HOST }}
|
||||
port: ${{ vars.SSH_DEPLOY_PORT }}
|
||||
username: ${{ env.DEPLOY_USER }}
|
||||
password: ${{ secrets.SSH_DEPLOY_PASSWORD }}
|
||||
script: |
|
||||
cd ~/repo
|
||||
|
||||
chmod +x ./replace-env.sh ./deploy.sh
|
||||
./replace-env.sh ECOURT_NOTE_TAG "${{ env.IMAGE_TAG }}"
|
||||
./deploy.sh
|
||||
|
||||
notify:
|
||||
name: Notify Deployment Status
|
||||
runs-on: ubuntu-latest
|
||||
needs: [build, deploy]
|
||||
if: always()
|
||||
steps:
|
||||
- name: Send Discord notification - Success
|
||||
if: ${{ needs.deploy.result == 'success' }}
|
||||
run: |
|
||||
curl -H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"embeds": [{
|
||||
"title": "✅ eCourt Note UAT Deployment Successful",
|
||||
"description": "eCourt Note Web deployed to UAT server",
|
||||
"color": 3066993,
|
||||
"fields": [
|
||||
{
|
||||
"name": "Environment",
|
||||
"value": "UAT",
|
||||
"inline": true
|
||||
},
|
||||
{
|
||||
"name": "Tag",
|
||||
"value": "${{ github.ref_name }}",
|
||||
"inline": true
|
||||
},
|
||||
{
|
||||
"name": "Commit",
|
||||
"value": "`${{ github.sha }}`",
|
||||
"inline": false
|
||||
},
|
||||
{
|
||||
"name": "Image Tag",
|
||||
"value": "`${{ env.IMAGE_TAG }}`",
|
||||
"inline": true
|
||||
},
|
||||
{
|
||||
"name": "Web URL",
|
||||
"value": "${{ env.NEXT_PUBLIC_APP_URL }}",
|
||||
"inline": false
|
||||
},
|
||||
{
|
||||
"name": "Deployed By",
|
||||
"value": "${{ github.actor }}",
|
||||
"inline": true
|
||||
}
|
||||
],
|
||||
"footer": {
|
||||
"text": "eCourt Note CD Pipeline"
|
||||
},
|
||||
"timestamp": "'"$(date -u +%Y-%m-%dT%H:%M:%S.000Z)"'"
|
||||
}]
|
||||
}' \
|
||||
${{ env.DISCORD_WEBHOOK_URL }}
|
||||
|
||||
- name: Send Discord notification - Failure
|
||||
if: ${{ needs.deploy.result == 'failure' || needs.build.result == 'failure' }}
|
||||
run: |
|
||||
curl -H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"embeds": [{
|
||||
"title": "❌ eCourt Note UAT Deployment Failed",
|
||||
"description": "Failed to deploy eCourt Note Web to UAT server",
|
||||
"color": 15158332,
|
||||
"fields": [
|
||||
{
|
||||
"name": "Environment",
|
||||
"value": "UAT",
|
||||
"inline": true
|
||||
},
|
||||
{
|
||||
"name": "Tag",
|
||||
"value": "${{ github.ref_name }}",
|
||||
"inline": true
|
||||
},
|
||||
{
|
||||
"name": "Commit",
|
||||
"value": "`${{ github.sha }}`",
|
||||
"inline": false
|
||||
},
|
||||
{
|
||||
"name": "Failed Job",
|
||||
"value": "${{ needs.build.result == 'failure' && 'Build' || 'Deploy' }}",
|
||||
"inline": true
|
||||
},
|
||||
{
|
||||
"name": "Deployed By",
|
||||
"value": "${{ github.actor }}",
|
||||
"inline": true
|
||||
}
|
||||
],
|
||||
"footer": {
|
||||
"text": "eCourt Note CD Pipeline"
|
||||
},
|
||||
"timestamp": "'"$(date -u +%Y-%m-%dT%H:%M:%S.000Z)"'"
|
||||
}]
|
||||
}' \
|
||||
${{ env.DISCORD_WEBHOOK_URL }}
|
||||
exit 1
|
||||
Loading…
Add table
Add a link
Reference in a new issue