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:
|
||||
- "deploy*.*.*"
|
||||
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:
|
||||
# Container Registry
|
||||
|
|
@ -12,11 +16,11 @@ env:
|
|||
REGISTRY_USERNAME: ${{ vars.CONTAINER_REGISTRY_USERNAME }}
|
||||
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
|
||||
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_USER: ${{ vars.SSH_DEPLOY_USER }}
|
||||
|
||||
|
|
@ -85,14 +89,28 @@ jobs:
|
|||
echo ""
|
||||
echo "📚 Reference: README.md / docs/PLAN.md §3"
|
||||
|
||||
build:
|
||||
name: Build Web Docker Image
|
||||
deploy:
|
||||
name: Deploy eCourt Note Web to UAT Server
|
||||
runs-on: ubuntu-latest
|
||||
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:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
- name: Resolve image tag (deploy1.2.3 / v1.2.3 → v1.2.3)
|
||||
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
|
||||
uses: docker/login-action@v3
|
||||
|
|
@ -101,39 +119,15 @@ jobs:
|
|||
username: ${{ env.REGISTRY_USERNAME }}
|
||||
password: ${{ env.REGISTRY_PASSWORD }}
|
||||
|
||||
- name: Build Docker image (no buildx)
|
||||
- name: Verify image exists in registry
|
||||
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 \
|
||||
.
|
||||
if ! docker manifest inspect "${{ env.REGISTRY_URL }}/${{ env.WEB_IMAGE_NAME }}:${{ steps.image-tag.outputs.tag }}" > /dev/null; then
|
||||
echo "❌ Image ${{ env.REGISTRY_URL }}/${{ env.WEB_IMAGE_NAME }}:${{ steps.image-tag.outputs.tag }} ไม่มีใน registry"
|
||||
echo "workflow นี้ไม่ build เอง — push tag ${{ steps.image-tag.outputs.tag }} ก่อน เพื่อให้ build.yml build + push image ให้"
|
||||
exit 1
|
||||
fi
|
||||
echo "✅ Image found — deploy ด้วย image เดียวกับ build.yml"
|
||||
|
||||
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:
|
||||
|
|
@ -145,13 +139,13 @@ jobs:
|
|||
cd ~/repo
|
||||
|
||||
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
|
||||
|
||||
notify:
|
||||
name: Notify Deployment Status
|
||||
runs-on: ubuntu-latest
|
||||
needs: [build, deploy]
|
||||
needs: [deploy]
|
||||
if: always()
|
||||
steps:
|
||||
- name: Send Discord notification - Success
|
||||
|
|
@ -171,7 +165,7 @@ jobs:
|
|||
},
|
||||
{
|
||||
"name": "Tag",
|
||||
"value": "${{ github.ref_name }}",
|
||||
"value": "${{ github.event_name == 'workflow_dispatch' && github.event.inputs.version || github.ref_name }}",
|
||||
"inline": true
|
||||
},
|
||||
{
|
||||
|
|
@ -181,7 +175,7 @@ jobs:
|
|||
},
|
||||
{
|
||||
"name": "Image Tag",
|
||||
"value": "`${{ env.IMAGE_TAG }}`",
|
||||
"value": "`${{ needs.deploy.outputs.image_tag }}`",
|
||||
"inline": true
|
||||
},
|
||||
{
|
||||
|
|
@ -204,7 +198,7 @@ jobs:
|
|||
${{ env.DISCORD_WEBHOOK_URL }}
|
||||
|
||||
- name: Send Discord notification - Failure
|
||||
if: ${{ needs.deploy.result == 'failure' || needs.build.result == 'failure' }}
|
||||
if: ${{ needs.deploy.result == 'failure' }}
|
||||
run: |
|
||||
curl -H "Content-Type: application/json" \
|
||||
-d '{
|
||||
|
|
@ -230,7 +224,7 @@ jobs:
|
|||
},
|
||||
{
|
||||
"name": "Failed Job",
|
||||
"value": "${{ needs.build.result == 'failure' && 'Build' || 'Deploy' }}",
|
||||
"value": "Deploy",
|
||||
"inline": true
|
||||
},
|
||||
{
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue