@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.
Files changed (117) hide show
  1. package/README.md +155 -30
  2. package/dist/cli.d.ts.map +1 -1
  3. package/dist/cli.js +91 -7
  4. package/dist/devenv/index.d.ts +10 -0
  5. package/dist/devenv/index.d.ts.map +1 -0
  6. package/dist/devenv/index.js +27 -0
  7. package/dist/lib/cli-package.d.ts +4 -0
  8. package/dist/lib/cli-package.d.ts.map +1 -0
  9. package/dist/lib/cli-package.js +15 -0
  10. package/dist/lib/run.d.ts +5 -0
  11. package/dist/lib/run.d.ts.map +1 -1
  12. package/dist/lib/run.js +13 -0
  13. package/dist/lib/workspace.d.ts +15 -1
  14. package/dist/lib/workspace.d.ts.map +1 -1
  15. package/dist/lib/workspace.js +25 -2
  16. package/dist/monorepo/commit-msg.d.ts +8 -1
  17. package/dist/monorepo/commit-msg.d.ts.map +1 -1
  18. package/dist/monorepo/commit-msg.js +85 -7
  19. package/dist/monorepo/index.d.ts +19 -2
  20. package/dist/monorepo/index.d.ts.map +1 -1
  21. package/dist/monorepo/index.js +104 -16
  22. package/dist/monorepo/managed-files.js +1 -1
  23. package/dist/monorepo/nx-sync.d.ts +2 -1
  24. package/dist/monorepo/nx-sync.d.ts.map +1 -1
  25. package/dist/monorepo/nx-sync.js +8 -2
  26. package/dist/monorepo/package-hygiene.d.ts +6 -2
  27. package/dist/monorepo/package-hygiene.d.ts.map +1 -1
  28. package/dist/monorepo/package-hygiene.js +12 -4
  29. package/dist/monorepo/package-policy.d.ts +22 -2
  30. package/dist/monorepo/package-policy.d.ts.map +1 -1
  31. package/dist/monorepo/package-policy.js +1167 -8
  32. package/dist/monorepo/packed-package.d.ts +3 -0
  33. package/dist/monorepo/packed-package.d.ts.map +1 -1
  34. package/dist/monorepo/packed-package.js +68 -36
  35. package/dist/monorepo/packs/index.d.ts +20 -1
  36. package/dist/monorepo/packs/index.d.ts.map +1 -1
  37. package/dist/monorepo/packs/index.js +238 -19
  38. package/dist/monorepo/publish-workflow.d.ts +0 -4
  39. package/dist/monorepo/publish-workflow.d.ts.map +1 -1
  40. package/dist/monorepo/publish-workflow.js +5 -12
  41. package/dist/monorepo/tool-validation.d.ts +22 -0
  42. package/dist/monorepo/tool-validation.d.ts.map +1 -0
  43. package/dist/monorepo/tool-validation.js +399 -0
  44. package/dist/nx/index.d.ts +24 -0
  45. package/dist/nx/index.d.ts.map +1 -0
  46. package/dist/nx/index.js +94 -0
  47. package/dist/release/bootstrap-npm-packages.d.ts +19 -0
  48. package/dist/release/bootstrap-npm-packages.d.ts.map +1 -0
  49. package/dist/release/bootstrap-npm-packages.js +58 -0
  50. package/dist/release/candidates.d.ts +11 -0
  51. package/dist/release/candidates.d.ts.map +1 -0
  52. package/dist/release/candidates.js +181 -0
  53. package/dist/release/core.d.ts +1 -0
  54. package/dist/release/core.d.ts.map +1 -1
  55. package/dist/release/github-release.js +2 -2
  56. package/dist/release/index.d.ts +25 -0
  57. package/dist/release/index.d.ts.map +1 -1
  58. package/dist/release/index.js +247 -49
  59. package/dist/release/npm-auth.d.ts +0 -1
  60. package/dist/release/npm-auth.d.ts.map +1 -1
  61. package/dist/release/npm-auth.js +4 -16
  62. package/dist/release/orchestration.d.ts +2 -1
  63. package/dist/release/orchestration.d.ts.map +1 -1
  64. package/dist/release/orchestration.js +9 -1
  65. package/dist/release/publish-plan.js +1 -1
  66. package/managed/raw/git-format-staged.yml +54 -0
  67. package/managed/raw/tooling/git-hooks/commit-msg.sh +1 -1
  68. package/managed/templates/github/actions/setup-devenv/action.yml +1 -7
  69. package/managed/templates/github/workflows/ci.yml +1 -0
  70. package/package.json +15 -3
  71. package/src/cli.ts +134 -20
  72. package/src/devenv/index.test.ts +49 -0
  73. package/src/devenv/index.ts +38 -0
  74. package/src/lib/cli-package.ts +18 -0
  75. package/src/lib/run.ts +19 -0
  76. package/src/lib/workspace.ts +41 -2
  77. package/src/monorepo/__tests__/publish-workflow.test.ts +16 -9
  78. package/src/monorepo/commit-msg.test.ts +45 -0
  79. package/src/monorepo/commit-msg.ts +107 -7
  80. package/src/monorepo/index.ts +142 -16
  81. package/src/monorepo/managed-files.ts +1 -1
  82. package/src/monorepo/nx-sync.ts +9 -2
  83. package/src/monorepo/package-hygiene.test.ts +34 -0
  84. package/src/monorepo/package-hygiene.ts +26 -4
  85. package/src/monorepo/package-policy.test.ts +902 -0
  86. package/src/monorepo/package-policy.ts +1393 -7
  87. package/src/monorepo/packed-package.ts +89 -37
  88. package/src/monorepo/packs/index.test.ts +189 -0
  89. package/src/monorepo/packs/index.ts +311 -20
  90. package/src/monorepo/publish-workflow.ts +8 -16
  91. package/src/monorepo/setup-test-tracing.test.ts +120 -0
  92. package/src/monorepo/tool-validation.test.ts +261 -0
  93. package/src/monorepo/tool-validation.ts +462 -0
  94. package/src/nx/index.test.ts +64 -0
  95. package/src/nx/index.ts +119 -0
  96. package/src/release/__tests__/bootstrap-npm-packages.test.ts +127 -0
  97. package/src/release/__tests__/candidates.test.ts +217 -0
  98. package/src/release/__tests__/core-properties.test.ts +4 -4
  99. package/src/release/__tests__/core-scenarios.test.ts +15 -5
  100. package/src/release/__tests__/core.test.ts +2 -2
  101. package/src/release/__tests__/fixture-repo.test.ts +22 -13
  102. package/src/release/__tests__/github-release.test.ts +13 -8
  103. package/src/release/__tests__/helpers/fixture-repo.ts +1 -0
  104. package/src/release/__tests__/npm-auth.test.ts +12 -21
  105. package/src/release/__tests__/orchestration.test.ts +51 -7
  106. package/src/release/__tests__/publish-plan.test.ts +9 -3
  107. package/src/release/__tests__/retag-unpublished.test.ts +1 -1
  108. package/src/release/__tests__/trust-publisher.test.ts +133 -0
  109. package/src/release/bootstrap-npm-packages.ts +88 -0
  110. package/src/release/candidates.ts +225 -0
  111. package/src/release/core.ts +1 -0
  112. package/src/release/github-release.ts +2 -2
  113. package/src/release/index.ts +346 -56
  114. package/src/release/npm-auth.ts +4 -33
  115. package/src/release/orchestration.ts +12 -2
  116. package/src/release/publish-plan.ts +1 -1
  117. 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 validatePackedPublicPackage(root, pkg);
22
+ failures += await validatePackedPublicPackageTool(root, pkg, validatePublint);
15
23
  }
16
24
  return failures;
17
25
  }
18
26
 
19
- async function validatePackedPublicPackage(root: string, pkg: PackageInfo): Promise<number> {
27
+ export async function validatePackedPublicPackageManifest(root: string): Promise<number> {
20
28
  let failures = 0;
21
- const packed = await packPackage(root, pkg);
22
- try {
23
- const lint = await publint({ pack: { tarball: packed.arrayBuffer }, level: 'warning', strict: true });
24
- for (const message of lint.messages) {
25
- console.error(`${pkg.path}: publint ${message.type} ${message.code}: ${formatMessage(message, lint.pkg)}`);
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
- const packedPackage = await readPackedPackageJson(root, packed.path, pkg.name);
30
- for (const message of validatePackedWorkspaceDependencies(root, pkg, packedPackage)) {
31
- console.error(message);
32
- failures++;
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
- const attwArgs = [
36
- packed.path,
37
- '--format',
38
- 'ascii',
39
- '--no-color',
40
- '--profile',
41
- 'node16',
42
- '--ignore-rules',
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
- failures++;
54
+ return 1;
58
55
  } finally {
59
56
  unlinkSync(packed.path);
60
57
  }
61
- if (failures === 0) {
62
- console.log(`${pkg.path}: packed package is valid.`);
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
+ });