Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
113 changes: 113 additions & 0 deletions .github/workflows/ci-global-upgrade.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
name: Global Install Upgrade Smoke

# Catches regressions where `npm install -g gitnexus@<new>` fails to upgrade
# cleanly over a prior global install. Prior precedent: issue #836 and PR #843's
# incomplete fix slipped past CI because no global-upgrade test existed.
#
# Reusable workflow — only callable from ci.yml. Concurrency is governed by the
# caller (ci.yml), so no `concurrency:` block here.

on:
workflow_call:

jobs:
global-upgrade:
name: ${{ matrix.os }} / upgrade over ${{ matrix.prior }}
strategy:
fail-fast: false
matrix:
# macOS is the reporter's platform (issue #836) and the highest-risk
# surface for npm global-install rmdir behavior. Linux and Windows
# provide cross-platform regression coverage.
os: [macos-latest, ubuntu-latest, windows-latest]
# Prior version that must be upgraded OVER. Should be a published rc
# that preceded the fix. Bump when a known-bad version changes.
prior: ['1.6.2-rc.8']
runs-on: ${{ matrix.os }}
timeout-minutes: 15
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2

- uses: ./.github/actions/setup-gitnexus
with:
build: 'false'

- name: Install prior published version globally
run: npm install -g gitnexus@${{ matrix.prior }}

- name: Verify prior version installed
run: gitnexus --version

- name: Pack current branch
working-directory: gitnexus
run: npm pack
shell: bash

- name: Compute packed tarball path
id: tarball
working-directory: gitnexus
run: |
TARBALL=$(ls gitnexus-*.tgz | head -1)
echo "path=$(pwd)/$TARBALL" >> "$GITHUB_OUTPUT"
shell: bash

- name: Upgrade over prior version (the actual regression test)
run: npm install -g "${{ steps.tarball.outputs.path }}"
shell: bash

- name: Verify upgraded version runs
run: gitnexus --version

- name: Verify vendor/ has no nested node_modules after install
shell: bash
run: |
# The original #836 bug was about vendor/tree-sitter-proto/node_modules/
# blocking rmdir on upgrade. That is what the fix eliminates. A
# vendor/tree-sitter-proto/build/ directory can still appear because
# node-gyp-build compiles through the npm-created symlink; the
# contents are plain object files and .node binaries that rmdir
# handles fine, evidenced by this test getting past the upgrade step.
GLOBAL_PREFIX=$(npm root -g)
if [ -d "$GLOBAL_PREFIX/gitnexus/vendor/tree-sitter-proto" ]; then
echo "=== Contents of global vendor/tree-sitter-proto/ ==="
ls -la "$GLOBAL_PREFIX/gitnexus/vendor/tree-sitter-proto/"
if [ -d "$GLOBAL_PREFIX/gitnexus/vendor/tree-sitter-proto/node_modules" ]; then
echo "::error::vendor/tree-sitter-proto/node_modules/ was created — this is the #836 hazard"
exit 1
fi
fi

ignore-scripts:
name: ${{ matrix.os }} / --ignore-scripts degraded mode
strategy:
fail-fast: false
matrix:
os: [macos-latest, ubuntu-latest, windows-latest]
runs-on: ${{ matrix.os }}
timeout-minutes: 10
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2

- uses: ./.github/actions/setup-gitnexus
with:
build: 'false'

- name: Pack current branch
working-directory: gitnexus
run: npm pack
shell: bash

- name: Compute packed tarball path
id: tarball
working-directory: gitnexus
run: |
TARBALL=$(ls gitnexus-*.tgz | head -1)
echo "path=$(pwd)/$TARBALL" >> "$GITHUB_OUTPUT"
shell: bash

- name: Install globally with --ignore-scripts
run: npm install -g --ignore-scripts "${{ steps.tarball.outputs.path }}"
shell: bash

- name: Verify CLI boots without postinstall (proto parsing may be unavailable)
run: gitnexus --version
22 changes: 17 additions & 5 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,11 @@ jobs:
permissions:
contents: read

global-upgrade:
uses: ./.github/workflows/ci-global-upgrade.yml
permissions:
contents: read

# ── Save PR metadata for the reporting workflow ─────────────────
# The ci-report.yml workflow (triggered by workflow_run) needs the
# PR number and job results to post a comment. We save them as an
Expand All @@ -56,7 +61,7 @@ jobs:
save-pr-meta:
name: Save PR Metadata
if: always() && github.event_name == 'pull_request'
needs: [quality, tests, e2e]
needs: [quality, tests, e2e, global-upgrade]
runs-on: ubuntu-latest
timeout-minutes: 5
steps:
Expand All @@ -67,6 +72,7 @@ jobs:
QUALITY: ${{ needs.quality.result }}
TESTS: ${{ needs.tests.result }}
E2E: ${{ needs.e2e.result }}
GLOBAL_UPGRADE: ${{ needs.global-upgrade.result }}
run: |
mkdir -p pr-meta
echo "$PR_NUMBER" > pr-meta/pr_number
Expand Down Expand Up @@ -95,7 +101,7 @@ jobs:
# Single required check for branch protection.
ci-status:
name: CI Gate
needs: [quality, tests, e2e]
needs: [quality, tests, e2e, global-upgrade]
if: always()
runs-on: ubuntu-latest
timeout-minutes: 5
Expand All @@ -106,10 +112,12 @@ jobs:
QUALITY: ${{ needs.quality.result }}
TESTS: ${{ needs.tests.result }}
E2E: ${{ needs.e2e.result }}
GLOBAL_UPGRADE: ${{ needs.global-upgrade.result }}
run: |
echo "Quality: $QUALITY"
echo "Tests: $TESTS"
echo "E2E: $E2E"
echo "Quality: $QUALITY"
echo "Tests: $TESTS"
echo "E2E: $E2E"
echo "Global upgrade: $GLOBAL_UPGRADE"
if [[ "$QUALITY" != "success" ]] ||
[[ "$TESTS" != "success" ]]; then
echo "::error::Quality or test jobs failed"
Expand All @@ -119,3 +127,7 @@ jobs:
echo "::error::E2E job failed"
exit 1
fi
if [[ "$GLOBAL_UPGRADE" != "success" && "$GLOBAL_UPGRADE" != "skipped" ]]; then
echo "::error::Global upgrade smoke failed"
exit 1
fi
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,11 @@ GitNexus.sln
# Git worktrees
.worktrees/

# Vendored tree-sitter grammar build artifacts (created at install time,
# never committed). See docs/plans/2026-04-15-002-fix-tree-sitter-proto-vendor-deps-plan.md
gitnexus/vendor/**/build/
gitnexus/vendor/**/node_modules/

/github/scripts/triage/__pycache__/

.claude-flow/
Expand Down
Loading
Loading