From dc8bd8fe470843b412214b0e1890d0ae63cf4033 Mon Sep 17 00:00:00 2001 From: hiondal Date: Wed, 1 Oct 2025 11:12:48 +0900 Subject: [PATCH] =?UTF-8?q?ArgoCD=20=EA=B8=B0=EB=B0=98=20CI/CD=20=ED=8C=8C?= =?UTF-8?q?=EC=9D=B4=ED=94=84=EB=9D=BC=EC=9D=B8=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - GitHub Actions 워크플로우 파일 추가 - 빌드, 테스트, 이미지 생성 자동화 - ArgoCD 동기화 트리거 구성 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- .claude/settings.local.json | 3 +- .github/workflows/backend-cicd_ArgoCD.yaml | 255 +++++++++++++++++++++ 2 files changed, 257 insertions(+), 1 deletion(-) create mode 100644 .github/workflows/backend-cicd_ArgoCD.yaml diff --git a/.claude/settings.local.json b/.claude/settings.local.json index 6d918e7..e172f48 100644 --- a/.claude/settings.local.json +++ b/.claude/settings.local.json @@ -4,7 +4,8 @@ "Bash(mkdir:*)", "Bash(chmod:*)", "Bash(sed:*)", - "Bash(find:*)" + "Bash(find:*)", + "Bash(git add:*)" ], "deny": [], "ask": [] diff --git a/.github/workflows/backend-cicd_ArgoCD.yaml b/.github/workflows/backend-cicd_ArgoCD.yaml new file mode 100644 index 0000000..ce3df94 --- /dev/null +++ b/.github/workflows/backend-cicd_ArgoCD.yaml @@ -0,0 +1,255 @@ +name: Backend Services CI/CD (ArgoCD) + +on: + push: + branches: [ main, develop ] + paths: + - 'api-gateway/**' + - 'user-service/**' + - 'bill-service/**' + - 'product-service/**' + - 'kos-mock/**' + - 'common/**' + - '.github/**' + pull_request: + branches: [ main ] + workflow_dispatch: + inputs: + ENVIRONMENT: + description: 'Target environment' + required: true + default: 'dev' + type: choice + options: + - dev + - staging + - prod + SKIP_SONARQUBE: + description: 'Skip SonarQube Analysis' + required: false + default: 'true' + type: choice + options: + - 'true' + - 'false' + +env: + REGISTRY: acrdigitalgarage01.azurecr.io + IMAGE_ORG: phonebill + RESOURCE_GROUP: rg-digitalgarage-01 + AKS_CLUSTER: aks-digitalgarage-01 + NAMESPACE: phonebill-dg0500 + +jobs: + build: + name: Build and Test + runs-on: ubuntu-latest + outputs: + #image_tag: ${{ steps.set_outputs.outputs.image_tag }} + image_tag: dg0500 + environment: ${{ steps.set_outputs.outputs.environment }} + + steps: + - name: Check out code + uses: actions/checkout@v4 + + - name: Set up JDK 21 + uses: actions/setup-java@v3 + with: + java-version: '21' + distribution: 'temurin' + cache: 'gradle' + + - name: Determine environment + id: determine_env + run: | + # Use input parameter or default to 'dev' + ENVIRONMENT="${{ github.event.inputs.ENVIRONMENT || 'dev' }}" + echo "environment=$ENVIRONMENT" >> $GITHUB_OUTPUT + + - name: Load environment variables + id: env_vars + run: | + ENV=${{ steps.determine_env.outputs.environment }} + + # Initialize variables with defaults + REGISTRY="acrdigitalgarage01.azurecr.io" + IMAGE_ORG="phonebill" + RESOURCE_GROUP="rg-digitalgarage-01" + AKS_CLUSTER="aks-digitalgarage-01" + NAMESPACE="phonebill-dg0500" + + # Read environment variables from .github/config file + if [[ -f ".github/config/deploy_env_vars_${ENV}" ]]; then + while IFS= read -r line || [[ -n "$line" ]]; do + # Skip comments and empty lines + [[ "$line" =~ ^#.*$ ]] && continue + [[ -z "$line" ]] && continue + + # Extract key-value pairs + key=$(echo "$line" | cut -d '=' -f1) + value=$(echo "$line" | cut -d '=' -f2-) + + # Override defaults if found in config + case "$key" in + "resource_group") RESOURCE_GROUP="$value" ;; + "cluster_name") AKS_CLUSTER="$value" ;; + esac + done < ".github/config/deploy_env_vars_${ENV}" + fi + + # Export for other jobs + echo "REGISTRY=$REGISTRY" >> $GITHUB_ENV + echo "IMAGE_ORG=$IMAGE_ORG" >> $GITHUB_ENV + echo "RESOURCE_GROUP=$RESOURCE_GROUP" >> $GITHUB_ENV + echo "AKS_CLUSTER=$AKS_CLUSTER" >> $GITHUB_ENV + + - name: Grant execute permission for gradlew + run: chmod +x gradlew + + - name: Build with Gradle + run: | + ./gradlew build -x test + + - name: SonarQube Analysis & Quality Gate + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} + SONAR_HOST_URL: ${{ secrets.SONAR_HOST_URL }} + run: | + # Check if SonarQube should be skipped + SKIP_SONARQUBE="${{ github.event.inputs.SKIP_SONARQUBE || 'true' }}" + + if [[ "$SKIP_SONARQUBE" == "true" ]]; then + echo "⏭️ Skipping SonarQube Analysis (SKIP_SONARQUBE=$SKIP_SONARQUBE)" + exit 0 + fi + + # Define services array + services=(api-gateway user-service bill-service product-service kos-mock) + + # Run tests, coverage reports, and SonarQube analysis for each service + for service in "${services[@]}"; do + ./gradlew :$service:test :$service:jacocoTestReport :$service:sonar \ + -Dsonar.projectKey=phonebill-$service-${{ steps.determine_env.outputs.environment }} \ + -Dsonar.projectName=phonebill-$service-${{ steps.determine_env.outputs.environment }} \ + -Dsonar.host.url=$SONAR_HOST_URL \ + -Dsonar.token=$SONAR_TOKEN \ + -Dsonar.java.binaries=build/classes/java/main \ + -Dsonar.coverage.jacoco.xmlReportPaths=build/reports/jacoco/test/jacocoTestReport.xml \ + -Dsonar.exclusions=**/config/**,**/entity/**,**/dto/**,**/*Application.class,**/exception/** + done + + - name: Upload build artifacts + uses: actions/upload-artifact@v4 + with: + name: app-builds + path: | + api-gateway/build/libs/*.jar + user-service/build/libs/*.jar + bill-service/build/libs/*.jar + product-service/build/libs/*.jar + kos-mock/build/libs/*.jar + + - name: Set outputs + id: set_outputs + run: | + # Generate timestamp for image tag + IMAGE_TAG=$(date +%Y%m%d%H%M%S) + echo "image_tag=$IMAGE_TAG" >> $GITHUB_OUTPUT + echo "environment=${{ steps.determine_env.outputs.environment }}" >> $GITHUB_OUTPUT + + release: + name: Build and Push Docker Images + needs: build + runs-on: ubuntu-latest + + steps: + - name: Check out code + uses: actions/checkout@v4 + + - name: Download build artifacts + uses: actions/download-artifact@v4 + with: + name: app-builds + + - name: Set environment variables from build job + run: | + echo "REGISTRY=${{ env.REGISTRY }}" >> $GITHUB_ENV + echo "IMAGE_ORG=${{ env.IMAGE_ORG }}" >> $GITHUB_ENV + echo "ENVIRONMENT=${{ needs.build.outputs.environment }}" >> $GITHUB_ENV + echo "IMAGE_TAG=${{ needs.build.outputs.image_tag }}" >> $GITHUB_ENV + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Login to Docker Hub (prevent rate limit) + uses: docker/login-action@v3 + with: + username: ${{ secrets.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_PASSWORD }} + + - name: Login to Azure Container Registry + uses: docker/login-action@v3 + with: + registry: ${{ env.REGISTRY }} + username: ${{ secrets.ACR_USERNAME }} + password: ${{ secrets.ACR_PASSWORD }} + + - name: Build and push Docker images for all services + run: | + # Define services array + services=(api-gateway user-service bill-service product-service kos-mock) + + # Build and push each service image + for service in "${services[@]}"; do + echo "Building and pushing $service..." + docker build \ + --build-arg BUILD_LIB_DIR="$service/build/libs" \ + --build-arg ARTIFACTORY_FILE="$service.jar" \ + -f deployment/container/Dockerfile-backend \ + -t ${{ env.REGISTRY }}/${{ env.IMAGE_ORG }}/$service:${{ needs.build.outputs.environment }}-${{ needs.build.outputs.image_tag }} . + + docker push ${{ env.REGISTRY }}/${{ env.IMAGE_ORG }}/$service:${{ needs.build.outputs.environment }}-${{ needs.build.outputs.image_tag }} + done + + update-manifest: + name: Update Manifest Repository + needs: [build, release] + runs-on: ubuntu-latest + + steps: + - name: Set image tag environment variable + run: | + echo "IMAGE_TAG=${{ needs.build.outputs.image_tag }}" >> $GITHUB_ENV + echo "ENVIRONMENT=${{ needs.build.outputs.environment }}" >> $GITHUB_ENV + + - name: Update Manifest Repository + run: | + # 매니페스트 레포지토리 클론 + REPO_URL=$(echo "https://github.com/cna-bootcamp/phonebill-manifest.git" | sed 's|https://||') + git clone https://${{ secrets.GIT_USERNAME }}:${{ secrets.GIT_PASSWORD }}@${REPO_URL} manifest-repo + cd manifest-repo + + # Kustomize 설치 + curl -s "https://raw.githubusercontent.com/kubernetes-sigs/kustomize/master/hack/install_kustomize.sh" | bash + sudo mv kustomize /usr/local/bin/ + + # 매니페스트 업데이트 + cd phonebill/kustomize/overlays/${{ env.ENVIRONMENT }} + + # 각 서비스별 이미지 태그 업데이트 + services="api-gateway user-service bill-service product-service kos-mock" + for service in $services; do + kustomize edit set image acrdigitalgarage01.azurecr.io/phonebill/$service:${{ env.ENVIRONMENT }}-${{ env.IMAGE_TAG }} + done + + # Git 설정 및 푸시 + cd ../../../.. + git config user.name "GitHub Actions" + git config user.email "actions@github.com" + git add . + git commit -m "🚀 Update phonebill ${{ env.ENVIRONMENT }} images to ${{ env.ENVIRONMENT }}-${{ env.IMAGE_TAG }}" + git push origin main + + echo "✅ 매니페스트 업데이트 완료. ArgoCD가 자동으로 배포합니다."