@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.
- package/dist/lib/json.d.ts +9 -0
- package/dist/lib/json.d.ts.map +1 -1
- package/dist/lib/json.js +65 -53
- package/dist/monorepo/managed-files.d.ts +9 -0
- package/dist/monorepo/managed-files.d.ts.map +1 -1
- package/dist/monorepo/managed-files.js +28 -2
- package/dist/monorepo/publish-workflow.d.ts.map +1 -1
- package/dist/monorepo/publish-workflow.js +52 -2
- package/dist/release/github-release.d.ts +16 -0
- package/dist/release/github-release.d.ts.map +1 -1
- package/dist/release/github-release.js +11 -2
- package/dist/release/index.d.ts +1 -1
- package/dist/release/index.d.ts.map +1 -1
- package/dist/release/index.js +29 -7
- package/dist/release/private-npm.d.ts +5 -0
- package/dist/release/private-npm.d.ts.map +1 -1
- package/dist/release/private-npm.js +26 -5
- package/managed/raw/tooling/direnv/devenv.smoo.nix +4 -2
- package/managed/raw/tooling/direnv/github-actions-bootstrap.sh +38 -0
- package/managed/raw/tooling/direnv/secret-references.ts +66 -0
- package/managed/raw/tooling/direnv/setup-environment.ts +81 -26
- package/managed/raw/tooling/direnv/toolchain-stamp.ts +88 -0
- package/managed/templates/github/actions/setup-devenv/action.yml +4 -2
- package/package.json +2 -2
- package/src/lib/json.ts +9 -0
- package/src/monorepo/__tests__/publish-workflow.test.ts +54 -0
- package/src/monorepo/managed-files.test.ts +26 -0
- package/src/monorepo/managed-files.ts +36 -2
- package/src/monorepo/publish-workflow.ts +70 -2
- package/src/monorepo/secret-references.test.ts +68 -0
- package/src/release/__tests__/private-npm-status.test.ts +37 -0
- package/src/release/__tests__/private-npm-workflow.test.ts +20 -0
- package/src/release/github-release.ts +31 -2
- package/src/release/index.ts +30 -4
- package/src/release/private-npm.ts +30 -5
package/src/release/index.ts
CHANGED
|
@@ -48,6 +48,7 @@ export {
|
|
|
48
48
|
type PrivateNpmRegistryConfigErrorKind,
|
|
49
49
|
type PublishDestination,
|
|
50
50
|
privateNpmPublishArgs,
|
|
51
|
+
privateNpmTokenEnvForMode,
|
|
51
52
|
privateNpmUserconfigContent,
|
|
52
53
|
publishPrivateWithDiagnostics,
|
|
53
54
|
type Result as PrivateNpmResult,
|
|
@@ -58,6 +59,7 @@ export {
|
|
|
58
59
|
withPrivateNpmUserconfig,
|
|
59
60
|
} from './private-npm.js';
|
|
60
61
|
|
|
62
|
+
import { PLATFORM_TARGET_GLOBS } from '@smoothbricks/nx-plugin/workspace-config-policy';
|
|
61
63
|
import { ciApiContext } from '../github-ci/api.js';
|
|
62
64
|
import { readProjectTargets } from '../nx/index.js';
|
|
63
65
|
import {
|
|
@@ -88,6 +90,7 @@ import {
|
|
|
88
90
|
import {
|
|
89
91
|
createOrUpdateGithubRelease,
|
|
90
92
|
githubReleaseLookupExists,
|
|
93
|
+
importWorkspaceNx,
|
|
91
94
|
renderNxProjectChangelogContents,
|
|
92
95
|
withNxWorkspaceRoot,
|
|
93
96
|
} from './github-release.js';
|
|
@@ -113,6 +116,7 @@ import {
|
|
|
113
116
|
npmPublishedVersionExists as npmPublishedVersionExistsOnRegistry,
|
|
114
117
|
type PrivateNpmRegistry,
|
|
115
118
|
privateNpmPublishArgs,
|
|
119
|
+
privateNpmTokenEnvForMode,
|
|
116
120
|
publishPrivateWithDiagnostics,
|
|
117
121
|
selectPublishDestination,
|
|
118
122
|
selectRegistryForPackage,
|
|
@@ -753,7 +757,13 @@ async function publishPrivatePackedPackage(
|
|
|
753
757
|
await publishPrivateWithDiagnostics(
|
|
754
758
|
pkg,
|
|
755
759
|
{
|
|
756
|
-
publish: () =>
|
|
760
|
+
publish: () =>
|
|
761
|
+
runNpm(root, args, {
|
|
762
|
+
NPM_CONFIG_USERCONFIG: userconfig,
|
|
763
|
+
// Env config outranks a committed project `.npmrc` auth line; see
|
|
764
|
+
// npmStatusEnv in private-npm.ts for why that matters here.
|
|
765
|
+
[`npm_config_${registry.authKey}`]: process.env[privateNpmTokenEnvForMode(registry, 'publish')] ?? '',
|
|
766
|
+
}),
|
|
757
767
|
// The open publish userconfig already authenticates this registry,
|
|
758
768
|
// so the failure probe reuses it. Opening a second read-mode
|
|
759
769
|
// userconfig here demanded a read credential the publishing job need
|
|
@@ -763,6 +773,7 @@ async function publishPrivatePackedPackage(
|
|
|
763
773
|
npmPublishedVersionExistsOnRegistry(root, pkg.name, pkg.version, {
|
|
764
774
|
registry: registry.registry,
|
|
765
775
|
userconfig,
|
|
776
|
+
credential: { authKey: registry.authKey, tokenEnv: privateNpmTokenEnvForMode(registry, 'publish') },
|
|
766
777
|
}),
|
|
767
778
|
log: (message) => console.log(message),
|
|
768
779
|
error: (message) => console.error(message),
|
|
@@ -881,8 +892,8 @@ async function runNxReleaseVersion(
|
|
|
881
892
|
|
|
882
893
|
async function runNxReleaseVersionPreview(root: string, projects: string, bump: string): Promise<ReleasePackage[]> {
|
|
883
894
|
return withNxWorkspaceRoot(root, async () => {
|
|
884
|
-
const { createAPI } = await
|
|
885
|
-
const { createAPI: createChangelogAPI } = await
|
|
895
|
+
const { createAPI } = await importWorkspaceNx(root, 'src/command-line/release/version.js');
|
|
896
|
+
const { createAPI: createChangelogAPI } = await importWorkspaceNx(root, 'src/command-line/release/changelog.js');
|
|
886
897
|
const projectNames = projects.split(',').filter(Boolean);
|
|
887
898
|
const result = await createAPI(
|
|
888
899
|
{},
|
|
@@ -1196,6 +1207,17 @@ function releaseRepairShell(root: string, platformOutputs: readonly string[]): R
|
|
|
1196
1207
|
const sourceSha = await gitHead(root);
|
|
1197
1208
|
const outputs = platformOutputs.map((base) => join(base, sourceSha));
|
|
1198
1209
|
if (outputs.length === 0) {
|
|
1210
|
+
// No producer job handed outputs over, so this runner is the producer:
|
|
1211
|
+
// build the platform legs at the checked-out ref. `build` alone gives a
|
|
1212
|
+
// package only the legs its own graph depends on — the host one and
|
|
1213
|
+
// whatever it declares — and the release gate demands the whole declared
|
|
1214
|
+
// native closure, so a foreign leg it never asked for was simply absent.
|
|
1215
|
+
console.log('Repair pending releases: building cross-platform outputs on this runner.');
|
|
1216
|
+
await githubCiNxRunMany(root, {
|
|
1217
|
+
targets: PLATFORM_TARGET_GLOBS.join(','),
|
|
1218
|
+
projects: releasePackageProjects(packages),
|
|
1219
|
+
allowEmptyProjects: true,
|
|
1220
|
+
});
|
|
1199
1221
|
return;
|
|
1200
1222
|
}
|
|
1201
1223
|
console.log(`Repair pending releases: applying cross-platform outputs from ${outputs.join(', ')}.`);
|
|
@@ -1864,7 +1886,11 @@ async function npmVersionExists(root: string, name: string, version: string): Pr
|
|
|
1864
1886
|
return npmPublishedVersionExistsOnRegistry(root, name, version);
|
|
1865
1887
|
}
|
|
1866
1888
|
return withPrivateNpmUserconfig(registry, 'read', (userconfig) =>
|
|
1867
|
-
npmPublishedVersionExistsOnRegistry(root, name, version, {
|
|
1889
|
+
npmPublishedVersionExistsOnRegistry(root, name, version, {
|
|
1890
|
+
registry: registry.registry,
|
|
1891
|
+
userconfig,
|
|
1892
|
+
credential: { authKey: registry.authKey, tokenEnv: privateNpmTokenEnvForMode(registry, 'read') },
|
|
1893
|
+
}),
|
|
1868
1894
|
);
|
|
1869
1895
|
}
|
|
1870
1896
|
|
|
@@ -247,7 +247,12 @@ export function resolvePrivateNpmWorkflowConfig(root: string): PackagePrivateNpm
|
|
|
247
247
|
return undefined;
|
|
248
248
|
}
|
|
249
249
|
const npmrcEnv = npmrcAuthTokenEnv(root, declared.scope);
|
|
250
|
-
|
|
250
|
+
// A publishing workspace reads the registry too: every release after the
|
|
251
|
+
// first checks the previous tag's durable state, and that check runs in the
|
|
252
|
+
// producer jobs that never see the publish credential. A declared read token
|
|
253
|
+
// therefore always renders; only the .npmrc fallback stays consumer-only, so
|
|
254
|
+
// a publish token is never promoted into a read role by inference.
|
|
255
|
+
const readTokenEnv = declared.readTokenEnv ?? (consumes ? npmrcEnv : undefined);
|
|
251
256
|
const publishTokenEnv = publishes ? (declared.publishTokenEnv ?? npmrcEnv) : undefined;
|
|
252
257
|
if (!readTokenEnv && !publishTokenEnv) {
|
|
253
258
|
return undefined;
|
|
@@ -412,10 +417,30 @@ export async function withPrivateNpmUserconfig<T>(
|
|
|
412
417
|
export interface NpmStatusOptions {
|
|
413
418
|
registry?: string;
|
|
414
419
|
userconfig?: string;
|
|
420
|
+
/** Path-scoped auth key and token env, so the credential can ride env config. */
|
|
421
|
+
credential?: { authKey: string; tokenEnv: string };
|
|
415
422
|
}
|
|
416
423
|
|
|
417
|
-
|
|
418
|
-
|
|
424
|
+
/**
|
|
425
|
+
* npm config precedence is cli > env > project `.npmrc` > userconfig. A
|
|
426
|
+
* repository that commits its own `//host/path:_authToken=${SOME_ENV}` line
|
|
427
|
+
* therefore OVERRIDES the userconfig this module writes, and when that env is
|
|
428
|
+
* unset npm sends the unexpanded value: the registry answers 401 on reads with
|
|
429
|
+
* a perfectly good read credential, naming nothing. So the credential also
|
|
430
|
+
* rides as env config, which the project file cannot outrank, and the token
|
|
431
|
+
* value stays out of every file on disk.
|
|
432
|
+
*/
|
|
433
|
+
function npmStatusEnv(
|
|
434
|
+
userconfig: string | undefined,
|
|
435
|
+
credential?: { authKey: string; tokenEnv: string },
|
|
436
|
+
): Record<string, string> | undefined {
|
|
437
|
+
if (!userconfig) return undefined;
|
|
438
|
+
const env: Record<string, string> = { NPM_CONFIG_USERCONFIG: userconfig };
|
|
439
|
+
const token = credential ? process.env[credential.tokenEnv] : undefined;
|
|
440
|
+
if (credential && token) {
|
|
441
|
+
env[`npm_config_${credential.authKey}`] = token;
|
|
442
|
+
}
|
|
443
|
+
return env;
|
|
419
444
|
}
|
|
420
445
|
|
|
421
446
|
function npmCommandFailedMessage(npmArgs: string[], exitCode: number, stdout = '', stderr = ''): string {
|
|
@@ -439,7 +464,7 @@ export async function npmPublishedVersionExists(
|
|
|
439
464
|
if (options.registry) {
|
|
440
465
|
args.push('--registry', options.registry);
|
|
441
466
|
}
|
|
442
|
-
const result = await runResult('npm', args, root, npmStatusEnv(options.userconfig));
|
|
467
|
+
const result = await runResult('npm', args, root, npmStatusEnv(options.userconfig, options.credential));
|
|
443
468
|
if (result.exitCode === 0) {
|
|
444
469
|
return true;
|
|
445
470
|
}
|
|
@@ -455,7 +480,7 @@ export async function npmPackageExists(root: string, name: string, options: NpmS
|
|
|
455
480
|
if (options.registry) {
|
|
456
481
|
args.push('--registry', options.registry);
|
|
457
482
|
}
|
|
458
|
-
const result = await runResult('npm', args, root, npmStatusEnv(options.userconfig));
|
|
483
|
+
const result = await runResult('npm', args, root, npmStatusEnv(options.userconfig, options.credential));
|
|
459
484
|
if (result.exitCode === 0) {
|
|
460
485
|
return true;
|
|
461
486
|
}
|