@smoothbricks/cli 0.11.16 → 0.11.17
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 +43 -0
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +44 -0
- package/dist/github-ci/index.d.ts +1 -1
- package/dist/github-ci/index.d.ts.map +1 -1
- package/dist/github-ci/index.js +7 -10
- package/dist/lib/secret-names.d.ts +35 -0
- package/dist/lib/secret-names.d.ts.map +1 -0
- package/dist/lib/secret-names.js +61 -0
- package/dist/monorepo/ci-workflow.d.ts.map +1 -1
- package/dist/monorepo/ci-workflow.js +15 -6
- package/dist/monorepo/publish-workflow.d.ts +10 -1
- package/dist/monorepo/publish-workflow.d.ts.map +1 -1
- package/dist/monorepo/publish-workflow.js +58 -20
- package/dist/secrets/commands.d.ts +45 -0
- package/dist/secrets/commands.d.ts.map +1 -0
- package/dist/secrets/commands.js +189 -0
- package/dist/secrets/index.d.ts +83 -0
- package/dist/secrets/index.d.ts.map +1 -0
- package/dist/secrets/index.js +149 -0
- package/dist/wrangler/deploy-stage.d.ts +13 -2
- package/dist/wrangler/deploy-stage.d.ts.map +1 -1
- package/dist/wrangler/deploy-stage.js +39 -54
- package/dist/wrangler/deployed-version.d.ts +44 -0
- package/dist/wrangler/deployed-version.d.ts.map +1 -0
- package/dist/wrangler/deployed-version.js +87 -0
- package/dist/wrangler/live-version.d.ts +146 -0
- package/dist/wrangler/live-version.d.ts.map +1 -0
- package/dist/wrangler/live-version.js +326 -0
- package/package.json +2 -2
- package/src/cli.ts +46 -1
- package/src/github-ci/index.test.ts +92 -8
- package/src/github-ci/index.ts +7 -10
- package/src/lib/secret-names.ts +70 -0
- package/src/monorepo/__tests__/ci-workflow.test.ts +27 -2
- package/src/monorepo/__tests__/publish-workflow.test.ts +33 -15
- package/src/monorepo/ci-workflow.ts +17 -6
- package/src/monorepo/managed-files.test.ts +1 -1
- package/src/monorepo/publish-workflow.ts +65 -19
- package/src/monorepo/secret-references.test.ts +1 -1
- package/src/release/__tests__/private-npm-status.test.ts +2 -2
- package/src/secrets/commands.ts +210 -0
- package/src/secrets/index.test.ts +92 -0
- package/src/secrets/index.ts +183 -0
- package/src/wrangler/deploy-stage.test.ts +190 -12
- package/src/wrangler/deploy-stage.ts +72 -45
- package/src/wrangler/deployed-version.test.ts +150 -0
- package/src/wrangler/deployed-version.ts +130 -0
- package/src/wrangler/live-version.ts +363 -0
package/README.md
CHANGED
|
@@ -428,6 +428,49 @@ that runs after Validate and the e2e job succeed on a push to the staging push b
|
|
|
428
428
|
stage-derived — carry `stage-deploy-target` or deploy through `smoo wrangler deploy-stage` — otherwise `--select-tag`
|
|
429
429
|
finds nothing and the job logs `No run-many deploy projects; skipping production.`
|
|
430
430
|
|
|
431
|
+
#### Ordering one deploy after another
|
|
432
|
+
|
|
433
|
+
When a project's deploy calls into what another project deploys — a site that signs in to its stage's backend — say so
|
|
434
|
+
with an ordinary Nx edge on the deploying project:
|
|
435
|
+
|
|
436
|
+
```json
|
|
437
|
+
{ "nx": { "targets": { "deploy": { "dependsOn": ["...", "app-backend:deploy"] } } } }
|
|
438
|
+
```
|
|
439
|
+
|
|
440
|
+
Nx then orders it, at any depth: `site:deploy` after `app-backend:deploy` after `db:deploy` all resolve inside the one
|
|
441
|
+
`nx run-many` that `smoo github-ci nx-deploy` already issues, and `nx deploy site --stage=…` run by hand gets the same
|
|
442
|
+
order. Keep the leading `"..."`: it expands the `deploy-build` edge the plugin infers (below), which a bare list would
|
|
443
|
+
drop.
|
|
444
|
+
|
|
445
|
+
What makes the edge safe is that a deploy is never cached and always cheap when there is nothing to do:
|
|
446
|
+
|
|
447
|
+
- `@smoothbricks/nx-plugin` gives every declared `deploy` target `cache: false`. An Nx cache hit on a deploy means "we
|
|
448
|
+
once uploaded this hash", which a rollback silently falsifies — the workspace is unchanged, so the hash is unchanged,
|
|
449
|
+
so a cached deploy would report success while the previous version keeps serving.
|
|
450
|
+
- `smoo wrangler deploy-stage` reads live state first. If the version tagged with this task's hash is already the one
|
|
451
|
+
serving 100% of traffic, it returns `remote-cache-hit` after two API calls: no upload, no migration, no traffic shift.
|
|
452
|
+
- The expensive, purely file-derived half belongs in a sibling `deploy-build` target (build the artifact, register it,
|
|
453
|
+
refresh what the build needs). The plugin gives that one `cache: true` and makes `deploy` depend on it, so a redundant
|
|
454
|
+
deploy costs two API calls rather than a rebuild.
|
|
455
|
+
- A deploy does not finish when Cloudflare accepts the traffic shift; it finishes when the new version is the one being
|
|
456
|
+
served. `deploy-stage` polls `wrangler deployments status` until the tag it activated is live, and fails with what it
|
|
457
|
+
expected and what it saw if that never happens. Pass `--version-endpoint <url>` to also require an endpoint served by
|
|
458
|
+
the worker — whose trimmed response body is the running version tag — to answer with it. Without that wait, an edge
|
|
459
|
+
onto a deploy orders nothing: the step returns while the edge still serves the old code.
|
|
460
|
+
|
|
461
|
+
**The policy caveat, plainly.** A cross-project edge is part of the graph, not of the selection: a run that selects only
|
|
462
|
+
the dependent project will still evaluate the dependency's `deploy`. When the dependency is already at that hash, that
|
|
463
|
+
evaluation is a no-op — two API calls. But it is not inert: if the dependency is intentionally behind (its production
|
|
464
|
+
deploy is being held back, say), a run that selects only the dependent project **will advance the dependency to the hash
|
|
465
|
+
the current workspace produces**. If you need a project to be deployable without touching what it depends on, do not add
|
|
466
|
+
the edge; sequence those two deploys as separate CI jobs instead.
|
|
467
|
+
|
|
468
|
+
`smoo wrangler deployed-version --stage <stage>` prints the tag serving all traffic for the project's worker on that
|
|
469
|
+
stage, so an operator can check the same fact the deploy checks. It caches its answer briefly under Nx's workspace data
|
|
470
|
+
directory; that cache is a convenience for repeated queries only. Nothing that decides whether to deploy reads it, and
|
|
471
|
+
it refuses — rather than answering `unknown` — without credentials, on an API error, or while traffic is split between
|
|
472
|
+
two versions.
|
|
473
|
+
|
|
431
474
|
Pushes to the staging push branch queue behind a running workflow instead of canceling it, so a newer push never cancels
|
|
432
475
|
a production deployment mid-flight. Pull requests and other branches keep canceling superseded runs. The e2e and
|
|
433
476
|
production jobs repeat the Cargo credential and sibling-source preflight before SetupDevenv, so their `--step` anchors
|
package/dist/cli.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"AAaA,wBAAsB,MAAM,CAAC,IAAI,WAAwB,GAAG,OAAO,CAAC,IAAI,CAAC,CAcxE;AAQD,wBAAgB,WAAW,CAAC,KAAK,EAAE,OAAO,GAAG,IAAI,CAiBhD"}
|
package/dist/cli.js
CHANGED
|
@@ -6,7 +6,9 @@ import { cliPackageVersion } from './lib/cli-package.js';
|
|
|
6
6
|
import { decode, findRepoRoot, printCommandOutput } from './lib/run.js';
|
|
7
7
|
import { ensureChromium } from './playwright/index.js';
|
|
8
8
|
import { resolvePrConflicts } from './pr/index.js';
|
|
9
|
+
import { secretsSet, secretsStatus, secretsSync } from './secrets/commands.js';
|
|
9
10
|
import { cleanupPullRequest, deployStage } from './wrangler/deploy-stage.js';
|
|
11
|
+
import { deployedVersion } from './wrangler/deployed-version.js';
|
|
10
12
|
import { scaffold } from './wrangler/scaffold.js';
|
|
11
13
|
export async function runCli(argv = process.argv.slice(2)) {
|
|
12
14
|
const program = buildProgram();
|
|
@@ -420,6 +422,30 @@ function buildProgram() {
|
|
|
420
422
|
.action(async () => {
|
|
421
423
|
await ensureChromium();
|
|
422
424
|
});
|
|
425
|
+
const secrets = program
|
|
426
|
+
.command('secrets')
|
|
427
|
+
.description('Reconcile declared secrets: what Workers need, what workflows pass, what the repository holds');
|
|
428
|
+
secrets
|
|
429
|
+
.command('status')
|
|
430
|
+
.description('Show every declared secret and refuse when a workflow passes one the repository lacks')
|
|
431
|
+
.option('--repo <owner/name>', 'repository to read secrets from; defaults to the current checkout')
|
|
432
|
+
.action(async (options) => {
|
|
433
|
+
process.exitCode = secretsStatus(await findRepoRoot(), options);
|
|
434
|
+
});
|
|
435
|
+
secrets
|
|
436
|
+
.command('set <name>')
|
|
437
|
+
.description('Set one repository secret from a pasted value; the value is read without echo and never logged')
|
|
438
|
+
.option('--repo <owner/name>', 'repository to set the secret on')
|
|
439
|
+
.action(async (name, options) => {
|
|
440
|
+
process.exitCode = await secretsSet(name, options);
|
|
441
|
+
});
|
|
442
|
+
secrets
|
|
443
|
+
.command('sync')
|
|
444
|
+
.description('Push every secret smoo.secrets can fetch locally to the repository')
|
|
445
|
+
.option('--repo <owner/name>', 'repository to set the secrets on')
|
|
446
|
+
.action(async (options) => {
|
|
447
|
+
process.exitCode = await secretsSync(await findRepoRoot(), options);
|
|
448
|
+
});
|
|
423
449
|
const wrangler = program.command('wrangler').description('Cloudflare wrangler project helpers');
|
|
424
450
|
wrangler
|
|
425
451
|
.command('scaffold <project>')
|
|
@@ -432,11 +458,29 @@ function buildProgram() {
|
|
|
432
458
|
.command('deploy-stage')
|
|
433
459
|
.requiredOption('--stage <stage>', 'staging, production, or prN')
|
|
434
460
|
.option('--config <path>', 'deploy a build-generated flat wrangler.json instead of ./wrangler.toml')
|
|
461
|
+
.option('--version-endpoint <url>', 'URL served by this worker whose trimmed body is the running version tag')
|
|
435
462
|
.action(async (options) => {
|
|
436
463
|
await deployStage(process.cwd(), {
|
|
437
464
|
stage: options.stage,
|
|
438
465
|
...(options.config ? { config: resolve(options.config) } : {}),
|
|
466
|
+
...(options.versionEndpoint ? { versionEndpoint: options.versionEndpoint } : {}),
|
|
467
|
+
});
|
|
468
|
+
});
|
|
469
|
+
wrangler
|
|
470
|
+
.command('deployed-version')
|
|
471
|
+
.description('Print the version tag serving all traffic for this project\u2019s worker on a stage')
|
|
472
|
+
.requiredOption('--stage <stage>', 'staging, production, or prN')
|
|
473
|
+
.option('--config <path>', 'resolve the worker name from a build-generated flat wrangler.json')
|
|
474
|
+
.option('--refresh', 'ask Cloudflare even when a fresh cached answer exists')
|
|
475
|
+
.action(async (options) => {
|
|
476
|
+
const report = await deployedVersion(process.cwd(), {
|
|
477
|
+
stage: options.stage,
|
|
478
|
+
...(options.config ? { config: resolve(options.config) } : {}),
|
|
479
|
+
...(options.refresh ? { refresh: true } : {}),
|
|
439
480
|
});
|
|
481
|
+
// The tag alone on stdout: this is read by humans and by `$(...)`, and a version deployed
|
|
482
|
+
// outside Nx genuinely has no tag, which `untagged` says without pretending to be one.
|
|
483
|
+
console.log(report.versionTag ?? 'untagged');
|
|
440
484
|
});
|
|
441
485
|
wrangler
|
|
442
486
|
.command('cleanup-pr')
|
|
@@ -68,7 +68,7 @@ export interface GithubCiNxDeployOptions {
|
|
|
68
68
|
selectTag?: string;
|
|
69
69
|
}
|
|
70
70
|
export interface GithubCiNxDeployDependencies {
|
|
71
|
-
listProjects?: (root: string,
|
|
71
|
+
listProjects?: (root: string, mode: 'affected' | 'run-many', stage: DeploymentStage, selectTag?: string) => Promise<string[]>;
|
|
72
72
|
runNx?: (args: string[], root: string) => Promise<number>;
|
|
73
73
|
appendSummary?: (summaryPath: string, content: string) => Promise<void>;
|
|
74
74
|
appendOutput?: (outputPath: string, content: string) => Promise<void>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/github-ci/index.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/github-ci/index.ts"],"names":[],"mappings":"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"}
|
package/dist/github-ci/index.js
CHANGED
|
@@ -260,9 +260,9 @@ export async function githubCiNxDeploy(root, options, dependencies = {}) {
|
|
|
260
260
|
const setStatus = dependencies.setStatus ??
|
|
261
261
|
((state) => state === 'pending' ? createGithubStatus(name, step) : updateGithubStatus(name, state, step));
|
|
262
262
|
const mode = resolveNxSmartMode(options.mode ?? 'run-many');
|
|
263
|
-
const listProjects = dependencies.listProjects ??
|
|
263
|
+
const listProjects = dependencies.listProjects ?? listNxDeployProjects;
|
|
264
264
|
const runNx = dependencies.runNx ?? ((args, commandRoot) => runStatus('nx', args, commandRoot));
|
|
265
|
-
const projects = await listProjects(root,
|
|
265
|
+
const projects = await listProjects(root, mode, stage, options.selectTag);
|
|
266
266
|
if (projects.length === 0) {
|
|
267
267
|
console.log(`No ${mode} deploy projects; skipping ${stage}.`);
|
|
268
268
|
await setStatus('pending');
|
|
@@ -275,8 +275,8 @@ export async function githubCiNxDeploy(root, options, dependencies = {}) {
|
|
|
275
275
|
? { stage, urls: previewUrlsForStage(github?.previewUrls, stage) }
|
|
276
276
|
: undefined;
|
|
277
277
|
await setStatus('pending');
|
|
278
|
-
const projectList = projects.join(',');
|
|
279
278
|
const targets = options.verify === true ? ['build', 'lint', 'test', 'deploy'] : ['deploy'];
|
|
279
|
+
const projectList = projects.join(',');
|
|
280
280
|
for (const target of targets) {
|
|
281
281
|
const nxArgs = [
|
|
282
282
|
'run-many',
|
|
@@ -286,6 +286,8 @@ export async function githubCiNxDeploy(root, options, dependencies = {}) {
|
|
|
286
286
|
`--exclude=${deployExclusions(stage)}`,
|
|
287
287
|
`--parallel=${NX_PARALLEL}`,
|
|
288
288
|
];
|
|
289
|
+
// Deploy ordering is a `dependsOn` edge in the project graph, not a second round here: one run-many
|
|
290
|
+
// already sequences any depth of `a:deploy -> b:deploy -> c:deploy`.
|
|
289
291
|
if (target === 'deploy') {
|
|
290
292
|
nxArgs.push(`--stage=${stage}`);
|
|
291
293
|
}
|
|
@@ -413,17 +415,12 @@ function previewUrlFromTemplate(template, stage) {
|
|
|
413
415
|
throw new Error(`preview URL template "${template}" must contain {stage}`);
|
|
414
416
|
return template.replaceAll('{stage}', stage);
|
|
415
417
|
}
|
|
416
|
-
async function
|
|
418
|
+
async function listNxDeployProjects(root, mode, stage, selectTag) {
|
|
417
419
|
const listArgs = ['show', 'projects'];
|
|
418
420
|
if (mode === 'affected')
|
|
419
421
|
listArgs.push('--affected');
|
|
420
|
-
listArgs.push('--withTarget',
|
|
421
|
-
if (target === 'deploy')
|
|
422
|
-
listArgs.push(`--exclude=${deployExclusions(stage)}`);
|
|
423
|
-
listArgs.push('--json');
|
|
422
|
+
listArgs.push('--withTarget', 'deploy', `--exclude=${deployExclusions(stage)}`, '--json');
|
|
424
423
|
const candidates = nxProjectList(await runText('nx', listArgs, root)).sort((left, right) => left.localeCompare(right));
|
|
425
|
-
if (target !== 'deploy')
|
|
426
|
-
return candidates;
|
|
427
424
|
return selectStageDeployProjects(candidates, stage, selectTag, async (project) => {
|
|
428
425
|
const parsed = parseNxProjectDeployTarget(await runText('nx', ['show', 'project', project, '--json'], root));
|
|
429
426
|
if (!parsed)
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* One rule for naming the repository secret behind an environment variable, so
|
|
3
|
+
* the workflow renderer, the reconciler and an operator all derive the same
|
|
4
|
+
* name instead of maintaining a map.
|
|
5
|
+
*
|
|
6
|
+
* GitHub refuses to create a secret whose name starts with `GITHUB_` (hence
|
|
7
|
+
* `RepositorySecretName`'s pattern), which is why a Worker's
|
|
8
|
+
* `GITHUB_CLIENT_SECRET` cannot be stored under its own name. Prefixing with
|
|
9
|
+
* the repository owner is the workaround operators already reach for by hand
|
|
10
|
+
* (`ACME_GITHUB_CLIENT_SECRET` for `acme/app`); making it the convention means
|
|
11
|
+
* nothing has to declare it.
|
|
12
|
+
*/
|
|
13
|
+
/** Names GitHub reserves: it rejects `gh secret set GITHUB_*` outright. */
|
|
14
|
+
export declare function isReservedRepositorySecretName(envName: string): boolean;
|
|
15
|
+
/**
|
|
16
|
+
* The repository secret an env name lives in. Identity for every name GitHub
|
|
17
|
+
* accepts; owner-prefixed for the reserved ones. `owner` comes from the
|
|
18
|
+
* repository URL, so a fork or a rename derives its own names rather than
|
|
19
|
+
* inheriting a hardcoded prefix.
|
|
20
|
+
*/
|
|
21
|
+
export declare function conventionalRepositorySecretName(envName: string, owner: string): string;
|
|
22
|
+
/**
|
|
23
|
+
* Resolve the whole env -> secret mapping for a set of declared env names.
|
|
24
|
+
* Explicit entries win: an exception stays expressible, but a repository that
|
|
25
|
+
* follows the convention declares nothing.
|
|
26
|
+
*/
|
|
27
|
+
export declare function repositorySecretMapping(envNames: readonly string[], owner: string, declared?: Readonly<Record<string, string>>): Record<string, string>;
|
|
28
|
+
/**
|
|
29
|
+
* Repository owner from a repository URL — `acme` from
|
|
30
|
+
* `https://github.com/acme/app.git`, and the same for an ssh or forge
|
|
31
|
+
* URL. The owner is derived rather than configured so a fork or a rename
|
|
32
|
+
* carries its own prefix instead of inheriting one.
|
|
33
|
+
*/
|
|
34
|
+
export declare function repositoryOwnerFromUrl(url: string): string | null;
|
|
35
|
+
//# sourceMappingURL=secret-names.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"secret-names.d.ts","sourceRoot":"","sources":["../../src/lib/secret-names.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,2EAA2E;AAC3E,wBAAgB,8BAA8B,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAEvE;AAED;;;;;GAKG;AACH,wBAAgB,gCAAgC,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAYvF;AAED;;;;GAIG;AACH,wBAAgB,uBAAuB,CACrC,QAAQ,EAAE,SAAS,MAAM,EAAE,EAC3B,KAAK,EAAE,MAAM,EACb,QAAQ,GAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAM,GAC9C,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CASxB;AAED;;;;;GAKG;AACH,wBAAgB,sBAAsB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAKjE"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* One rule for naming the repository secret behind an environment variable, so
|
|
3
|
+
* the workflow renderer, the reconciler and an operator all derive the same
|
|
4
|
+
* name instead of maintaining a map.
|
|
5
|
+
*
|
|
6
|
+
* GitHub refuses to create a secret whose name starts with `GITHUB_` (hence
|
|
7
|
+
* `RepositorySecretName`'s pattern), which is why a Worker's
|
|
8
|
+
* `GITHUB_CLIENT_SECRET` cannot be stored under its own name. Prefixing with
|
|
9
|
+
* the repository owner is the workaround operators already reach for by hand
|
|
10
|
+
* (`ACME_GITHUB_CLIENT_SECRET` for `acme/app`); making it the convention means
|
|
11
|
+
* nothing has to declare it.
|
|
12
|
+
*/
|
|
13
|
+
/** Names GitHub reserves: it rejects `gh secret set GITHUB_*` outright. */
|
|
14
|
+
export function isReservedRepositorySecretName(envName) {
|
|
15
|
+
return /^GITHUB_/i.test(envName);
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* The repository secret an env name lives in. Identity for every name GitHub
|
|
19
|
+
* accepts; owner-prefixed for the reserved ones. `owner` comes from the
|
|
20
|
+
* repository URL, so a fork or a rename derives its own names rather than
|
|
21
|
+
* inheriting a hardcoded prefix.
|
|
22
|
+
*/
|
|
23
|
+
export function conventionalRepositorySecretName(envName, owner) {
|
|
24
|
+
if (!isReservedRepositorySecretName(envName))
|
|
25
|
+
return envName;
|
|
26
|
+
const prefix = owner
|
|
27
|
+
.replace(/[^A-Za-z0-9]+/g, '_')
|
|
28
|
+
.replace(/^_+|_+$/g, '')
|
|
29
|
+
.toUpperCase();
|
|
30
|
+
if (prefix.length === 0) {
|
|
31
|
+
throw new Error(`Cannot derive a repository secret name for ${envName}: GitHub reserves the GITHUB_ prefix and the repository owner is empty.`);
|
|
32
|
+
}
|
|
33
|
+
return `${prefix}_${envName}`;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Resolve the whole env -> secret mapping for a set of declared env names.
|
|
37
|
+
* Explicit entries win: an exception stays expressible, but a repository that
|
|
38
|
+
* follows the convention declares nothing.
|
|
39
|
+
*/
|
|
40
|
+
export function repositorySecretMapping(envNames, owner, declared = {}) {
|
|
41
|
+
const mapping = {};
|
|
42
|
+
for (const envName of [...envNames].sort((left, right) => left.localeCompare(right))) {
|
|
43
|
+
mapping[envName] = declared[envName] ?? conventionalRepositorySecretName(envName, owner);
|
|
44
|
+
}
|
|
45
|
+
for (const [envName, secretName] of Object.entries(declared)) {
|
|
46
|
+
mapping[envName] = secretName;
|
|
47
|
+
}
|
|
48
|
+
return mapping;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Repository owner from a repository URL — `acme` from
|
|
52
|
+
* `https://github.com/acme/app.git`, and the same for an ssh or forge
|
|
53
|
+
* URL. The owner is derived rather than configured so a fork or a rename
|
|
54
|
+
* carries its own prefix instead of inheriting one.
|
|
55
|
+
*/
|
|
56
|
+
export function repositoryOwnerFromUrl(url) {
|
|
57
|
+
const withoutProtocol = url.replace(/^[a-z+]+:\/\//i, '').replace(/^git@/i, '');
|
|
58
|
+
const path = withoutProtocol.replace(/^[^/:]+[/:]/, '');
|
|
59
|
+
const owner = path.split('/')[0];
|
|
60
|
+
return owner && owner.length > 0 ? owner.replace(/\.git$/i, '') : null;
|
|
61
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ci-workflow.d.ts","sourceRoot":"","sources":["../../src/monorepo/ci-workflow.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EACV,aAAa,EACb,6BAA6B,EAE7B,uBAAuB,EACvB,wBAAwB,EACxB,iBAAiB,EACjB,6BAA6B,EAC7B,2BAA2B,EAC5B,MAAM,gBAAgB,CAAC;AAGxB,oBAAY,kBAAkB;IAC5B,QAAQ,aAAa;IACrB,eAAe,qBAAqB;IACpC,WAAW,iBAAiB;IAC5B,gBAAgB,sBAAsB;IACtC,SAAS,gBAAgB;IACzB,cAAc,qBAAqB;IACnC,KAAK,UAAU;IACf,YAAY,kBAAkB;IAC9B,IAAI,SAAS;IACb,SAAS,eAAe;IACxB,iBAAiB,wBAAwB;IACzC,oBAAoB,2BAA2B;IAC/C,MAAM,WAAW;IACjB,WAAW,kBAAkB;IAC7B,cAAc,qBAAqB;IACnC,aAAa,oBAAoB;CAClC;AAED,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,kBAAkB,CAAC;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;CAChB;AAED;;;;;;GAMG;AACH,MAAM,WAAW,sBAAsB;IACrC,cAAc,CAAC,EAAE,YAAY,CAAC;IAC9B,wEAAwE;IACxE,aAAa,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACxC;AAED,MAAM,WAAW,2BAA4B,SAAQ,sBAAsB;IACzE,eAAe,CAAC,EAAE,iBAAiB,CAAC,iBAAiB,CAAC,CAAC;IACvD,MAAM,EAAE,OAAO,CAAC;IAChB,YAAY,EAAE,OAAO,CAAC;IACtB,aAAa,EAAE,OAAO,CAAC;IACvB,2EAA2E;IAC3E,YAAY,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC;IACpC,0CAA0C;IAC1C,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;IAC3B;;;;;OAKG;IACH,UAAU,CAAC,EAAE,uBAAuB,CAAC;IACrC;;;;OAIG;IACH,eAAe,CAAC,EAAE,2BAA2B,EAAE,CAAC;IAChD;;;;;OAKG;IACH,gBAAgB,CAAC,EAAE,6BAA6B,CAAC;IACjD;;;;OAIG;IACH,WAAW,CAAC,EAAE,wBAAwB,CAAC;IACvC,yGAAyG;IACzG,YAAY,CAAC,EAAE,6BAA6B,CAAC;IAC7C,kFAAkF;IAClF,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACpC,yFAAyF;IACzF,gBAAgB,CAAC,EAAE,OAAO,CAAC;CAC5B;AAID,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,2BAA2B,GAAG,cAAc,EAAE,CAgCvF;AAED,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,2BAA2B,GAAG,MAAM,CAQjF;
|
|
1
|
+
{"version":3,"file":"ci-workflow.d.ts","sourceRoot":"","sources":["../../src/monorepo/ci-workflow.ts"],"names":[],"mappings":"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"}
|
|
@@ -64,12 +64,19 @@ permissions:
|
|
|
64
64
|
${options.deploy ? ' deployments: write\n' : ''} statuses: write
|
|
65
65
|
|
|
66
66
|
concurrency:
|
|
67
|
-
|
|
68
|
-
#
|
|
69
|
-
#
|
|
70
|
-
#
|
|
67
|
+
${options.deploy
|
|
68
|
+
? ` # One in-flight run per ref. Pushes to the staging push branch queue behind a
|
|
69
|
+
# running workflow instead of canceling it, so a newer push never cancels the
|
|
70
|
+
# deploy job mid-flight. Pull requests and other branches keep canceling
|
|
71
|
+
# superseded runs.
|
|
71
72
|
group: \${{ github.workflow }}-\${{ github.ref }}
|
|
72
|
-
cancel-in-progress: \${{ github.ref != ${stagingRefLiteral(options)} }}
|
|
73
|
+
cancel-in-progress: \${{ github.ref != ${stagingRefLiteral(options)} }}`
|
|
74
|
+
: ` # This workflow validates and never deploys, so there is no in-flight
|
|
75
|
+
# deployment for a newer push to protect: every ref cancels its superseded
|
|
76
|
+
# runs. Queuing them instead serializes the staging branch, and a burst of
|
|
77
|
+
# pushes then reports the newest commit one full run per queued push late.
|
|
78
|
+
group: \${{ github.workflow }}-\${{ github.ref }}
|
|
79
|
+
cancel-in-progress: true`}
|
|
73
80
|
|
|
74
81
|
defaults:
|
|
75
82
|
run:
|
|
@@ -828,6 +835,7 @@ function renderProductionDeployJob(options) {
|
|
|
828
835
|
needs: ${needs}
|
|
829
836
|
${renderRunsOnLine(options.runsOn)}
|
|
830
837
|
timeout-minutes: 30
|
|
838
|
+
# prettier-ignore
|
|
831
839
|
if: \${{ !cancelled() && github.event_name == 'push' && github.ref == ${stagingRefLiteral(options)} && needs.main.result == 'success'${e2eGate} }}
|
|
832
840
|
${environmentLine(options.environments?.production)} env:
|
|
833
841
|
GH_TOKEN: \${{ github.token }}
|
|
@@ -835,7 +843,8 @@ ${remoteCacheJobEnvLines(options.remoteCache)}${cargoCredentialJobEnvLines(optio
|
|
|
835
843
|
${renderCiWorkflowSteps(followUpSetupSteps(options, numbers), options)}
|
|
836
844
|
# Step ${numbers.middle}
|
|
837
845
|
- name: 🚀 Deploy Production
|
|
838
|
-
${renderOptionalLines(deployStepSecretEnvLines(options))}
|
|
846
|
+
${renderOptionalLines(deployStepSecretEnvLines(options))} # prettier-ignore
|
|
847
|
+
run: smoo github-ci nx-deploy --stage production --mode run-many --select-tag ${PRODUCTION_PUSH_DEPLOY_TAG} --name "Deploy Production" --step ${numbers.middle}
|
|
839
848
|
|
|
840
849
|
${renderCiWorkflowSteps(followUpCleanupStep(numbers), options)}`;
|
|
841
850
|
}
|
|
@@ -2,7 +2,7 @@ import type { PackageCargoCredentialsConfig, PackagePrivateNpmConfig, PackageRem
|
|
|
2
2
|
import { type DeployStepSecretConfig } from './ci-workflow.js';
|
|
3
3
|
import { type WorkflowRunsOn } from './github-runs-on.js';
|
|
4
4
|
export type PublishWorkflowBump = 'auto' | 'patch' | 'minor' | 'major' | 'prerelease';
|
|
5
|
-
export type PublishWorkflowCondition = 'version-mode-not-none' | 'deploy-production' | 'deploy-production-standalone' | 'failure' | 'always';
|
|
5
|
+
export type PublishWorkflowCondition = 'plan-mode-not-none' | 'version-mode-not-none' | 'deploy-production' | 'deploy-production-standalone' | 'failure' | 'always';
|
|
6
6
|
export type PublishWorkflowNxTarget = 'build' | 'lint' | 'test';
|
|
7
7
|
export type PublishWorkflowDeployStage = 'none' | 'production';
|
|
8
8
|
export declare enum PublishWorkflowStepKind {
|
|
@@ -13,6 +13,7 @@ export declare enum PublishWorkflowStepKind {
|
|
|
13
13
|
ConfigureReleaseAuthor = "configure-release-author",
|
|
14
14
|
BuildNxVersionActions = "build-nx-version-actions",
|
|
15
15
|
RepairPendingReleases = "repair-pending-releases",
|
|
16
|
+
PlanRelease = "plan-release",
|
|
16
17
|
VersionRelease = "version-release",
|
|
17
18
|
CheckManagedMonorepoFiles = "check-managed-monorepo-files",
|
|
18
19
|
Build = "build",
|
|
@@ -105,6 +106,14 @@ export interface PublishWorkflowCallbacks {
|
|
|
105
106
|
bump: PublishWorkflowBump;
|
|
106
107
|
dryRun: boolean;
|
|
107
108
|
}): Promise<PublishWorkflowVersionOutputs>;
|
|
109
|
+
/**
|
|
110
|
+
* The selection the bump WILL make, computed without writing anything, so the
|
|
111
|
+
* gates that run before the version commit know what to run over. Defaults to
|
|
112
|
+
* a dry-run `versionRelease` when a caller supplies none.
|
|
113
|
+
*/
|
|
114
|
+
planRelease?(input: {
|
|
115
|
+
bump: PublishWorkflowBump;
|
|
116
|
+
}): Promise<PublishWorkflowVersionOutputs>;
|
|
108
117
|
checkManagedMonorepoFiles(): Promise<void>;
|
|
109
118
|
nxRunMany(input: {
|
|
110
119
|
target: PublishWorkflowNxTarget;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"publish-workflow.d.ts","sourceRoot":"","sources":["../../src/monorepo/publish-workflow.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"publish-workflow.d.ts","sourceRoot":"","sources":["../../src/monorepo/publish-workflow.ts"],"names":[],"mappings":"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"}
|
|
@@ -31,6 +31,7 @@ export var PublishWorkflowStepKind;
|
|
|
31
31
|
PublishWorkflowStepKind["ConfigureReleaseAuthor"] = "configure-release-author";
|
|
32
32
|
PublishWorkflowStepKind["BuildNxVersionActions"] = "build-nx-version-actions";
|
|
33
33
|
PublishWorkflowStepKind["RepairPendingReleases"] = "repair-pending-releases";
|
|
34
|
+
PublishWorkflowStepKind["PlanRelease"] = "plan-release";
|
|
34
35
|
PublishWorkflowStepKind["VersionRelease"] = "version-release";
|
|
35
36
|
PublishWorkflowStepKind["CheckManagedMonorepoFiles"] = "check-managed-monorepo-files";
|
|
36
37
|
PublishWorkflowStepKind["Build"] = "build";
|
|
@@ -45,6 +46,9 @@ export var PublishWorkflowStepKind;
|
|
|
45
46
|
})(PublishWorkflowStepKind || (PublishWorkflowStepKind = {}));
|
|
46
47
|
export function definePublishWorkflow(options = {}) {
|
|
47
48
|
const versionMode = githubExpression('steps.version.outputs.mode');
|
|
49
|
+
// Steps that run before the bump must label themselves from the plan: the
|
|
50
|
+
// version step's outputs do not exist yet, so the interpolation renders empty.
|
|
51
|
+
const planMode = githubExpression('steps.plan.outputs.mode');
|
|
48
52
|
if (options.release === false) {
|
|
49
53
|
return { steps: defineDeployOnlyWorkflowSteps(options) };
|
|
50
54
|
}
|
|
@@ -86,30 +90,37 @@ export function definePublishWorkflow(options = {}) {
|
|
|
86
90
|
kind: PublishWorkflowStepKind.RepairPendingReleases,
|
|
87
91
|
name: '🧯 Repair pending releases',
|
|
88
92
|
},
|
|
89
|
-
|
|
93
|
+
// Plan first, gate second, bump third. Lint and test hash the source, so
|
|
94
|
+
// running them BEFORE the version commit means their task hashes match
|
|
95
|
+
// the ones ci already computed for the same source — the publish reuses
|
|
96
|
+
// that cache instead of re-running 189 tasks. Build stays after the bump
|
|
97
|
+
// on purpose: an artifact built from pre-bump sources would ship the
|
|
98
|
+
// previous version string.
|
|
99
|
+
{ kind: PublishWorkflowStepKind.PlanRelease, name: '🧭 Plan release', id: 'plan' },
|
|
90
100
|
{
|
|
91
101
|
kind: PublishWorkflowStepKind.CheckManagedMonorepoFiles,
|
|
92
|
-
name: `✅ Check managed monorepo files (${
|
|
93
|
-
condition: '
|
|
94
|
-
},
|
|
95
|
-
{
|
|
96
|
-
kind: PublishWorkflowStepKind.Build,
|
|
97
|
-
name: `🔨 Build (${versionMode})`,
|
|
98
|
-
condition: 'version-mode-not-none',
|
|
99
|
-
nxTarget: 'build',
|
|
102
|
+
name: `✅ Check managed monorepo files (${planMode})`,
|
|
103
|
+
condition: 'plan-mode-not-none',
|
|
100
104
|
},
|
|
101
105
|
{
|
|
102
106
|
kind: PublishWorkflowStepKind.Lint,
|
|
103
|
-
name: `🔍 Lint (${
|
|
104
|
-
condition: '
|
|
107
|
+
name: `🔍 Lint (${planMode})`,
|
|
108
|
+
condition: 'plan-mode-not-none',
|
|
105
109
|
nxTarget: 'lint',
|
|
106
110
|
},
|
|
107
111
|
{
|
|
108
112
|
kind: PublishWorkflowStepKind.UnitTests,
|
|
109
|
-
name: `🧪 Unit Tests (${
|
|
110
|
-
condition: '
|
|
113
|
+
name: `🧪 Unit Tests (${planMode})`,
|
|
114
|
+
condition: 'plan-mode-not-none',
|
|
111
115
|
nxTarget: 'test',
|
|
112
116
|
},
|
|
117
|
+
{ kind: PublishWorkflowStepKind.VersionRelease, name: '🔢 Version release', id: 'version' },
|
|
118
|
+
{
|
|
119
|
+
kind: PublishWorkflowStepKind.Build,
|
|
120
|
+
name: `🔨 Build (${versionMode})`,
|
|
121
|
+
condition: 'version-mode-not-none',
|
|
122
|
+
nxTarget: 'build',
|
|
123
|
+
},
|
|
113
124
|
{ kind: PublishWorkflowStepKind.UploadTraceDbs, name: '📎 Upload trace DBs', condition: 'failure' },
|
|
114
125
|
{
|
|
115
126
|
kind: PublishWorkflowStepKind.ValidateMonorepoConfig,
|
|
@@ -158,10 +169,11 @@ function numberWorkflowSteps(steps) {
|
|
|
158
169
|
export async function runPublishWorkflow(workflow, context) {
|
|
159
170
|
let setupOutputs = { nixCacheHit: '', devenvCacheHit: '' };
|
|
160
171
|
let version = { mode: 'none', projects: [] };
|
|
172
|
+
let plan = { mode: 'none', projects: [] };
|
|
161
173
|
let failed = false;
|
|
162
174
|
let failure;
|
|
163
175
|
for (const step of workflow.steps) {
|
|
164
|
-
if (!shouldRunStep(step, version, failed, context.inputs)) {
|
|
176
|
+
if (!shouldRunStep(step, version, failed, context.inputs, plan)) {
|
|
165
177
|
continue;
|
|
166
178
|
}
|
|
167
179
|
try {
|
|
@@ -187,6 +199,11 @@ export async function runPublishWorkflow(workflow, context) {
|
|
|
187
199
|
dryRun: context.inputs.dryRun,
|
|
188
200
|
});
|
|
189
201
|
break;
|
|
202
|
+
case PublishWorkflowStepKind.PlanRelease:
|
|
203
|
+
plan = context.callbacks.planRelease
|
|
204
|
+
? await context.callbacks.planRelease({ bump: context.inputs.bump })
|
|
205
|
+
: await context.callbacks.versionRelease({ bump: context.inputs.bump, dryRun: true });
|
|
206
|
+
break;
|
|
190
207
|
case PublishWorkflowStepKind.VersionRelease:
|
|
191
208
|
version = await context.callbacks.versionRelease(context.inputs);
|
|
192
209
|
break;
|
|
@@ -199,7 +216,12 @@ export async function runPublishWorkflow(workflow, context) {
|
|
|
199
216
|
if (!step.nxTarget) {
|
|
200
217
|
throw new Error(`Workflow step ${step.kind} is missing an Nx target.`);
|
|
201
218
|
}
|
|
202
|
-
|
|
219
|
+
// Lint and test run before the bump exists, so they select from the
|
|
220
|
+
// plan; build runs after it and selects from the written version.
|
|
221
|
+
await context.callbacks.nxRunMany({
|
|
222
|
+
target: step.nxTarget,
|
|
223
|
+
projects: step.kind === PublishWorkflowStepKind.Build ? version.projects : plan.projects,
|
|
224
|
+
});
|
|
203
225
|
break;
|
|
204
226
|
case PublishWorkflowStepKind.UploadTraceDbs:
|
|
205
227
|
await context.callbacks.uploadTraceDbs();
|
|
@@ -234,7 +256,10 @@ export async function runPublishWorkflow(workflow, context) {
|
|
|
234
256
|
}
|
|
235
257
|
return { version, failed };
|
|
236
258
|
}
|
|
237
|
-
function shouldRunStep(step, version, failed, inputs) {
|
|
259
|
+
function shouldRunStep(step, version, failed, inputs, plan = version) {
|
|
260
|
+
if (step.condition === 'plan-mode-not-none') {
|
|
261
|
+
return plan.mode !== 'none';
|
|
262
|
+
}
|
|
238
263
|
if (step.condition === 'version-mode-not-none') {
|
|
239
264
|
return version.mode !== 'none';
|
|
240
265
|
}
|
|
@@ -421,6 +446,16 @@ function yamlLinesForStep(step, options) {
|
|
|
421
446
|
...privateNpmPublisherStepEnv(options),
|
|
422
447
|
` run: smoo release repair-pending --dry-run "${githubExpression('inputs.dry_run')}"`,
|
|
423
448
|
];
|
|
449
|
+
case PublishWorkflowStepKind.PlanRelease:
|
|
450
|
+
// The same selection the bump will make, computed without writing: the
|
|
451
|
+
// gates need `mode` and `projects` before any version commit exists.
|
|
452
|
+
return [
|
|
453
|
+
` - name: ${step.name}`,
|
|
454
|
+
' id: plan',
|
|
455
|
+
' run:',
|
|
456
|
+
` smoo release version --bump "${githubExpression('inputs.bump')}" --projects "${githubExpression('inputs.projects')}" --dry-run "true" --github-output`,
|
|
457
|
+
' "$GITHUB_OUTPUT"',
|
|
458
|
+
];
|
|
424
459
|
case PublishWorkflowStepKind.VersionRelease:
|
|
425
460
|
return [
|
|
426
461
|
` - name: ${step.name}`,
|
|
@@ -436,9 +471,9 @@ function yamlLinesForStep(step, options) {
|
|
|
436
471
|
case PublishWorkflowStepKind.Build:
|
|
437
472
|
return conditionalRunStep(step, `smoo github-ci nx-run-many --targets build --projects "${githubExpression('steps.version.outputs.projects')}"`);
|
|
438
473
|
case PublishWorkflowStepKind.Lint:
|
|
439
|
-
return conditionalRunStep(step, `smoo github-ci nx-run-many --targets lint --projects "${githubExpression('steps.
|
|
474
|
+
return conditionalRunStep(step, `smoo github-ci nx-run-many --targets lint --projects "${githubExpression('steps.plan.outputs.projects')}"`);
|
|
440
475
|
case PublishWorkflowStepKind.UnitTests:
|
|
441
|
-
return conditionalRunStep(step, `smoo github-ci nx-run-many --targets test --projects "${githubExpression('steps.
|
|
476
|
+
return conditionalRunStep(step, `smoo github-ci nx-run-many --targets test --projects "${githubExpression('steps.plan.outputs.projects')}"`);
|
|
442
477
|
case PublishWorkflowStepKind.UploadTraceDbs:
|
|
443
478
|
return artifactStepLines(options.actionsProvider, step.name, 'upload', [
|
|
444
479
|
`name: trace-results-${githubExpression('github.run_id')}`,
|
|
@@ -513,8 +548,11 @@ function deployProductionStep(step, options) {
|
|
|
513
548
|
];
|
|
514
549
|
}
|
|
515
550
|
function conditionalRunStep(step, run) {
|
|
516
|
-
|
|
517
|
-
|
|
551
|
+
// A step gated on the plan must read the PLAN's mode: it runs before the
|
|
552
|
+
// version step exists, and `steps.version.outputs.mode` is empty there, which
|
|
553
|
+
// silently skips the gate rather than running it.
|
|
554
|
+
const source = step.condition === 'plan-mode-not-none' ? 'plan' : 'version';
|
|
555
|
+
return [` - name: ${step.name}`, ` if: steps.${source}.outputs.mode != 'none'`, ` run: ${run}`];
|
|
518
556
|
}
|
|
519
557
|
function siblingSourceCheckoutStepLines(options) {
|
|
520
558
|
const checkouts = options.sourceCheckouts;
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `smoo secrets` — the operator side of the reconciliation in ./index.ts.
|
|
3
|
+
*
|
|
4
|
+
* Values are handed to `gh` over stdin, never through argv (a process list is
|
|
5
|
+
* world-readable) and never printed. Reading one from the terminal disables
|
|
6
|
+
* echo, so a pasted key does not end up in a scrollback buffer or a screen
|
|
7
|
+
* share.
|
|
8
|
+
*/
|
|
9
|
+
/** Repository secret names GitHub currently holds, or a refusal naming what failed. */
|
|
10
|
+
export declare function readRepositorySecrets(repo: string | undefined): {
|
|
11
|
+
ok: true;
|
|
12
|
+
names: string[];
|
|
13
|
+
} | {
|
|
14
|
+
ok: false;
|
|
15
|
+
reason: string;
|
|
16
|
+
};
|
|
17
|
+
/** Write one secret, value over stdin so it never reaches argv. */
|
|
18
|
+
export declare function writeRepositorySecret(name: string, value: string, repo: string | undefined): Promise<{
|
|
19
|
+
ok: true;
|
|
20
|
+
} | {
|
|
21
|
+
ok: false;
|
|
22
|
+
reason: string;
|
|
23
|
+
}>;
|
|
24
|
+
/**
|
|
25
|
+
* Print every known secret with its sources. Exit code 1 when a workflow
|
|
26
|
+
* promises a value the repository does not hold — that combination is the one
|
|
27
|
+
* that fails a deploy, and it fails talking about the value rather than the
|
|
28
|
+
* missing secret.
|
|
29
|
+
*/
|
|
30
|
+
export declare function secretsStatus(root: string, options: {
|
|
31
|
+
repo?: string;
|
|
32
|
+
}): number;
|
|
33
|
+
/** Set one secret from a pasted value. */
|
|
34
|
+
export declare function secretsSet(name: string, options: {
|
|
35
|
+
repo?: string;
|
|
36
|
+
}): Promise<number>;
|
|
37
|
+
/**
|
|
38
|
+
* Push every locally fetchable secret to the repository. Only names
|
|
39
|
+
* `smoo.secrets` declares a command for: everything else has no source here
|
|
40
|
+
* and must be pasted with `smoo secrets set`.
|
|
41
|
+
*/
|
|
42
|
+
export declare function secretsSync(root: string, options: {
|
|
43
|
+
repo?: string;
|
|
44
|
+
}): Promise<number>;
|
|
45
|
+
//# sourceMappingURL=commands.d.ts.map
|