Skip to content

feat(core): derive stable repo key from normalized remote and relative path - #36439

Merged
FrozenPandaz merged 9 commits into
masterfrom
feature/nxc-4650-repo-key-derivation
Jul 24, 2026
Merged

feat(core): derive stable repo key from normalized remote and relative path#36439
FrozenPandaz merged 9 commits into
masterfrom
feature/nxc-4650-repo-key-derivation

Conversation

@FrozenPandaz

Copy link
Copy Markdown
Contributor

Current Behavior

The CLI has no stable, protocol-independent identifier for a workspace's repository. generateWorkspaceId() hashes the raw remote URL, so ssh, https, and CI token-authenticated URLs of the same repo produce different ids, and two nx workspaces nested in one repository collide on the same id.

Expected Behavior

New deriveRepoKey() utility (packages/nx/src/utils/repo-key.ts) derives the claimable-record key for the repoTelemetry registry:

  • sha256(domain/slug + '#' + workspace-relative-path), unsalted.
  • The remote is normalized via getVcsRemoteInfo(), so every URL form of the same repo yields the same key.
  • The workspace's path relative to the git root ('' at the root, posix-separated on every OS) distinguishes nested workspaces.
  • Fallback when no remote exists: the first-commit SHA as the identity (deterministically the sorted-first root when merged histories produce several). Shallow clones without a remote return null — their truncated history has no stable root commit.
  • Not wired into any caller yet — this is the W1 foundation the per-run telemetry event (NXC-4677) and the registry ingestion endpoint (CLOUD-4727) build on.

Covered by unit tests exercising protocol-independence (ssh/https/token URLs → one key), nested-workspace distinction, the first-commit fallback, and the null cases, against real temporary git repos.

Related Issue(s)

Linear: NXC-4650


View session information ↗

…e path

Adds deriveRepoKey: sha256(domain/slug + '#' + git-root-relative path),
using getVcsRemoteInfo for protocol-independent remote normalization (ssh,
https, and token URLs of one repo all yield the same key) and including
the workspace's path inside the repo so nested workspaces get distinct
keys. Falls back to the first-commit SHA when no remote exists (null for
shallow clones - their truncated history has no stable root; sorted-first
root when merged histories produce several). Not wired into any caller
yet - this is the W1 foundation for the repoTelemetry registry.
@netlify

netlify Bot commented Jul 22, 2026

Copy link
Copy Markdown

Deploy Preview for nx-dev ready!

Name Link
🔨 Latest commit 46032e1
🔍 Latest deploy log https://app.netlify.com/projects/nx-dev/deploys/6a61260ded75e60009caa879
😎 Deploy Preview https://deploy-preview-36439--nx-dev.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@netlify

netlify Bot commented Jul 22, 2026

Copy link
Copy Markdown

Deploy Preview for nx-docs ready!

Name Link
🔨 Latest commit 46032e1
🔍 Latest deploy log https://app.netlify.com/projects/nx-docs/deploys/6a61260df4ede000084fc91b
😎 Deploy Preview https://deploy-preview-36439--nx-docs.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@nx-cloud

nx-cloud Bot commented Jul 22, 2026

Copy link
Copy Markdown
Contributor

View your CI Pipeline Execution ↗ for commit 46032e1

Command Status Duration Result
nx affected --targets=lint,test,build,e2e,e2e-c... ✅ Succeeded 8m 51s View ↗
nx run-many -t check-imports check-lock-files c... ✅ Succeeded 4s View ↗
nx-cloud record -- pnpm nx-cloud conformance:check ✅ Succeeded 1m 4s View ↗
nx build workspace-plugin ✅ Succeeded <1s View ↗
nx-cloud record -- nx sync:check ✅ Succeeded 18s View ↗
nx-cloud record -- nx format:check ✅ Succeeded 5s View ↗

☁️ Nx Cloud last updated this comment at 2026-07-23 16:56:10 UTC

nx-cloud[bot]

This comment was marked as outdated.

nx-cloud Bot and others added 8 commits July 22, 2026 17:06
generateWorkspaceId now uses deriveRepoKey instead of hashing the raw
remote URL: ssh/https/token URL forms of one repo converge on one GA
client id, and nested workspaces in one repo get distinct ids. nxCloudId
precedence is unchanged, so Cloud-connected workspaces keep identity
continuity. For URL-hash workspaces this is a one-time GA identity reset,
bundled with the CI uid change in this branch so the discontinuity lands
once.
A CI fleet is not a user: runners built from one image share a baked
/etc/machine-id, so machineId x workspaceId collapses the whole fleet
into a single GA user - the source of GA's single-user-ID warning and of
per-user daily collection caps silently discarding events. uid (and
up.user_id) are now omitted when isCI(); GA's Blended identity falls back
to cid = workspace, so CI activity still attributes to the repo.
Hosts route case-insensitively and hold one canonical casing, so
git@GitHub.com:NRWL/Nx.git and git@github.com:nrwl/nx.git are one repo and
must produce one key - otherwise a hand-typed remote yields a record the
claim flow can never match, since it derives keys from canonically-cased
host API repo lists.
The git-root-relative path, shallow check, and first-commit lookup are git concerns, so they join the other standalone helpers in git-utils rather than living in repo-key. GitRepository.getGitRootPath now delegates to an exported function instead of holding a second copy of the rev-parse call, and the relative path uses the file's existing sep/posix imports. repo-key keeps only identity selection and hashing.
…t root

deriveRepoKey no longer defaults its directory to workspaceRoot - callers pass it, so the module holds no implicit global state. generateWorkspaceId moves here from analytics-prompt (which is about consent prompting, not identity) and likewise takes an explicit root. The new git helpers use execFileSync rather than execSync: the commands are constant today, but an argv array keeps a later edit from interpolating a variable into a shell string, and it skips the shell entirely.
A repo with several root commits (merged unrelated histories) would keep a trailing carriage return on the first line when git output is CRLF, silently forking the derived key on that platform.
startAnalytics read it three times: isAnalyticsEnabled, the local nxJson, and generateWorkspaceId. Both now take the config the caller already has, so workspace-id does no file IO of its own.
@polygraph-app
polygraph-app Bot marked this pull request as ready for review July 22, 2026 20:27
@polygraph-app
polygraph-app Bot requested a review from a team as a code owner July 22, 2026 20:27
@polygraph-app
polygraph-app Bot requested a review from AgentEnder July 22, 2026 20:27

@nx-cloud nx-cloud Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Important

At least one additional CI pipeline execution has run since the conclusion below was written and it may no longer be applicable.

Nx Cloud has identified a possible root cause for your failed CI:

We investigated this E2E timeout and determined it is unrelated to the PR changes. Our changes are scoped entirely to the nx project (a new deriveRepoKey() utility), while the failing test exercises Angular ESM Module Federation browser loading — a completely separate concern. We recommend rerunning the task, as the failure appears to be a transient environment/infrastructure timeout.

No code changes were suggested for this issue.

Trigger a rerun:

Rerun CI

Nx Cloud View detailed reasoning on Nx Cloud ↗

🔔 Heads up, your workspace has pending recommendations ↗ to auto-apply fixes for similar failures.


🎓 Learn more about Self-Healing CI on nx.dev

@FrozenPandaz
FrozenPandaz merged commit 9c735d4 into master Jul 24, 2026
26 of 27 checks passed
@FrozenPandaz
FrozenPandaz deleted the feature/nxc-4650-repo-key-derivation branch July 24, 2026 17:51
FrozenPandaz added a commit that referenced this pull request Jul 29, 2026
…e path (#36439)

## Current Behavior

The CLI has no stable, protocol-independent identifier for a workspace's
repository. `generateWorkspaceId()` hashes the raw remote URL, so ssh,
https, and CI token-authenticated URLs of the same repo produce
different ids, and two nx workspaces nested in one repository collide on
the same id.

## Expected Behavior

New `deriveRepoKey()` utility (`packages/nx/src/utils/repo-key.ts`)
derives the claimable-record key for the repoTelemetry registry:

- `sha256(domain/slug + '#' + workspace-relative-path)`, unsalted.
- The remote is normalized via `getVcsRemoteInfo()`, so every URL form
of the same repo yields the same key.
- The workspace's path relative to the git root ('' at the root,
posix-separated on every OS) distinguishes nested workspaces.
- Fallback when no remote exists: the first-commit SHA as the identity
(deterministically the sorted-first root when merged histories produce
several). Shallow clones without a remote return null — their truncated
history has no stable root commit.
- Not wired into any caller yet — this is the W1 foundation the per-run
telemetry event (NXC-4677) and the registry ingestion endpoint
(CLOUD-4727) build on.

Covered by unit tests exercising protocol-independence (ssh/https/token
URLs → one key), nested-workspace distinction, the first-commit
fallback, and the null cases, against real temporary git repos.

## Related Issue(s)

Linear: NXC-4650

<!-- polygraph-session-start -->
---
[View session information
↗](https://app.trypolygraph.com/orgs/6a061dcb561c062131116eca/sessions/Repo-key-derivation-in-the-CLI-NXC-4650-94f75f84)
<!-- polygraph-session-end -->

---------

Co-authored-by: nx-cloud[bot] <71083854+nx-cloud[bot]@users.noreply.github.com>
(cherry picked from commit 9c735d4)
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.

2 participants