@smoothbricks/cli 0.1.1 → 0.2.0
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/README.md +155 -30
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +91 -7
- package/dist/devenv/index.d.ts +10 -0
- package/dist/devenv/index.d.ts.map +1 -0
- package/dist/devenv/index.js +27 -0
- package/dist/lib/cli-package.d.ts +4 -0
- package/dist/lib/cli-package.d.ts.map +1 -0
- package/dist/lib/cli-package.js +15 -0
- package/dist/lib/run.d.ts +5 -0
- package/dist/lib/run.d.ts.map +1 -1
- package/dist/lib/run.js +13 -0
- package/dist/lib/workspace.d.ts +15 -1
- package/dist/lib/workspace.d.ts.map +1 -1
- package/dist/lib/workspace.js +25 -2
- package/dist/monorepo/commit-msg.d.ts +8 -1
- package/dist/monorepo/commit-msg.d.ts.map +1 -1
- package/dist/monorepo/commit-msg.js +85 -7
- package/dist/monorepo/index.d.ts +19 -2
- package/dist/monorepo/index.d.ts.map +1 -1
- package/dist/monorepo/index.js +104 -16
- package/dist/monorepo/managed-files.js +1 -1
- package/dist/monorepo/nx-sync.d.ts +2 -1
- package/dist/monorepo/nx-sync.d.ts.map +1 -1
- package/dist/monorepo/nx-sync.js +8 -2
- package/dist/monorepo/package-hygiene.d.ts +6 -2
- package/dist/monorepo/package-hygiene.d.ts.map +1 -1
- package/dist/monorepo/package-hygiene.js +12 -4
- package/dist/monorepo/package-policy.d.ts +22 -2
- package/dist/monorepo/package-policy.d.ts.map +1 -1
- package/dist/monorepo/package-policy.js +1167 -8
- package/dist/monorepo/packed-package.d.ts +3 -0
- package/dist/monorepo/packed-package.d.ts.map +1 -1
- package/dist/monorepo/packed-package.js +68 -36
- package/dist/monorepo/packs/index.d.ts +20 -1
- package/dist/monorepo/packs/index.d.ts.map +1 -1
- package/dist/monorepo/packs/index.js +238 -19
- package/dist/monorepo/publish-workflow.d.ts +0 -4
- package/dist/monorepo/publish-workflow.d.ts.map +1 -1
- package/dist/monorepo/publish-workflow.js +5 -12
- package/dist/monorepo/tool-validation.d.ts +22 -0
- package/dist/monorepo/tool-validation.d.ts.map +1 -0
- package/dist/monorepo/tool-validation.js +399 -0
- package/dist/nx/index.d.ts +24 -0
- package/dist/nx/index.d.ts.map +1 -0
- package/dist/nx/index.js +94 -0
- package/dist/release/bootstrap-npm-packages.d.ts +19 -0
- package/dist/release/bootstrap-npm-packages.d.ts.map +1 -0
- package/dist/release/bootstrap-npm-packages.js +58 -0
- package/dist/release/candidates.d.ts +11 -0
- package/dist/release/candidates.d.ts.map +1 -0
- package/dist/release/candidates.js +181 -0
- package/dist/release/core.d.ts +1 -0
- package/dist/release/core.d.ts.map +1 -1
- package/dist/release/github-release.js +2 -2
- package/dist/release/index.d.ts +25 -0
- package/dist/release/index.d.ts.map +1 -1
- package/dist/release/index.js +247 -49
- package/dist/release/npm-auth.d.ts +0 -1
- package/dist/release/npm-auth.d.ts.map +1 -1
- package/dist/release/npm-auth.js +4 -16
- package/dist/release/orchestration.d.ts +2 -1
- package/dist/release/orchestration.d.ts.map +1 -1
- package/dist/release/orchestration.js +9 -1
- package/dist/release/publish-plan.js +1 -1
- package/managed/raw/git-format-staged.yml +54 -0
- package/managed/raw/tooling/git-hooks/commit-msg.sh +1 -1
- package/managed/templates/github/actions/setup-devenv/action.yml +1 -7
- package/managed/templates/github/workflows/ci.yml +1 -0
- package/package.json +15 -3
- package/src/cli.ts +134 -20
- package/src/devenv/index.test.ts +49 -0
- package/src/devenv/index.ts +38 -0
- package/src/lib/cli-package.ts +18 -0
- package/src/lib/run.ts +19 -0
- package/src/lib/workspace.ts +41 -2
- package/src/monorepo/__tests__/publish-workflow.test.ts +16 -9
- package/src/monorepo/commit-msg.test.ts +45 -0
- package/src/monorepo/commit-msg.ts +107 -7
- package/src/monorepo/index.ts +142 -16
- package/src/monorepo/managed-files.ts +1 -1
- package/src/monorepo/nx-sync.ts +9 -2
- package/src/monorepo/package-hygiene.test.ts +34 -0
- package/src/monorepo/package-hygiene.ts +26 -4
- package/src/monorepo/package-policy.test.ts +902 -0
- package/src/monorepo/package-policy.ts +1393 -7
- package/src/monorepo/packed-package.ts +89 -37
- package/src/monorepo/packs/index.test.ts +189 -0
- package/src/monorepo/packs/index.ts +311 -20
- package/src/monorepo/publish-workflow.ts +8 -16
- package/src/monorepo/setup-test-tracing.test.ts +120 -0
- package/src/monorepo/tool-validation.test.ts +261 -0
- package/src/monorepo/tool-validation.ts +462 -0
- package/src/nx/index.test.ts +64 -0
- package/src/nx/index.ts +119 -0
- package/src/release/__tests__/bootstrap-npm-packages.test.ts +127 -0
- package/src/release/__tests__/candidates.test.ts +217 -0
- package/src/release/__tests__/core-properties.test.ts +4 -4
- package/src/release/__tests__/core-scenarios.test.ts +15 -5
- package/src/release/__tests__/core.test.ts +2 -2
- package/src/release/__tests__/fixture-repo.test.ts +22 -13
- package/src/release/__tests__/github-release.test.ts +13 -8
- package/src/release/__tests__/helpers/fixture-repo.ts +1 -0
- package/src/release/__tests__/npm-auth.test.ts +12 -21
- package/src/release/__tests__/orchestration.test.ts +51 -7
- package/src/release/__tests__/publish-plan.test.ts +9 -3
- package/src/release/__tests__/retag-unpublished.test.ts +1 -1
- package/src/release/__tests__/trust-publisher.test.ts +133 -0
- package/src/release/bootstrap-npm-packages.ts +88 -0
- package/src/release/candidates.ts +225 -0
- package/src/release/core.ts +1 -0
- package/src/release/github-release.ts +2 -2
- package/src/release/index.ts +346 -56
- package/src/release/npm-auth.ts +4 -33
- package/src/release/orchestration.ts +12 -2
- package/src/release/publish-plan.ts +1 -1
- package/managed/raw/.git-format-staged.yml +0 -47
|
@@ -3,67 +3,119 @@ import { join } from 'node:path';
|
|
|
3
3
|
import { publint } from 'publint';
|
|
4
4
|
import { formatMessage } from 'publint/utils';
|
|
5
5
|
import { isRecord } from '../lib/json.js';
|
|
6
|
-
import { runStatus } from '../lib/run.js';
|
|
6
|
+
import { runResult, runStatus } from '../lib/run.js';
|
|
7
7
|
import type { PackageInfo } from '../lib/workspace.js';
|
|
8
8
|
import { listPublicPackages } from '../lib/workspace.js';
|
|
9
9
|
import { readPackedPackageJson, validatePackedWorkspaceDependencies } from './packed-manifest.js';
|
|
10
10
|
|
|
11
11
|
export async function validatePackedPublicPackages(root: string): Promise<number> {
|
|
12
|
+
return (
|
|
13
|
+
(await validatePackedPublicPackagePublint(root)) +
|
|
14
|
+
(await validatePackedPublicPackageManifest(root)) +
|
|
15
|
+
(await validatePackedPublicPackageTypes(root))
|
|
16
|
+
);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export async function validatePackedPublicPackagePublint(root: string): Promise<number> {
|
|
12
20
|
let failures = 0;
|
|
13
21
|
for (const pkg of listPublicPackages(root)) {
|
|
14
|
-
failures += await
|
|
22
|
+
failures += await validatePackedPublicPackageTool(root, pkg, validatePublint);
|
|
15
23
|
}
|
|
16
24
|
return failures;
|
|
17
25
|
}
|
|
18
26
|
|
|
19
|
-
async function
|
|
27
|
+
export async function validatePackedPublicPackageManifest(root: string): Promise<number> {
|
|
20
28
|
let failures = 0;
|
|
21
|
-
const
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
failures++;
|
|
27
|
-
}
|
|
29
|
+
for (const pkg of listPublicPackages(root)) {
|
|
30
|
+
failures += await validatePackedPublicPackageTool(root, pkg, validatePackedManifest);
|
|
31
|
+
}
|
|
32
|
+
return failures;
|
|
33
|
+
}
|
|
28
34
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
35
|
+
export async function validatePackedPublicPackageTypes(root: string): Promise<number> {
|
|
36
|
+
let failures = 0;
|
|
37
|
+
for (const pkg of listPublicPackages(root)) {
|
|
38
|
+
failures += await validatePackedPublicPackageTool(root, pkg, validateAttw);
|
|
39
|
+
}
|
|
40
|
+
return failures;
|
|
41
|
+
}
|
|
34
42
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
'cjs-resolves-to-esm',
|
|
44
|
-
...attwExcludedEntrypointArgs(pkg),
|
|
45
|
-
];
|
|
46
|
-
const attwStatus = await runStatus('attw', ['--quiet', ...attwArgs], root, true);
|
|
47
|
-
if (attwStatus !== 0) {
|
|
48
|
-
await runStatus('attw', attwArgs, root);
|
|
49
|
-
console.error(`${pkg.path}: are-the-types-wrong validation failed`);
|
|
50
|
-
failures++;
|
|
51
|
-
} else {
|
|
52
|
-
console.log(`${pkg.path}: are-the-types-wrong valid.`);
|
|
53
|
-
}
|
|
43
|
+
async function validatePackedPublicPackageTool(
|
|
44
|
+
root: string,
|
|
45
|
+
pkg: PackageInfo,
|
|
46
|
+
validate: (root: string, pkg: PackageInfo, packed: { path: string; arrayBuffer: ArrayBuffer }) => Promise<number>,
|
|
47
|
+
): Promise<number> {
|
|
48
|
+
const packed = await packPackage(root, pkg);
|
|
49
|
+
try {
|
|
50
|
+
return await validate(root, pkg, packed);
|
|
54
51
|
} catch (error) {
|
|
55
52
|
const message = error instanceof Error ? error.message : String(error);
|
|
56
53
|
console.error(`${pkg.path}: packed package validation failed: ${message}`);
|
|
57
|
-
|
|
54
|
+
return 1;
|
|
58
55
|
} finally {
|
|
59
56
|
unlinkSync(packed.path);
|
|
60
57
|
}
|
|
61
|
-
|
|
62
|
-
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
async function validatePublint(
|
|
61
|
+
_root: string,
|
|
62
|
+
pkg: PackageInfo,
|
|
63
|
+
packed: { path: string; arrayBuffer: ArrayBuffer },
|
|
64
|
+
): Promise<number> {
|
|
65
|
+
let failures = 0;
|
|
66
|
+
const lint = await publint({ pack: { tarball: packed.arrayBuffer }, level: 'warning', strict: true });
|
|
67
|
+
for (const message of lint.messages) {
|
|
68
|
+
console.error(`${pkg.path}: publint ${message.type} ${message.code}: ${formatMessage(message, lint.pkg)}`);
|
|
69
|
+
failures++;
|
|
70
|
+
}
|
|
71
|
+
return failures;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
async function validatePackedManifest(
|
|
75
|
+
root: string,
|
|
76
|
+
pkg: PackageInfo,
|
|
77
|
+
packed: { path: string; arrayBuffer: ArrayBuffer },
|
|
78
|
+
): Promise<number> {
|
|
79
|
+
let failures = 0;
|
|
80
|
+
const packedPackage = await readPackedPackageJson(root, packed.path, pkg.name);
|
|
81
|
+
for (const message of validatePackedWorkspaceDependencies(root, pkg, packedPackage)) {
|
|
82
|
+
console.error(message);
|
|
83
|
+
failures++;
|
|
63
84
|
}
|
|
64
85
|
return failures;
|
|
65
86
|
}
|
|
66
87
|
|
|
88
|
+
async function validateAttw(root: string, pkg: PackageInfo, packed: { path: string }): Promise<number> {
|
|
89
|
+
const attwArgs = [
|
|
90
|
+
packed.path,
|
|
91
|
+
'--format',
|
|
92
|
+
'ascii',
|
|
93
|
+
'--no-color',
|
|
94
|
+
'--profile',
|
|
95
|
+
'node16',
|
|
96
|
+
'--ignore-rules',
|
|
97
|
+
'cjs-resolves-to-esm',
|
|
98
|
+
...attwExcludedEntrypointArgs(pkg),
|
|
99
|
+
];
|
|
100
|
+
const attw = await runResult('attw', attwArgs, root);
|
|
101
|
+
if (attw.exitCode === 0) {
|
|
102
|
+
return 0;
|
|
103
|
+
}
|
|
104
|
+
printAttwOutput(attw.stdout);
|
|
105
|
+
printAttwOutput(attw.stderr);
|
|
106
|
+
console.error(`${pkg.path}: are-the-types-wrong validation failed`);
|
|
107
|
+
return 1;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
function printAttwOutput(output: string): void {
|
|
111
|
+
for (const line of output.split('\n')) {
|
|
112
|
+
if (!line || line.includes('(ignored)')) {
|
|
113
|
+
continue;
|
|
114
|
+
}
|
|
115
|
+
console.error(line);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
67
119
|
function attwExcludedEntrypointArgs(pkg: PackageInfo): string[] {
|
|
68
120
|
const excluded = wasmExportEntrypoints(pkg.json.exports);
|
|
69
121
|
return excluded.length === 0 ? [] : ['--exclude-entrypoints', ...excluded];
|
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
import { describe, expect, it } from 'bun:test';
|
|
2
|
+
import type { MonorepoPack } from './index.js';
|
|
3
|
+
import { runValidatePacks } from './index.js';
|
|
4
|
+
|
|
5
|
+
const ctx = { root: '/workspace', syncRuntime: false };
|
|
6
|
+
|
|
7
|
+
describe('monorepo validation pack phases', () => {
|
|
8
|
+
it('runs fix mode in pre-fix, build, post-fix, then validation order', async () => {
|
|
9
|
+
const events: string[] = [];
|
|
10
|
+
const packs: MonorepoPack[] = [
|
|
11
|
+
{
|
|
12
|
+
name: 'pre',
|
|
13
|
+
fixPreBuild() {
|
|
14
|
+
events.push('pre-fix');
|
|
15
|
+
},
|
|
16
|
+
validatePreBuild() {
|
|
17
|
+
events.push('pre-validate');
|
|
18
|
+
return 0;
|
|
19
|
+
},
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
name: 'post',
|
|
23
|
+
fixPostBuild() {
|
|
24
|
+
events.push('post-fix');
|
|
25
|
+
},
|
|
26
|
+
validatePostBuild() {
|
|
27
|
+
events.push('post-validate');
|
|
28
|
+
return 0;
|
|
29
|
+
},
|
|
30
|
+
},
|
|
31
|
+
];
|
|
32
|
+
|
|
33
|
+
const result = await runValidatePacks(
|
|
34
|
+
ctx,
|
|
35
|
+
{ fix: true },
|
|
36
|
+
{
|
|
37
|
+
packs,
|
|
38
|
+
runBuild() {
|
|
39
|
+
events.push('build');
|
|
40
|
+
return 0;
|
|
41
|
+
},
|
|
42
|
+
},
|
|
43
|
+
);
|
|
44
|
+
|
|
45
|
+
expect(result).toEqual({ failures: 0, failedChecks: 0 });
|
|
46
|
+
expect(events).toEqual(['pre-fix', 'build', 'post-fix', 'pre-validate', 'post-validate']);
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
it('runs normal mode in pre-validation, build, then post-validation order', async () => {
|
|
50
|
+
const events: string[] = [];
|
|
51
|
+
const packs: MonorepoPack[] = [
|
|
52
|
+
{
|
|
53
|
+
name: 'pre',
|
|
54
|
+
validatePreBuild() {
|
|
55
|
+
events.push('pre-validate');
|
|
56
|
+
return 0;
|
|
57
|
+
},
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
name: 'post',
|
|
61
|
+
validatePostBuild() {
|
|
62
|
+
events.push('post-validate');
|
|
63
|
+
return 0;
|
|
64
|
+
},
|
|
65
|
+
},
|
|
66
|
+
];
|
|
67
|
+
|
|
68
|
+
const result = await runValidatePacks(
|
|
69
|
+
ctx,
|
|
70
|
+
{},
|
|
71
|
+
{
|
|
72
|
+
packs,
|
|
73
|
+
runBuild() {
|
|
74
|
+
events.push('build');
|
|
75
|
+
return 0;
|
|
76
|
+
},
|
|
77
|
+
},
|
|
78
|
+
);
|
|
79
|
+
|
|
80
|
+
expect(result).toEqual({ failures: 0, failedChecks: 0 });
|
|
81
|
+
expect(events).toEqual(['pre-validate', 'build', 'post-validate']);
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
it('counts separate post-build packs as separate failed checks', async () => {
|
|
85
|
+
const packs: MonorepoPack[] = [
|
|
86
|
+
{
|
|
87
|
+
name: 'workspace-dependencies',
|
|
88
|
+
validatePostBuild() {
|
|
89
|
+
return 88;
|
|
90
|
+
},
|
|
91
|
+
},
|
|
92
|
+
{
|
|
93
|
+
name: 'package-hygiene',
|
|
94
|
+
validatePostBuild() {
|
|
95
|
+
return 0;
|
|
96
|
+
},
|
|
97
|
+
},
|
|
98
|
+
];
|
|
99
|
+
|
|
100
|
+
const result = await runValidatePacks(
|
|
101
|
+
ctx,
|
|
102
|
+
{},
|
|
103
|
+
{
|
|
104
|
+
packs,
|
|
105
|
+
runBuild() {
|
|
106
|
+
return 0;
|
|
107
|
+
},
|
|
108
|
+
},
|
|
109
|
+
);
|
|
110
|
+
|
|
111
|
+
expect(result).toEqual({ failures: 88, failedChecks: 1 });
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
it('does not build or run post-build validation after a fail-fast pre-build failure', async () => {
|
|
115
|
+
const events: string[] = [];
|
|
116
|
+
const packs: MonorepoPack[] = [
|
|
117
|
+
{
|
|
118
|
+
name: 'pre',
|
|
119
|
+
validatePreBuild() {
|
|
120
|
+
events.push('pre-validate');
|
|
121
|
+
return 2;
|
|
122
|
+
},
|
|
123
|
+
},
|
|
124
|
+
{
|
|
125
|
+
name: 'post',
|
|
126
|
+
validatePostBuild() {
|
|
127
|
+
events.push('post-validate');
|
|
128
|
+
return 0;
|
|
129
|
+
},
|
|
130
|
+
},
|
|
131
|
+
];
|
|
132
|
+
|
|
133
|
+
const result = await runValidatePacks(
|
|
134
|
+
ctx,
|
|
135
|
+
{ failFast: true },
|
|
136
|
+
{
|
|
137
|
+
packs,
|
|
138
|
+
runBuild() {
|
|
139
|
+
events.push('build');
|
|
140
|
+
return 0;
|
|
141
|
+
},
|
|
142
|
+
},
|
|
143
|
+
);
|
|
144
|
+
|
|
145
|
+
expect(result).toEqual({ failures: 2, failedChecks: 1 });
|
|
146
|
+
expect(events).toEqual(['pre-validate']);
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
it('does not run post-build fixers or validation after a build failure', async () => {
|
|
150
|
+
const events: string[] = [];
|
|
151
|
+
const packs: MonorepoPack[] = [
|
|
152
|
+
{
|
|
153
|
+
name: 'pre',
|
|
154
|
+
fixPreBuild() {
|
|
155
|
+
events.push('pre-fix');
|
|
156
|
+
},
|
|
157
|
+
validatePreBuild() {
|
|
158
|
+
events.push('pre-validate');
|
|
159
|
+
return 0;
|
|
160
|
+
},
|
|
161
|
+
},
|
|
162
|
+
{
|
|
163
|
+
name: 'post',
|
|
164
|
+
fixPostBuild() {
|
|
165
|
+
events.push('post-fix');
|
|
166
|
+
},
|
|
167
|
+
validatePostBuild() {
|
|
168
|
+
events.push('post-validate');
|
|
169
|
+
return 0;
|
|
170
|
+
},
|
|
171
|
+
},
|
|
172
|
+
];
|
|
173
|
+
|
|
174
|
+
const result = await runValidatePacks(
|
|
175
|
+
ctx,
|
|
176
|
+
{ fix: true },
|
|
177
|
+
{
|
|
178
|
+
packs,
|
|
179
|
+
runBuild() {
|
|
180
|
+
events.push('build');
|
|
181
|
+
return 1;
|
|
182
|
+
},
|
|
183
|
+
},
|
|
184
|
+
);
|
|
185
|
+
|
|
186
|
+
expect(result).toEqual({ failures: 1, failedChecks: 1 });
|
|
187
|
+
expect(events).toEqual(['pre-fix', 'build']);
|
|
188
|
+
});
|
|
189
|
+
});
|