diff --git a/.github/workflows/deploy-gcloud.yml b/.github/workflows/deploy-gcloud.yml new file mode 100644 index 0000000..9701237 --- /dev/null +++ b/.github/workflows/deploy-gcloud.yml @@ -0,0 +1,156 @@ +name: Deploy to Google Cloud Artifact Registry + +on: + push: + branches: + - main + - develop + paths: + - 'src/**' + - 'appsettings*.json' + - 'Dockerfile' + - 'docker-compose.yml' + - '.github/workflows/deploy-gcloud.yml' + pull_request: + branches: + - main + paths: + - 'src/**' + - 'appsettings*.json' + - 'Dockerfile' + - 'docker-compose.yml' + workflow_dispatch: + inputs: + version_tag: + description: 'Custom version tag (optional, will use SHA if empty)' + required: false + type: string + +env: + PROJECT_ID: lucky-union-472503-c7 + REGION: asia-southeast1 + REPOSITORY: backendnetcore + IMAGE_NAME: webapi + SERVICE_NAME: legal-assistant-api + +jobs: + build-and-deploy: + runs-on: ubuntu-latest + permissions: + contents: read + id-token: write + + steps: + - name: Checkout code + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Generate version tag + id: version + run: | + if [ "${{ github.event_name }}" == "workflow_dispatch" ] && [ -n "${{ inputs.version_tag }}" ]; then + VERSION="${{ inputs.version_tag }}" + elif [ "${{ github.ref_type }}" == "tag" ]; then + VERSION="${{ github.ref_name }}" + else + # Use date + short SHA for immutable versioning + VERSION="$(date +%Y%m%d)-${GITHUB_SHA::7}" + fi + echo "VERSION=${VERSION}" >> $GITHUB_OUTPUT + echo "Generated version: ${VERSION}" + + - name: Authenticate to Google Cloud + uses: google-github-actions/auth@v2 + with: + credentials_json: ${{ secrets.GCP_SA_KEY }} + + - name: Set up Cloud SDK + uses: google-github-actions/setup-gcloud@v2 + + - name: Configure Docker for Artifact Registry + run: | + gcloud auth configure-docker ${{ env.REGION }}-docker.pkg.dev --quiet + + - name: Build Docker image + run: | + docker build -t ${{ env.IMAGE_NAME }}:latest -f src/Web.Api/Dockerfile . + + - name: Tag Docker image + run: | + REMOTE_IMAGE="${{ env.REGION }}-docker.pkg.dev/${{ env.PROJECT_ID }}/${{ env.REPOSITORY }}/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.VERSION }}" + REMOTE_IMAGE_LATEST="${{ env.REGION }}-docker.pkg.dev/${{ env.PROJECT_ID }}/${{ env.REPOSITORY }}/${{ env.IMAGE_NAME }}:latest" + + docker tag ${{ env.IMAGE_NAME }}:latest ${REMOTE_IMAGE} + docker tag ${{ env.IMAGE_NAME }}:latest ${REMOTE_IMAGE_LATEST} + + echo "REMOTE_IMAGE=${REMOTE_IMAGE}" >> $GITHUB_ENV + echo "REMOTE_IMAGE_LATEST=${REMOTE_IMAGE_LATEST}" >> $GITHUB_ENV + + - name: Push Docker image to Artifact Registry + run: | + docker push ${{ env.REMOTE_IMAGE }} + docker push ${{ env.REMOTE_IMAGE_LATEST }} + + - name: Deploy to Cloud Run (Production) + if: github.ref == 'refs/heads/main' && github.event_name == 'push' + run: | + gcloud run deploy ${{ env.SERVICE_NAME }} \ + --image ${{ env.REMOTE_IMAGE }} \ + --platform managed \ + --region ${{ env.REGION }} \ + --allow-unauthenticated \ + --memory 512Mi \ + --cpu 1 \ + --max-instances 10 \ + --min-instances 0 \ + --port 8080 \ + --set-env-vars "ASPNETCORE_ENVIRONMENT=Production" \ + --quiet + + - name: Deploy to Cloud Run (Staging) + if: github.ref == 'refs/heads/develop' && github.event_name == 'push' + run: | + gcloud run deploy ${{ env.SERVICE_NAME }}-staging \ + --image ${{ env.REMOTE_IMAGE }} \ + --platform managed \ + --region ${{ env.REGION }} \ + --allow-unauthenticated \ + --memory 512Mi \ + --cpu 1 \ + --max-instances 5 \ + --min-instances 0 \ + --port 8080 \ + --set-env-vars "ASPNETCORE_ENVIRONMENT=Staging" \ + --quiet + + - name: Output deployment info + run: | + echo "=== Deployment Complete ===" + echo "Version: ${{ steps.version.outputs.VERSION }}" + echo "Image: ${{ env.REMOTE_IMAGE }}" + echo "" + if [ "${{ github.ref }}" == "refs/heads/main" ]; then + SERVICE_URL=$(gcloud run services describe ${{ env.SERVICE_NAME }} --region ${{ env.REGION }} --format 'value(status.url)') + echo "Production URL: ${SERVICE_URL}" + elif [ "${{ github.ref }}" == "refs/heads/develop" ]; then + SERVICE_URL=$(gcloud run services describe ${{ env.SERVICE_NAME }}-staging --region ${{ env.REGION }} --format 'value(status.url)') + echo "Staging URL: ${SERVICE_URL}" + fi + + - name: Create deployment summary + run: | + echo "## Deployment Summary 🚀" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + echo "- **Version**: \`${{ steps.version.outputs.VERSION }}\`" >> $GITHUB_STEP_SUMMARY + echo "- **Image**: \`${{ env.REMOTE_IMAGE }}\`" >> $GITHUB_STEP_SUMMARY + echo "- **Branch**: \`${{ github.ref_name }}\`" >> $GITHUB_STEP_SUMMARY + echo "- **Commit**: \`${GITHUB_SHA::7}\`" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + if [ "${{ github.ref }}" == "refs/heads/main" ]; then + echo "- **Environment**: Production" >> $GITHUB_STEP_SUMMARY + elif [ "${{ github.ref }}" == "refs/heads/develop" ]; then + echo "- **Environment**: Staging" >> $GITHUB_STEP_SUMMARY + else + echo "- **Environment**: Image built only (no deployment)" >> $GITHUB_STEP_SUMMARY + fi diff --git a/scripts/ci-cd-deploy-gcloud.sh b/scripts/ci-cd-deploy-gcloud.sh new file mode 100644 index 0000000..a43bce0 --- /dev/null +++ b/scripts/ci-cd-deploy-gcloud.sh @@ -0,0 +1,5 @@ +#!/bin/bash +gcloud projects add-iam-policy-binding lucky-union-472503-c7 --member="serviceAccount:ci-cd-fucntions-hosting@lucky-union-472503-c7.iam.gserviceaccount.com" --role="roles/run.admin" + +# Tạo key cho service account +gcloud iam service-accounts keys create github-key.json --iam-account=ci-cd-fucntions-hosting@lucky-union-472503-c7.iam.gserviceaccount.com \ No newline at end of file