🩺 fix: Capture GitNexus Serve Output and Add Startup Health Check (#12599)

* fix: capture gitnexus serve output and add startup health check

gitnexus serve was backgrounded with no log capture, so crash
reasons were invisible in Fly logs. Now pipes output to stdout
and waits up to 30s for the server to be ready before starting
Caddy, with early exit if the process dies.

* fix: install newer libstdc++ for LadybugDB native addon

@ladybugdb/core prebuilt binary requires GLIBCXX_3.4.32 (GCC 13+)
but node:24-slim ships Bookworm's libstdc++6 which only has 3.4.31.
Pull libstdc++6 from Debian Trixie to satisfy the runtime dependency.

* fix: separate build tools from libstdc++ upgrade to avoid conflict

Installing Trixie's libstdc++6 alongside Bookworm's g++ fails because
the Trixie libc6 transitive dep conflicts with Bookworm's libc6-dev.
Split into two RUN steps: compile native addons first, remove g++,
then upgrade libstdc++ from Trixie with no conflicting packages.

* fix: name repo as LibreChat and add dev branch deploy support

- Use REPO_NAME build arg (default: LibreChat) as the WORKDIR so
  gitnexus registers the index with a proper name instead of "repo"
- Deploy workflow now triggers on both main and dev branch index runs
- Dev branch registers as "LibreChat-dev", main as "LibreChat"
- workflow_dispatch gains a branch selector input

* feat: serve both main and dev indexes from one container + auto-embed main

- Dockerfile now copies multiple indexes from indexes/<name>/.gitnexus
  and registers each with gitnexus, so one server handles both branches
- Deploy workflow downloads latest successful main + dev artifacts in
  parallel and bundles them into a single deploy
- list_repos returns LibreChat and LibreChat-dev; queries target either
  via the repo parameter
- Main branch pushes auto-enable --embeddings for semantic search;
  dev and PRs remain graph-only for speed (opt-in via dispatch input)
- Bump index job timeout to 25m to account for embedding generation

* fix: raise Fly machine memory to 1GB + add swap + cap Node heap

The 512MB machine was getting OOM-killed when gitnexus serve's default
--max-old-space-size=8192 over-committed memory during query spikes.

- Bump VM memory 512mb -> 1gb
- Add 512MB swap file to absorb transient spikes
- Cap Node heap at 768MB via NODE_OPTIONS so it stays within the
  machine's real capacity and leaves headroom for Caddy and the OS
This commit is contained in:
Danny Avila 2026-04-10 12:35:11 -04:00 committed by GitHub
parent 4f133f8955
commit a121ae3dea
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 104 additions and 41 deletions

View file

@ -1,8 +1,9 @@
# Deploys the GitNexus index to Fly.io as a persistent MCP + REST server.
# Deploys the GitNexus indexes for both main and dev to Fly.io as a
# persistent MCP + REST server, serving both branches simultaneously.
#
# Endpoints available after deploy:
# /api/mcp — MCP-over-HTTP (StreamableHTTP transport)
# /api/query — Search execution flows
# /api/query — Search execution flows (specify repo: LibreChat or LibreChat-dev)
# /api/search — Hybrid BM25 + semantic search
# /api/repos — List indexed repositories
# /api/info — Server version and status
@ -20,7 +21,7 @@ name: GitNexus Deploy
on:
workflow_run:
workflows: ['GitNexus Index']
branches: [main]
branches: [main, dev]
types: [completed]
workflow_dispatch:
@ -29,7 +30,7 @@ permissions:
concurrency:
group: gitnexus-deploy
cancel-in-progress: true
cancel-in-progress: false
env:
GITNEXUS_VERSION: '1.5.3'
@ -40,7 +41,7 @@ jobs:
github.event_name == 'workflow_dispatch' ||
github.event.workflow_run.conclusion == 'success'
runs-on: ubuntu-latest
timeout-minutes: 10
timeout-minutes: 15
steps:
- name: Checkout deploy config
uses: actions/checkout@v4
@ -48,37 +49,52 @@ jobs:
sparse-checkout: .fly/gitnexus
fetch-depth: 1
- name: Resolve index run
- name: Resolve latest successful index runs per branch
id: resolve
uses: actions/github-script@v7
with:
script: |
const runId = context.payload.workflow_run?.id;
if (runId) {
core.setOutput('run_id', String(runId));
const branches = ['main', 'dev'];
const result = {};
for (const branch of branches) {
const { data } = await github.rest.actions.listWorkflowRuns({
owner: context.repo.owner,
repo: context.repo.repo,
workflow_id: 'gitnexus-index.yml',
branch,
status: 'success',
per_page: 1,
});
if (data.workflow_runs.length) {
result[branch] = data.workflow_runs[0].id;
core.info(`${branch}: run ${result[branch]}`);
} else {
core.warning(`No successful index run found for ${branch}`);
}
}
if (!Object.keys(result).length) {
core.setFailed('No successful index runs found for any branch');
return;
}
// workflow_dispatch: find latest successful index run on main
const { data } = await github.rest.actions.listWorkflowRuns({
owner: context.repo.owner,
repo: context.repo.repo,
workflow_id: 'gitnexus-index.yml',
branch: 'main',
status: 'success',
per_page: 1,
});
if (!data.workflow_runs.length) {
core.setFailed('No successful GitNexus Index runs found on main');
return;
}
core.setOutput('run_id', String(data.workflow_runs[0].id));
core.setOutput('main_run', result.main || '');
core.setOutput('dev_run', result.dev || '');
- name: Download GitNexus index
- name: Download main index
if: steps.resolve.outputs.main_run != ''
uses: actions/download-artifact@v4
with:
name: gitnexus-index-main
path: deploy/.gitnexus
run-id: ${{ steps.resolve.outputs.run_id }}
path: deploy/indexes/LibreChat/.gitnexus
run-id: ${{ steps.resolve.outputs.main_run }}
github-token: ${{ secrets.GITHUB_TOKEN }}
- name: Download dev index
if: steps.resolve.outputs.dev_run != ''
uses: actions/download-artifact@v4
with:
name: gitnexus-index-dev
path: deploy/indexes/LibreChat-dev/.gitnexus
run-id: ${{ steps.resolve.outputs.dev_run }}
github-token: ${{ secrets.GITHUB_TOKEN }}
- name: Prepare deploy context
@ -88,7 +104,8 @@ jobs:
cp .fly/gitnexus/entrypoint.sh deploy/entrypoint.sh
echo "Deploy context:"
ls -la deploy/
ls -la deploy/.gitnexus/
echo "Indexes staged:"
ls -la deploy/indexes/ || echo "(none)"
- name: Setup Fly
uses: superfly/flyctl-actions/setup-flyctl@master

View file

@ -37,7 +37,7 @@ jobs:
github.event.pull_request.author_association == 'MEMBER' ||
github.event.pull_request.author_association == 'COLLABORATOR'
runs-on: ubuntu-latest
timeout-minutes: 15
timeout-minutes: 25
steps:
- name: Checkout repository
uses: actions/checkout@v4
@ -59,7 +59,9 @@ jobs:
- name: Run GitNexus Analyze
run: |
FLAGS="--skip-agents-md --verbose"
if [ "${{ inputs.embeddings }}" = "true" ]; then
# Auto-enable embeddings for main branch pushes; opt-in via dispatch input elsewhere
if [ "${{ inputs.embeddings }}" = "true" ] || \
([ "${{ github.event_name }}" = "push" ] && [ "${{ github.ref }}" = "refs/heads/main" ]); then
FLAGS="$FLAGS --embeddings"
fi
if [ "${{ inputs.force }}" = "true" ]; then