name: Remote Deployment Pipeline on: push: branches: - main pull_request: types: [opened, synchronize, reopened, closed] env: # Base path for PR preview environments REMOTE_DEPLOY_PATH: /var/app/test/test # --- CUSTOMIZABLE PRODUCTION PATH --- # Set the absolute path for your production deployment on the remote server. REMOTE_PROD_PATH: /var/app/test/test-prod SSH_HOST: ${{ secrets.SSH_HOST }} SSH_USER: ${{ secrets.SSH_USER }} SSH_PRIVATE_KEY: ${{ secrets.SSH_PRIVATE_KEY }} SSH_PORT: ${{ secrets.SSH_PORT || 22 }} jobs: prepare_deployment_vars: name: Prepare deployment vars runs-on: ubuntu-latest outputs: deploy_path: ${{ steps.set-vars.outputs.deploy_path }} steps: - name: Set deployment variables id: set-vars run: | REPO_NAME=$(echo "${{ github.repository }}" | cut -d '/' -f 2) if [[ "${{ github.event_name }}" == "pull_request" ]]; then # For PRs, create a unique directory under the base path DEPLOY_PATH="${REMOTE_DEPLOY_PATH}/${REPO_NAME}-pr-${{ github.event.pull_request.number }}" else # For 'main' branch, use the specified production path. # Fallback to a default if REMOTE_PROD_PATH is empty. DEPLOY_PATH="${REMOTE_PROD_PATH:-${REMOTE_DEPLOY_PATH}/main}" fi echo "DEPLOY_PATH=${DEPLOY_PATH}" >> $GITHUB_ENV echo "deploy_path=${DEPLOY_PATH}" >> $GITHUB_OUTPUT echo "DEPLOY_PATH will be: ${DEPLOY_PATH}" create_remote_directory: name: Create remote directory runs-on: ubuntu-latest needs: prepare_deployment_vars if: | (github.event_name == 'pull_request' && github.event.action != 'closed' && github.event.pull_request.merged == false) || github.ref == 'refs/heads/main' steps: - name: Setup SSH uses: webfactory/ssh-agent@a6f90b1f127823b31d4d4a8d96047790581349bd # v0.9.1 with: ssh-private-key: ${{ env.SSH_PRIVATE_KEY }} - name: Add host to known_hosts run: | mkdir -p ~/.ssh chmod 700 ~/.ssh ssh-keyscan -p "$SSH_PORT" -T 10 -H "$SSH_HOST" >> ~/.ssh/known_hosts 2>/dev/null || { echo "::error::Failed to ssh-keyscan $SSH_HOST:$SSH_PORT" exit 1 } chmod 644 ~/.ssh/known_hosts - name: Create directory on remote run: ssh -p "$SSH_PORT" $SSH_USER@$SSH_HOST "mkdir -p '${{ needs.prepare_deployment_vars.outputs.deploy_path }}'" sync_repo_files: name: Sync repository files runs-on: ubuntu-latest needs: [create_remote_directory, prepare_deployment_vars] if: | (github.event_name == 'pull_request' && github.event.action != 'closed' && github.event.pull_request.merged == false) || github.ref == 'refs/heads/main' steps: - name: Checkout repository uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6 - name: Sync files via scp uses: appleboy/scp-action@master with: host: ${{ env.SSH_HOST }} username: ${{ env.SSH_USER }} key: ${{ env.SSH_PRIVATE_KEY }} port: ${{ env.SSH_PORT }} source: "./" target: "${{ needs.prepare_deployment_vars.outputs.deploy_path }}" run_docker_compose: name: Run docker-compose remotely runs-on: ubuntu-latest needs: [sync_repo_files, prepare_deployment_vars] if: | (github.event_name == 'pull_request' && github.event.action != 'closed' && github.event.pull_request.merged == false) || github.ref == 'refs/heads/main' steps: - name: Setup SSH uses: webfactory/ssh-agent@a6f90b1f127823b31d4d4a8d96047790581349bd # v0.9.1 with: ssh-private-key: ${{ env.SSH_PRIVATE_KEY }} - name: Add host to known_hosts run: | mkdir -p ~/.ssh chmod 700 ~/.ssh ssh-keyscan -p "$SSH_PORT" -T 10 -H "$SSH_HOST" >> ~/.ssh/known_hosts 2>/dev/null || { echo "::error::Failed to ssh-keyscan $SSH_HOST:$SSH_PORT" exit 1 } chmod 644 ~/.ssh/known_hosts - name: Run docker-compose on remote host run: ssh -p "$SSH_PORT" $SSH_USER@$SSH_HOST "cd '${{ needs.prepare_deployment_vars.outputs.deploy_path }}' && docker-compose up -d --build" cleanup_mr_environment: name: Cleanup MR environment runs-on: ubuntu-latest needs: prepare_deployment_vars if: | github.event_name == 'pull_request' && (github.event.action == 'closed' || github.event.pull_request.merged == true) steps: - name: Setup SSH uses: webfactory/ssh-agent@a6f90b1f127823b31d4d4a8d96047790581349bd # v0.9.1 with: ssh-private-key: ${{ env.SSH_PRIVATE_KEY }} - name: Add host to known_hosts run: | mkdir -p ~/.ssh chmod 700 ~/.ssh ssh-keyscan -p "$SSH_PORT" -T 10 -H "$SSH_HOST" >> ~/.ssh/known_hosts 2>/dev/null || { echo "::error::Failed to ssh-keyscan $SSH_HOST:$SSH_PORT" exit 1 } chmod 644 ~/.ssh/known_hosts - name: Run docker-compose down on remote host run: ssh -p "$SSH_PORT" $SSH_USER@$SSH_HOST "cd '${{ needs.prepare_deployment_vars.outputs.deploy_path }}' && docker-compose down" - name: Delete deployment directory run: | ssh -p "$SSH_PORT" $SSH_USER@$SSH_HOST "if [ -d '${{ needs.prepare_deployment_vars.outputs.deploy_path }}' ]; then rm -rf '${{ needs.prepare_deployment_vars.outputs.deploy_path }}'; echo 'Directory removed.'; else echo 'Directory not found, skipping.'; fi"