diff --git a/.github/workflows/PR-Demos.yml b/.github/workflows/PR-Demos.yml new file mode 100644 index 000000000..d01cdcd14 --- /dev/null +++ b/.github/workflows/PR-Demos.yml @@ -0,0 +1,227 @@ +name: PR Deployment + +on: + pull_request: + types: [opened, synchronize, reopened, closed] + +permissions: + contents: write + pull-requests: write + +env: + SERVER_IP: ${{ secrets.VPS_IP }} # Add this to your GitHub secrets + +jobs: + check-changes: + runs-on: ubuntu-latest + if: github.event.action != 'closed' + outputs: + should_run: ${{ steps.filter.outputs.src_changed }} + + steps: + - uses: actions/checkout@v4 + + - name: Check for relevant file changes + id: filter + uses: dorny/paths-filter@v2 + with: + filters: | + src_changed: + - '**/*.java' + - '**/*.html' + - '**/*.css' + - '**/*.js' + - '**/*.gradle' + + deploy-pr: + needs: check-changes + runs-on: ubuntu-latest + if: needs.check-changes.outputs.should_run == 'true' + + steps: + - uses: actions/checkout@v4 + + - name: Set up JDK and Gradle + uses: actions/setup-java@v4 + with: + java-version: '17' + distribution: 'temurin' + gradle-version: 8.7 + + - name: Run Gradle Command + run: ./gradlew clean build + env: + DOCKER_ENABLE_SECURITY: false + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Get version number + id: versionNumber + run: echo "versionNumber=$(./gradlew printVersion --quiet | tail -1)" >> $GITHUB_OUTPUT + + - name: Login to Docker Hub + uses: docker/login-action@v3 + with: + username: ${{ secrets.DOCKER_HUB_USERNAME }} + password: ${{ secrets.DOCKER_HUB_API }} + + - name: Build and push PR-specific image + uses: docker/build-push-action@v6 + with: + context: . + file: ./Dockerfile + push: true + tags: ${{ secrets.DOCKER_HUB_USERNAME }}/test:pr-${{ github.event.pull_request.number }} + build-args: VERSION_TAG=${{ steps.versionNumber.outputs.versionNumber }} + platforms: linux/amd64 + + + - name: Set up SSH + run: | + mkdir -p ~/.ssh/ + echo "${{ secrets.VPS_SSH_KEY }}" > ../private.key + sudo chmod 600 ../private.key + ssh-keyscan -H ${{ secrets.VPS_HOST }} >> ~/.ssh/known_hosts + + - name: Deploy to VPS + run: | + # First create the docker-compose content locally + cat > docker-compose.yml << 'EOF' + version: '3.3' + services: + stirling-pdf: + container_name: stirling-pdf-pr-${{ github.event.pull_request.number }} + image: ${{ secrets.DOCKER_HUB_USERNAME }}/test:pr-${{ github.event.pull_request.number }} + ports: + - "${{ github.event.pull_request.number }}:8080" + volumes: + - /stirling/PR-${{ github.event.pull_request.number }}/data:/usr/share/tessdata:rw + - /stirling/PR-${{ github.event.pull_request.number }}/config:/configs:rw + - /stirling/PR-${{ github.event.pull_request.number }}/logs:/logs:rw + environment: + DOCKER_ENABLE_SECURITY: "false" + SECURITY_ENABLELOGIN: "false" + SYSTEM_DEFAULTLOCALE: en-GB + UI_APPNAME: "Stirling-PDF PR-${{ github.event.pull_request.number }}" + UI_HOMEDESCRIPTION: "PR-${{ github.event.pull_request.number }} for Stirling-PDF Latest" + UI_APPNAMENAVBAR: "PR-${{ github.event.pull_request.number }}" + SYSTEM_MAXFILESIZE: "100" + METRICS_ENABLED: "false" + SYSTEM_GOOGLEVISIBILITY: "false" + SYSTEM_ENABLEANALYTICS: "false" + restart: on-failure:5 + EOF + + # Then copy the file and execute commands + scp -i ../private.key -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null docker-compose.yml ${{ secrets.VPS_USERNAME }}@${{ secrets.VPS_HOST }}:/tmp/docker-compose.yml + + ssh -i ../private.key -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -T ${{ secrets.VPS_USERNAME }}@${{ secrets.VPS_HOST }} << 'ENDSSH' + # Create PR-specific directories + mkdir -p /stirling/PR-${{ github.event.pull_request.number }}/{data,config,logs} + + # Move docker-compose file to correct location + mv /tmp/docker-compose.yml /stirling/PR-${{ github.event.pull_request.number }}/docker-compose.yml + + # Start or restart the container + cd /stirling/PR-${{ github.event.pull_request.number }} + docker-compose pull + docker-compose up -d + ENDSSH + + - name: Post deployment URL to PR + uses: actions/github-script@v7 + with: + script: | + const { GITHUB_REPOSITORY } = process.env; + const [repoOwner, repoName] = GITHUB_REPOSITORY.split('/'); + const prNumber = context.issue.number; + + const deploymentUrl = `http://${{ secrets.VPS_HOST }}:${prNumber}`; + const commentBody = `## ๐Ÿš€ PR Test Deployment\n\n` + + `Your PR has been deployed for testing!\n\n` + + `๐Ÿ”— **Test URL:** [${deploymentUrl}](${deploymentUrl})\n\n` + + `This deployment will be automatically cleaned up when the PR is closed.\n`; + + // Find existing comment + const comments = await github.rest.issues.listComments({ + owner: repoOwner, + repo: repoName, + issue_number: prNumber + }); + + const existingComment = comments.data.find(c => + c.body.includes("## ๐Ÿš€ PR Test Deployment") && + c.user.login === "github-actions[bot]" + ); + + if (existingComment) { + await github.rest.issues.updateComment({ + owner: repoOwner, + repo: repoName, + comment_id: existingComment.id, + body: commentBody + }); + } else { + await github.rest.issues.createComment({ + owner: repoOwner, + repo: repoName, + issue_number: prNumber, + body: commentBody + }); + } + + cleanup: + runs-on: ubuntu-latest + if: github.event.action == 'closed' + + steps: + - name: Set up SSH + run: | + mkdir -p ~/.ssh/ + echo "${{ secrets.VPS_SSH_KEY }}" > ../private.key + sudo chmod 600 ../private.key + + - name: Cleanup PR deployment + run: | + ssh -i ../private.key -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -T ${{ secrets.VPS_USERNAME }}@${{ secrets.VPS_HOST }} << 'ENDSSH' + # Check if directory exists before attempting cleanup + if [ -d "/stirling/PR-${{ github.event.pull_request.number }}" ]; then + echo "Found PR directory, proceeding with cleanup..." + + # Stop and remove containers + cd /stirling/PR-${{ github.event.pull_request.number }} + docker-compose down || true + + # Go back to root before removal + cd / + + # Remove PR-specific directories + rm -rf /stirling/PR-${{ github.event.pull_request.number }} + + # Remove the Docker image + docker rmi ${{ secrets.DOCKER_HUB_USERNAME }}/test:pr-${{ github.event.pull_request.number }} || true + + echo "Cleanup completed successfully" + else + echo "PR directory not found, nothing to clean up" + fi + ENDSSH + + - name: Post cleanup notice to PR + uses: actions/github-script@v7 + with: + script: | + const { GITHUB_REPOSITORY } = process.env; + const [repoOwner, repoName] = GITHUB_REPOSITORY.split('/'); + const prNumber = context.issue.number; + + const commentBody = `## ๐Ÿงน Deployment Cleanup\n\n` + + `The test deployment for this PR has been cleaned up.`; + + await github.rest.issues.createComment({ + owner: repoOwner, + repo: repoName, + issue_number: prNumber, + body: commentBody + }); diff --git a/build.gradle b/build.gradle index d0e1d58ff..035e8606d 100644 --- a/build.gradle +++ b/build.gradle @@ -10,6 +10,8 @@ plugins { //id "nebula.lint" version "19.0.3" } + + import com.github.jk1.license.render.* ext {