# Removes a PR's GitNexus index from the droplet when the PR is closed # (merged or not). The deploy workflow also prunes stale folders as a # safety net, but this gives us immediate cleanup without waiting for # the next deploy trigger. name: GitNexus Cleanup PR on: pull_request: types: [closed] permissions: contents: read actions: read concurrency: group: gitnexus-cleanup-pr-${{ github.event.pull_request.number }} cancel-in-progress: false jobs: cleanup: # Skip fork PRs entirely. GitHub withholds repository secrets from # pull_request events originating on forks, so an SSH deploy job run # from a fork close would fail noisily. The deploy workflow's stale- # folder pruning step catches any fork-contributor indexes that # actually made it onto the droplet. if: github.event.pull_request.head.repo.full_name == github.repository runs-on: ubuntu-latest timeout-minutes: 5 steps: # Skip the SSH round-trip entirely when no index artifact was ever # built for this PR (docs-only PRs, paths-ignored PRs, PRs closed # before indexing finished, etc). Eliminates ~95% of no-op SSH # sessions on a busy repo. - name: Check for index artifact id: check uses: actions/github-script@v7 with: script: | const { data } = await github.rest.actions.listArtifactsForRepo({ owner: context.repo.owner, repo: context.repo.repo, name: `gitnexus-index-pr-${context.payload.pull_request.number}`, per_page: 1, }); const hasArtifact = data.total_count > 0; core.info(`Artifact exists: ${hasArtifact}`); core.setOutput('has_artifact', hasArtifact ? 'true' : 'false'); - name: Setup SSH if: steps.check.outputs.has_artifact == 'true' env: SSH_KEY: ${{ secrets.GITNEXUS_DO_SSH_KEY }} KNOWN_HOST: ${{ secrets.GITNEXUS_DO_KNOWN_HOST }} run: | set -e mkdir -p ~/.ssh chmod 700 ~/.ssh printf '%s\n' "$SSH_KEY" > ~/.ssh/deploy_key chmod 600 ~/.ssh/deploy_key if [ -z "$KNOWN_HOST" ]; then echo "::error::GITNEXUS_DO_KNOWN_HOST secret is empty" exit 1 fi printf '%s\n' "$KNOWN_HOST" > ~/.ssh/known_hosts chmod 600 ~/.ssh/known_hosts - name: Remove PR index from droplet if: steps.check.outputs.has_artifact == 'true' env: SSH_USER: ${{ secrets.GITNEXUS_DO_USER }} SSH_HOST: ${{ secrets.GITNEXUS_DO_HOST }} PR_NUM: ${{ github.event.pull_request.number }} run: | ssh -i ~/.ssh/deploy_key "$SSH_USER@$SSH_HOST" PR_NUM="$PR_NUM" bash <<'REMOTE' set -e TARGET="/opt/gitnexus/indexes/LibreChat-pr-$PR_NUM" if [ -d "$TARGET" ]; then echo "Removing $TARGET" rm -rf "$TARGET" cd /opt/gitnexus docker compose up -d --force-recreate gitnexus echo "GitNexus restarted without PR #$PR_NUM" else echo "No index to clean up for PR #$PR_NUM (artifact existed but droplet folder did not)" fi REMOTE - name: Cleanup SSH key if: always() run: rm -f ~/.ssh/deploy_key