diff --git a/ci-cd.yml b/ci-cd.yml new file mode 100644 index 0000000..1e3736a --- /dev/null +++ b/ci-cd.yml @@ -0,0 +1,97 @@ +# CI: Maven build + unit tests on every push/PR to main or master. +# CD: Build Docker image and push to GitHub Container Registry (ghcr.io) on push to main/master. +# Optional: SSH deploy when repository variable ENABLE_SSH_DEPLOY=true and deploy secrets are set. +# +# Repository variables (Settings → Secrets and variables → Actions → Variables): +# ENABLE_SSH_DEPLOY = true (optional; omit or false to skip deploy job) +# +# Optional deploy secrets (Settings → Secrets and variables → Actions → Secrets): +# DEPLOY_HOST, DEPLOY_USER, DEPLOY_SSH_KEY, DEPLOY_SCRIPT +# DEPLOY_SCRIPT: multiline shell to run on the server (e.g. cd /opt/app && docker compose pull && docker compose up -d) +# +# Pull the image as: ghcr.io//:latest or : + +name: CI/CD + +on: + push: + branches: [main, master] + pull_request: + branches: [main, master] + workflow_dispatch: + +permissions: + contents: read + packages: write + +env: + JAVA_VERSION: "21" + +jobs: + build-and-test: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Set up JDK + uses: actions/setup-java@v4 + with: + distribution: temurin + java-version: ${{ env.JAVA_VERSION }} + cache: maven + + # Unit tests only; @EnabledIfEnvironmentVariable(RUN_INTEGRATION_TESTS) tests stay skipped unless you add a separate job with secrets. + - name: Maven verify + run: mvn -B -ntp verify + + docker-build-push: + needs: build-and-test + if: github.event_name == 'push' && (github.ref == 'refs/heads/main' || github.ref == 'refs/heads/master') + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Log in to GitHub Container Registry + uses: docker/login-action@v3 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Image name (lowercase for GHCR) + id: image + run: | + IMG=$(echo "${{ github.repository }}" | tr '[:upper:]' '[:lower:]') + echo "name=ghcr.io/${IMG}" >> "$GITHUB_OUTPUT" + + - name: Build and push + uses: docker/build-push-action@v6 + with: + context: . + push: true + tags: | + ${{ steps.image.outputs.name }}:latest + ${{ steps.image.outputs.name }}:${{ github.sha }} + cache-from: type=gha + cache-to: type=gha,mode=max + + deploy: + needs: docker-build-push + # Set ENABLE_SSH_DEPLOY=true in repo Variables to run this job; otherwise skipped. + if: vars.ENABLE_SSH_DEPLOY == 'true' + runs-on: ubuntu-latest + # Optional: uncomment for manual approval gates (create "production" in Environments first). + # environment: production + steps: + - name: Deploy over SSH + uses: appleboy/ssh-action@v1.2.2 + with: + host: ${{ secrets.DEPLOY_HOST }} + username: ${{ secrets.DEPLOY_USER }} + key: ${{ secrets.DEPLOY_SSH_KEY }} + script: ${{ secrets.DEPLOY_SCRIPT }}