Hotfix : 권한 추가 #176
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: CI | |
| on: | |
| push: | |
| branches: ["main"] | |
| permissions: | |
| contents: read | |
| jobs: | |
| build-and-push: | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v4 | |
| # -------------------------- | |
| # 0) Sanitize secrets (host/newlines) | |
| # -------------------------- | |
| - name: Sanitize connection vars | |
| id: sanitize | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| # SSH host: remove CR/LF, strip http(s):// prefix | |
| SSH_HOST_CLEAN="$(printf '%s' "${{ secrets.SSH_HOST }}" | tr -d '\r\n' | sed -E 's#^https?://##')" | |
| # OCIR vars: remove CR/LF | |
| OCIR_HOST_CLEAN="$(printf '%s' "${{ secrets.OCIR_HOST }}" | tr -d '\r\n')" | |
| OCIR_NS_CLEAN="$(printf '%s' "${{ secrets.OCIR_TENANCY_NAMESPACE }}" | tr -d '\r\n')" | |
| OCIR_REPO_CLEAN="$(printf '%s' "${{ secrets.OCIR_REPO }}" | tr -d '\r\n')" | |
| OCIR_USER_CLEAN="$(printf '%s' "${{ secrets.OCIR_USERNAME }}" | tr -d '\r\n')" | |
| # Validate minimal formats (fail fast) | |
| if [[ -z "$SSH_HOST_CLEAN" ]]; then | |
| echo "SSH_HOST is empty after sanitizing" >&2 | |
| exit 1 | |
| fi | |
| if [[ "$SSH_HOST_CLEAN" == *"/"* ]]; then | |
| echo "SSH_HOST should be only an IP/hostname, got: $SSH_HOST_CLEAN" >&2 | |
| exit 1 | |
| fi | |
| if [[ -z "$OCIR_HOST_CLEAN" || -z "$OCIR_NS_CLEAN" || -z "$OCIR_REPO_CLEAN" || -z "$OCIR_USER_CLEAN" ]]; then | |
| echo "One of OCIR secrets is empty after sanitizing" >&2 | |
| exit 1 | |
| fi | |
| echo "ssh_host=$SSH_HOST_CLEAN" >> "$GITHUB_OUTPUT" | |
| echo "ocir_host=$OCIR_HOST_CLEAN" >> "$GITHUB_OUTPUT" | |
| echo "ocir_ns=$OCIR_NS_CLEAN" >> "$GITHUB_OUTPUT" | |
| echo "ocir_repo=$OCIR_REPO_CLEAN" >> "$GITHUB_OUTPUT" | |
| echo "ocir_user=$OCIR_USER_CLEAN" >> "$GITHUB_OUTPUT" | |
| # -------------------------- | |
| # 1) Build JAR (Gradle) | |
| # -------------------------- | |
| - name: Set up JDK | |
| uses: actions/setup-java@v4 | |
| with: | |
| distribution: "temurin" | |
| java-version: "17" | |
| cache: gradle | |
| - name: Build (Gradle) | |
| if: ${{ hashFiles('**/build.gradle*') != '' }} | |
| run: | | |
| chmod +x ./gradlew | |
| ./gradlew clean bootJar | |
| JAR=$(ls build/libs/*.jar | head -n 1) | |
| cp "$JAR" app.jar | |
| # -------------------------- | |
| # 2) Compute image name + tags | |
| # -------------------------- | |
| - name: Compute image name (OCIR) | |
| id: img | |
| run: | | |
| echo "name=${{ steps.sanitize.outputs.ocir_host }}/${{ steps.sanitize.outputs.ocir_ns }}/${{ steps.sanitize.outputs.ocir_repo }}" >> "$GITHUB_OUTPUT" | |
| - name: Extract Docker metadata (tags, labels) | |
| id: meta | |
| uses: docker/metadata-action@v5 | |
| with: | |
| images: ${{ steps.img.outputs.name }} | |
| tags: | | |
| type=raw,value=latest,enable=${{ github.ref == 'refs/heads/main' }} | |
| type=sha | |
| - name: Set up Docker Buildx | |
| uses: docker/setup-buildx-action@v3 | |
| # -------------------------- | |
| # 3) Login to OCIR + Build & Push | |
| # -------------------------- | |
| - name: Log in to OCIR | |
| uses: docker/login-action@v3 | |
| with: | |
| registry: ${{ steps.sanitize.outputs.ocir_host }} | |
| username: ${{ steps.sanitize.outputs.ocir_user }} | |
| password: ${{ secrets.OCIR_AUTH_TOKEN }} | |
| - name: Build and push | |
| uses: docker/build-push-action@v6 | |
| 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 | |
| # -------------------------- | |
| # 4) Create .env (multiline safe) | |
| # -------------------------- | |
| - name: Create .env file | |
| shell: bash | |
| run: | | |
| # ENV_FILE이 멀티라인이라면 echo 대신 printf가 안전합니다. | |
| printf "%s" "${{ secrets.ENV_FILE }}" > .env | |
| # -------------------------- | |
| # 5) Copy files to OCI Compute | |
| # -------------------------- | |
| - name: Copy files to OCI Compute | |
| uses: appleboy/scp-action@master | |
| with: | |
| host: ${{ steps.sanitize.outputs.ssh_host }} | |
| username: ${{ secrets.SSH_USERNAME }} | |
| key: ${{ secrets.SSH_KEY }} | |
| port: 22 | |
| source: "docker/*,.env,nginx/,deploy.sh" | |
| target: "/home/ubuntu/tinybite/" | |
| # -------------------------- | |
| # 6) Deploy to OCI Compute | |
| # -------------------------- | |
| - name: Deploy to OCI Compute | |
| uses: appleboy/ssh-action@master | |
| with: | |
| host: ${{ steps.sanitize.outputs.ssh_host }} | |
| username: ${{ secrets.SSH_USERNAME }} | |
| key: ${{ secrets.SSH_KEY }} | |
| port: 22 | |
| script: | | |
| set -e | |
| cd /home/ubuntu/tinybite | |
| mv /home/ubuntu/tinybite/docker/* /home/ubuntu/tinybite/ || true | |
| # OCIR login (use sanitized host/user) | |
| echo "${{ secrets.OCIR_AUTH_TOKEN }}" | docker login "${{ steps.sanitize.outputs.ocir_host }}" \ | |
| -u "${{ steps.sanitize.outputs.ocir_user }}" --password-stdin | |
| export APP_IMAGE="${{ steps.img.outputs.name }}:latest" | |
| sudo docker compose -f docker-compose.blue.yml pull | |
| sudo docker compose -f docker-compose.blue.yml down || true | |
| sudo docker compose -f docker-compose.blue.yml up -d | |
| sudo docker image prune -f |