@smoothbricks/cli 0.11.14 → 0.11.16

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (35) hide show
  1. package/dist/lib/json.d.ts +9 -0
  2. package/dist/lib/json.d.ts.map +1 -1
  3. package/dist/lib/json.js +65 -53
  4. package/dist/monorepo/managed-files.d.ts +9 -0
  5. package/dist/monorepo/managed-files.d.ts.map +1 -1
  6. package/dist/monorepo/managed-files.js +28 -2
  7. package/dist/monorepo/publish-workflow.d.ts.map +1 -1
  8. package/dist/monorepo/publish-workflow.js +52 -2
  9. package/dist/release/github-release.d.ts +16 -0
  10. package/dist/release/github-release.d.ts.map +1 -1
  11. package/dist/release/github-release.js +11 -2
  12. package/dist/release/index.d.ts +1 -1
  13. package/dist/release/index.d.ts.map +1 -1
  14. package/dist/release/index.js +29 -7
  15. package/dist/release/private-npm.d.ts +5 -0
  16. package/dist/release/private-npm.d.ts.map +1 -1
  17. package/dist/release/private-npm.js +26 -5
  18. package/managed/raw/tooling/direnv/devenv.smoo.nix +4 -2
  19. package/managed/raw/tooling/direnv/github-actions-bootstrap.sh +38 -0
  20. package/managed/raw/tooling/direnv/secret-references.ts +66 -0
  21. package/managed/raw/tooling/direnv/setup-environment.ts +81 -26
  22. package/managed/raw/tooling/direnv/toolchain-stamp.ts +88 -0
  23. package/managed/templates/github/actions/setup-devenv/action.yml +4 -2
  24. package/package.json +2 -2
  25. package/src/lib/json.ts +9 -0
  26. package/src/monorepo/__tests__/publish-workflow.test.ts +54 -0
  27. package/src/monorepo/managed-files.test.ts +26 -0
  28. package/src/monorepo/managed-files.ts +36 -2
  29. package/src/monorepo/publish-workflow.ts +70 -2
  30. package/src/monorepo/secret-references.test.ts +68 -0
  31. package/src/release/__tests__/private-npm-status.test.ts +37 -0
  32. package/src/release/__tests__/private-npm-workflow.test.ts +20 -0
  33. package/src/release/github-release.ts +31 -2
  34. package/src/release/index.ts +30 -4
  35. package/src/release/private-npm.ts +30 -5
@@ -45,6 +45,22 @@ export declare function nxProjectChangelogArgs(pkg: ReleasePackageInfo, previous
45
45
  export declare function projectChangelogContents(result: ProjectChangelogLookupResult, projectName: string): string;
46
46
  export declare function githubReleaseLookupExists(tag: string, exitCode: number, stdout: string, stderr: string): boolean;
47
47
  export declare function githubReleaseCommandArgs(tag: string, notesFile: string, releaseExists: boolean, version: string): string[];
48
+ /**
49
+ * A module of the WORKSPACE's Nx, not of smoo's own dependency. smoo installs
50
+ * with its own `nx` in the global virtual store, where the workspace's
51
+ * node_modules is invisible: that Nx cannot resolve the workspace's
52
+ * `versionActions` plugin (`Unable to resolve the "versionActions"
53
+ * implementation ... "@smoothbricks/nx-plugin/version-actions"`), and it is
54
+ * a second Nx version driving one release. Every in-process Nx call for a
55
+ * workspace resolves from that workspace's root, exactly as `nx` on its PATH
56
+ * would.
57
+ */
58
+ interface WorkspaceNxModules {
59
+ 'src/utils/workspace-root.js': typeof import('nx/src/utils/workspace-root.js');
60
+ 'src/command-line/release/version.js': typeof import('nx/src/command-line/release/version.js');
61
+ 'src/command-line/release/changelog.js': typeof import('nx/src/command-line/release/changelog.js');
62
+ }
63
+ export declare function importWorkspaceNx<Subpath extends keyof WorkspaceNxModules>(root: string, subpath: Subpath): Promise<WorkspaceNxModules[Subpath]>;
48
64
  export declare function withNxWorkspaceRoot<T>(root: string, run: () => Promise<T>): Promise<T>;
49
65
  export {};
50
66
  //# sourceMappingURL=github-release.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"github-release.d.ts","sourceRoot":"","sources":["../../src/release/github-release.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,KAAK,kBAAkB,EAAc,MAAM,WAAW,CAAC;AAYhE,UAAU,4BAA4B;IACpC,iBAAiB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CAC1D;AAED,MAAM,WAAW,6BAA6B,CAAC,OAAO,SAAS,kBAAkB,GAAG,kBAAkB;IACpG,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,OAAO,CAAC;IACb,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,MAAM,EAAE,OAAO,CAAC;CACjB;AAED,MAAM,WAAW,uBAAuB;IACtC,mBAAmB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IACnD,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC5C,GAAG,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;CAC5B;AAED,wBAAsB,gCAAgC,CAAC,KAAK,EAAE,6BAA6B,GAAG,OAAO,CAAC,MAAM,CAAC,CAS5G;AAED,wBAAsB,2BAA2B,CAC/C,GAAG,EAAE,kBAAkB,EACvB,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,uBAAuB,GAC7B,OAAO,CAAC,IAAI,CAAC,CAaf;AAED,wBAAgB,sBAAsB,CAAC,GAAG,EAAE,kBAAkB,EAAE,WAAW,EAAE,MAAM,GAAG,IAAI,EAAE,MAAM,EAAE,OAAO;;;;;;;;;;;;;;;;;;;;;;;;EAc1G;AAED,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,4BAA4B,EAAE,WAAW,EAAE,MAAM,GAAG,MAAM,CAM1G;AAED,wBAAgB,yBAAyB,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAShH;AAED,wBAAgB,wBAAwB,CACtC,GAAG,EAAE,MAAM,EACX,SAAS,EAAE,MAAM,EACjB,aAAa,EAAE,OAAO,EACtB,OAAO,EAAE,MAAM,GACd,MAAM,EAAE,CAgBV;AAMD,wBAAsB,mBAAmB,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAmB5F"}
1
+ {"version":3,"file":"github-release.d.ts","sourceRoot":"","sources":["../../src/release/github-release.ts"],"names":[],"mappings":"AAOA,OAAO,EAAE,KAAK,kBAAkB,EAAc,MAAM,WAAW,CAAC;AAYhE,UAAU,4BAA4B;IACpC,iBAAiB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CAC1D;AAED,MAAM,WAAW,6BAA6B,CAAC,OAAO,SAAS,kBAAkB,GAAG,kBAAkB;IACpG,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,OAAO,CAAC;IACb,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,MAAM,EAAE,OAAO,CAAC;CACjB;AAED,MAAM,WAAW,uBAAuB;IACtC,mBAAmB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IACnD,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC5C,GAAG,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;CAC5B;AAED,wBAAsB,gCAAgC,CAAC,KAAK,EAAE,6BAA6B,GAAG,OAAO,CAAC,MAAM,CAAC,CAS5G;AAED,wBAAsB,2BAA2B,CAC/C,GAAG,EAAE,kBAAkB,EACvB,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,uBAAuB,GAC7B,OAAO,CAAC,IAAI,CAAC,CAaf;AAED,wBAAgB,sBAAsB,CAAC,GAAG,EAAE,kBAAkB,EAAE,WAAW,EAAE,MAAM,GAAG,IAAI,EAAE,MAAM,EAAE,OAAO;;;;;;;;;;;;;;;;;;;;;;;;EAc1G;AAED,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,4BAA4B,EAAE,WAAW,EAAE,MAAM,GAAG,MAAM,CAM1G;AAED,wBAAgB,yBAAyB,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAShH;AAED,wBAAgB,wBAAwB,CACtC,GAAG,EAAE,MAAM,EACX,SAAS,EAAE,MAAM,EACjB,aAAa,EAAE,OAAO,EACtB,OAAO,EAAE,MAAM,GACd,MAAM,EAAE,CAgBV;AAMD;;;;;;;;;GASG;AACH,UAAU,kBAAkB;IAC1B,6BAA6B,EAAE,cAAc,gCAAgC,CAAC,CAAC;IAC/E,qCAAqC,EAAE,cAAc,wCAAwC,CAAC,CAAC;IAC/F,uCAAuC,EAAE,cAAc,0CAA0C,CAAC,CAAC;CACpG;AAED,wBAAsB,iBAAiB,CAAC,OAAO,SAAS,MAAM,kBAAkB,EAC9E,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,OAAO,GACf,OAAO,CAAC,kBAAkB,CAAC,OAAO,CAAC,CAAC,CAMtC;AAED,wBAAsB,mBAAmB,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAmB5F"}
@@ -1,6 +1,8 @@
1
1
  import { mkdtemp, rm, writeFile } from 'node:fs/promises';
2
+ import { createRequire } from 'node:module';
2
3
  import { tmpdir } from 'node:os';
3
4
  import { join } from 'node:path';
5
+ import { pathToFileURL } from 'node:url';
4
6
  import { releaseTag } from './core.js';
5
7
  const nxRenderOnlyReleaseConfig = {
6
8
  changelog: {
@@ -13,7 +15,7 @@ const nxRenderOnlyReleaseConfig = {
13
15
  };
14
16
  export async function renderNxProjectChangelogContents(input) {
15
17
  return withNxWorkspaceRoot(input.root, async () => {
16
- const { createAPI } = await import('nx/src/command-line/release/changelog.js');
18
+ const { createAPI } = await importWorkspaceNx(input.root, 'src/command-line/release/changelog.js');
17
19
  const result = await createAPI(nxRenderOnlyReleaseConfig, false)(nxProjectChangelogArgs(input.pkg, input.previousTag, input.dryRun));
18
20
  return projectChangelogContents(result, input.pkg.projectName);
19
21
  });
@@ -84,8 +86,15 @@ export function githubReleaseCommandArgs(tag, notesFile, releaseExists, version)
84
86
  function isPrereleaseVersion(version) {
85
87
  return version.includes('-');
86
88
  }
89
+ export async function importWorkspaceNx(root, subpath) {
90
+ const resolved = createRequire(join(root, 'package.json')).resolve(`nx/${subpath}`);
91
+ // A dynamic specifier types as `any`; the map above is the declared shape of
92
+ // the module the workspace's Nx serves at that subpath.
93
+ const module = await import(pathToFileURL(resolved).href);
94
+ return module;
95
+ }
87
96
  export async function withNxWorkspaceRoot(root, run) {
88
- const workspaceRootModule = await import('nx/src/utils/workspace-root.js');
97
+ const workspaceRootModule = await importWorkspaceNx(root, 'src/utils/workspace-root.js');
89
98
  const previousWorkspaceRoot = workspaceRootModule.workspaceRoot;
90
99
  const previousEnvWorkspaceRoot = process.env.NX_WORKSPACE_ROOT_PATH;
91
100
  const previousCwd = process.cwd();
@@ -1,5 +1,5 @@
1
1
  export { assertPackedArtifact, type ReleasePackManifest, type ReleasePackOptions, type ReleasePackPackageEntry, releasePack, resolvePackClosure, } from './pack.js';
2
- export { assertPrivatePackage, checkPrivatePackage, isPrivatePackage, type NpmStatusOptions, npmPackageExists as npmPackageExistsOnRegistry, npmPublishedVersionExists as npmPublishedVersionExistsOnRegistry, type PrivateNpmRegistry, type PrivateNpmRegistryConfigError, type PrivateNpmRegistryConfigErrorKind, type PublishDestination, privateNpmPublishArgs, privateNpmUserconfigContent, publishPrivateWithDiagnostics, type Result as PrivateNpmResult, requirePrivateNpmRegistry, resolvePrivateNpmRegistry, selectPublishDestination, selectRegistryForPackage, withPrivateNpmUserconfig, } from './private-npm.js';
2
+ export { assertPrivatePackage, checkPrivatePackage, isPrivatePackage, type NpmStatusOptions, npmPackageExists as npmPackageExistsOnRegistry, npmPublishedVersionExists as npmPublishedVersionExistsOnRegistry, type PrivateNpmRegistry, type PrivateNpmRegistryConfigError, type PrivateNpmRegistryConfigErrorKind, type PublishDestination, privateNpmPublishArgs, privateNpmTokenEnvForMode, privateNpmUserconfigContent, publishPrivateWithDiagnostics, type Result as PrivateNpmResult, requirePrivateNpmRegistry, resolvePrivateNpmRegistry, selectPublishDestination, selectRegistryForPackage, withPrivateNpmUserconfig, } from './private-npm.js';
3
3
  import { type BootstrapNpmPackagesOptions } from './bootstrap-npm-packages.js';
4
4
  import { type ReleasePackageInfo } from './core.js';
5
5
  export interface ReleaseVersionOptions {
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/release/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/release/index.ts"],"names":[],"mappings":"AA8BA,OAAO,EACL,oBAAoB,EACpB,KAAK,mBAAmB,EACxB,KAAK,kBAAkB,EACvB,KAAK,uBAAuB,EAC5B,WAAW,EACX,kBAAkB,GACnB,MAAM,WAAW,CAAC;AACnB,OAAO,EACL,oBAAoB,EACpB,mBAAmB,EACnB,gBAAgB,EAChB,KAAK,gBAAgB,EACrB,gBAAgB,IAAI,0BAA0B,EAC9C,yBAAyB,IAAI,mCAAmC,EAChE,KAAK,kBAAkB,EACvB,KAAK,6BAA6B,EAClC,KAAK,iCAAiC,EACtC,KAAK,kBAAkB,EACvB,qBAAqB,EACrB,yBAAyB,EACzB,2BAA2B,EAC3B,6BAA6B,EAC7B,KAAK,MAAM,IAAI,gBAAgB,EAC/B,yBAAyB,EACzB,yBAAyB,EACzB,wBAAwB,EACxB,wBAAwB,EACxB,wBAAwB,GACzB,MAAM,kBAAkB,CAAC;AAK1B,OAAO,EACL,KAAK,2BAA2B,EAIjC,MAAM,6BAA6B,CAAC;AAQrC,OAAO,EAQL,KAAK,kBAAkB,EAGxB,MAAM,WAAW,CAAC;AAiDnB,MAAM,WAAW,qBAAqB;IACpC,IAAI,EAAE,MAAM,CAAC;IACb,yGAAyG;IACzG,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,iBAAiB;IAChC,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED,MAAM,WAAW,qBAAqB;IACpC,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;CACrB;AAED,MAAM,WAAW,2BAA2B;IAC1C,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,2EAA2E;IAC3E,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,6BAA6B;IAC5C,IAAI,EAAE,MAAM,CAAC;IACb,0CAA0C;IAC1C,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,MAAM,EAAE,MAAM,CAAC;IACf,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,4BAA4B;IAC3C,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;CACrB;AAED,MAAM,WAAW,kCAAkC;IACjD,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;CACrB;AAED,MAAM,WAAW,8BAA8B;IAC7C,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,wBAAsB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,qBAAqB,GAAG,OAAO,CAAC,IAAI,CAAC,CA4BhG;AAED;;;;;;GAMG;AACH,wBAAsB,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,iBAAiB,GAAG,OAAO,CAAC,IAAI,CAAC,CAe/F;AAED,wBAAsB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,qBAAqB,GAAG,OAAO,CAAC,IAAI,CAAC,CAiDhG;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,EAAE,eAAe,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,EAAE,CAM/F;AAKD,wBAAsB,oBAAoB,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,2BAA2B,GAAG,OAAO,CAAC,IAAI,CAAC,CAc5G;AAED,wBAAsB,6BAA6B,CACjD,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,6BAA6B,GACrC,OAAO,CAAC,IAAI,CAAC,CAgDf;AAED,wBAAsB,qBAAqB,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,4BAA4B,GAAG,OAAO,CAAC,IAAI,CAAC,CAgC9G;AAED,wBAAgB,kBAAkB,CAChC,WAAW,EAAE,MAAM,EACnB,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,OAAO,GACd,MAAM,EAAE,CAMV;AAED,MAAM,WAAW,mBAAmB,CAAC,OAAO,SAAS,kBAAkB,GAAG,kBAAkB;IAC1F,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,mBAAmB,IAAI,OAAO,EAAE,CAAC;IACjC,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAC9C,oBAAoB,CAAC,OAAO,EAAE,2BAA2B,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC,CAAC;IAC/E,cAAc,CAAC,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,OAAO,CAAC,oBAAoB,CAAC,CAAC;IAC3G,iBAAiB,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CAAC,sBAAsB,CAAC,CAAC;IACjE,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACvB,GAAG,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,KAAK,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;CAC9B;AAED,MAAM,MAAM,oBAAoB,GAAG,YAAY,GAAG,oBAAoB,CAAC;AAEvE,MAAM,WAAW,gBAAgB;IAC/B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,MAAM,EAAE,eAAe,CAAC;IACjC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,MAAM,sBAAsB,GAAG,gBAAgB,EAAE,GAAG,oBAAoB,CAAC;AAE/E,wBAAsB,0BAA0B,CAAC,OAAO,SAAS,kBAAkB,EACjF,KAAK,EAAE,mBAAmB,CAAC,OAAO,CAAC,EACnC,OAAO,EAAE,4BAA4B,GACpC,OAAO,CAAC,IAAI,CAAC,CAuEf;AAkED,wBAAsB,2BAA2B,CAC/C,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,kCAAkC,GAC1C,OAAO,CAAC,IAAI,CAAC,CAmBf;AAED,wBAAsB,uBAAuB,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,8BAA8B,GAAG,OAAO,CAAC,IAAI,CAAC,CAelH;AAED,wBAAsB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAEnE;AA8UD;;;;;;;;;GASG;AACH,wBAAsB,oBAAoB,CAAC,OAAO,SAAS,kBAAkB,EAC3E,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,OAAO,EAAE,EACnB,GAAG,EAAE,MAAM,GACV,OAAO,CAAC,OAAO,EAAE,CAAC,CAgBpB;AAkhCD,oEAAoE;AACpE,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAShF;AA8CD,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,gBAAgB,EAAE,CAkB9F"}
@@ -15,18 +15,19 @@ import { parseNxJsonText, parseNxProjectJsonText, parsePackageJsonText, } from '
15
15
  import { decode, run, runInteractiveStatus, runResult, runText } from '../lib/run.js';
16
16
  import { getWorkspacePackages, listPublicReleasePackages, listReleasePackages, readPackageJson, repositoryInfo, } from '../lib/workspace.js';
17
17
  export { assertPackedArtifact, releasePack, resolvePackClosure, } from './pack.js';
18
- export { assertPrivatePackage, checkPrivatePackage, isPrivatePackage, npmPackageExists as npmPackageExistsOnRegistry, npmPublishedVersionExists as npmPublishedVersionExistsOnRegistry, privateNpmPublishArgs, privateNpmUserconfigContent, publishPrivateWithDiagnostics, requirePrivateNpmRegistry, resolvePrivateNpmRegistry, selectPublishDestination, selectRegistryForPackage, withPrivateNpmUserconfig, } from './private-npm.js';
18
+ export { assertPrivatePackage, checkPrivatePackage, isPrivatePackage, npmPackageExists as npmPackageExistsOnRegistry, npmPublishedVersionExists as npmPublishedVersionExistsOnRegistry, privateNpmPublishArgs, privateNpmTokenEnvForMode, privateNpmUserconfigContent, publishPrivateWithDiagnostics, requirePrivateNpmRegistry, resolvePrivateNpmRegistry, selectPublishDestination, selectRegistryForPackage, withPrivateNpmUserconfig, } from './private-npm.js';
19
+ import { PLATFORM_TARGET_GLOBS } from '@smoothbricks/nx-plugin/workspace-config-policy';
19
20
  import { ciApiContext } from '../github-ci/api.js';
20
21
  import { readProjectTargets } from '../nx/index.js';
21
22
  import { bootstrapNpmPackages, NPM_BOOTSTRAP_DIST_TAG, NPM_BOOTSTRAP_VERSION, } from './bootstrap-npm-packages.js';
22
23
  import { resolveBuildInputPatterns } from './build-inputs.js';
23
24
  import { parseReleaseProjectSelection, releaseCandidatePackages, } from './candidates.js';
24
25
  import { classifyReleaseBranchPush, collectOwnedReleaseTagRecords, divergedReleaseBranchMessage, pendingReleaseTargets, releaseTag, releaseTagAliases, } from './core.js';
25
- import { createOrUpdateGithubRelease, githubReleaseLookupExists, renderNxProjectChangelogContents, withNxWorkspaceRoot, } from './github-release.js';
26
+ import { createOrUpdateGithubRelease, githubReleaseLookupExists, importWorkspaceNx, renderNxProjectChangelogContents, withNxWorkspaceRoot, } from './github-release.js';
26
27
  import { publishWithAuthDiagnostics } from './npm-auth.js';
27
28
  import { bumpStableReleaseToNext, collectRepairPlatformOutputs, completeReleaseAtHead as completeReleaseAtHeadWithShell, prepareReleaseCandidate, repairPendingTargets, runReleaseTag, runReleaseVersion, } from './orchestration.js';
28
29
  import { packReleaseTarball } from './pack.js';
29
- import { assertPrivatePackage, npmPackageExists as npmPackageExistsOnRegistry, npmPublishedVersionExists as npmPublishedVersionExistsOnRegistry, privateNpmPublishArgs, publishPrivateWithDiagnostics, selectPublishDestination, selectRegistryForPackage, withPrivateNpmUserconfig, } from './private-npm.js';
30
+ import { assertPrivatePackage, npmPackageExists as npmPackageExistsOnRegistry, npmPublishedVersionExists as npmPublishedVersionExistsOnRegistry, privateNpmPublishArgs, privateNpmTokenEnvForMode, publishPrivateWithDiagnostics, selectPublishDestination, selectRegistryForPackage, withPrivateNpmUserconfig, } from './private-npm.js';
30
31
  import { retagUnpublished } from './retag-unpublished.js';
31
32
  import { forgejoAuthHeaders, forgejoReleaseLookupExists, resolveSourceReleaseEndpoint, resolveSourceRepository, sourceReleaseTokenEnvNames, sourceReleaseUrl, } from './source-release.js';
32
33
  export async function releaseVersion(root, options) {
@@ -426,7 +427,12 @@ async function publishPrivatePackedPackage(root, pkg, tag, dryRun, registry) {
426
427
  }
427
428
  await withPrivateNpmUserconfig(registry, 'publish', async (userconfig) => {
428
429
  await publishPrivateWithDiagnostics(pkg, {
429
- publish: () => runNpm(root, args, { NPM_CONFIG_USERCONFIG: userconfig }),
430
+ publish: () => runNpm(root, args, {
431
+ NPM_CONFIG_USERCONFIG: userconfig,
432
+ // Env config outranks a committed project `.npmrc` auth line; see
433
+ // npmStatusEnv in private-npm.ts for why that matters here.
434
+ [`npm_config_${registry.authKey}`]: process.env[privateNpmTokenEnvForMode(registry, 'publish')] ?? '',
435
+ }),
430
436
  // The open publish userconfig already authenticates this registry,
431
437
  // so the failure probe reuses it. Opening a second read-mode
432
438
  // userconfig here demanded a read credential the publishing job need
@@ -435,6 +441,7 @@ async function publishPrivatePackedPackage(root, pkg, tag, dryRun, registry) {
435
441
  versionExists: () => npmPublishedVersionExistsOnRegistry(root, pkg.name, pkg.version, {
436
442
  registry: registry.registry,
437
443
  userconfig,
444
+ credential: { authKey: registry.authKey, tokenEnv: privateNpmTokenEnvForMode(registry, 'publish') },
438
445
  }),
439
446
  log: (message) => console.log(message),
440
447
  error: (message) => console.error(message),
@@ -520,8 +527,8 @@ async function runNxReleaseVersion(root, projects, bump, dryRun) {
520
527
  }
521
528
  async function runNxReleaseVersionPreview(root, projects, bump) {
522
529
  return withNxWorkspaceRoot(root, async () => {
523
- const { createAPI } = await import('nx/src/command-line/release/version.js');
524
- const { createAPI: createChangelogAPI } = await import('nx/src/command-line/release/changelog.js');
530
+ const { createAPI } = await importWorkspaceNx(root, 'src/command-line/release/version.js');
531
+ const { createAPI: createChangelogAPI } = await importWorkspaceNx(root, 'src/command-line/release/changelog.js');
525
532
  const projectNames = projects.split(',').filter(Boolean);
526
533
  const result = await createAPI({}, false)({
527
534
  specifier: bump === 'auto' ? undefined : bump,
@@ -782,6 +789,17 @@ function releaseRepairShell(root, platformOutputs) {
782
789
  const sourceSha = await gitHead(root);
783
790
  const outputs = platformOutputs.map((base) => join(base, sourceSha));
784
791
  if (outputs.length === 0) {
792
+ // No producer job handed outputs over, so this runner is the producer:
793
+ // build the platform legs at the checked-out ref. `build` alone gives a
794
+ // package only the legs its own graph depends on — the host one and
795
+ // whatever it declares — and the release gate demands the whole declared
796
+ // native closure, so a foreign leg it never asked for was simply absent.
797
+ console.log('Repair pending releases: building cross-platform outputs on this runner.');
798
+ await githubCiNxRunMany(root, {
799
+ targets: PLATFORM_TARGET_GLOBS.join(','),
800
+ projects: releasePackageProjects(packages),
801
+ allowEmptyProjects: true,
802
+ });
785
803
  return;
786
804
  }
787
805
  console.log(`Repair pending releases: applying cross-platform outputs from ${outputs.join(', ')}.`);
@@ -1366,7 +1384,11 @@ async function npmVersionExists(root, name, version) {
1366
1384
  assertPublicStatusAllowed(root, name);
1367
1385
  return npmPublishedVersionExistsOnRegistry(root, name, version);
1368
1386
  }
1369
- return withPrivateNpmUserconfig(registry, 'read', (userconfig) => npmPublishedVersionExistsOnRegistry(root, name, version, { registry: registry.registry, userconfig }));
1387
+ return withPrivateNpmUserconfig(registry, 'read', (userconfig) => npmPublishedVersionExistsOnRegistry(root, name, version, {
1388
+ registry: registry.registry,
1389
+ userconfig,
1390
+ credential: { authKey: registry.authKey, tokenEnv: privateNpmTokenEnvForMode(registry, 'read') },
1391
+ }));
1370
1392
  }
1371
1393
  async function npmPackageExists(root, name) {
1372
1394
  const registry = selectRegistryForPackage(root, name);
@@ -103,6 +103,11 @@ export declare function withPrivateNpmUserconfig<T>(resolved: PrivateNpmRegistry
103
103
  export interface NpmStatusOptions {
104
104
  registry?: string;
105
105
  userconfig?: string;
106
+ /** Path-scoped auth key and token env, so the credential can ride env config. */
107
+ credential?: {
108
+ authKey: string;
109
+ tokenEnv: string;
110
+ };
106
111
  }
107
112
  /**
108
113
  * Failure-aware registry status: only a genuine not-found result means absent.
@@ -1 +1 @@
1
- {"version":3,"file":"private-npm.d.ts","sourceRoot":"","sources":["../../src/release/private-npm.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"private-npm.d.ts","sourceRoot":"","sources":["../../src/release/private-npm.ts"],"names":[],"mappings":"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"}
@@ -179,7 +179,12 @@ export function resolvePrivateNpmWorkflowConfig(root) {
179
179
  return undefined;
180
180
  }
181
181
  const npmrcEnv = npmrcAuthTokenEnv(root, declared.scope);
182
- const readTokenEnv = consumes ? (declared.readTokenEnv ?? npmrcEnv) : undefined;
182
+ // A publishing workspace reads the registry too: every release after the
183
+ // first checks the previous tag's durable state, and that check runs in the
184
+ // producer jobs that never see the publish credential. A declared read token
185
+ // therefore always renders; only the .npmrc fallback stays consumer-only, so
186
+ // a publish token is never promoted into a read role by inference.
187
+ const readTokenEnv = declared.readTokenEnv ?? (consumes ? npmrcEnv : undefined);
183
188
  const publishTokenEnv = publishes ? (declared.publishTokenEnv ?? npmrcEnv) : undefined;
184
189
  if (!readTokenEnv && !publishTokenEnv) {
185
190
  return undefined;
@@ -312,8 +317,24 @@ export async function withPrivateNpmUserconfig(resolved, mode, fn) {
312
317
  await rm(dir, { recursive: true, force: true });
313
318
  }
314
319
  }
315
- function npmStatusEnv(userconfig) {
316
- return userconfig ? { NPM_CONFIG_USERCONFIG: userconfig } : undefined;
320
+ /**
321
+ * npm config precedence is cli > env > project `.npmrc` > userconfig. A
322
+ * repository that commits its own `//host/path:_authToken=${SOME_ENV}` line
323
+ * therefore OVERRIDES the userconfig this module writes, and when that env is
324
+ * unset npm sends the unexpanded value: the registry answers 401 on reads with
325
+ * a perfectly good read credential, naming nothing. So the credential also
326
+ * rides as env config, which the project file cannot outrank, and the token
327
+ * value stays out of every file on disk.
328
+ */
329
+ function npmStatusEnv(userconfig, credential) {
330
+ if (!userconfig)
331
+ return undefined;
332
+ const env = { NPM_CONFIG_USERCONFIG: userconfig };
333
+ const token = credential ? process.env[credential.tokenEnv] : undefined;
334
+ if (credential && token) {
335
+ env[`npm_config_${credential.authKey}`] = token;
336
+ }
337
+ return env;
317
338
  }
318
339
  function npmCommandFailedMessage(npmArgs, exitCode, stdout = '', stderr = '') {
319
340
  const detail = `${stdout}\n${stderr}`.trim();
@@ -330,7 +351,7 @@ export async function npmPublishedVersionExists(root, name, version, options = {
330
351
  if (options.registry) {
331
352
  args.push('--registry', options.registry);
332
353
  }
333
- const result = await runResult('npm', args, root, npmStatusEnv(options.userconfig));
354
+ const result = await runResult('npm', args, root, npmStatusEnv(options.userconfig, options.credential));
334
355
  if (result.exitCode === 0) {
335
356
  return true;
336
357
  }
@@ -345,7 +366,7 @@ export async function npmPackageExists(root, name, options = {}) {
345
366
  if (options.registry) {
346
367
  args.push('--registry', options.registry);
347
368
  }
348
- const result = await runResult('npm', args, root, npmStatusEnv(options.userconfig));
369
+ const result = await runResult('npm', args, root, npmStatusEnv(options.userconfig, options.credential));
349
370
  if (result.exitCode === 0) {
350
371
  return true;
351
372
  }
@@ -372,9 +372,11 @@
372
372
  esac
373
373
  ''}
374
374
  '')
375
- # Epilogue: the wrapper runs devenv from tooling/direnv, so return the shell
376
- # to wherever the caller invoked it. Last, after every project step.
375
+ # Epilogue, after every project step (a project's own enterShell may resolve
376
+ # SDKROOT/compilers; the toolchain identity must see the final values). The
377
+ # stamp logic lives in toolchain-stamp.ts; see its header for why.
377
378
  (lib.mkAfter ''
379
+ bun "$DEVENV_ROOT/toolchain-stamp.ts" || exit $?
378
380
  if [ -n "$DEVENV_SHELL_PWD" ]; then
379
381
  cd "$DEVENV_SHELL_PWD"
380
382
  fi
@@ -140,14 +140,52 @@ devenv_path_and_caches() {
140
140
  }
141
141
 
142
142
  build_devenv_shell() {
143
+ local since
144
+ since="$(date +%s)"
143
145
  # One evaluation: the shell that captures the environment is the shell
144
146
  # build. A separate `devenv shell -- date` evaluated everything twice.
145
147
  persist_devenv_environment
148
+ # Only the ephemeral-runner path of setup-devenv opts in: the scan walks the
149
+ # whole store, which on a developer host or a host runner is large and not
150
+ # ours to root.
151
+ if [ "${SMOO_ROOT_BUILD_INPUTS:-false}" = true ]; then
152
+ root_build_inputs "$since"
153
+ fi
146
154
  # Add repo-local tools only after the shell exists; cleanup steps use an
147
155
  # explicit PATH because failures before this point must still refresh caches.
148
156
  add_repo_paths
149
157
  }
150
158
 
159
+ # The store cache's post phase collects garbage down to the live roots before
160
+ # it saves, and the shell's own root (.devenv/gc/shell) covers only the build
161
+ # closure. What evaluation fetched and built - flake input sources, the
162
+ # import-from-derivation outputs devenv-nixpkgs-patched and cabal2nix-* - has
163
+ # no root, so it was collected on the miss run and every hit run rebuilt it
164
+ # (measured at ~80s of a 150s setup on hosted macOS, run 34427309827). devenv
165
+ # records no store paths in its eval cache, so the exact set is the paths this
166
+ # build registered: root them under .devenv/gc, which the devenv cache carries
167
+ # and /nix/var/nix/gcroots/auto (inside the store cache) points at.
168
+ root_build_inputs() {
169
+ local since="$1" gcdir="$PWD/.devenv/gc/build-inputs" paths
170
+ rm -rf "$gcdir"
171
+ mkdir -p "$gcdir"
172
+ # `nix path-info --all --json` is an object keyed by path on Nix >= 2.19 and
173
+ # an array of {path} objects before that.
174
+ paths="$(nix path-info --all --json 2>/dev/null | jq -r --argjson since "$since" '
175
+ (if type == "array" then map({key: .path, value: .}) | from_entries else . end)
176
+ | to_entries[] | select(.value.registrationTime >= $since) | select(.key | endswith(".drv") | not) | .key')"
177
+ if [ -z "$paths" ]; then
178
+ echo "no store paths registered since $since; nothing to root"
179
+ return 0
180
+ fi
181
+ # Store paths are installables; --out-link names the first link and numbers
182
+ # the rest, each an indirect gc root. Derivations are excluded: keep-derivations
183
+ # retains the ones whose outputs are rooted, and realising a .drv would build it.
184
+ # shellcheck disable=SC2086
185
+ nix build --out-link "$gcdir/path" $paths
186
+ echo "rooted $(printf '%s\n' "$paths" | wc -l | tr -d ' ') store paths registered during the shell build under $gcdir"
187
+ }
188
+
151
189
  # Workflow steps run their commands directly — never through `devenv shell` —
152
190
  # so nothing the shell hooks export survives this composite action on its own.
153
191
  # Persisting a hand-picked list here proved to be whack-a-mole: the TTSC
@@ -26,6 +26,9 @@
26
26
  * Failures aggregate so a single direnv reload surfaces every problem.
27
27
  * Error text names variables and exit codes only: secret values, provider
28
28
  * stdout/stderr, and command arguments are never echoed.
29
+ * A resolved value still reaches the environment of the install its caller
30
+ * runs next, so `maskSecretValues` redacts those values out of any captured
31
+ * child output that caller replays.
29
32
  *
30
33
  * The variable `smoo.remoteCache.tokenSecret` names is never resolved here,
31
34
  * nor anywhere at shell entry. A remote cache is an optimization, and shell
@@ -311,6 +314,69 @@ const runSecretCommand: SecretCommandRunner = async (argv) => {
311
314
  return stdout;
312
315
  };
313
316
 
317
+ /** '*', the byte a redacted secret leaves behind. */
318
+ const MASK_BYTE = 0x2a;
319
+
320
+ /**
321
+ * A copy of captured child output with every resolved secret value replaced
322
+ * by the same number of `*` bytes.
323
+ *
324
+ * setup-environment.ts puts the values this file resolves into the
325
+ * environment of the install it then runs, and replays that child's captured
326
+ * stdout/stderr verbatim when it fails. Whatever the child echoes — a prepare
327
+ * script printing its environment, a registry URL carrying an inline
328
+ * credential — would otherwise walk straight past the suppression the rest of
329
+ * this file maintains. Redaction is byte-exact and same-length, so the
330
+ * failure being reported stays legible and every offset in it still lines up.
331
+ * Output with nothing to redact is returned as it came in, so the path that
332
+ * has no secrets to hide copies nothing.
333
+ */
334
+ export function maskSecretValues(output: Uint8Array, values: Iterable<string>): Uint8Array {
335
+ const encoder = new TextEncoder();
336
+ let masked: Uint8Array | undefined;
337
+ for (const value of values) {
338
+ const needle = encoder.encode(value);
339
+ if (needle.length === 0 || needle.length > output.length) {
340
+ continue;
341
+ }
342
+ for (let from = 0; from + needle.length <= output.length; ) {
343
+ const at = indexOfBytes(masked ?? output, needle, from);
344
+ if (at < 0) {
345
+ break;
346
+ }
347
+ // `new Uint8Array`, not `.slice()`: a captured child's output arrives as
348
+ // a node Buffer, whose `slice` is `subarray` — a view. Masking through
349
+ // one would rewrite the caller's own captured bytes.
350
+ masked ??= new Uint8Array(output);
351
+ masked.fill(MASK_BYTE, at, at + needle.length);
352
+ from = at + needle.length;
353
+ }
354
+ }
355
+ return masked ?? output;
356
+ }
357
+
358
+ /** First occurrence of `needle` in `haystack` at or after `from`, or -1. */
359
+ function indexOfBytes(haystack: Uint8Array, needle: Uint8Array, from: number): number {
360
+ const first = needle[0];
361
+ if (first === undefined) {
362
+ return -1;
363
+ }
364
+ const last = haystack.length - needle.length;
365
+ for (let at = haystack.indexOf(first, from); at >= 0 && at <= last; at = haystack.indexOf(first, at + 1)) {
366
+ let matches = true;
367
+ for (let offset = 1; offset < needle.length; offset += 1) {
368
+ if (haystack[at + offset] !== needle[offset]) {
369
+ matches = false;
370
+ break;
371
+ }
372
+ }
373
+ if (matches) {
374
+ return at;
375
+ }
376
+ }
377
+ return -1;
378
+ }
379
+
314
380
  /**
315
381
  * The declared secrets an install needs, resolved before it runs. The cache
316
382
  * token is deliberately not among them: a remote cache is an optimization, so
@@ -4,7 +4,7 @@ import { mkdir, rmdir, stat } from 'node:fs/promises';
4
4
  import { createRequire } from 'node:module';
5
5
  import path from 'node:path';
6
6
  import { $ } from 'bun';
7
- import { resolveSecretEnvironment } from './secret-references.ts';
7
+ import { maskSecretValues, resolveSecretEnvironment } from './secret-references.ts';
8
8
 
9
9
  // DEVENV_ROOT is set by the devenv shell, which is how this script normally
10
10
  // runs. CI jobs that install dependencies without building that shell (the
@@ -24,6 +24,14 @@ class CapturedCommandError extends Error {
24
24
  }
25
25
  }
26
26
 
27
+ // Every value resolved out of smoo.secrets below. The install inherits them,
28
+ // so whatever a failing child echoed is redacted before its captured output
29
+ // is replayed. Declared above the first replay site (resolveProjectRoot's own
30
+ // failure) because module consts are not hoisted: a reference from there to a
31
+ // const declared further down would report a temporal-dead-zone error instead
32
+ // of the failure it was called to report.
33
+ const resolvedSecretValues: string[] = [];
34
+
27
35
  async function resolveProjectRoot(): Promise<string> {
28
36
  if (devenvRoot) {
29
37
  return path.resolve(`${devenvRoot}/../..`);
@@ -66,19 +74,11 @@ const TYPESCRIPT_API_VERSION = '6.0.3';
66
74
  process.chdir(projectRoot);
67
75
 
68
76
  try {
69
- // Provider-declared secrets (smoo.secrets) resolve before any install. The
70
- // values land in THIS process environment only — bun install, the prepare
71
- // scripts it runs, and every later child of this script inherit them (for
72
- // example .npmrc `${VAR}` auth); the direnv shell itself does not, which is
73
- // the point: this script must never act as a global shell export.
74
- for (const [name, value] of Object.entries(await resolveSecretEnvironment({ root: projectRoot }))) {
75
- process.env[name] = value;
76
- }
77
-
78
77
  // Bootstrap only: install deps + wire local git hooks/config.
79
78
  // Do not import workspace packages here — this script is what installs them,
80
79
  // and package resolution/Typia transforms are not available yet.
81
80
  if (process.env.CI) {
81
+ await resolveSecrets();
82
82
  // Concurrent devenv activations share one node_modules, so the CI
83
83
  // installs race exactly like local ones (EEXIST link failures under
84
84
  // parallel shells). Serialize them under the same setup lock. Nothing
@@ -118,24 +118,60 @@ try {
118
118
  process.exit(1);
119
119
  }
120
120
  } else {
121
- await installLocalDependencies();
121
+ // A local secret-resolution or install failure (a provider that is not
122
+ // signed in, an unpublished private package, a missing registry
123
+ // credential, a lockfile that needs `devenv update`) must not take the
124
+ // shell down with it: direnv drops the whole environment on a non-zero
125
+ // exit, and then bun, nx, op and every other tool needed to repair the
126
+ // install are gone too. Report it, finish what does not depend on the
127
+ // install, and load the shell. CI above stays strict.
128
+ const installError = await installLocalDependencies();
129
+ if (installError === undefined) {
130
+ // Pin unscoped typescript → API 6 for root and Bun's shared .bun hoist (Nx).
131
+ ensureTypeScriptApiPackage(projectRoot);
132
+ }
133
+ await applyWorkspaceGitConfig(projectRoot);
134
+ if (installError !== undefined) {
135
+ reportDegradedSetup(installError);
136
+ }
122
137
  }
123
-
124
- // Pin unscoped typescript → API 6 for root and Bun's shared .bun hoist (Nx).
125
- ensureTypeScriptApiPackage(projectRoot);
126
-
127
- await applyWorkspaceGitConfig(projectRoot);
128
138
  } catch (error) {
129
139
  reportSetupFailure(error);
130
140
  }
131
141
 
132
- async function installLocalDependencies(): Promise<void> {
142
+ /**
143
+ * Provider-declared secrets (smoo.secrets) resolve before any install. The
144
+ * values land in THIS process environment only — bun install, the prepare
145
+ * scripts it runs, and every later child of this script inherit them (for
146
+ * example .npmrc `${VAR}` auth); the direnv shell itself does not, which is
147
+ * the point: this script must never act as a global shell export.
148
+ */
149
+ async function resolveSecrets(): Promise<void> {
150
+ for (const [name, value] of Object.entries(await resolveSecretEnvironment({ root: projectRoot }))) {
151
+ process.env[name] = value;
152
+ resolvedSecretValues.push(value);
153
+ }
154
+ }
155
+
156
+ async function installLocalDependencies(): Promise<unknown> {
157
+ try {
158
+ await resolveSecrets();
159
+ } catch (error) {
160
+ return error;
161
+ }
133
162
  // bun install runs the root prepare script. Multiple concurrent direnv
134
163
  // activations can otherwise race while mutating the same files under
135
- // node_modules.
164
+ // node_modules. Nothing that exits the process may run inside the callback
165
+ // (see the CI branch), so the failure is returned, not thrown.
166
+ let installError: unknown;
136
167
  await withSetupLock(async () => {
137
- await runSetupCommand('bun install --no-summary', $`bun install --no-summary`);
168
+ try {
169
+ await runSetupCommand('bun install --no-summary', $`bun install --no-summary`);
170
+ } catch (error) {
171
+ installError = error;
172
+ }
138
173
  });
174
+ return installError;
139
175
  }
140
176
 
141
177
  function ensureTypeScriptApiPackage(root: string): void {
@@ -374,25 +410,44 @@ function isFileExistsError(error: unknown): boolean {
374
410
  }
375
411
 
376
412
  function reportSetupFailure(error: unknown): never {
413
+ describeFailure('ERROR', error);
414
+ process.exit(1);
415
+ }
416
+
417
+ function reportDegradedSetup(error: unknown): void {
418
+ describeFailure('WARNING', error);
419
+ console.error(
420
+ 'The shell is loaded WITHOUT installed dependencies so the tools to repair this stay available.\n' +
421
+ 'Fix the cause above (missing registry credential, unpublished package, stale lockfile → `devenv update`),\n' +
422
+ 'then run `bun install` or `direnv reload`.',
423
+ );
424
+ console.error('---');
425
+ }
426
+
427
+ function describeFailure(level: 'ERROR' | 'WARNING', error: unknown): void {
377
428
  if (error instanceof CapturedCommandError) {
378
- console.error(`--- ERROR: setup-environment.ts failed while running: ${error.command}`);
429
+ console.error(`--- ${level}: setup-environment.ts failed while running: ${error.command}`);
379
430
  console.error(`exit code: ${error.exitCode}`);
380
431
  } else {
381
- console.error(`--- ERROR: setup-environment.ts failed: ${error}`);
432
+ console.error(`--- ${level}: setup-environment.ts failed: ${error}`);
382
433
  }
383
434
  replayCapturedOutput(error);
384
435
  console.error('\n---');
385
- process.exit(1);
386
436
  }
387
437
 
388
438
  function replayCapturedOutput(error: unknown): void {
389
439
  if (!(error instanceof CapturedCommandError)) {
390
440
  return;
391
441
  }
392
- if (error.stdout.length > 0) {
393
- process.stdout.write(error.stdout);
442
+ // The install ran with every resolved secret in its environment, so its
443
+ // output is redacted before replay. Masking is same-length, which keeps the
444
+ // failure this replay exists to show intact.
445
+ const stdout = maskSecretValues(error.stdout, resolvedSecretValues);
446
+ const stderr = maskSecretValues(error.stderr, resolvedSecretValues);
447
+ if (stdout.length > 0) {
448
+ process.stdout.write(stdout);
394
449
  }
395
- if (error.stderr.length > 0) {
396
- process.stderr.write(error.stderr);
450
+ if (stderr.length > 0) {
451
+ process.stderr.write(stderr);
397
452
  }
398
453
  }