@smoothbricks/cli 0.3.4 โ 0.4.1
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/cli.js +14 -0
- package/dist/github-ci/index.d.ts +12 -0
- package/dist/github-ci/index.d.ts.map +1 -1
- package/dist/github-ci/index.js +72 -4
- package/dist/lib/run.d.ts +1 -0
- package/dist/lib/run.d.ts.map +1 -1
- package/dist/lib/run.js +11 -0
- package/dist/monorepo/ci-workflow.d.ts +26 -0
- package/dist/monorepo/ci-workflow.d.ts.map +1 -0
- package/dist/monorepo/ci-workflow.js +201 -0
- package/dist/monorepo/managed-files.d.ts.map +1 -1
- package/dist/monorepo/managed-files.js +97 -5
- package/dist/monorepo/nx-sync.d.ts.map +1 -1
- package/dist/monorepo/nx-sync.js +18 -4
- package/dist/monorepo/package-hygiene.d.ts +5 -0
- package/dist/monorepo/package-hygiene.d.ts.map +1 -1
- package/dist/monorepo/package-hygiene.js +18 -4
- package/dist/monorepo/package-policy.d.ts.map +1 -1
- package/dist/monorepo/package-policy.js +4 -2
- package/dist/monorepo/packed-package.js +5 -4
- package/dist/monorepo/packs/index.js +6 -2
- package/dist/monorepo/publish-workflow.d.ts +7 -1
- package/dist/monorepo/publish-workflow.d.ts.map +1 -1
- package/dist/monorepo/publish-workflow.js +59 -15
- package/managed/raw/git-format-staged.yml +4 -0
- package/package.json +2 -2
- package/src/cli.ts +35 -5
- package/src/github-ci/index.ts +94 -8
- package/src/lib/run.ts +13 -0
- package/src/monorepo/__tests__/ci-workflow.test.ts +34 -0
- package/src/monorepo/__tests__/publish-workflow.test.ts +65 -2
- package/src/monorepo/ci-workflow.ts +229 -0
- package/src/monorepo/managed-files.ts +115 -5
- package/src/monorepo/nx-sync.ts +18 -4
- package/src/monorepo/package-hygiene.test.ts +54 -1
- package/src/monorepo/package-hygiene.ts +34 -4
- package/src/monorepo/package-policy.test.ts +16 -6
- package/src/monorepo/package-policy.ts +4 -2
- package/src/monorepo/packed-package.ts +5 -5
- package/src/monorepo/packs/index.ts +6 -2
- package/src/monorepo/publish-workflow.ts +73 -16
- package/managed/templates/github/workflows/ci.yml +0 -102
|
@@ -1,11 +1,20 @@
|
|
|
1
|
-
import { run, runStatus } from '../lib/run.js';
|
|
1
|
+
import { printCommandOutput, run, runResult, runStatus } from '../lib/run.js';
|
|
2
2
|
|
|
3
3
|
export interface PackageHygieneShell {
|
|
4
4
|
run(command: string, args: string[], cwd: string): Promise<void>;
|
|
5
|
+
runResult?(
|
|
6
|
+
command: string,
|
|
7
|
+
args: string[],
|
|
8
|
+
cwd: string,
|
|
9
|
+
): Promise<{
|
|
10
|
+
exitCode: number;
|
|
11
|
+
stdout: string;
|
|
12
|
+
stderr: string;
|
|
13
|
+
}>;
|
|
5
14
|
runStatus(command: string, args: string[], cwd: string, quiet?: boolean): Promise<number>;
|
|
6
15
|
}
|
|
7
16
|
|
|
8
|
-
const defaultShell: PackageHygieneShell = { run, runStatus };
|
|
17
|
+
const defaultShell: PackageHygieneShell = { run, runResult, runStatus };
|
|
9
18
|
|
|
10
19
|
export async function fixPackageHygiene(
|
|
11
20
|
root: string,
|
|
@@ -14,8 +23,12 @@ export async function fixPackageHygiene(
|
|
|
14
23
|
): Promise<void> {
|
|
15
24
|
const verbose = typeof verboseOrShell === 'boolean' ? verboseOrShell : false;
|
|
16
25
|
const shell = typeof verboseOrShell === 'boolean' ? maybeShell : verboseOrShell;
|
|
17
|
-
const
|
|
26
|
+
const result = await runPackageHygieneCommand(shell, 'sherif', ['-f', '--select', 'highest'], root, verbose);
|
|
27
|
+
const status = result.exitCode;
|
|
18
28
|
if (status !== 0) {
|
|
29
|
+
if (!verbose) {
|
|
30
|
+
printCommandOutput(result.stdout, result.stderr);
|
|
31
|
+
}
|
|
19
32
|
throw new Error(`sherif -f --select highest failed with exit code ${status}`);
|
|
20
33
|
}
|
|
21
34
|
}
|
|
@@ -27,10 +40,27 @@ export async function validatePackageHygiene(
|
|
|
27
40
|
): Promise<number> {
|
|
28
41
|
const verbose = typeof verboseOrShell === 'boolean' ? verboseOrShell : false;
|
|
29
42
|
const shell = typeof verboseOrShell === 'boolean' ? maybeShell : verboseOrShell;
|
|
30
|
-
const
|
|
43
|
+
const result = await runPackageHygieneCommand(shell, 'sherif', ['--fail-on-warnings'], root, verbose);
|
|
44
|
+
const status = result.exitCode;
|
|
31
45
|
if (status !== 0) {
|
|
46
|
+
if (!verbose) {
|
|
47
|
+
printCommandOutput(result.stdout, result.stderr);
|
|
48
|
+
}
|
|
32
49
|
console.error('sherif package hygiene validation failed');
|
|
33
50
|
return 1;
|
|
34
51
|
}
|
|
35
52
|
return 0;
|
|
36
53
|
}
|
|
54
|
+
|
|
55
|
+
async function runPackageHygieneCommand(
|
|
56
|
+
shell: PackageHygieneShell,
|
|
57
|
+
command: string,
|
|
58
|
+
args: string[],
|
|
59
|
+
root: string,
|
|
60
|
+
verbose: boolean,
|
|
61
|
+
): Promise<{ exitCode: number; stdout: string; stderr: string }> {
|
|
62
|
+
if (!verbose && shell.runResult) {
|
|
63
|
+
return shell.runResult(command, args, root);
|
|
64
|
+
}
|
|
65
|
+
return { exitCode: await shell.runStatus(command, args, root, !verbose), stdout: '', stderr: '' };
|
|
66
|
+
}
|
|
@@ -51,14 +51,17 @@ describe('root smoo monorepo policy', () => {
|
|
|
51
51
|
);
|
|
52
52
|
await writeJson(join(root, 'nx.json'), validNxJson());
|
|
53
53
|
|
|
54
|
-
expect(validateRootPackagePolicy(root)).toBe(
|
|
55
|
-
expect(validateNxReleaseConfig(root)).toBe(
|
|
54
|
+
expect(validateRootPackagePolicy(root)).toBe(7);
|
|
55
|
+
expect(validateNxReleaseConfig(root)).toBe(8);
|
|
56
56
|
|
|
57
57
|
applyFixableMonorepoDefaults(root);
|
|
58
58
|
|
|
59
59
|
const rootPackage = await readJson(join(root, 'package.json'));
|
|
60
60
|
const nxJson = await readJson(join(root, 'nx.json'));
|
|
61
61
|
expect(rootPackage.scripts).toEqual({
|
|
62
|
+
clean: 'nx run-many -t clean; nx reset',
|
|
63
|
+
'clean:node_modules':
|
|
64
|
+
'rm -rf node_modules && find e* t* p* -type d -name node_modules -print0 | xargs -0 rm -rvf',
|
|
62
65
|
'format:changed': 'git-format-staged --config tooling/git-hooks/git-format-staged.yml --also-unstaged',
|
|
63
66
|
'format:staged': 'git-format-staged --config tooling/git-hooks/git-format-staged.yml',
|
|
64
67
|
lint: 'nx run-many -t lint',
|
|
@@ -66,7 +69,7 @@ describe('root smoo monorepo policy', () => {
|
|
|
66
69
|
});
|
|
67
70
|
expect(rootPackage).toMatchObject({ nx: { includedScripts: [] } });
|
|
68
71
|
expect(nxJson.namedInputs).toEqual(validNamedInputs());
|
|
69
|
-
expect(nxJson.targetDefaults).toEqual(
|
|
72
|
+
expect(nxJson.targetDefaults).toEqual(validTargetDefaults());
|
|
70
73
|
expect(nxJson.plugins).toEqual([
|
|
71
74
|
{
|
|
72
75
|
plugin: '@nx/js/typescript',
|
|
@@ -152,12 +155,12 @@ describe('root smoo monorepo policy', () => {
|
|
|
152
155
|
},
|
|
153
156
|
});
|
|
154
157
|
|
|
155
|
-
expect(validateNxReleaseConfig(root)).toBe(
|
|
158
|
+
expect(validateNxReleaseConfig(root)).toBe(6);
|
|
156
159
|
|
|
157
160
|
applyFixableMonorepoDefaults(root);
|
|
158
161
|
|
|
159
162
|
const nxJson = await readJson(join(root, 'nx.json'));
|
|
160
|
-
expect(nxJson.targetDefaults).toEqual(
|
|
163
|
+
expect(nxJson.targetDefaults).toEqual(validTargetDefaults());
|
|
161
164
|
expect(validateNxReleaseConfig(root)).toBe(0);
|
|
162
165
|
} finally {
|
|
163
166
|
await rm(root, { recursive: true, force: true });
|
|
@@ -1096,7 +1099,7 @@ function validConfiguredNxJson(): Record<string, unknown> {
|
|
|
1096
1099
|
return {
|
|
1097
1100
|
...validNxJson(),
|
|
1098
1101
|
namedInputs: validNamedInputs(),
|
|
1099
|
-
targetDefaults:
|
|
1102
|
+
targetDefaults: validTargetDefaults(),
|
|
1100
1103
|
plugins: [
|
|
1101
1104
|
{
|
|
1102
1105
|
plugin: '@nx/js/typescript',
|
|
@@ -1115,6 +1118,13 @@ function validConfiguredNxJson(): Record<string, unknown> {
|
|
|
1115
1118
|
};
|
|
1116
1119
|
}
|
|
1117
1120
|
|
|
1121
|
+
function validTargetDefaults(): Record<string, unknown> {
|
|
1122
|
+
return {
|
|
1123
|
+
build: { cache: true, outputs: ['{projectRoot}/dist'] },
|
|
1124
|
+
clean: { executor: '@smoothbricks/nx-plugin:clean-outputs', cache: false },
|
|
1125
|
+
};
|
|
1126
|
+
}
|
|
1127
|
+
|
|
1118
1128
|
function validNamedInputs(): Record<string, unknown> {
|
|
1119
1129
|
return {
|
|
1120
1130
|
default: ['{projectRoot}/**/*', 'sharedGlobals'],
|
|
@@ -48,10 +48,12 @@ export { SMOO_NX_RELEASE_TAG_PATTERN, SMOO_NX_VERSION_ACTIONS };
|
|
|
48
48
|
|
|
49
49
|
const extraCommitScopes = ['release'];
|
|
50
50
|
const rootScriptPolicy: Record<string, string> = {
|
|
51
|
+
clean: 'nx run-many -t clean; nx reset',
|
|
52
|
+
'clean:node_modules': 'rm -rf node_modules && find e* t* p* -type d -name node_modules -print0 | xargs -0 rm -rvf',
|
|
53
|
+
'format:changed': 'git-format-staged --config tooling/git-hooks/git-format-staged.yml --also-unstaged',
|
|
54
|
+
'format:staged': 'git-format-staged --config tooling/git-hooks/git-format-staged.yml',
|
|
51
55
|
lint: 'nx run-many -t lint',
|
|
52
56
|
'lint:fix': 'git-format-staged --config tooling/git-hooks/git-format-staged.yml --unstaged',
|
|
53
|
-
'format:staged': 'git-format-staged --config tooling/git-hooks/git-format-staged.yml',
|
|
54
|
-
'format:changed': 'git-format-staged --config tooling/git-hooks/git-format-staged.yml --also-unstaged',
|
|
55
57
|
};
|
|
56
58
|
|
|
57
59
|
export function applyFixableMonorepoDefaults(root: string): void {
|
|
@@ -3,7 +3,7 @@ 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 {
|
|
6
|
+
import { printCommandOutput, runResult } 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';
|
|
@@ -142,14 +142,14 @@ async function packPackage(root: string, pkg: PackageInfo): Promise<{ path: stri
|
|
|
142
142
|
const tarballName = `.smoo-${process.pid}-${Date.now()}.tgz`;
|
|
143
143
|
const tarballPath = join(root, tarballName);
|
|
144
144
|
try {
|
|
145
|
-
const
|
|
145
|
+
const result = await runResult(
|
|
146
146
|
'bun',
|
|
147
147
|
['pm', 'pack', '--filename', tarballName, '--ignore-scripts', '--quiet'],
|
|
148
148
|
packageDir,
|
|
149
|
-
true,
|
|
150
149
|
);
|
|
151
|
-
if (
|
|
152
|
-
|
|
150
|
+
if (result.exitCode !== 0) {
|
|
151
|
+
printCommandOutput(result.stdout, result.stderr);
|
|
152
|
+
throw new Error(`bun pm pack failed with exit code ${result.exitCode}`);
|
|
153
153
|
}
|
|
154
154
|
const bytes = new Uint8Array(readFileSync(tarballPath));
|
|
155
155
|
return { path: tarballPath, arrayBuffer: bytes.slice().buffer };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { chmodSync, existsSync, statSync } from 'node:fs';
|
|
2
2
|
import { join } from 'node:path';
|
|
3
|
-
import { runStatus } from '../../lib/run.js';
|
|
3
|
+
import { printCommandOutput, runResult, runStatus } from '../../lib/run.js';
|
|
4
4
|
import { readProjectTargets } from '../../nx/index.js';
|
|
5
5
|
import { syncBunLockfileVersions, validateBunLockfileVersions } from '../lockfile.js';
|
|
6
6
|
import { validateManagedFiles } from '../managed-files.js';
|
|
@@ -315,10 +315,14 @@ async function runBuild(ctx: MonorepoContext, options: ValidatePackOptions = {})
|
|
|
315
315
|
if (options.verbose) {
|
|
316
316
|
printCheckHeading('build', true);
|
|
317
317
|
}
|
|
318
|
-
const
|
|
318
|
+
const result = options.verbose
|
|
319
|
+
? { exitCode: await runStatus('nx', ['run-many', '-t', 'build'], ctx.root, false), stdout: '', stderr: '' }
|
|
320
|
+
: await runResult('nx', ['run-many', '-t', 'build'], ctx.root);
|
|
321
|
+
const status = result.exitCode;
|
|
319
322
|
if (status !== 0) {
|
|
320
323
|
if (!options.verbose) {
|
|
321
324
|
printCheckHeading('build', true);
|
|
325
|
+
printCommandOutput(result.stdout, result.stderr);
|
|
322
326
|
}
|
|
323
327
|
console.error('nx run-many -t build failed');
|
|
324
328
|
printCheckStatus('build', 1);
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { isSmoothBricksCodebasePackageName } from '../lib/cli-package.js';
|
|
2
2
|
|
|
3
3
|
export type PublishWorkflowBump = 'auto' | 'patch' | 'minor' | 'major' | 'prerelease';
|
|
4
|
-
export type PublishWorkflowCondition = 'version-mode-not-none' | 'failure' | 'always';
|
|
4
|
+
export type PublishWorkflowCondition = 'version-mode-not-none' | 'deploy-production' | 'failure' | 'always';
|
|
5
5
|
export type PublishWorkflowNxTarget = 'build' | 'lint' | 'test';
|
|
6
|
+
export type PublishWorkflowDeployEnvironment = 'none' | 'production';
|
|
6
7
|
|
|
7
8
|
export enum PublishWorkflowStepKind {
|
|
8
9
|
Checkout = 'checkout',
|
|
@@ -18,6 +19,7 @@ export enum PublishWorkflowStepKind {
|
|
|
18
19
|
UploadTraceDbs = 'upload-trace-dbs',
|
|
19
20
|
ValidateMonorepoConfig = 'validate-monorepo-config',
|
|
20
21
|
PublishRelease = 'publish-release',
|
|
22
|
+
DeployProduction = 'deploy-production',
|
|
21
23
|
SaveNixDevenv = 'save-nix-devenv',
|
|
22
24
|
}
|
|
23
25
|
|
|
@@ -35,11 +37,14 @@ export interface PublishWorkflowDefinition {
|
|
|
35
37
|
}
|
|
36
38
|
|
|
37
39
|
export interface PublishWorkflowDefinitionOptions {
|
|
40
|
+
deploy?: boolean;
|
|
41
|
+
deployProvider?: 'cloudflare';
|
|
38
42
|
repoName?: string;
|
|
39
43
|
}
|
|
40
44
|
|
|
41
45
|
export interface PublishWorkflowInputs {
|
|
42
46
|
bump: PublishWorkflowBump;
|
|
47
|
+
deployEnvironment: PublishWorkflowDeployEnvironment;
|
|
43
48
|
dryRun: boolean;
|
|
44
49
|
}
|
|
45
50
|
|
|
@@ -65,6 +70,7 @@ export interface PublishWorkflowCallbacks {
|
|
|
65
70
|
uploadTraceDbs(): Promise<void>;
|
|
66
71
|
validateMonorepoConfig(): Promise<void>;
|
|
67
72
|
publishRelease(input: { bump: PublishWorkflowBump; dryRun: boolean }): Promise<void>;
|
|
73
|
+
deployProduction(): Promise<void>;
|
|
68
74
|
saveNixDevenv(input: PublishWorkflowSetupOutputs): Promise<void>;
|
|
69
75
|
}
|
|
70
76
|
|
|
@@ -90,6 +96,19 @@ export function definePublishWorkflow(options: PublishWorkflowDefinitionOptions
|
|
|
90
96
|
if (isSmoothBricksCodebasePackageName(options.repoName)) {
|
|
91
97
|
setupSteps.push({ kind: PublishWorkflowStepKind.BuildSelfHostedCli, name: '๐๏ธ Build self-hosted smoo' });
|
|
92
98
|
}
|
|
99
|
+
const releaseSteps: PublishWorkflowStepInput[] = [
|
|
100
|
+
{
|
|
101
|
+
kind: PublishWorkflowStepKind.PublishRelease,
|
|
102
|
+
name: `๐ฆ Publish release (${versionMode})`,
|
|
103
|
+
},
|
|
104
|
+
];
|
|
105
|
+
if (options.deploy === true) {
|
|
106
|
+
releaseSteps.push({
|
|
107
|
+
kind: PublishWorkflowStepKind.DeployProduction,
|
|
108
|
+
name: '๐ Deploy production',
|
|
109
|
+
condition: 'deploy-production',
|
|
110
|
+
});
|
|
111
|
+
}
|
|
93
112
|
return {
|
|
94
113
|
steps: numberWorkflowSteps([
|
|
95
114
|
...setupSteps,
|
|
@@ -127,10 +146,7 @@ export function definePublishWorkflow(options: PublishWorkflowDefinitionOptions
|
|
|
127
146
|
name: `โ
Validate monorepo config (${versionMode})`,
|
|
128
147
|
condition: 'version-mode-not-none',
|
|
129
148
|
},
|
|
130
|
-
|
|
131
|
-
kind: PublishWorkflowStepKind.PublishRelease,
|
|
132
|
-
name: `๐ฆ Publish release (${versionMode})`,
|
|
133
|
-
},
|
|
149
|
+
...releaseSteps,
|
|
134
150
|
{
|
|
135
151
|
kind: PublishWorkflowStepKind.SaveNixDevenv,
|
|
136
152
|
name: '๐งน Cleanup and cache Nix/devenv',
|
|
@@ -153,7 +169,7 @@ export async function runPublishWorkflow(
|
|
|
153
169
|
let failed = false;
|
|
154
170
|
let failure: unknown;
|
|
155
171
|
for (const step of workflow.steps) {
|
|
156
|
-
if (!shouldRunStep(step, version, failed)) {
|
|
172
|
+
if (!shouldRunStep(step, version, failed, context.inputs)) {
|
|
157
173
|
continue;
|
|
158
174
|
}
|
|
159
175
|
try {
|
|
@@ -201,6 +217,9 @@ export async function runPublishWorkflow(
|
|
|
201
217
|
dryRun: context.inputs.dryRun,
|
|
202
218
|
});
|
|
203
219
|
break;
|
|
220
|
+
case PublishWorkflowStepKind.DeployProduction:
|
|
221
|
+
await context.callbacks.deployProduction();
|
|
222
|
+
break;
|
|
204
223
|
case PublishWorkflowStepKind.SaveNixDevenv:
|
|
205
224
|
await context.callbacks.saveNixDevenv(setupOutputs);
|
|
206
225
|
break;
|
|
@@ -216,10 +235,18 @@ export async function runPublishWorkflow(
|
|
|
216
235
|
return { version, failed };
|
|
217
236
|
}
|
|
218
237
|
|
|
219
|
-
function shouldRunStep(
|
|
238
|
+
function shouldRunStep(
|
|
239
|
+
step: PublishWorkflowStep,
|
|
240
|
+
version: PublishWorkflowVersionOutputs,
|
|
241
|
+
failed: boolean,
|
|
242
|
+
inputs: PublishWorkflowInputs,
|
|
243
|
+
): boolean {
|
|
220
244
|
if (step.condition === 'version-mode-not-none') {
|
|
221
245
|
return version.mode !== 'none';
|
|
222
246
|
}
|
|
247
|
+
if (step.condition === 'deploy-production') {
|
|
248
|
+
return version.mode !== 'none' && inputs.deployEnvironment === 'production' && !inputs.dryRun;
|
|
249
|
+
}
|
|
223
250
|
if (step.condition === 'failure') {
|
|
224
251
|
return failed;
|
|
225
252
|
}
|
|
@@ -228,10 +255,19 @@ function shouldRunStep(step: PublishWorkflowStep, version: PublishWorkflowVersio
|
|
|
228
255
|
|
|
229
256
|
export function renderPublishWorkflowYaml(options: PublishWorkflowDefinitionOptions = {}): string {
|
|
230
257
|
const steps = definePublishWorkflow(options).steps;
|
|
231
|
-
return `${renderPublishWorkflowHeader()}${renderPublishWorkflowSteps(steps)}`;
|
|
258
|
+
return `${renderPublishWorkflowHeader(options)}${renderPublishWorkflowSteps(steps, options)}`;
|
|
232
259
|
}
|
|
233
260
|
|
|
234
|
-
function renderPublishWorkflowHeader(): string {
|
|
261
|
+
function renderPublishWorkflowHeader(options: PublishWorkflowDefinitionOptions): string {
|
|
262
|
+
const deployInput =
|
|
263
|
+
options.deploy === true
|
|
264
|
+
? `
|
|
265
|
+
deploy_environment:
|
|
266
|
+
type: choice
|
|
267
|
+
description: Deploy live systems after a successful publish.
|
|
268
|
+
options: [none, production]
|
|
269
|
+
default: none`
|
|
270
|
+
: '';
|
|
235
271
|
return `name: Publish
|
|
236
272
|
|
|
237
273
|
on:
|
|
@@ -247,7 +283,7 @@ on:
|
|
|
247
283
|
dry_run:
|
|
248
284
|
type: boolean
|
|
249
285
|
description: Run release commands without writing versions, tags, publishes, or GitHub Releases.
|
|
250
|
-
default: false
|
|
286
|
+
default: false${deployInput}
|
|
251
287
|
|
|
252
288
|
permissions:
|
|
253
289
|
contents: write
|
|
@@ -271,12 +307,12 @@ jobs:
|
|
|
271
307
|
`;
|
|
272
308
|
}
|
|
273
309
|
|
|
274
|
-
function renderPublishWorkflowSteps(steps: PublishWorkflowStep[]): string {
|
|
310
|
+
function renderPublishWorkflowSteps(steps: PublishWorkflowStep[], options: PublishWorkflowDefinitionOptions): string {
|
|
275
311
|
const lines: string[] = [];
|
|
276
312
|
for (const step of steps) {
|
|
277
313
|
lines.push(...sectionLinesBefore(step));
|
|
278
314
|
lines.push(...commentLinesForStep(step));
|
|
279
|
-
lines.push(...yamlLinesForStep(step));
|
|
315
|
+
lines.push(...yamlLinesForStep(step, options));
|
|
280
316
|
lines.push('');
|
|
281
317
|
}
|
|
282
318
|
return `${lines.join('\n').trimEnd()}\n`;
|
|
@@ -319,7 +355,7 @@ function commentLinesForStep(step: PublishWorkflowStep): string[] {
|
|
|
319
355
|
return [` # Step ${step.number}`];
|
|
320
356
|
}
|
|
321
357
|
|
|
322
|
-
function yamlLinesForStep(step: PublishWorkflowStep): string[] {
|
|
358
|
+
function yamlLinesForStep(step: PublishWorkflowStep, options: PublishWorkflowDefinitionOptions): string[] {
|
|
323
359
|
switch (step.kind) {
|
|
324
360
|
case PublishWorkflowStepKind.Checkout:
|
|
325
361
|
return [
|
|
@@ -396,6 +432,8 @@ function yamlLinesForStep(step: PublishWorkflowStep): string[] {
|
|
|
396
432
|
' # Missing package names are bootstrapped locally before trust setup.',
|
|
397
433
|
` run: smoo release publish --bump "${githubExpression('inputs.bump')}" --dry-run "${githubExpression('inputs.dry_run')}"`,
|
|
398
434
|
];
|
|
435
|
+
case PublishWorkflowStepKind.DeployProduction:
|
|
436
|
+
return deployProductionStep(step, options);
|
|
399
437
|
case PublishWorkflowStepKind.SaveNixDevenv:
|
|
400
438
|
return [
|
|
401
439
|
` - name: ${step.name}`,
|
|
@@ -408,14 +446,33 @@ function yamlLinesForStep(step: PublishWorkflowStep): string[] {
|
|
|
408
446
|
}
|
|
409
447
|
}
|
|
410
448
|
|
|
411
|
-
function
|
|
449
|
+
function deployProductionStep(step: PublishWorkflowStep, options: PublishWorkflowDefinitionOptions): string[] {
|
|
412
450
|
return [
|
|
413
451
|
` - name: ${step.name}`,
|
|
414
|
-
|
|
415
|
-
|
|
452
|
+
' if:',
|
|
453
|
+
" ${{ steps.version.outputs.mode != 'none' && inputs.deploy_environment == 'production' && inputs.dry_run !=",
|
|
454
|
+
" 'true' }}",
|
|
455
|
+
...deployEnvLines(options),
|
|
456
|
+
' run: smoo github-ci nx-deploy --configuration production --mode run-many --verify --name "Deploy Production"',
|
|
416
457
|
];
|
|
417
458
|
}
|
|
418
459
|
|
|
460
|
+
function deployEnvLines(options: PublishWorkflowDefinitionOptions): string[] {
|
|
461
|
+
if (options.deployProvider !== 'cloudflare') {
|
|
462
|
+
return [];
|
|
463
|
+
}
|
|
464
|
+
return [
|
|
465
|
+
' env:',
|
|
466
|
+
' CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }}',
|
|
467
|
+
' CLOUDFLARE_ACCOUNT_ID: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}',
|
|
468
|
+
];
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
function conditionalRunStep(step: PublishWorkflowStep, run: string): string[] {
|
|
472
|
+
const condition = "steps.version.outputs.mode != 'none'";
|
|
473
|
+
return [` - name: ${step.name}`, ` if: ${githubExpression(condition)}`, ` run: ${run}`];
|
|
474
|
+
}
|
|
475
|
+
|
|
419
476
|
function githubExpression(expression: string): string {
|
|
420
477
|
return ['$', '{{ ', expression, ' }}'].join('');
|
|
421
478
|
}
|
|
@@ -1,102 +0,0 @@
|
|
|
1
|
-
name: CI
|
|
2
|
-
|
|
3
|
-
on:
|
|
4
|
-
push:
|
|
5
|
-
branches:
|
|
6
|
-
- '**'
|
|
7
|
-
pull_request:
|
|
8
|
-
|
|
9
|
-
permissions:
|
|
10
|
-
actions: read
|
|
11
|
-
contents: read
|
|
12
|
-
statuses: write
|
|
13
|
-
|
|
14
|
-
defaults:
|
|
15
|
-
run:
|
|
16
|
-
working-directory: tooling/direnv
|
|
17
|
-
|
|
18
|
-
jobs:
|
|
19
|
-
main:
|
|
20
|
-
name: Validate
|
|
21
|
-
runs-on: ubuntu-latest
|
|
22
|
-
timeout-minutes: 45
|
|
23
|
-
env:
|
|
24
|
-
NIX_STORE_NAR: ${{ github.workspace }}/nix-store.nar
|
|
25
|
-
GH_TOKEN: ${{ github.token }}
|
|
26
|
-
steps:
|
|
27
|
-
# Step 1: GitHub adds "Set up job" automatically
|
|
28
|
-
# Step 2
|
|
29
|
-
- name: ๐ฅ Checkout
|
|
30
|
-
uses: actions/checkout@v6.0.2
|
|
31
|
-
with:
|
|
32
|
-
filter: blob:none
|
|
33
|
-
fetch-depth: 0
|
|
34
|
-
|
|
35
|
-
# Step 3. Composite action internals do not affect top-level job step
|
|
36
|
-
# anchors; update the nx-smart --step values below if top-level steps move.
|
|
37
|
-
- name: ๐งฑ Setup Nix/devenv
|
|
38
|
-
id: setup
|
|
39
|
-
uses: ./.github/actions/setup-devenv
|
|
40
|
-
|
|
41
|
-
# --- Nx -----------------------------------------------------------------
|
|
42
|
-
|
|
43
|
-
# Step 4
|
|
44
|
-
# Sets the base and head SHAs required for the nx affected commands
|
|
45
|
-
- name: ๐งญ Set Nx SHAs
|
|
46
|
-
uses: nrwl/nx-set-shas@v5.0.1
|
|
47
|
-
with:
|
|
48
|
-
workflow-id: ci.yml
|
|
49
|
-
|
|
50
|
-
# Step 5
|
|
51
|
-
- name: ๐ง Restore Nx cache
|
|
52
|
-
id: nx-cache
|
|
53
|
-
uses: ./.github/actions/cache-nx
|
|
54
|
-
|
|
55
|
-
# Step 6
|
|
56
|
-
- name: ๐จ Build
|
|
57
|
-
run: smoo github-ci nx-smart --target build --name "Build" --step 6
|
|
58
|
-
|
|
59
|
-
# Step 7
|
|
60
|
-
- name: ๐ Lint
|
|
61
|
-
run: smoo github-ci nx-smart --target lint --name "Lint" --step 7
|
|
62
|
-
|
|
63
|
-
# Step 8
|
|
64
|
-
- name: ๐งช Unit Tests
|
|
65
|
-
run: smoo github-ci nx-smart --target test --name "Unit Tests" --step 8
|
|
66
|
-
|
|
67
|
-
# Step 9
|
|
68
|
-
# Nx's database cache needs artifact files and .nx/workspace-data DB
|
|
69
|
-
# metadata restored together; GitHub Actions cache is only the archive
|
|
70
|
-
# transport. Save runs only after build/lint/test succeed on the default
|
|
71
|
-
# branch, so PRs may restore shared cache but cannot publish it.
|
|
72
|
-
- name: ๐พ Save Nx cache
|
|
73
|
-
if:
|
|
74
|
-
${{ github.event_name == 'push' && github.ref == format('refs/heads/{0}',
|
|
75
|
-
github.event.repository.default_branch) && steps.nx-cache.outputs.cache-hit != 'true' }}
|
|
76
|
-
uses: actions/cache/save@v5.0.5
|
|
77
|
-
with:
|
|
78
|
-
path: |
|
|
79
|
-
.nx/cache
|
|
80
|
-
.nx/workspace-data/*.db*
|
|
81
|
-
key: ${{ runner.os }}-nx-db-v1-${{ github.sha }}
|
|
82
|
-
|
|
83
|
-
# Step 10
|
|
84
|
-
- name: ๐ Upload trace DBs
|
|
85
|
-
if: ${{ always() }}
|
|
86
|
-
uses: actions/upload-artifact@v7.0.1
|
|
87
|
-
with:
|
|
88
|
-
name: trace-results-${{ github.run_id }}
|
|
89
|
-
path: packages/*/.trace-results.db
|
|
90
|
-
if-no-files-found: ignore
|
|
91
|
-
retention-days: 14
|
|
92
|
-
include-hidden-files: true
|
|
93
|
-
|
|
94
|
-
# --- Cleanup ------------------------------------------------------------
|
|
95
|
-
|
|
96
|
-
# Step 11
|
|
97
|
-
- name: ๐งน Cleanup and cache Nix/devenv
|
|
98
|
-
if: ${{ always() }}
|
|
99
|
-
uses: ./.github/actions/save-nix-devenv
|
|
100
|
-
with:
|
|
101
|
-
nix-cache-hit: ${{ steps.setup.outputs.nix-cache-hit }}
|
|
102
|
-
devenv-cache-hit: ${{ steps.setup.outputs.devenv-cache-hit }}
|