name: Docker Build and Deploy on: push: tags: [ 'v*' ] workflow_run: #workflows: ["CI Pipeline"] branches: [main] types: [completed] jobs: docker: name: Build and Push Docker Image runs-on: ubuntu-latest if: ${{ github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v') || github.event.workflow_run.conclusion == 'success' }} steps: - uses: actions/checkout@v4 - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3 - name: Login to Gitea Container Registry uses: docker/login-action@v3 with: registry: ${{ secrets.REGISTRY_URL }} username: ${{ secrets.REGISTRY_USERNAME }} password: ${{ secrets.REGISTRY_PASSWORD }} - name: Extract metadata id: meta uses: docker/metadata-action@v5 with: images: ${{ secrets.REGISTRY_URL }}/${{ gitea.repository }} tags: | type=semver,pattern={{version}} type=ref,event=branch type=sha,format=short - name: Build and push uses: docker/build-push-action@v5 with: context: . file: ./Dockerfile push: true tags: ${{ steps.meta.outputs.tags }} labels: ${{ steps.meta.outputs.labels }} cache-from: type=registry,ref=${{ secrets.REGISTRY_URL }}/${{ gitea.repository }}:buildcache cache-to: type=registry,ref=${{ secrets.REGISTRY_URL }}/${{ gitea.repository }}:buildcache,mode=max - name: Verify image run: | echo "Image successfully built and pushed with tags: ${{ steps.meta.outputs.tags }}" echo "::notice::Docker image built and pushed successfully." deploy: name: Deploy to VPS runs-on: ${{ secrets.DEPLOY_RUNNER || 'ubuntu-latest' }} needs: docker if: ${{ github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v') }} steps: - name: Set image name run: echo "IMAGE_NAME=${{ secrets.REGISTRY_URL }}/${{ secrets.REPOSITORY_PATH }}:${{ gitea.ref_name || 'latest' }}" >> $GITEA_ENV - name: Install Docker CLI run: | apt-get update apt-get install -y docker.io curl docker version - name: Login to Gitea Container Registry uses: docker/login-action@v3 with: registry: ${{ secrets.REGISTRY_URL }} username: ${{ secrets.REGISTRY_USERNAME }} password: ${{ secrets.REGISTRY_PASSWORD }} - name: Deploy to VPS run: | echo "Deploying image: ${{ env.IMAGE_NAME }}" # Pull latest image docker pull ${{ env.IMAGE_NAME }} # Stop and remove existing container docker stop ulflow-api-container || true docker rm ulflow-api-container || true # Run new container docker run -d \ --name ${{ secrets.CONTAINER_NAME || 'ulflow-api-container' }} \ --network ${{ secrets.DOCKER_NETWORK || 'ulflow-network' }} \ --restart always \ -p ${{ secrets.APP_PORT || '3000' }}:3000 \ -e APP_ENV=${{ secrets.APP_ENV || 'production' }} \ -e DB_HOST=${{ secrets.DB_HOST }} \ -e DB_USER=${{ secrets.DB_USER }} \ -e DB_PASSWORD=${{ secrets.DB_PASSWORD }} \ -e DB_NAME=${{ secrets.DB_NAME }} \ -e JWT_SECRET_KEY=${{ secrets.JWT_SECRET_KEY }} \ -e REFRESH_TOKEN_SECRET=${{ secrets.REFRESH_TOKEN_SECRET }} \ -e API_KEY=${{ secrets.API_KEY }} \ -e ENCRYPTION_KEY=${{ secrets.ENCRYPTION_KEY }} \ --health-cmd "${{ secrets.HEALTH_CMD || 'curl -f http://localhost:3000/health || exit 1' }}" \ --health-interval ${{ secrets.HEALTH_INTERVAL || '30s' }} \ --memory ${{ secrets.CONTAINER_MEMORY || '1g' }} \ --cpus ${{ secrets.CONTAINER_CPU || '1' }} \ ${{ env.IMAGE_NAME }} - name: Verify deployment run: | # Wait for container to start sleep 10 # Check container is running if docker ps | grep ${{ secrets.CONTAINER_NAME || 'ulflow-api-container' }}; then echo "Container is running" else echo "::error::Container failed to start" docker logs ${{ secrets.CONTAINER_NAME || 'ulflow-api-container' }} exit 1 fi # Check health endpoint curl -f http://localhost:${{ secrets.APP_PORT || '3000' }}/health || (echo "::error::Health check failed" && exit 1) echo "::notice::Deployment successful!" - name: Send notification if: always() run: | if [[ "${{ job.status }}" == "success" ]]; then echo "::notice::🚀 Deployment to VPS successful! Version: ${{ gitea.ref_name }}" else echo "::error::❌ Deployment to VPS failed! Check logs for details." fi