From b87ab63ac259fee5d82dc3ab54bf7f830a740b16 Mon Sep 17 00:00:00 2001 From: Gabriel Santana de Menezes Date: Mon, 11 May 2026 22:02:05 -0400 Subject: [PATCH] chore: deploy --- .github/workflows/deploy-main.yml | 147 ++++++++++++++++++ GITHUB_SECRETS_CHECKLIST.md | 32 ++++ README.md | 50 ++++++ backend/.env.example | 9 +- backend/Dockerfile | 28 ++++ .../src/main/resources/application.properties | 9 +- deploy/.env.production.example | 11 ++ deploy/docker-compose.prod.yml | 22 +++ frontend/Dockerfile | 20 +++ frontend/nginx.conf | 11 ++ 10 files changed, 326 insertions(+), 13 deletions(-) create mode 100644 .github/workflows/deploy-main.yml create mode 100644 GITHUB_SECRETS_CHECKLIST.md create mode 100644 backend/Dockerfile create mode 100644 deploy/.env.production.example create mode 100644 deploy/docker-compose.prod.yml create mode 100644 frontend/Dockerfile create mode 100644 frontend/nginx.conf diff --git a/.github/workflows/deploy-main.yml b/.github/workflows/deploy-main.yml new file mode 100644 index 0000000..92885bb --- /dev/null +++ b/.github/workflows/deploy-main.yml @@ -0,0 +1,147 @@ +name: Deploy to Hostinger + +on: + push: + branches: + - main + workflow_dispatch: + +env: + REGISTRY: ghcr.io + FRONTEND_IMAGE_NAME: ${{ github.repository }}-frontend + BACKEND_IMAGE_NAME: ${{ github.repository }}-backend + +jobs: + build-and-deploy: + runs-on: ubuntu-latest + permissions: + contents: read + packages: write + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Set up Java + uses: actions/setup-java@v4 + with: + distribution: temurin + java-version: "21" + cache: maven + + - name: Set up Node.js + uses: actions/setup-node@v4 + with: + node-version: "22" + cache: npm + cache-dependency-path: frontend/package-lock.json + + - name: Run backend tests + working-directory: backend + run: ./mvnw -B test + + - name: Run frontend build + working-directory: frontend + run: | + npm ci + npm run build + + - name: Log in to GHCR + uses: docker/login-action@v3 + with: + registry: ${{ env.REGISTRY }} + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Extract Docker metadata for frontend + id: meta-frontend + uses: docker/metadata-action@v5 + with: + images: ${{ env.REGISTRY }}/${{ env.FRONTEND_IMAGE_NAME }} + tags: | + type=raw,value=latest + type=sha + + - name: Extract Docker metadata for backend + id: meta-backend + uses: docker/metadata-action@v5 + with: + images: ${{ env.REGISTRY }}/${{ env.BACKEND_IMAGE_NAME }} + tags: | + type=raw,value=latest + type=sha + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Build and push frontend image + uses: docker/build-push-action@v6 + with: + context: ./frontend + file: ./frontend/Dockerfile + push: true + tags: ${{ steps.meta-frontend.outputs.tags }} + labels: ${{ steps.meta-frontend.outputs.labels }} + build-args: | + VITE_API_URL=${{ secrets.FRONTEND_VITE_API_URL }} + + - name: Build and push backend image + uses: docker/build-push-action@v6 + with: + context: ./backend + file: ./backend/Dockerfile + push: true + tags: ${{ steps.meta-backend.outputs.tags }} + labels: ${{ steps.meta-backend.outputs.labels }} + + - name: Copy deploy files to server + uses: appleboy/scp-action@v0.1.7 + with: + host: ${{ secrets.HOSTINGER_HOST }} + username: ${{ secrets.HOSTINGER_USER }} + key: ${{ secrets.HOSTINGER_SSH_KEY }} + port: ${{ secrets.HOSTINGER_PORT || 22 }} + source: "deploy/docker-compose.prod.yml" + target: "${{ secrets.HOSTINGER_APP_PATH }}" + strip_components: 1 + + - name: Deploy on Hostinger + uses: appleboy/ssh-action@v1.2.0 + env: + FRONTEND_IMAGE: ${{ env.REGISTRY }}/${{ env.FRONTEND_IMAGE_NAME }}:latest + BACKEND_IMAGE: ${{ env.REGISTRY }}/${{ env.BACKEND_IMAGE_NAME }}:latest + POSTGRES_USER: ${{ secrets.POSTGRES_USER }} + POSTGRES_PASSWORD: ${{ secrets.POSTGRES_PASSWORD }} + DB_URL: ${{ secrets.DB_URL }} + MP_JWT_VERIFY_ISSUER: ${{ secrets.MP_JWT_VERIFY_ISSUER }} + SMALLRYE_JWT_SIGN_KEY_LOCATION: ${{ secrets.SMALLRYE_JWT_SIGN_KEY_LOCATION }} + MP_JWT_VERIFY_PUBLICKEY_LOCATION: ${{ secrets.MP_JWT_VERIFY_PUBLICKEY_LOCATION }} + GHCR_USERNAME: ${{ secrets.GHCR_USERNAME }} + GHCR_TOKEN: ${{ secrets.GHCR_READ_TOKEN }} + with: + host: ${{ secrets.HOSTINGER_HOST }} + username: ${{ secrets.HOSTINGER_USER }} + key: ${{ secrets.HOSTINGER_SSH_KEY }} + port: ${{ secrets.HOSTINGER_PORT || 22 }} + envs: FRONTEND_IMAGE,BACKEND_IMAGE,POSTGRES_USER,POSTGRES_PASSWORD,DB_URL,MP_JWT_VERIFY_ISSUER,SMALLRYE_JWT_SIGN_KEY_LOCATION,MP_JWT_VERIFY_PUBLICKEY_LOCATION,GHCR_USERNAME,GHCR_TOKEN + script: | + set -eu + APP_DIR="${{ secrets.HOSTINGER_APP_PATH }}" + mkdir -p "$APP_DIR" + cd "$APP_DIR" + + cat > .env.production <