@astrale-os/sdk 0.6.0-beta.15 → 0.6.0-beta.16
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/deployment/adapter/adapter.d.ts +3 -2
- package/dist/deployment/adapter/index.d.ts +1 -0
- package/dist/deployment/adapter/index.js +1 -0
- package/dist/deployment/adapter/release/refusal.d.ts +10 -0
- package/dist/deployment/adapter/release/refusal.js +14 -0
- package/dist/tooling/cli/arguments.d.ts +7 -1
- package/dist/tooling/cli/arguments.js +67 -5
- package/dist/tooling/cli/commit.d.ts +12 -0
- package/dist/tooling/cli/commit.js +19 -0
- package/dist/tooling/cli/deploy-mode.d.ts +18 -6
- package/dist/tooling/cli/deploy-mode.js +28 -1
- package/dist/tooling/cli/diff/declared.d.ts +7 -0
- package/dist/tooling/cli/diff/declared.js +27 -0
- package/dist/tooling/cli/diff/index.d.ts +30 -0
- package/dist/tooling/cli/diff/index.js +58 -0
- package/dist/tooling/cli/diff/render.d.ts +15 -0
- package/dist/tooling/cli/diff/render.js +131 -0
- package/dist/tooling/cli/diff/report.d.ts +88 -0
- package/dist/tooling/cli/diff/report.js +154 -0
- package/dist/tooling/cli/help.js +98 -0
- package/dist/tooling/cli/immutable-deployment.d.ts +65 -9
- package/dist/tooling/cli/immutable-deployment.js +59 -19
- package/dist/tooling/cli/index.d.ts +8 -2
- package/dist/tooling/cli/index.js +6 -2
- package/dist/tooling/cli/orchestrate.js +104 -2
- package/dist/tooling/cli/publish/index.d.ts +74 -0
- package/dist/tooling/cli/publish/index.js +364 -0
- package/dist/tooling/cli/publish/report.d.ts +49 -0
- package/dist/tooling/cli/publish/report.js +15 -0
- package/dist/tooling/cli/registry/client.d.ts +127 -0
- package/dist/tooling/cli/registry/client.js +328 -0
- package/dist/tooling/cli/registry/executable.d.ts +20 -0
- package/dist/tooling/cli/registry/executable.js +79 -0
- package/dist/tooling/cli/registry/index.d.ts +6 -0
- package/dist/tooling/cli/registry/index.js +6 -0
- package/dist/tooling/cli/registry/process.d.ts +21 -0
- package/dist/tooling/cli/registry/process.js +84 -0
- package/dist/tooling/cli/yank.d.ts +34 -0
- package/dist/tooling/cli/yank.js +32 -0
- package/package.json +2 -2
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import type { DomainSchema } from '@astrale-os/kernel-dsl/v1/schema';
|
|
2
|
+
import type { BumpLevel, Version } from '../../../platform/versioning/index.js';
|
|
3
|
+
import type { RegistryIndex, RegistryPublication } from '../registry/index.js';
|
|
4
|
+
/** One change since the baseline, with the level it alone requires. */
|
|
5
|
+
export interface DiffChangeV1 {
|
|
6
|
+
/**
|
|
7
|
+
* The compared member's Key (`issues.astrale.ai:class.Issue.property.priority`), or the Domain's
|
|
8
|
+
* origin for a change of the whole build or Schema.
|
|
9
|
+
*/
|
|
10
|
+
readonly subject: string;
|
|
11
|
+
/**
|
|
12
|
+
* The compatibility engine's facet (`method.existence`, `property.required`, …), `schema` for a
|
|
13
|
+
* new Schema revision of equivalent meaning, `build` for new code under the same revision.
|
|
14
|
+
*/
|
|
15
|
+
readonly facet: string;
|
|
16
|
+
readonly state: 'missing' | 'changed' | 'added';
|
|
17
|
+
readonly bump: BumpLevel;
|
|
18
|
+
/** What differs, such as `optional → required`, when the observation says. */
|
|
19
|
+
readonly detail?: string;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* `astrale-domain diff --json` on stdout: the version the Project declares, checked against the
|
|
23
|
+
* highest published stable version up to it (CT30).
|
|
24
|
+
*/
|
|
25
|
+
export interface DiffReportV1 {
|
|
26
|
+
readonly format: 'astrale.diff-report';
|
|
27
|
+
readonly version: 1;
|
|
28
|
+
readonly origin: string;
|
|
29
|
+
/** `package.json` `version`. */
|
|
30
|
+
readonly declared: string;
|
|
31
|
+
/** The declared version already names a Publication: the report is informational. */
|
|
32
|
+
readonly published: boolean;
|
|
33
|
+
/** `unregistered`: no Domain of this origin the caller may read; nothing is compared. */
|
|
34
|
+
readonly registry: 'read' | 'unregistered';
|
|
35
|
+
/** The highest published stable version up to the declared one, yanked ones included. */
|
|
36
|
+
readonly baseline?: string;
|
|
37
|
+
/** The level the changes since the baseline require. */
|
|
38
|
+
readonly level?: BumpLevel;
|
|
39
|
+
/** The level after the 0.x rule. */
|
|
40
|
+
readonly effective?: BumpLevel;
|
|
41
|
+
/** The smallest version the changes admit, a pre-release such as `2.0.0-0`. */
|
|
42
|
+
readonly minimum?: string;
|
|
43
|
+
/** The stable form of the required version, such as `2.0.0`. */
|
|
44
|
+
readonly next?: string;
|
|
45
|
+
/** For a refused pre-release, the first pre-release of the required version on its channel. */
|
|
46
|
+
readonly suggestion?: string;
|
|
47
|
+
/**
|
|
48
|
+
* The declared version reaches the minimum, or there is nothing to compare. It judges an
|
|
49
|
+
* unpublished version: a published stable one is its own baseline and is never accepted, so a
|
|
50
|
+
* consumer decides on `published || accepted`, the exit status.
|
|
51
|
+
*/
|
|
52
|
+
readonly accepted: boolean;
|
|
53
|
+
/** Every change since the baseline, ordered by subject Key then observation; empty for none. */
|
|
54
|
+
readonly changes: readonly DiffChangeV1[];
|
|
55
|
+
}
|
|
56
|
+
export interface DiffInput {
|
|
57
|
+
readonly origin: string;
|
|
58
|
+
readonly declared: Version;
|
|
59
|
+
/**
|
|
60
|
+
* Which published versions can be the baseline (AM-23): `diff` compares with the highest stable
|
|
61
|
+
* version up to the declared one (`<=`, the default); `publish`, which never runs for a published
|
|
62
|
+
* version, with the highest one below it (`<`).
|
|
63
|
+
*/
|
|
64
|
+
readonly bound?: '<' | '<=';
|
|
65
|
+
/** The Schema revision the Project builds now. */
|
|
66
|
+
readonly revision: string;
|
|
67
|
+
/** The caller's view of the registry; `undefined` when it holds no readable Domain of `origin`. */
|
|
68
|
+
readonly index: RegistryIndex | undefined;
|
|
69
|
+
/** The Schema the Project builds now. */
|
|
70
|
+
readonly current: () => DomainSchema;
|
|
71
|
+
/** The build digest of every distinct bundler; read only when the Schema revision is unchanged. */
|
|
72
|
+
readonly builds: () => Promise<readonly string[]>;
|
|
73
|
+
/** The Schema a Publication names; read only when its revision differs from the Project's. */
|
|
74
|
+
readonly published: (publication: RegistryPublication) => Promise<DomainSchema>;
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Compare the Project with the highest published stable version up to the declared one
|
|
78
|
+
* (`baselineVersion(index, declared, '<=')`, or below it for `publish`, AM-23) and judge the declared version against the
|
|
79
|
+
* level its changes require (tech Versioning [.21507], [.106102]). The judgement always receives a
|
|
80
|
+
* level beside its baseline (AM-56): the compatibility engine's when the Schema revision changed,
|
|
81
|
+
* otherwise patch, the smallest level, which `diff` picks itself when nothing changed at all.
|
|
82
|
+
*/
|
|
83
|
+
export declare function diffReport(input: DiffInput): Promise<DiffReportV1>;
|
|
84
|
+
/**
|
|
85
|
+
* Decode the bundle a Publication stores and admit it only as that Publication's Schema: the
|
|
86
|
+
* Domain's origin and the Publication's Schema revision.
|
|
87
|
+
*/
|
|
88
|
+
export declare function publishedSchema(bytes: Uint8Array, publication: RegistryPublication, origin: string): DomainSchema;
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
import * as bundle from '@astrale-os/kernel-dsl/v1/bundle/transport';
|
|
2
|
+
import { requiredBump } from '@astrale-os/kernel-dsl/v1/schema/compatibility';
|
|
3
|
+
import { revision } from '@astrale-os/kernel-dsl/v1/schema/revision';
|
|
4
|
+
import { baselineVersion, judgeVersion } from '../../../platform/versioning/index.js';
|
|
5
|
+
/**
|
|
6
|
+
* Compare the Project with the highest published stable version up to the declared one
|
|
7
|
+
* (`baselineVersion(index, declared, '<=')`, or below it for `publish`, AM-23) and judge the declared version against the
|
|
8
|
+
* level its changes require (tech Versioning [.21507], [.106102]). The judgement always receives a
|
|
9
|
+
* level beside its baseline (AM-56): the compatibility engine's when the Schema revision changed,
|
|
10
|
+
* otherwise patch, the smallest level, which `diff` picks itself when nothing changed at all.
|
|
11
|
+
*/
|
|
12
|
+
export async function diffReport(input) {
|
|
13
|
+
const identity = {
|
|
14
|
+
format: 'astrale.diff-report',
|
|
15
|
+
version: 1,
|
|
16
|
+
origin: input.origin,
|
|
17
|
+
declared: input.declared,
|
|
18
|
+
};
|
|
19
|
+
if (input.index === undefined) {
|
|
20
|
+
return Object.freeze({
|
|
21
|
+
...identity,
|
|
22
|
+
published: false,
|
|
23
|
+
registry: 'unregistered',
|
|
24
|
+
accepted: true,
|
|
25
|
+
changes: Object.freeze([]),
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
const publications = input.index.publications;
|
|
29
|
+
const published = publications.some(({ version }) => version === input.declared);
|
|
30
|
+
// An index entry that is not a canonical version is never a baseline: `baselineVersion` keeps
|
|
31
|
+
// only canonical stable versions (AM-56), so the registry's strings need no admission here.
|
|
32
|
+
const index = publications.map(({ version, yanked }) => ({
|
|
33
|
+
version: version,
|
|
34
|
+
yanked,
|
|
35
|
+
}));
|
|
36
|
+
const baseline = baselineVersion(index, input.declared, input.bound ?? '<=');
|
|
37
|
+
if (baseline === undefined) {
|
|
38
|
+
// Without a stable version before it there is nothing to check (tech [.106102]).
|
|
39
|
+
const verdict = judgeVersion({ declared: input.declared });
|
|
40
|
+
return Object.freeze({
|
|
41
|
+
...identity,
|
|
42
|
+
published,
|
|
43
|
+
registry: 'read',
|
|
44
|
+
accepted: verdict.accepted,
|
|
45
|
+
changes: Object.freeze([]),
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
const publication = publications.find(({ version }) => version === baseline);
|
|
49
|
+
const { level, changes } = await changesSince(publication, input);
|
|
50
|
+
const verdict = judgeVersion({ declared: input.declared, previous: baseline, level });
|
|
51
|
+
return Object.freeze({
|
|
52
|
+
...identity,
|
|
53
|
+
published,
|
|
54
|
+
registry: 'read',
|
|
55
|
+
baseline,
|
|
56
|
+
level,
|
|
57
|
+
effective: verdict.effective,
|
|
58
|
+
minimum: verdict.minimum,
|
|
59
|
+
next: verdict.next,
|
|
60
|
+
...(verdict.suggestion === undefined ? {} : { suggestion: verdict.suggestion }),
|
|
61
|
+
accepted: verdict.accepted,
|
|
62
|
+
changes,
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Decode the bundle a Publication stores and admit it only as that Publication's Schema: the
|
|
67
|
+
* Domain's origin and the Publication's Schema revision.
|
|
68
|
+
*/
|
|
69
|
+
export function publishedSchema(bytes, publication, origin) {
|
|
70
|
+
const root = bundle.decode(bytes).root;
|
|
71
|
+
if (root.origin !== origin || revision(root) !== publication.schemaRevision) {
|
|
72
|
+
throw new TypeError(`The stored bundle of ${origin}@${publication.version} is not that Publication's Schema ${publication.schemaRevision}.`);
|
|
73
|
+
}
|
|
74
|
+
return root;
|
|
75
|
+
}
|
|
76
|
+
async function changesSince(publication, input) {
|
|
77
|
+
if (publication.schemaRevision !== input.revision) {
|
|
78
|
+
const required = requiredBump(await input.published(publication), input.current());
|
|
79
|
+
const changes = required.changes.map(change);
|
|
80
|
+
return {
|
|
81
|
+
level: required.level,
|
|
82
|
+
changes: Object.freeze(changes.length > 0
|
|
83
|
+
? changes
|
|
84
|
+
: // A new revision whose meaning the engine finds equivalent, such as descriptions.
|
|
85
|
+
[
|
|
86
|
+
Object.freeze({
|
|
87
|
+
subject: input.origin,
|
|
88
|
+
facet: 'schema',
|
|
89
|
+
state: 'changed',
|
|
90
|
+
bump: 'patch',
|
|
91
|
+
detail: 'same meaning',
|
|
92
|
+
}),
|
|
93
|
+
]),
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
const builds = await input.builds();
|
|
97
|
+
if (builds.includes(publication.buildDigest)) {
|
|
98
|
+
// No change at all: same build digest and no row of [.21507] (AM-56).
|
|
99
|
+
return { level: 'patch', changes: Object.freeze([]) };
|
|
100
|
+
}
|
|
101
|
+
// Code only, same Schema revision ([.21507], first row).
|
|
102
|
+
return {
|
|
103
|
+
level: 'patch',
|
|
104
|
+
changes: Object.freeze([
|
|
105
|
+
Object.freeze({
|
|
106
|
+
subject: input.origin,
|
|
107
|
+
facet: 'build',
|
|
108
|
+
state: 'changed',
|
|
109
|
+
bump: 'patch',
|
|
110
|
+
detail: `${publication.buildDigest} → ${builds.length === 0 ? 'none' : builds.join(', ')}`,
|
|
111
|
+
}),
|
|
112
|
+
]),
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
function change({ subject, observation, bump }) {
|
|
116
|
+
const detail = describe(observation);
|
|
117
|
+
return Object.freeze({
|
|
118
|
+
subject: subject.key,
|
|
119
|
+
facet: observation.facet,
|
|
120
|
+
// `requiredBump` lists only observations that are not equal.
|
|
121
|
+
state: observation.state,
|
|
122
|
+
bump,
|
|
123
|
+
...(detail === undefined ? {} : { detail }),
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
const DETAILED_DIFFERENCES = 3;
|
|
127
|
+
const VALUE_LENGTH = 40;
|
|
128
|
+
/** The observation's differences in a few words: `optional → required`, `input/type: "string" → "number"`. */
|
|
129
|
+
function describe(observation) {
|
|
130
|
+
const differences = observation.differences;
|
|
131
|
+
if (differences.length === 0)
|
|
132
|
+
return undefined;
|
|
133
|
+
const [first] = differences;
|
|
134
|
+
if (differences.length === 1 &&
|
|
135
|
+
first.path === '/required' &&
|
|
136
|
+
typeof first.before === 'boolean' &&
|
|
137
|
+
typeof first.after === 'boolean') {
|
|
138
|
+
return first.after ? 'optional → required' : 'required → optional';
|
|
139
|
+
}
|
|
140
|
+
const described = differences.slice(0, DETAILED_DIFFERENCES).map((difference) => {
|
|
141
|
+
const path = difference.path === '' ? '/' : difference.path.slice(1);
|
|
142
|
+
if (difference.before === undefined)
|
|
143
|
+
return `${path}: added ${value(difference.after)}`;
|
|
144
|
+
if (difference.after === undefined)
|
|
145
|
+
return `${path}: removed ${value(difference.before)}`;
|
|
146
|
+
return `${path}: ${value(difference.before)} → ${value(difference.after)}`;
|
|
147
|
+
});
|
|
148
|
+
const more = differences.length - described.length;
|
|
149
|
+
return more > 0 ? `${described.join('; ')}; ${more} more` : described.join('; ');
|
|
150
|
+
}
|
|
151
|
+
function value(input) {
|
|
152
|
+
const text = JSON.stringify(input) ?? String(input);
|
|
153
|
+
return text.length > VALUE_LENGTH ? `${text.slice(0, VALUE_LENGTH - 1)}…` : text;
|
|
154
|
+
}
|
package/dist/tooling/cli/help.js
CHANGED
|
@@ -22,11 +22,14 @@ Commands:
|
|
|
22
22
|
dev [environment] Deprecated: use deploy, then astrale domain install.
|
|
23
23
|
build Build, verify and print the build digest.
|
|
24
24
|
deploy <environment> Deploy one Environment; never installs.
|
|
25
|
+
diff Show the changes since the published version and the minimum.
|
|
25
26
|
list List the deployments of the Project's Environments.
|
|
27
|
+
publish <environment> Deploy, verify and publish the package.json version; never installs.
|
|
26
28
|
test Run Project tests, optionally against one Environment.
|
|
27
29
|
lint Check Domain source and architecture.
|
|
28
30
|
package Prepare public declarations for publication.
|
|
29
31
|
upgrade Update Astrale dependencies through pnpm (default: beta).
|
|
32
|
+
yank <version> Take a published version out of resolution, or put it back.
|
|
30
33
|
|
|
31
34
|
Options:
|
|
32
35
|
-h, --help Show help.
|
|
@@ -187,6 +190,79 @@ Behavior:
|
|
|
187
190
|
takes.
|
|
188
191
|
Exit status: 0 listed, 1 a host could not be listed (with --json, nothing on
|
|
189
192
|
stdout), 2 usage error.
|
|
193
|
+
`,
|
|
194
|
+
diff: `Show the changes since the last published version and the version they require.
|
|
195
|
+
|
|
196
|
+
Usage:
|
|
197
|
+
astrale-domain diff [--as <identity>] [--json]
|
|
198
|
+
|
|
199
|
+
Options:
|
|
200
|
+
--as <identity> Select the Astrale identity that reads the Domain registry.
|
|
201
|
+
--json Print one DiffReportV1 on stdout; the summary goes to stderr.
|
|
202
|
+
-h, --help Show help for diff.
|
|
203
|
+
|
|
204
|
+
Behavior:
|
|
205
|
+
Reads the declared version from package.json and compares the Domain with the
|
|
206
|
+
highest published stable version up to it, yanked versions included. The level
|
|
207
|
+
the changes require is a floor: removing or changing a member is major, adding
|
|
208
|
+
one minor, anything else (code, descriptions) patch; below 1.0.0 a breaking
|
|
209
|
+
change raises the minor. Callable authorization is outside the floor: raise the
|
|
210
|
+
version yourself when you narrow it.
|
|
211
|
+
When package.json still names a published version, as on a feature branch, the
|
|
212
|
+
report is informational and exits 0. Otherwise the declared version must reach
|
|
213
|
+
the minimum: a version that is too low exits 1 and names what requires more, as
|
|
214
|
+
on a release PR, where Release-As: 2.0.0 or a feat!: commit raises the number.
|
|
215
|
+
Nothing to compare (no published stable version, or a Domain absent from the
|
|
216
|
+
registry or not readable by the caller) exits 0.
|
|
217
|
+
Reads the registry through the Astrale CLI (domain versions) with the caller's
|
|
218
|
+
own credential, and the stored bundle of the compared version only when its
|
|
219
|
+
Schema differs. Builds the Domain when the Schema is unchanged, to compare build
|
|
220
|
+
digests. Deploys, publishes and installs nothing.
|
|
221
|
+
Exit status: 0 accepted, published or nothing to compare; 1 too low or failed
|
|
222
|
+
(with --json, a failure prints nothing on stdout); 2 usage error.
|
|
223
|
+
`,
|
|
224
|
+
publish: `Deploy one Environment, verify it, and publish the version package.json declares.
|
|
225
|
+
|
|
226
|
+
Usage:
|
|
227
|
+
astrale-domain publish <environment> [--allow-dirty] [--as <identity>] [--json]
|
|
228
|
+
|
|
229
|
+
Arguments:
|
|
230
|
+
environment Required adapter environment key, usually production.
|
|
231
|
+
|
|
232
|
+
Options:
|
|
233
|
+
--allow-dirty Publish from a working tree with changes, or outside git; the
|
|
234
|
+
Publication is marked dirty.
|
|
235
|
+
--as <identity> Select the Astrale identity that reads and writes the Domain
|
|
236
|
+
registry and deploys.
|
|
237
|
+
--json Print one PublishReportV1 on stdout; progress goes to stderr.
|
|
238
|
+
-h, --help Show help for publish.
|
|
239
|
+
|
|
240
|
+
Behavior:
|
|
241
|
+
Names one immutable deployment's release with the version in package.json, in
|
|
242
|
+
this order, deploying only once the registry allows the version:
|
|
243
|
+
1. Before any effect: refuses an Environment that does not deploy immutable
|
|
244
|
+
deployments, a working tree with changes or no git commit (unless
|
|
245
|
+
--allow-dirty), and warns when no remote branch holds the commit; then builds,
|
|
246
|
+
freezes the configuration, places the deployment and seals its release.
|
|
247
|
+
2. Reads the version from package.json and the registry through the Astrale CLI.
|
|
248
|
+
A version already published with this release succeeds without effect; with
|
|
249
|
+
another release it is refused: a published version never changes.
|
|
250
|
+
3. Compares with the highest stable version below it, yanked versions included,
|
|
251
|
+
as diff does, and refuses a version that is too low.
|
|
252
|
+
4. Deploys the release, or reuses its deployment, as deploy does.
|
|
253
|
+
5. Verifies that the deployment serves the sealed release, within 60 seconds.
|
|
254
|
+
6. Asks Admin for the Publication, which Admin creates under the Domain's lock. A
|
|
255
|
+
version published meanwhile with another release is refused, and this
|
|
256
|
+
deployment stays a preview. On a platform dispatch namespace the published
|
|
257
|
+
deployment is then kept from expiry; Admin keeps those of its Services itself.
|
|
258
|
+
A failure leaves at most a deployment without a version, and says whether a rerun
|
|
259
|
+
can help: when it can, rerun publish, which reuses it; a refusal Admin repeats
|
|
260
|
+
(a missing domain_admin right, a release it will not name) names its cause.
|
|
261
|
+
Admin unavailable or the Domain absent from the registry: nothing is deployed.
|
|
262
|
+
It never installs the Domain: install the URL it prints with
|
|
263
|
+
${installCommand()}.
|
|
264
|
+
Exit status: 0 published or already published; 1 refused or failed (with --json,
|
|
265
|
+
a failure prints nothing on stdout); 2 usage error.
|
|
190
266
|
`,
|
|
191
267
|
test: `Run Project tests locally or against one selected Environment.
|
|
192
268
|
|
|
@@ -214,6 +290,28 @@ Options:
|
|
|
214
290
|
--fix Apply supported fixes.
|
|
215
291
|
--format <format> Select stylish or json output (default: stylish).
|
|
216
292
|
-h, --help Show help for lint.
|
|
293
|
+
`,
|
|
294
|
+
yank: `Take one published version of the Domain out of resolution, or put it back.
|
|
295
|
+
|
|
296
|
+
Usage:
|
|
297
|
+
astrale-domain yank <version> [--undo] [--json]
|
|
298
|
+
|
|
299
|
+
Arguments:
|
|
300
|
+
version One published version of this Project's Domain, e.g. 1.5.0.
|
|
301
|
+
|
|
302
|
+
Options:
|
|
303
|
+
--undo Let line references choose the version again.
|
|
304
|
+
--json Print one YankReportV1 on stdout.
|
|
305
|
+
-h, --help Show help for yank.
|
|
306
|
+
|
|
307
|
+
Behavior:
|
|
308
|
+
Changes the version in the Admin registry through the Astrale CLI, with its configured
|
|
309
|
+
Admin target and identity; yanking requires administering the Domain. A line reference
|
|
310
|
+
such as @1.5 never chooses a yanked version, and an exact reference installs it with a
|
|
311
|
+
warning. Installations keep running and the deployment keeps serving: yanking only
|
|
312
|
+
changes resolution. A version already in the requested state answers unchanged, so a
|
|
313
|
+
rerun is safe. Exit status: 0 done, 1 refused or failed, 2 usage error; a refused or
|
|
314
|
+
failed run prints nothing on stdout.
|
|
217
315
|
`,
|
|
218
316
|
package: `Prepare public TypeScript declarations for package publication.
|
|
219
317
|
|
|
@@ -1,15 +1,71 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { DeploymentCommitV1, FrozenConfigurationV1 } from '../../deployment/address/index.js';
|
|
2
|
+
import type { Adapter, Build, Bundle, LegacyAdapter, Placement, Release, ResolvedRuntimeReference } from '../../deployment/index.js';
|
|
2
3
|
import type { DeployResultV1 } from './deploy-result.js';
|
|
3
4
|
/**
|
|
4
|
-
*
|
|
5
|
+
* Everything the deploy of one canonical Environment derives before its only effectful call: the
|
|
6
|
+
* Bundle, the Environment's current secrets, the frozen configuration, where the host places the
|
|
7
|
+
* deployment, its label, the sealed release it serves and the commit it is built from. Planning has
|
|
8
|
+
* no effect at the host: `placement` only reads, and nothing is created, reused or written.
|
|
9
|
+
*/
|
|
10
|
+
export interface ImmutableDeploymentPlan {
|
|
11
|
+
readonly projectDir: string;
|
|
12
|
+
readonly environment: string;
|
|
13
|
+
readonly adapter: Adapter<object>;
|
|
14
|
+
readonly parameters: object;
|
|
15
|
+
readonly identity?: string;
|
|
16
|
+
readonly bundle: Bundle;
|
|
17
|
+
readonly secrets: Readonly<Record<string, string>>;
|
|
18
|
+
readonly configuration: FrozenConfigurationV1;
|
|
19
|
+
readonly placement: Placement;
|
|
20
|
+
/** `<line>-<content>`: the deployment's DNS label and provider script. */
|
|
21
|
+
readonly label: string;
|
|
22
|
+
/** The `DomainRelease` v4 the deployment serves at its URL, `release.url`. */
|
|
23
|
+
readonly release: Release;
|
|
24
|
+
/** The commit this deploy runs from, which a deployment it creates declares. */
|
|
25
|
+
readonly commit: DeploymentCommitV1 | null;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Plan the immutable deployment of one canonical Environment (CT33), without any effect.
|
|
29
|
+
*
|
|
30
|
+
* The SDK bundles exactly as `astrale-domain build` does, asks the adapter to freeze the
|
|
31
|
+
* Environment's configuration and say where its host places deployments, derives the deployment
|
|
32
|
+
* label and URL from them (S3), seals the `DomainRelease` v4 the deployment serves at that URL
|
|
33
|
+
* (S4a), and reads the commit it is built from. `deploy` deploys the plan at once; `publish`
|
|
34
|
+
* checks the registry against the sealed release first, and deploys only when it may name it.
|
|
35
|
+
*/
|
|
36
|
+
export declare function planImmutableDeployment(input: {
|
|
37
|
+
readonly projectDir: string;
|
|
38
|
+
readonly environment: string;
|
|
39
|
+
/** A canonical Environment's adapter (CT33), which implements adapter interface v2. */
|
|
40
|
+
readonly adapter: Adapter<object> | LegacyAdapter<object>;
|
|
41
|
+
readonly parameters: object;
|
|
42
|
+
readonly build: Build;
|
|
43
|
+
readonly runtime: ResolvedRuntimeReference;
|
|
44
|
+
readonly identity?: string;
|
|
45
|
+
/** The commit provenance the caller already read (`publish` checks it first); read otherwise. */
|
|
46
|
+
readonly commit?: DeploymentCommitV1 | null;
|
|
47
|
+
readonly signal: AbortSignal;
|
|
48
|
+
}): Promise<ImmutableDeploymentPlan>;
|
|
49
|
+
/**
|
|
50
|
+
* The commit the Project's runtime module is built from, as a deployment declares it (CT18
|
|
51
|
+
* `commit`): its sha, whether the tree holds changes it does not, and the last release tag before
|
|
52
|
+
* it. `null` outside git.
|
|
53
|
+
*/
|
|
54
|
+
export declare function runtimeCommit(projectDir: string, runtime: ResolvedRuntimeReference, signal: AbortSignal): Promise<DeploymentCommitV1 | null>;
|
|
55
|
+
/**
|
|
56
|
+
* Create, or reuse, the immutable deployment a plan describes: the adapter's `deployRelease` is
|
|
57
|
+
* its only effectful call. The SDK makes no Kernel call, the deploy calls no instance and installs
|
|
58
|
+
* nothing: `astrale domain install <url>` installs the URL it prints.
|
|
5
59
|
*
|
|
6
|
-
*
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
60
|
+
* Returns the deploy result, or nothing once a failure is reported on stderr.
|
|
61
|
+
*/
|
|
62
|
+
export declare function deployPlannedRelease(plan: ImmutableDeploymentPlan, input: {
|
|
63
|
+
readonly signal: AbortSignal;
|
|
64
|
+
readonly report: (line: string) => void;
|
|
65
|
+
}): Promise<DeployResultV1 | undefined>;
|
|
66
|
+
/**
|
|
67
|
+
* Deploy one canonical Environment (CT33) as the immutable deployment of one sealed release: plan
|
|
68
|
+
* it without effect, then make the adapter's one effectful call.
|
|
13
69
|
*
|
|
14
70
|
* Returns the deploy result, or nothing once a failure is reported on stderr.
|
|
15
71
|
*/
|
|
@@ -7,19 +7,15 @@ import { deployResult } from './deploy-result.js';
|
|
|
7
7
|
import { error } from './log.js';
|
|
8
8
|
import { environmentSecrets } from './secrets.js';
|
|
9
9
|
/**
|
|
10
|
-
*
|
|
10
|
+
* Plan the immutable deployment of one canonical Environment (CT33), without any effect.
|
|
11
11
|
*
|
|
12
|
-
* The SDK
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
* the deploy calls no instance and installs nothing: `astrale domain install <url>` installs the
|
|
18
|
-
* URL it prints.
|
|
19
|
-
*
|
|
20
|
-
* Returns the deploy result, or nothing once a failure is reported on stderr.
|
|
12
|
+
* The SDK bundles exactly as `astrale-domain build` does, asks the adapter to freeze the
|
|
13
|
+
* Environment's configuration and say where its host places deployments, derives the deployment
|
|
14
|
+
* label and URL from them (S3), seals the `DomainRelease` v4 the deployment serves at that URL
|
|
15
|
+
* (S4a), and reads the commit it is built from. `deploy` deploys the plan at once; `publish`
|
|
16
|
+
* checks the registry against the sealed release first, and deploys only when it may name it.
|
|
21
17
|
*/
|
|
22
|
-
export async function
|
|
18
|
+
export async function planImmutableDeployment(input) {
|
|
23
19
|
const { parameters, environment, build, signal } = input;
|
|
24
20
|
const adapter = releaseAdapter(input.adapter);
|
|
25
21
|
const identity = input.identity === undefined ? {} : { identity: input.identity };
|
|
@@ -39,25 +35,59 @@ export async function deployImmutable(input) {
|
|
|
39
35
|
const origin = build.schema.compiled.root.origin;
|
|
40
36
|
const label = deploymentLabel(deploymentLine({ origin, environment, addressing: placement.addressing }), deploymentContent(bundle.digest, configuration));
|
|
41
37
|
const release = assemble(build, bundle.digest, deploymentUrl(label, placement.routingDomain));
|
|
42
|
-
const commit =
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
signal,
|
|
47
|
-
});
|
|
48
|
-
const deployed = await adapter.deployRelease(parameters, {
|
|
38
|
+
const commit = input.commit !== undefined
|
|
39
|
+
? input.commit
|
|
40
|
+
: await runtimeCommit(input.projectDir, input.runtime, signal);
|
|
41
|
+
return Object.freeze({
|
|
49
42
|
projectDir: input.projectDir,
|
|
50
43
|
environment,
|
|
44
|
+
adapter,
|
|
45
|
+
parameters,
|
|
51
46
|
...identity,
|
|
52
|
-
secrets,
|
|
53
47
|
bundle,
|
|
48
|
+
secrets,
|
|
54
49
|
configuration,
|
|
55
50
|
placement,
|
|
56
51
|
label,
|
|
57
52
|
release,
|
|
58
53
|
commit,
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* The commit the Project's runtime module is built from, as a deployment declares it (CT18
|
|
58
|
+
* `commit`): its sha, whether the tree holds changes it does not, and the last release tag before
|
|
59
|
+
* it. `null` outside git.
|
|
60
|
+
*/
|
|
61
|
+
export function runtimeCommit(projectDir, runtime, signal) {
|
|
62
|
+
return deploymentCommit({
|
|
63
|
+
projectDir,
|
|
64
|
+
// The configuration sits in the Project directory, and names its runtime relative to it.
|
|
65
|
+
runtimeModule: resolve(projectDir, runtime.reference.path),
|
|
59
66
|
signal,
|
|
60
67
|
});
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Create, or reuse, the immutable deployment a plan describes: the adapter's `deployRelease` is
|
|
71
|
+
* its only effectful call. The SDK makes no Kernel call, the deploy calls no instance and installs
|
|
72
|
+
* nothing: `astrale domain install <url>` installs the URL it prints.
|
|
73
|
+
*
|
|
74
|
+
* Returns the deploy result, or nothing once a failure is reported on stderr.
|
|
75
|
+
*/
|
|
76
|
+
export async function deployPlannedRelease(plan, input) {
|
|
77
|
+
const { adapter, environment, label, release } = plan;
|
|
78
|
+
const deployed = await adapter.deployRelease(plan.parameters, {
|
|
79
|
+
projectDir: plan.projectDir,
|
|
80
|
+
environment,
|
|
81
|
+
...(plan.identity === undefined ? {} : { identity: plan.identity }),
|
|
82
|
+
secrets: plan.secrets,
|
|
83
|
+
bundle: plan.bundle,
|
|
84
|
+
configuration: plan.configuration,
|
|
85
|
+
placement: plan.placement,
|
|
86
|
+
label,
|
|
87
|
+
release,
|
|
88
|
+
commit: plan.commit,
|
|
89
|
+
signal: input.signal,
|
|
90
|
+
});
|
|
61
91
|
if (deployed.status !== 'ready') {
|
|
62
92
|
error(`Deployment failed during ${deployed.phase}: ${deployed.error.message}`);
|
|
63
93
|
return undefined;
|
|
@@ -74,6 +104,16 @@ export async function deployImmutable(input) {
|
|
|
74
104
|
input.report('Ready: deployment verified');
|
|
75
105
|
return result;
|
|
76
106
|
}
|
|
107
|
+
/**
|
|
108
|
+
* Deploy one canonical Environment (CT33) as the immutable deployment of one sealed release: plan
|
|
109
|
+
* it without effect, then make the adapter's one effectful call.
|
|
110
|
+
*
|
|
111
|
+
* Returns the deploy result, or nothing once a failure is reported on stderr.
|
|
112
|
+
*/
|
|
113
|
+
export async function deployImmutable(input) {
|
|
114
|
+
const plan = await planImmutableDeployment(input);
|
|
115
|
+
return deployPlannedRelease(plan, { signal: input.signal, report: input.report });
|
|
116
|
+
}
|
|
77
117
|
/**
|
|
78
118
|
* What the deploy did to the secrets of the one deployment it made or reused: `bound` to the new
|
|
79
119
|
* deployment, or `updated` or left `unchanged` in place on the reused one. No other deployment's
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* `@astrale-os/sdk/cli` — the `astrale-domain` CLI
|
|
3
|
-
* (dev | build | deploy | list | test | lint | package), its JSON results,
|
|
4
|
-
*
|
|
3
|
+
* (dev | build | deploy | diff | list | publish | test | lint | package | yank), its JSON results,
|
|
4
|
+
* the deploy mode each command selects for an Environment (CT33), and the explicit dotenv boundary.
|
|
5
|
+
* `dev` is deprecated and lives in `legacy/development/`.
|
|
5
6
|
*
|
|
6
7
|
* Node-only: the CLI imports `node:fs`/`node:module`/`node:url` and runs under
|
|
7
8
|
* Bun (it imports the project's `astrale.config.ts` directly). This subpath is
|
|
@@ -13,5 +14,10 @@
|
|
|
13
14
|
export { run } from './run.js';
|
|
14
15
|
export type { BuildResultV1 } from './build.js';
|
|
15
16
|
export type { DeployResultV1, DeploymentSecretsState } from './deploy-result.js';
|
|
17
|
+
export type { DiffChangeV1, DiffReportV1 } from './diff/index.js';
|
|
16
18
|
export type { ListedDeploymentV1, ListResultV1, UnlistedEnvironmentV1 } from './list.js';
|
|
19
|
+
export type { PublishReportV1 } from './publish/index.js';
|
|
20
|
+
export type { YankReportV1 } from './yank.js';
|
|
21
|
+
export { selectDeployMode } from './deploy-mode.js';
|
|
22
|
+
export type { CloudflareDirectParameter, DeployMode, DeployModeCommand, DeployRefusal, LegacyDirectReason, } from './deploy-mode.js';
|
|
17
23
|
export { loadDeclaredSecrets } from './dotenv.js';
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* `@astrale-os/sdk/cli` — the `astrale-domain` CLI
|
|
3
|
-
* (dev | build | deploy | list | test | lint | package), its JSON results,
|
|
4
|
-
*
|
|
3
|
+
* (dev | build | deploy | diff | list | publish | test | lint | package | yank), its JSON results,
|
|
4
|
+
* the deploy mode each command selects for an Environment (CT33), and the explicit dotenv boundary.
|
|
5
|
+
* `dev` is deprecated and lives in `legacy/development/`.
|
|
5
6
|
*
|
|
6
7
|
* Node-only: the CLI imports `node:fs`/`node:module`/`node:url` and runs under
|
|
7
8
|
* Bun (it imports the project's `astrale.config.ts` directly). This subpath is
|
|
@@ -11,4 +12,7 @@
|
|
|
11
12
|
* The bin lives at `./bin`.
|
|
12
13
|
*/
|
|
13
14
|
export { run } from './run.js';
|
|
15
|
+
// The domain-publish Action asks the selection `publish` makes before it runs it, to skip an
|
|
16
|
+
// Environment that is not canonical with a notice instead of failing on its refusal.
|
|
17
|
+
export { selectDeployMode } from './deploy-mode.js';
|
|
14
18
|
export { loadDeclaredSecrets } from './dotenv.js';
|