Skip to content

fix(ts-sdk): resolve git context from CI env vars - #100

Open
gbsierra wants to merge 3 commits into
traceroot-ai:mainfrom
gbsierra:fix/sdk-ts-ci-git-context
Open

fix(ts-sdk): resolve git context from CI env vars#100
gbsierra wants to merge 3 commits into
traceroot-ai:mainfrom
gbsierra:fix/sdk-ts-ci-git-context

Conversation

@gbsierra

@gbsierra gbsierra commented Jun 3, 2026

Copy link
Copy Markdown

Summary

Fixes traceroot-ai/traceroot#1023

Adds CI/platform git context resolution before local git auto-detection.

Changes

  • Added harvestCiGitContext(env) for CI/deploy metadata.
  • Wired resolution as explicit args -> TRACEROOT_GIT_* -> CI/platform env -> local git -> warn once.
  • Added warn-once behavior when git context remains unresolved.
  • Kept unresolved fields omitted instead of fabricating values.
  • Normalized Windows stack paths for existing source-location tests.

Acceptance Criteria

  • harvestCiGitContext(env) returns { gitRepo?, gitRef? }, normalizes repo to owner/repo, and resolves repo/ref independently.
  • Covers GitHub Actions, Vercel, GitLab CI, CircleCI, Bitbucket, Render, empty env, and first-platform-wins precedence.
  • Resolution is wired between TRACEROOT_GIT_* and local git detection.
  • Missing git context warns once, does not throw, and does not create default values.
  • Tests cover platform rows, empty env, precedence, independent fields, and warn-once behavior.
  • Test, typecheck, lint, and format checks pass.

Design Decisions

  • CI/platform resolution is a pure helper so env behavior is easy to test.
  • Repo and ref are filled separately because some platforms provide only one field.
  • Local git detection remains the development fallback.
  • The warning fires only when both repo and ref are unresolved, matching the issue wording.
  • Windows path normalization was included because the full suite failed on existing source-location tests on Windows.

Validation

pnpm --filter @traceroot-ai/traceroot test
pnpm --filter @traceroot-ai/traceroot typecheck
pnpm --filter @traceroot-ai/traceroot lint
pnpm format:check

Follow-Up Considerations

  • Consider injectable git auto-detection to avoid clearing PATH in tests.
  • Consider warning when either repo or ref is missing.

Summary by cubic

Resolve git repo/ref in the TS SDK from CI env vars before local git, and harden path and remote parsing across platforms. This prevents missing git context in production and avoids invalid repo stamping or absolute path leaks.

  • Bug Fixes
    • Added harvestCiGitContext() to read git repo/ref from CI env vars (GitHub Actions, Vercel, GitLab CI, CircleCI, Bitbucket, Render), resolving fields independently and normalizing owner/repo.
    • Updated resolution order: explicit options → TRACEROOT_GIT_* → CI/platform env → local git. No fabricated defaults.
    • Warn once when both repo and ref are missing; omit fields instead of guessing.
    • Safer path handling: normalize file:// stack paths and Windows slashes, prevent prefix collisions, handle macOS case-insensitive repo paths, and never emit absolute paths.
    • Safer remote parsing: accept only https/ssh/git@ URL forms; ignore local filesystem paths and bare names. Expanded tests for platforms, precedence, independent fields, warn-once, remote parsing, and path edges.

Written for commit e0b3b65. Summary will update on new commits.

Review in cubic

@gbsierra

gbsierra commented Jun 3, 2026

Copy link
Copy Markdown
Author

Note: The issue references dev_docs/plans/2026-06-03-sdk-git-context-IMPL.md, but I could not find it.
However, this follows the issue acceptance criteria directly.

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

2 issues found across 5 files

Confidence score: 3/5

  • There is concrete regression risk in packages/traceroot/src/git_context.ts: normalizeRepo can return raw non-URL remotes, and autoDetectGitContext() then uses that value, which may expose local filesystem paths in gitRepo.
  • relativePath in packages/traceroot/src/git_context.ts appears to rely on prefix matching without a directory-boundary check, so files outside the repo can be incorrectly treated as inside, which can skew tracing/context behavior.
  • Given the high confidence and medium-high severities (6–7/10), this is not merge-blocking by itself but carries meaningful user-impact risk and should be fixed or mitigated before relying on the new behavior.
  • Pay close attention to packages/traceroot/src/git_context.ts - repo normalization and path-boundary handling can leak metadata and misclassify file scope.
Architecture diagram
sequenceDiagram
    participant User as User Code
    participant Init as TraceRoot.initialize()
    participant Harvest as harvestCiGitContext()
    participant Auto as autoDetectGitContext()
    participant Git as local git
    
    Note over User,Git: Git context resolution order
    
    User->>Init: NEW: options.gitRepo?, options.gitRef?
    alt Explicit args provided
        Init->>Init: Use directly
    else Explicit missing → TRACEROOT_GIT_* env
        Init->>Init: Read TRACEROOT_GIT_REPO, TRACEROOT_GIT_REF
    end
    
    Note over Init,Harvest: NEW: CI/platform resolution inserted here
    
    alt repo or ref still missing
        Init->>Harvest: harvestCiGitContext(process.env)
        Harvest->>Harvest: Check platform candidates in order:
        Note over Harvest: GitHub Actions, Vercel, GitLab CI,<br/>CircleCI, Bitbucket, Render
        Harvest->>Harvest: For each platform:
        Note over Harvest: First platform with repo wins for repo<br/>First platform with ref wins for ref (independent)
        Harvest-->>Init: { gitRepo?, gitRef? }
        Init->>Init: Fill missing fields from CI context
    end
    
    alt repo or ref still missing
        Init->>Auto: autoDetectGitContext()
        Auto->>Git: git remote get-url origin
        Git-->>Auto: remote URL
        Auto->>Git: git rev-parse HEAD
        Git-->>Auto: commit SHA
        Auto-->>Init: { gitRepo?, gitRef? }
        Init->>Init: Fill remaining missing fields
    end
    
    opt both repo and ref still undefined
        Init->>Init: warnMissingGitContextOnce()
        Note over Init: Warn once, omit fields from spans
    end
    
    Init->>Init: Proceed with initialization
Loading

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

Comment thread packages/traceroot/src/git_context.ts Outdated
Comment thread packages/traceroot/src/git_context.ts Outdated

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

1 issue found across 2 files (changes from recent commits).

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

Comment thread packages/traceroot/src/git_context.ts Outdated
@gbsierra

gbsierra commented Jun 3, 2026

Copy link
Copy Markdown
Author

@cubic-dev-ai review

@cubic-dev-ai

cubic-dev-ai Bot commented Jun 3, 2026

Copy link
Copy Markdown

@cubic-dev-ai review

@gbsierra I have started the AI code review. It will take a few minutes to complete.

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

No issues found across 5 files

Confidence score: 5/5

  • Automated review surfaced no issues in the provided summaries.
  • No files require special attention.
Architecture diagram
sequenceDiagram
    participant App as User Application
    participant SDK as TraceRoot SDK
    participant GitCtx as git_context.ts
    participant CiEnv as CI Environment
    participant LocalGit as Local .git directory
    participant Telemetry as OpenTelemetry Pipeline

    Note over App,Telemetry: Git Context Resolution Flow

    App->>SDK: initialize({ gitRepo?, gitRef? })

    Note over SDK: Resolution order: explicit args → TRACEROOT_GIT_* env → CI/platform env → local git

    alt Explicit args provided
        SDK->>SDK: Use options.gitRepo / options.gitRef
    else Check TRACEROOT_GIT_* env vars
        SDK->>CiEnv: Read TRACEROOT_GIT_REPO, TRACEROOT_GIT_REF
        CiEnv-->>SDK: env values or undefined
        SDK->>SDK: Use if available
    end

    alt Still missing repo or ref
        SDK->>GitCtx: harvestCiGitContext(process.env)

        Note over GitCtx: Check platform env vars in priority order
        GitCtx->>CiEnv: GitHub Actions (GITHUB_REPOSITORY, GITHUB_SHA)
        GitCtx->>CiEnv: Vercel (VERCEL_GIT_REPO_OWNER, VERCEL_GIT_REPO_SLUG, VERCEL_GIT_COMMIT_SHA)
        GitCtx->>CiEnv: GitLab CI (CI_PROJECT_PATH, CI_COMMIT_SHA)
        GitCtx->>CiEnv: CircleCI (CIRCLE_PROJECT_USERNAME, CIRCLE_PROJECT_REPONAME, CIRCLE_SHA1)
        GitCtx->>CiEnv: Bitbucket (BITBUCKET_REPO_FULL_NAME, BITBUCKET_COMMIT)
        GitCtx->>CiEnv: Render (RENDER_GIT_COMMIT)

        Note over GitCtx: Resolve repo and ref independently from first matching platform
        CiEnv-->>GitCtx: Platform env values
        GitCtx-->>SDK: { gitRepo?, gitRef? }
        SDK->>SDK: Use CI values if still missing
    end

    alt Still missing repo or ref
        SDK->>GitCtx: autoDetectGitContext()

        GitCtx->>LocalGit: git remote get-url origin
        LocalGit-->>GitCtx: Remote URL

        GitCtx->>GitCtx: normalizeRemoteRepo(remote)
        Note over GitCtx: Accepts only https/ssh/git@ URL forms, rejects local paths

        GitCtx->>LocalGit: git rev-parse HEAD
        LocalGit-->>GitCtx: Commit SHA

        GitCtx-->>SDK: { gitRepo?, gitRef? }
        SDK->>SDK: Use local git values if still missing
    end

    alt Both repo and ref unresolved
        SDK->>SDK: warnMissingGitContextOnce()
        Note over SDK: Single warning, no fabricated defaults, fields omitted from spans
    end

    SDK->>Telemetry: Configure provider with gitRepo, gitRef resource attributes
    SDK-->>App: initialize() complete

    Note over App,SDK: Source Location Capture (after init)

    App->>SDK: observe() / trace operations
    SDK->>GitCtx: captureSourceLocation()
    GitCtx->>GitCtx: Parse call stack, skip internal frames
    GitCtx->>GitCtx: stackPathToFilePath() - normalize file:// URLs
    GitCtx->>GitCtx: relativePath(filepath, gitRoot)
    Note over GitCtx: Handles Windows paths, macOS case-insensitive matching, prefix collision prevention
    GitCtx-->>SDK: { file?, line?, function? }
    SDK->>Telemetry: Attach source location to span
Loading

Re-trigger cubic

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[SDK/ts] Resolve git context from CI/platform env vars + warn when unresolved

1 participant