250 lines
8.6 KiB
YAML
250 lines
8.6 KiB
YAML
|
|
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
|