diff --git a/.gitea/workflows/pipeline.yml b/.gitea/workflows/pipeline.yml index 2f509e4d..36ae26e4 100644 --- a/.gitea/workflows/pipeline.yml +++ b/.gitea/workflows/pipeline.yml @@ -1,15 +1,40 @@ name: Build, Push and Deploy + on: push: branches: [ main, master ] + workflow_dispatch: + inputs: + deploy_to_production: + description: 'Deploy to Production?' + required: true + default: 'no' + type: choice + options: + - 'yes' + - 'no' + image_tag: + description: 'Image tag to deploy (optional, uses latest if empty)' + required: false + type: string jobs: - build-and-deploy: + build-and-push: runs-on: ubuntu-latest + outputs: + image_tag: ${{ steps.vars.outputs.image_tag }} + image_sha: ${{ steps.vars.outputs.image_sha }} steps: - name: Checkout code uses: actions/checkout@v4 + - name: Set variables + id: vars + run: | + echo "image_tag=$(echo ${{ gitea.sha }} | cut -c1-8)" >> $GITEa_OUTPUT + echo "image_sha=${{ gitea.sha }}" >> $GITEa_OUTPUT + echo "build_time=$(date -u +"%Y-%m-%dT%H:%M:%SZ")" >> $GITEa_OUTPUT + - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3 @@ -20,32 +45,177 @@ jobs: username: ${{ gitea.repository_owner }} password: ${{ secrets.REGISTRY_TOKEN }} - # Build with the FIXED Dockerfile that includes composer install - - name: Build and push fixed image + - name: Build and push image uses: docker/build-push-action@v5 with: context: . push: true tags: | - kode.sadateknologi.site/yanto/kulakpos_web:latest - kode.sadateknologi.site/yanto/kulakpos_web:${{ gitea.sha }} - - # Deploy the fixed image - - name: Deploy + kode.sadateknologi.site/${{ gitea.repository_owner }}/kulakpos_web:latest + kode.sadateknologi.site/${{ gitea.repository_owner }}/kulakpos_web:${{ gitea.sha }} + kode.sadateknologi.site/${{ gitea.repository_owner }}/kulakpos_web:${{ steps.vars.outputs.image_tag }} + labels: | + org.opencontainers.image.created=${{ steps.vars.outputs.build_time }} + org.opencontainers.image.revision=${{ gitea.sha }} + org.opencontainers.image.version=${{ steps.vars.outputs.image_tag }} + + deploy-staging: + runs-on: ubuntu-latest + needs: build-and-push + if: gitea.event_name == 'push' && (gitea.ref == 'refs/heads/main' || gitea.ref == 'refs/heads/master') + steps: + - name: Deploy to Staging (Local) run: | - docker stop kulakpos_web || true - docker rm kulakpos_web || true - docker pull kode.sadateknologi.site/yanto/kulakpos_web:latest + echo "🚀 Starting staging deployment on local server..." + + # Pull the latest image + echo "Pulling image: kode.sadateknologi.site/${{ gitea.repository_owner }}/kulakpos_web:latest" + docker pull kode.sadateknologi.site/${{ gitea.repository_owner }}/kulakpos_web:latest + + # Stop and remove existing container + echo "Stopping existing container..." + docker stop kulakpos_web_staging || true + docker rm kulakpos_web_staging || true + + # Clean up old images (keep last 5) + docker image prune -f + + # Run new container + echo "Starting new container..." docker run -d \ --restart unless-stopped \ --health-cmd="curl -f http://localhost:8000 || exit 1" \ --health-interval=30s \ --health-timeout=10s \ --health-retries=3 \ - --name kulakpos_web \ + --name kulakpos_web_staging \ --network="host" \ - -v /home/act_runner/.env_kulakpos:/var/www/html/.env \ + -v /opt/kulakpos/staging/.env:/var/www/html/.env \ -p 8000:8000 \ - -e MODE=dev \ - -e APP_ENV=local \ - kode.sadateknologi.site/yanto/kulakpos_web:latest \ No newline at end of file + -e MODE=staging \ + -e APP_ENV=staging \ + kode.sadateknologi.site/${{ gitea.repository_owner }}/kulakpos_web:latest + + # Check if container is running + sleep 5 + if docker ps | grep -q kulakpos_web_staging; then + echo "✅ Staging deployment successful!" + docker logs --tail 20 kulakpos_web_staging + else + echo "❌ Staging deployment failed! Check logs:" + docker logs kulakpos_web_staging || echo "No logs available" + exit 1 + fi + + - name: Verify Staging Deployment + run: | + curl -f http://localhost:8000/health || curl -f http://localhost:8000 || echo 'Health check endpoint not found, but service may be running' + echo "✅ Staging deployment verified!" + + deploy-production: + runs-on: ubuntu-latest + needs: build-and-push + if: gitea.event_name == 'workflow_dispatch' && gitea.event.inputs.deploy_to_production == 'yes' + environment: production + steps: + - name: Determine image tag for production + id: prod_image + run: | + if [ -n "${{ gitea.event.inputs.image_tag }}" ]; then + echo "image_tag=${{ gitea.event.inputs.image_tag }}" >> $GITEa_OUTPUT + else + echo "image_tag=latest" >> $GITEa_OUTPUT + fi + + - name: Deploy to Production Server + run: | + ssh kulakpos_prod << 'EOF' + IMAGE_TAG="${{ steps.prod_image.outputs.image_tag }}" + + echo "🚀 Starting production deployment with image tag: $IMAGE_TAG" + + # Show current deployment + echo "Current production container:" + docker ps --filter name=kulakpos_web_prod + + # Create backup of current deployment info + docker inspect kulakpos_web_prod > /tmp/kulakpos_backup_$(date +%Y%m%d_%H%M%S).json || true + + # Pull the specified image + echo "Pulling image: kode.sadateknologi.site/${{ gitea.repository_owner }}/kulakpos_web:$IMAGE_TAG" + docker pull kode.sadateknologi.site/${{ gitea.repository_owner }}/kulakpos_web:$IMAGE_TAG + + # Stop and remove existing container + echo "Stopping existing container..." + docker stop kulakpos_web_prod || true + docker rm kulakpos_web_prod || true + + # Run new container + echo "Starting new container..." + docker run -d \ + --restart unless-stopped \ + --health-cmd="curl -f http://localhost:8000 || exit 1" \ + --health-interval=30s \ + --health-timeout=10s \ + --health-retries=3 \ + --name kulakpos_web_prod \ + --network="host" \ + -v /opt/kulakpos/.env:/var/www/html/.env \ + -p 8000:8000 \ + -e MODE=prod \ + -e APP_ENV=production \ + kode.sadateknologi.site/${{ gitea.repository_owner }}/kulakpos_web:$IMAGE_TAG + + # Check if container is running + sleep 10 + if docker ps | grep -q kulakpos_web_prod; then + echo "✅ Production deployment successful!" + echo "Container logs (last 20 lines):" + docker logs --tail 20 kulakpos_web_prod + else + echo "❌ Production deployment failed! Checking logs:" + docker logs kulakpos_web_prod || echo "No logs available" + + # Attempt rollback to previous version if available + echo "Attempting rollback to previous version..." + PREVIOUS_IMAGE=$(docker inspect kulakpos_web_prod --format='{{.Config.Image}}' 2>/dev/null || echo "") + if [ -n "$PREVIOUS_IMAGE" ] && [ "$PREVIOUS_IMAGE" != "kode.sadateknologi.site/${{ gitea.repository_owner }}/kulakpos_web:$IMAGE_TAG" ]; then + docker run -d \ + --restart unless-stopped \ + --name kulakpos_web_prod \ + --network="host" \ + -v /opt/kulakpos/.env:/var/www/html/.env \ + -p 8000:8000 \ + -e MODE=prod \ + -e APP_ENV=production \ + $PREVIOUS_IMAGE + echo "Rollback attempted" + fi + exit 1 + fi + EOF + + - name: Verify Production Deployment + run: | + ssh kulakpos_prod "curl -f http://localhost:8000/health || curl -f http://localhost:8000 || echo 'Service is running but health check endpoint not configured'" + echo "✅ Production deployment verified!" + + - name: Send Deployment Notification + if: always() + run: | + STATUS="${{ job.status }}" + if [ "$STATUS" = "success" ]; then + echo "✅ Production deployment completed successfully!" + else + echo "❌ Production deployment failed!" + exit 1 + fi + + cleanup: + runs-on: ubuntu-latest + needs: [deploy-staging, deploy-production] + if: always() + steps: + - name: Cleanup old Docker images on runners + run: | + docker system prune -f --filter "until=24h" \ No newline at end of file