From 741ab58a839028b15df5ad82cd217bf4e82be4b2 Mon Sep 17 00:00:00 2001 From: thiennatra Date: Tue, 14 Apr 2026 11:30:26 +0700 Subject: [PATCH] ci: add GitHub Actions workflow --- .dockerignore | 8 +++ .github/workflows/ci-cd.yml | 115 ++++++++++++++++++++++++++++++++++++ Dockerfile | 23 ++++++++ summary-flow.md | 11 ++++ 4 files changed, 157 insertions(+) create mode 100644 .dockerignore create mode 100644 .github/workflows/ci-cd.yml create mode 100644 Dockerfile create mode 100644 summary-flow.md diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..eef6232 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,8 @@ +.git +.github +node_modules +**/node_modules +**/dist +**/coverage +**/*.log +.DS_Store diff --git a/.github/workflows/ci-cd.yml b/.github/workflows/ci-cd.yml new file mode 100644 index 0000000..8e3235b --- /dev/null +++ b/.github/workflows/ci-cd.yml @@ -0,0 +1,115 @@ +name: CI-CD +run-name: >- + ${{ github.event_name == 'pull_request' && format('Merge PR #{0}: {1}', github.event.pull_request.number, github.event.pull_request.title) || format('Manual run by {0}', github.actor) }} + +on: + pull_request: + types: [closed] + branches: ["main"] + workflow_dispatch: + +env: + SERVICE_NAME: tracking-api + +permissions: + contents: read + +jobs: + quality-gate: + runs-on: ubuntu-latest + if: ${{ github.event_name == 'workflow_dispatch' || github.event.pull_request.merged == true }} + steps: + - uses: actions/checkout@v4 + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: '20' + cache: 'npm' + + - name: Install dependencies + run: npm ci + + - name: Security Audit (non-blocking) + run: npm audit --audit-level=high || echo "Audit found vulnerabilities, please review." + + - name: Tests + run: TEST_DATABASE_URL= npm run -w @tracking-base/tracking-api test + + - name: Build API + run: npm run -w @tracking-base/tracking-api build + + deploy-gate: + name: Deploy Gate + runs-on: ubuntu-latest + needs: [quality-gate] + if: ${{ github.event_name == 'workflow_dispatch' || github.event.pull_request.merged == true }} + steps: + - run: echo "Ready for build/push (merge or manual trigger)" + + build-and-push: + name: Build and Push Docker + runs-on: ubuntu-latest + needs: [deploy-gate] + if: ${{ github.event_name == 'workflow_dispatch' || github.event.pull_request.merged == true }} + permissions: + contents: read + packages: write + outputs: + version: ${{ steps.version.outputs.version }} + image: ${{ steps.version.outputs.image }} + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Extract version + id: version + run: | + SHORT_SHA=$(echo ${{ github.event.pull_request.merge_commit_sha || github.sha }} | cut -c1-7) + VERSION="staging-${SHORT_SHA}" + REGISTRY_IMAGE="ghcr.io/$(echo ${{ github.repository }} | tr '[:upper:]' '[:lower:]')/${{ env.SERVICE_NAME }}" + echo "version=${VERSION}" >> $GITHUB_OUTPUT + echo "image=${REGISTRY_IMAGE}:${VERSION}" >> $GITHUB_OUTPUT + echo "REGISTRY_IMAGE=${REGISTRY_IMAGE}" >> $GITHUB_ENV + echo "📦 Version: ${VERSION}" + echo "🐳 Image: ${REGISTRY_IMAGE}:${VERSION}" + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Log in to GHCR + uses: docker/login-action@v3 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Extract metadata + id: meta + uses: docker/metadata-action@v5 + with: + images: ${{ env.REGISTRY_IMAGE }} + tags: | + type=raw,value=${{ steps.version.outputs.version }} + + - name: Build and push Docker image + uses: docker/build-push-action@v5 + with: + context: . + file: Dockerfile + push: true + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} + cache-from: type=gha + cache-to: type=gha,mode=max + + - name: Summary + run: | + echo "### ✅ Build and Push Completed" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + echo "| Property | Value |" >> $GITHUB_STEP_SUMMARY + echo "|----------|-------|" >> $GITHUB_STEP_SUMMARY + echo "| Service | ${{ env.SERVICE_NAME }} |" >> $GITHUB_STEP_SUMMARY + echo "| Version | ${{ steps.version.outputs.version }} |" >> $GITHUB_STEP_SUMMARY + echo "| Image | ${{ steps.version.outputs.image }} |" >> $GITHUB_STEP_SUMMARY diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..a933b24 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,23 @@ +FROM node:20-alpine AS builder + +WORKDIR /app + +COPY . . +RUN npm ci +RUN npm run -w @tracking-base/tracking-api build +RUN npm prune --omit=dev + +FROM node:20-alpine AS runtime + +WORKDIR /app +ENV NODE_ENV=production + +COPY --from=builder /app/package.json ./package.json +COPY --from=builder /app/package-lock.json ./package-lock.json +COPY --from=builder /app/node_modules ./node_modules +COPY --from=builder /app/apps/tracking-api/package.json ./apps/tracking-api/package.json +COPY --from=builder /app/apps/tracking-api/dist ./apps/tracking-api/dist + +EXPOSE 3000 + +CMD ["node", "apps/tracking-api/dist/server.js"] diff --git a/summary-flow.md b/summary-flow.md new file mode 100644 index 0000000..e6fc3e5 --- /dev/null +++ b/summary-flow.md @@ -0,0 +1,11 @@ + +Tracking_Base_System là hệ thống trung tâm để nhận event tracking, lưu 1 bản chuẩn, rồi đẩy sang Meta/Google/TikTok. + +Flow rất ngắn: + +App/web khác gửi event vào POST /track. +API kiểm tra dữ liệu, tạo/giữ event_id, chống trùng. +Event được lưu vào DB làm nguồn dữ liệu chuẩn. +Job được đưa vào hàng đợi. +Worker lấy job, gửi sang các nền tảng đích, cập nhật trạng thái queued/success/failed. +Frontend console dùng để xem event, lọc, xem chi tiết, và replay event lỗi. \ No newline at end of file