Skip to content

fix: altimate-dbt commands fail with hardcoded CI path in published binary#467

Merged
anandgupta42 merged 13 commits intomainfrom
fix/dbt-tools-python-bridge-dirname
Mar 26, 2026
Merged

fix: altimate-dbt commands fail with hardcoded CI path in published binary#467
anandgupta42 merged 13 commits intomainfrom
fix/dbt-tools-python-bridge-dirname

Conversation

@suryaiyer95
Copy link
Contributor

@suryaiyer95 suryaiyer95 commented Mar 26, 2026

What does this PR do?

  • Fixes altimate-dbt commands failing in published binaries because bun build freezes __dirname as a compile-time string, baking the CI runner path (/home/runner/work/...) into every release
  • All altimate-dbt commands that use the Python bridge (build, run, test, compile, execute) have been broken since PR feat: consolidate dbt skills and add altimate-dbt CLI package #201
  • Post-build script now copies node_python_bridge.py into dist/ and patches the frozen __dirname to import.meta.dirname (runtime resolution)
  • Build integrity test prevents regression
  • CI smoke test added to release workflow

Type of change

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • Documentation update

Issue for this PR

Closes #466

How did you verify your code works?

  • bun run build prints "Patched __dirname"
  • grep 'var __dirname' dist/index.js shows import.meta.dirname, not a hardcoded path
  • node_python_bridge.py exists in dist/
  • No home/runner strings in bundle
  • Build integrity tests pass (3/3)
  • CI smoke test validates bundle before npm publish

Checklist

  • My code follows the project's coding standards
  • I have added tests that prove my fix is effective
  • New and existing unit tests pass locally with my changes

Summary by CodeRabbit

  • Tests

    • Added build integrity validation to ensure generated artifacts are correctly produced and properly configured.
    • Added comprehensive adversarial testing to verify bundle patching behavior and runtime safety.
  • Chores

    • Enhanced CI/CD pipeline with automated smoke tests to catch build issues early.
    • Improved build artifact handling and verification in the deployment process.

…bt` works in published releases

`bun build` replaces `__dirname` with a compile-time constant when bundling
`python-bridge` (transitive dep of `@altimateai/dbt-integration`). In CI this
bakes `/home/runner/work/...` into the bundle, causing `altimate-dbt build`
and all Python-bridge commands to fail with ENOENT on every user's machine.

Fix:
- Copy `node_python_bridge.py` into `dist/` alongside `index.js`
- Post-process the bundle to replace the frozen path with `import.meta.dirname`
- Fail the build if the patch pattern isn't found (safety net)
- Add CI smoke test to prevent regression

Broken since PR #201. Closes #466.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings March 26, 2026 00:45
Copy link

@claude claude bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Claude Code Review

This repository is configured for manual code reviews. Comment @claude review to trigger a review.

Tip: disable this comment in your organization's Code Review settings.

@coderabbitai
Copy link

coderabbitai bot commented Mar 26, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Copies node_python_bridge.py into packages/dbt-tools/dist, patches hardcoded var __dirname = "..." in dist/index.js to use runtime import.meta.dirname resolution, adds post-build verification tests and CI smoke-test, and includes the bridge in opencode packaging and publish workflow.

Changes

Cohort / File(s) Summary
CI / Release workflow
.github/workflows/release.yml
Added Smoke test dbt-tools bundle step in publish-npm to assert dist/node_python_bridge.py exists, detect hardcoded absolute __dirname patterns, and verify the import.meta.dirname patch.
dbt-tools build & post-build
packages/dbt-tools/script/copy-python.ts
Compute dist path, copy node_python_bridge.py from @altimateai/dbt-integration into dist/, and read/patch dist/index.js replacing a hardcoded var __dirname = "..." with an import.meta.dirname + fallback expression; fail if expected pattern not found.
dbt-tools tests & package config
packages/dbt-tools/test/build-integrity.test.ts, packages/dbt-tools/test/build-adversarial.test.ts, packages/dbt-tools/test/dbt-cli.test.ts, packages/dbt-tools/package.json
Added build-integrity.test.ts and build-adversarial.test.ts to validate bridge presence, patch correctness, idempotency, and adversarial cases; updated dbt-cli.test.ts to preserve real child_process exports while mocking execFile; included new test in package test script.
Publish packaging
packages/opencode/script/publish.ts
copyAssets() copies ../dbt-tools/dist/node_python_bridge.py into ${targetDir}/dbt-tools/dist/; minor formatting/peer-dependency key normalization.

Sequence Diagram(s)

sequenceDiagram
    participant CI as CI (release workflow)
    participant Builder as bun build (dbt-tools)
    participant CopyScript as copy-python.ts
    participant Test as build-integrity.test / adversarial tests
    participant PublishPack as packages/opencode/script/publish.ts
    CI->>Builder: trigger build of packages/dbt-tools
    Builder->>CopyScript: run post-build copy/patch steps
    CopyScript->>Builder: copy node_python_bridge.py into dist and patch dist/index.js
    CopyScript-->>Builder: emit patched dist artifacts
    CI->>Test: run smoke tests / build-integrity tests against dist
    Test-->>CI: pass/fail result
    CI->>PublishPack: package assets (includes dbt-tools/dist/*) if smoke test passed
    PublishPack-->>CI: proceed to npm publish
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Poem

🐇 I hopped through builds with care and speed,
I brought the bridge where runtimes need,
I swapped the path for dynamic light,
I tested, patched, and set things right,
🥕—a rabbit’s grin for shipping freed.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The PR title clearly and specifically addresses the main issue: fixing broken altimate-dbt commands caused by a hardcoded CI path in the published binary.
Description check ✅ Passed The PR description is comprehensive and follows the template structure with all key sections: summary of changes, type of change, linked issue, verification steps, and completion checklist.
Linked Issues check ✅ Passed All coding requirements from issue #466 are met: runtime __dirname resolution via import.meta.dirname patching [#466], node_python_bridge.py copied to dist/ [#466], and CI path leakage prevented [#466].
Out of Scope Changes check ✅ Passed All changes are directly related to resolving issue #466: build script patching, integrity tests, CI smoke test, and asset copying are all necessary to fix the Python bridge path issue.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/dbt-tools-python-bridge-dirname

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Fixes a regression in the @altimateai/dbt-tools bundled output where bun build freezes __dirname to a CI runner path, breaking altimate-dbt commands that rely on python-bridge.

Changes:

  • Adds a post-build script to copy node_python_bridge.py into dist/ and patch the frozen __dirname in the bundle.
  • Adds a build-integrity test to prevent regressions (no CI path leaks; node_python_bridge.py present; patched dirname marker).
  • Adds a release-workflow smoke test to validate the dbt-tools bundle before publishing.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 3 comments.

File Description
packages/dbt-tools/script/copy-python.ts Copies Python assets into dist/ and patches the bundled __dirname string.
packages/dbt-tools/test/build-integrity.test.ts Rebuilds and asserts the dist/ output doesn’t contain CI-path leaks and includes required Python bridge file.
packages/dbt-tools/package.json Includes the new build-integrity test in the package test suite.
.github/workflows/release.yml Adds a publish-time smoke test to catch bundle regressions.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
.github/workflows/release.yml (1)

165-173: Harden smoke checks to catch any hardcoded absolute __dirname path.

Line 165 currently keys on a specific CI substring. Consider also failing on any absolute var __dirname = "..." assignment and using fixed-string grep for literals.

Suggested workflow hardening
-          if grep -q 'home/runner' packages/dbt-tools/dist/index.js; then
+          if grep -Fq 'home/runner' packages/dbt-tools/dist/index.js; then
             echo "::error::dbt-tools bundle contains hardcoded CI runner path"
             exit 1
           fi
           # Verify __dirname was patched to runtime resolution
-          if ! grep -q 'import.meta.dirname' packages/dbt-tools/dist/index.js; then
+          if ! grep -Fq 'import.meta.dirname' packages/dbt-tools/dist/index.js; then
             echo "::error::dbt-tools bundle missing import.meta.dirname patch"
             exit 1
           fi
+          # Verify no absolute __dirname assignment remains (unix/windows)
+          if grep -Eq 'var __dirname[[:space:]]*=[[:space:]]*"([A-Za-z]:\\\\|/)' packages/dbt-tools/dist/index.js; then
+            echo "::error::dbt-tools bundle still has hardcoded absolute __dirname"
+            exit 1
+          fi
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/release.yml around lines 165 - 173, The smoke-checks
should fail on any hardcoded absolute __dirname assignment and use fixed-string
matching; update the checks that inspect packages/dbt-tools/dist/index.js to (1)
use fixed-string grep (-F) for the existing home/runner check, and (2) add a
regex grep (eg. grep -E) to detect literal assignments like var __dirname =
"..." that start with an absolute path (patterns matching leading / or Windows
drive letters, e.g. grep -E 'var __dirname = ["'\''](/|[A-Za-z]:\\)') and fail
if found; keep the existing import.meta.dirname check (searching for
import.meta.dirname) unchanged.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@packages/dbt-tools/script/copy-python.ts`:
- Line 25: The patch sets __dirname via import.meta.dirname in the line with
code.replace(pattern, `var __dirname = import.meta.dirname`), which requires
Node >=20.11.0; either add an engines constraint to the package (add "engines":
{ "node": ">=20.11.0" } in the package.json for this package) or change the
generated replacement to a backwards-compatible fallback that uses
path.dirname(fileURLToPath(import.meta.url)) when import.meta.dirname isn't
available; update the code generation/replace logic in copy-python.ts (the
code.replace(...) call) to emit the fallback expression or ensure package.json
contains the engines.node minimum.

---

Nitpick comments:
In @.github/workflows/release.yml:
- Around line 165-173: The smoke-checks should fail on any hardcoded absolute
__dirname assignment and use fixed-string matching; update the checks that
inspect packages/dbt-tools/dist/index.js to (1) use fixed-string grep (-F) for
the existing home/runner check, and (2) add a regex grep (eg. grep -E) to detect
literal assignments like var __dirname = "..." that start with an absolute path
(patterns matching leading / or Windows drive letters, e.g. grep -E 'var
__dirname = ["'\''](/|[A-Za-z]:\\)') and fail if found; keep the existing
import.meta.dirname check (searching for import.meta.dirname) unchanged.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 99a24cac-e090-40ef-8693-99382a5406b7

📥 Commits

Reviewing files that changed from the base of the PR and between 79c34c5 and baa5dfd.

📒 Files selected for processing (4)
  • .github/workflows/release.yml
  • packages/dbt-tools/package.json
  • packages/dbt-tools/script/copy-python.ts
  • packages/dbt-tools/test/build-integrity.test.ts

@suryaiyer95 suryaiyer95 marked this pull request as draft March 26, 2026 00:54
@suryaiyer95 suryaiyer95 changed the title fix: patch hardcoded __dirname in dbt-tools bundle fix: altimate-dbt commands fail with hardcoded CI path in published binary Mar 26, 2026
suryaiyer95 and others added 4 commits March 25, 2026 17:56
…ions

- Use `fileURLToPath(import.meta.url)` fallback for Node < 20.11.0
- Broaden smoke test and build integrity checks to catch any hardcoded
  absolute path (Unix + Windows), not just `home/runner`
…` in bundle

GLM-5 review correctly identified that `path` is defined AFTER `__dirname`
in the bundled output, so the `path.dirname(fileURLToPath(...))` fallback
would throw `ReferenceError` on Node < 20.11.0.

Since Node 18 is EOL (April 2025), use `import.meta.dirname` unconditionally.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…udes it

`copyAssets` copied `dbt-tools/dist/index.js` but not the `.py` file
the patched `__dirname` resolves to. Without this, the fix would still
break in published packages.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…eSync` leak

`mock.module("child_process")` in `dbt-cli.test.ts` only provided `execFile`,
causing `dbt-resolve.test.ts` to fail with `Export named 'execFileSync' not found`
when Bun leaks the mock across test files.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@suryaiyer95 suryaiyer95 marked this pull request as ready for review March 26, 2026 02:57
`import.meta.dirname` is unavailable before Node 20.11.0. The previous
fallback was dropped because `path`/`fileURLToPath` weren't in scope at
that point in the bun-generated __commonJS IIFE. Using `__require` (a
module-level closure bun always emits) works at any Node version.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
anandgupta42 and others added 2 commits March 25, 2026 21:28
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
22 tests covering regex edge cases, runtime resolution, idempotency,
CI smoke test parity, and built bundle invariants.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
packages/dbt-tools/test/build-adversarial.test.ts (1)

101-105: Avoid stale dist artifacts in adversarial invariants

The setup says “fresh build” but only rebuilds when dist/index.js is missing. If dist exists but is stale, these tests may validate old output. Consider always rebuilding (or cleaning first) in this suite.

Proposed fix
   beforeAll(async () => {
-    // Ensure we have a fresh build
-    if (!existsSync(join(dist, "index.js"))) {
-      await $`bun run build`.cwd(join(import.meta.dir, ".."))
-    }
+    // Ensure we have a fresh build for deterministic invariants
+    await $`bun run build`.cwd(join(import.meta.dir, ".."))
   })
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/dbt-tools/test/build-adversarial.test.ts` around lines 101 - 105,
The beforeAll setup in build-adversarial.test.ts currently only runs the build
when existsSync(join(dist, "index.js")) is false, which can leave stale
artifacts; modify the beforeAll block (the setup surrounding the existsSync
check) to ensure a fresh build every run by either removing/cleaning the dist
directory before building or by always invoking the build command
unconditionally (e.g., always run `bun run build` in the same cwd used now) so
tests never use stale dist/index.js.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@packages/dbt-tools/test/build-adversarial.test.ts`:
- Around line 157-164: The test "patched __dirname evaluates to a real directory
at runtime" currently asserts dirname.not.toContain("runner"), which is
environment-coupled and flaky; remove that substring exclusion and instead
validate dirname as a real directory (e.g. using import.meta.dir value stored in
dirname and verifying it's a non-empty string, an absolute path, and that it
exists/is a directory via fs.existsSync + fs.statSync(...).isDirectory()).
Update the assertions around import.meta.dir / dirname in this test to check
directory validity rather than excluding "runner".

---

Nitpick comments:
In `@packages/dbt-tools/test/build-adversarial.test.ts`:
- Around line 101-105: The beforeAll setup in build-adversarial.test.ts
currently only runs the build when existsSync(join(dist, "index.js")) is false,
which can leave stale artifacts; modify the beforeAll block (the setup
surrounding the existsSync check) to ensure a fresh build every run by either
removing/cleaning the dist directory before building or by always invoking the
build command unconditionally (e.g., always run `bun run build` in the same cwd
used now) so tests never use stale dist/index.js.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 90a5eb0f-b3a1-435a-9cfa-9deba7726be6

📥 Commits

Reviewing files that changed from the base of the PR and between 6764fef and 825750b.

📒 Files selected for processing (1)
  • packages/dbt-tools/test/build-adversarial.test.ts

anandgupta42 and others added 5 commits March 25, 2026 22:39
…ostics

- Add `existsSync` check before copying `node_python_bridge.py` with
  a clear error message if the file is missing from the dependency
- Fix misleading comment that said "no fallback needed" while fallback
  code existed — now accurately describes the `__require` fallback
- Log the nearest `__dirname` match on pattern mismatch to aid debugging

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
… and mutation

New test categories:
- Script execution: verify exit codes, progress output, build determinism
- Bundle runtime structure: `__require` origin, `__commonJS` scope, spawn chain
- Publish pipeline: patched artifacts integrity before copy
- Mutation testing: verify guards catch removal of key fix components
- Regex performance: no catastrophic backtracking on 100KB+ input
- Malformed inputs: unicode, spaces, special chars, surrounding code preservation

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…tests

Root causes:
- `dispatcher.test.ts`: Bun's multi-file runner leaks `_ensureRegistered`
  hook from other files' `native/index.ts` imports. `reset()` clears
  handlers but not the hook, so `call()` triggers lazy registration
  instead of throwing. Fix: clear hook in `beforeEach`.
- `dbt-first-execution.test.ts`: `mock.module` for DuckDB leaked across
  files. Fix: spread real module exports + ensure native/index.ts import.
- `tracing-adversarial-final.test.ts`: 50ms snapshot waits too tight for
  CI under load. Fix: increase to 200ms/300ms.

Result: 0 failures in full suite (4961 pass, 340 skip).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…istence check

Address CodeRabbit review: `expect(dirname).not.toContain("runner")`
would fail on GitHub CI where test runs under `/home/runner/`. Use
`existsSync(dirname)` to validate the directory is real instead.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@anandgupta42 anandgupta42 merged commit 1a6610d into main Mar 26, 2026
10 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

fix: altimate-dbt commands fail with hardcoded CI path in published binary

4 participants