CD: uat.yml ไม่ build image เอง reuse ของ build.yml + ขึ้น UAT ผ่าน Forgejo UI ได้ — ลบ job build ทั้ง job (เดิม build ซ้ำทุกครั้ง) แทนด้วย steps ใหม่ใน deploy job: Resolve image tag map deploy1.2.3/1.2.3/v1.2.3 → v1.2.3 เสมอ (ตัด prefix deploy ตัด v เติม v กลับ — ใช้ image เดียวกับที่ build.yml push ตอน tag v*) + login registry + docker manifest inspect เช็ค image มีจริงก่อน SSH (fail-fast พร้อมข้อความบอกให้ push tag v* ก่อน ถ้ายังไม่มี) + workflow_dispatch เพิ่ม input version (required) — กด Run workflow ใน UI ใส่เวอร์ชันได้เลยไม่ต้องสร้าง tag deploy* (ทางเดิมยังใช้ได้) — deploy job เปิด if ให้รันกรณ้ dispatch (always() && !failure() && !cancelled() — ผ่านเมื่อ validate-schema success หรือ skip แต่ยัง block ถ้า fail เหมือนเดิม) + notify ถอด needs.build ที่ลบไป + field Tag โชว์เวอร์ชันจาก input ตอน dispatch แทนชื่อ branch + field Image Tag ดึงจาก output ของ deploy job — กติกาคงเดิม: image เกิดจาก build.yml ตอน push tag v* (deploy Test ไปด้วย) เท่านั้น UAT แค่ reuse — verify: js-yaml parse ผ่าน + ทดสอบ normalize ครบ 3 รูปแบบ (deploy1.2.3/v1.2.3/1.2.3 → v1.2.3)
Co-Authored-By: Claude Code <noreply@anthropic.com>
This commit is contained in:
parent
fa880b314e
commit
8ba911a119
1 changed files with 39 additions and 45 deletions
|
|
@ -5,6 +5,10 @@ on:
|
||||||
tags:
|
tags:
|
||||||
- "deploy*.*.*"
|
- "deploy*.*.*"
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
|
inputs:
|
||||||
|
version:
|
||||||
|
description: "เวอร์ชันที่จะ deploy เช่น 1.2.3 / v1.2.3 / deploy1.2.3 — จะ map เป็น image v1.2.3 (ต้อง push tag v1.2.3 ให้ build.yml build ไว้ก่อน)"
|
||||||
|
required: true
|
||||||
|
|
||||||
env:
|
env:
|
||||||
# Container Registry
|
# Container Registry
|
||||||
|
|
@ -12,11 +16,11 @@ env:
|
||||||
REGISTRY_USERNAME: ${{ vars.CONTAINER_REGISTRY_USERNAME }}
|
REGISTRY_USERNAME: ${{ vars.CONTAINER_REGISTRY_USERNAME }}
|
||||||
REGISTRY_PASSWORD: ${{ secrets.CONTAINER_REGISTRY_PASSWORD }}
|
REGISTRY_PASSWORD: ${{ secrets.CONTAINER_REGISTRY_PASSWORD }}
|
||||||
|
|
||||||
# Docker Image
|
# Docker Image — ไม่ build เอง ใช้ image เดียวกับที่ build.yml push ไว้
|
||||||
|
# (push tag deploy1.2.3 หรือ Run workflow จาก UI ใส่เวอร์ชัน → map เป็น image v1.2.3 เสมอ)
|
||||||
WEB_IMAGE_NAME: chamomind/ecourt-note
|
WEB_IMAGE_NAME: chamomind/ecourt-note
|
||||||
IMAGE_TAG: ${{ github.ref_name }}
|
|
||||||
|
|
||||||
# SSH Deployment — ต่างจาก build.yml ตัวเดียว: ชี้เครื่อง UAT (ตั้ง vars.SSH_UAT_DEPLOY_HOST เพิ่มใน Forgejo)
|
# SSH Deployment — ต่างจาก build.yml: ชี้เครื่อง UAT (ตั้ง vars.SSH_UAT_DEPLOY_HOST เพิ่มใน Forgejo) + ไม่ build image เอง
|
||||||
DEPLOY_HOST: ${{ vars.SSH_UAT_DEPLOY_HOST }}
|
DEPLOY_HOST: ${{ vars.SSH_UAT_DEPLOY_HOST }}
|
||||||
DEPLOY_USER: ${{ vars.SSH_DEPLOY_USER }}
|
DEPLOY_USER: ${{ vars.SSH_DEPLOY_USER }}
|
||||||
|
|
||||||
|
|
@ -85,14 +89,28 @@ jobs:
|
||||||
echo ""
|
echo ""
|
||||||
echo "📚 Reference: README.md / docs/PLAN.md §3"
|
echo "📚 Reference: README.md / docs/PLAN.md §3"
|
||||||
|
|
||||||
build:
|
deploy:
|
||||||
name: Build Web Docker Image
|
name: Deploy eCourt Note Web to UAT Server
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
needs: validate-schema
|
needs: validate-schema
|
||||||
if: startsWith(github.ref, 'refs/tags/')
|
# รันได้ 2 ทาง: push tag deploy*.*.* หรือกด Run workflow จาก UI (ใส่เวอร์ชันใน input)
|
||||||
|
# !failure() && !cancelled() = ผ่านได้เมื่อ validate-schema success หรือถูก skip (กรณี dispatch)
|
||||||
|
# แต่ยังไม่รันถ้า validate-schema fail (tag ไม่อยู่บน dev)
|
||||||
|
if: >-
|
||||||
|
always() && !failure() && !cancelled() &&
|
||||||
|
(startsWith(github.ref, 'refs/tags/') || github.event_name == 'workflow_dispatch')
|
||||||
|
outputs:
|
||||||
|
image_tag: ${{ steps.image-tag.outputs.tag }}
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout code
|
- name: Resolve image tag (deploy1.2.3 / v1.2.3 → v1.2.3)
|
||||||
uses: actions/checkout@v4
|
id: image-tag
|
||||||
|
run: |
|
||||||
|
RAW="${{ github.event_name == 'workflow_dispatch' && github.event.inputs.version || github.ref_name }}"
|
||||||
|
TAG="${RAW#deploy}"
|
||||||
|
TAG="${TAG#v}"
|
||||||
|
TAG="v$TAG"
|
||||||
|
echo "tag=$TAG" >> $GITHUB_OUTPUT
|
||||||
|
echo "Reuse image จาก build.yml: ${{ env.REGISTRY_URL }}/${{ env.WEB_IMAGE_NAME }}:$TAG"
|
||||||
|
|
||||||
- name: Log in to Container Registry
|
- name: Log in to Container Registry
|
||||||
uses: docker/login-action@v3
|
uses: docker/login-action@v3
|
||||||
|
|
@ -101,39 +119,15 @@ jobs:
|
||||||
username: ${{ env.REGISTRY_USERNAME }}
|
username: ${{ env.REGISTRY_USERNAME }}
|
||||||
password: ${{ env.REGISTRY_PASSWORD }}
|
password: ${{ env.REGISTRY_PASSWORD }}
|
||||||
|
|
||||||
- name: Build Docker image (no buildx)
|
- name: Verify image exists in registry
|
||||||
run: |
|
run: |
|
||||||
# Build using standard docker build (not buildx)
|
if ! docker manifest inspect "${{ env.REGISTRY_URL }}/${{ env.WEB_IMAGE_NAME }}:${{ steps.image-tag.outputs.tag }}" > /dev/null; then
|
||||||
git reset --hard HEAD
|
echo "❌ Image ${{ env.REGISTRY_URL }}/${{ env.WEB_IMAGE_NAME }}:${{ steps.image-tag.outputs.tag }} ไม่มีใน registry"
|
||||||
cd ${{ github.workspace }}
|
echo "workflow นี้ไม่ build เอง — push tag ${{ steps.image-tag.outputs.tag }} ก่อน เพื่อให้ build.yml build + push image ให้"
|
||||||
docker build \
|
exit 1
|
||||||
--no-cache \
|
fi
|
||||||
--pull \
|
echo "✅ Image found — deploy ด้วย image เดียวกับ build.yml"
|
||||||
--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
|
- name: Deploy web on UAT server
|
||||||
uses: appleboy/ssh-action@v1.2.1
|
uses: appleboy/ssh-action@v1.2.1
|
||||||
with:
|
with:
|
||||||
|
|
@ -145,13 +139,13 @@ jobs:
|
||||||
cd ~/repo
|
cd ~/repo
|
||||||
|
|
||||||
chmod +x ./replace-env.sh ./deploy.sh
|
chmod +x ./replace-env.sh ./deploy.sh
|
||||||
./replace-env.sh ECOURT_NOTE_TAG "${{ env.IMAGE_TAG }}"
|
./replace-env.sh ECOURT_NOTE_TAG "${{ steps.image-tag.outputs.tag }}"
|
||||||
./deploy.sh
|
./deploy.sh
|
||||||
|
|
||||||
notify:
|
notify:
|
||||||
name: Notify Deployment Status
|
name: Notify Deployment Status
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
needs: [build, deploy]
|
needs: [deploy]
|
||||||
if: always()
|
if: always()
|
||||||
steps:
|
steps:
|
||||||
- name: Send Discord notification - Success
|
- name: Send Discord notification - Success
|
||||||
|
|
@ -171,7 +165,7 @@ jobs:
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Tag",
|
"name": "Tag",
|
||||||
"value": "${{ github.ref_name }}",
|
"value": "${{ github.event_name == 'workflow_dispatch' && github.event.inputs.version || github.ref_name }}",
|
||||||
"inline": true
|
"inline": true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
@ -181,7 +175,7 @@ jobs:
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Image Tag",
|
"name": "Image Tag",
|
||||||
"value": "`${{ env.IMAGE_TAG }}`",
|
"value": "`${{ needs.deploy.outputs.image_tag }}`",
|
||||||
"inline": true
|
"inline": true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
@ -204,7 +198,7 @@ jobs:
|
||||||
${{ env.DISCORD_WEBHOOK_URL }}
|
${{ env.DISCORD_WEBHOOK_URL }}
|
||||||
|
|
||||||
- name: Send Discord notification - Failure
|
- name: Send Discord notification - Failure
|
||||||
if: ${{ needs.deploy.result == 'failure' || needs.build.result == 'failure' }}
|
if: ${{ needs.deploy.result == 'failure' }}
|
||||||
run: |
|
run: |
|
||||||
curl -H "Content-Type: application/json" \
|
curl -H "Content-Type: application/json" \
|
||||||
-d '{
|
-d '{
|
||||||
|
|
@ -230,7 +224,7 @@ jobs:
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Failed Job",
|
"name": "Failed Job",
|
||||||
"value": "${{ needs.build.result == 'failure' && 'Build' || 'Deploy' }}",
|
"value": "Deploy",
|
||||||
"inline": true
|
"inline": true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue