@deployfoundation/foundation-deploy 0.1.1 → 0.1.3
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/bin/foundation-deploy.js +22 -3
- package/package.json +1 -1
- package/src/deploy/cli.ts +14 -0
- package/src/deploy/config-sync.ts +24 -3
- package/src/deploy/endpoint.ts +15 -1
|
@@ -70,10 +70,16 @@ async function unpackReleaseSkills(ctx, release) {
|
|
|
70
70
|
const key = release.manifest?.skills.key ?? skillsKey(release.version);
|
|
71
71
|
const dir = mkdtempSync(join(tmpdir(), "foundation-skills-"));
|
|
72
72
|
const tarball = join(dir, "skills.tar.gz");
|
|
73
|
-
const contents = join(dir, "skills");
|
|
74
|
-
mkdirSync(contents, { recursive: true });
|
|
75
73
|
await awsMutate(ctx, ["s3", "cp", `s3://${release.bucket}/${key}`, tarball]);
|
|
76
|
-
await
|
|
74
|
+
return await extractSkillsTarball(tarball, dir, { dryRun: ctx.dryRun });
|
|
75
|
+
}
|
|
76
|
+
async function extractSkillsTarball(tarball, dir, opts = {}) {
|
|
77
|
+
const contents = join(dir, "skills");
|
|
78
|
+
await run(["tar", "-xzf", tarball, "-C", dir], { dryRun: opts.dryRun });
|
|
79
|
+
if (opts.dryRun !== true && !existsSync(contents))
|
|
80
|
+
throw new Error(`${tarball} has no top-level skills/ directory`);
|
|
81
|
+
if (opts.dryRun === true)
|
|
82
|
+
mkdirSync(contents, { recursive: true });
|
|
77
83
|
return contents;
|
|
78
84
|
}
|
|
79
85
|
|
|
@@ -416,6 +422,10 @@ async function ensureEndpoint(runner, opts) {
|
|
|
416
422
|
return "created";
|
|
417
423
|
}
|
|
418
424
|
async function promoteEndpoint(runner, opts) {
|
|
425
|
+
if (opts.dryRun !== true && await endpointState(runner, opts.id, opts.name) === undefined) {
|
|
426
|
+
await ensureEndpoint(runner, opts);
|
|
427
|
+
return;
|
|
428
|
+
}
|
|
419
429
|
await runner.mutate([
|
|
420
430
|
"bedrock-agentcore-control",
|
|
421
431
|
"update-agent-runtime-endpoint",
|
|
@@ -1831,6 +1841,15 @@ ${USAGE}`);
|
|
|
1831
1841
|
}
|
|
1832
1842
|
if (command === "slack-manifest") {
|
|
1833
1843
|
const paths = loadInstanceContext(resolveInstanceFilePath(args, process.env));
|
|
1844
|
+
if (process.env.EVENTS_REQUEST_URL === undefined)
|
|
1845
|
+
console.error([
|
|
1846
|
+
"warning: EVENTS_REQUEST_URL is not set, so this manifest has NO event",
|
|
1847
|
+
"subscriptions, slash commands or interactivity. Applying it to an existing",
|
|
1848
|
+
"app removes them. Set EVENTS_REQUEST_URL to the <Prefix>Api stack's EventsUrl",
|
|
1849
|
+
"output (commands and interactivity are derived from it) unless you are",
|
|
1850
|
+
"creating the app for the first time."
|
|
1851
|
+
].join(`
|
|
1852
|
+
`));
|
|
1834
1853
|
console.log(JSON.stringify(slackManifestFor(paths.instance, {
|
|
1835
1854
|
...process.env.EVENTS_REQUEST_URL === undefined ? {} : { EVENTS_REQUEST_URL: process.env.EVENTS_REQUEST_URL },
|
|
1836
1855
|
...process.env.COMMANDS_REQUEST_URL === undefined ? {} : { COMMANDS_REQUEST_URL: process.env.COMMANDS_REQUEST_URL },
|
package/package.json
CHANGED
package/src/deploy/cli.ts
CHANGED
|
@@ -116,6 +116,20 @@ export async function main(argv: readonly string[] = process.argv.slice(2)): Pro
|
|
|
116
116
|
// print a banner into it; every other command announces its target first.
|
|
117
117
|
if (command === "slack-manifest") {
|
|
118
118
|
const paths = loadInstanceContext(resolveInstanceFilePath(args, process.env));
|
|
119
|
+
// Without the request URLs the manifest omits event subscriptions, slash
|
|
120
|
+
// commands and interactivity. That is right for creating a brand-new app,
|
|
121
|
+
// and destructive for an existing one: applying it strips the app's
|
|
122
|
+
// wiring. Say so on stderr, so stdout stays a clean manifest.
|
|
123
|
+
if (process.env.EVENTS_REQUEST_URL === undefined)
|
|
124
|
+
console.error(
|
|
125
|
+
[
|
|
126
|
+
"warning: EVENTS_REQUEST_URL is not set, so this manifest has NO event",
|
|
127
|
+
"subscriptions, slash commands or interactivity. Applying it to an existing",
|
|
128
|
+
"app removes them. Set EVENTS_REQUEST_URL to the <Prefix>Api stack's EventsUrl",
|
|
129
|
+
"output (commands and interactivity are derived from it) unless you are",
|
|
130
|
+
"creating the app for the first time.",
|
|
131
|
+
].join("\n"),
|
|
132
|
+
);
|
|
119
133
|
console.log(
|
|
120
134
|
JSON.stringify(
|
|
121
135
|
slackManifestFor(paths.instance, {
|
|
@@ -83,11 +83,32 @@ export async function unpackReleaseSkills(
|
|
|
83
83
|
const key = release.manifest?.skills.key ?? skillsKey(release.version);
|
|
84
84
|
const dir = mkdtempSync(join(tmpdir(), "foundation-skills-"));
|
|
85
85
|
const tarball = join(dir, "skills.tar.gz");
|
|
86
|
-
const contents = join(dir, "skills");
|
|
87
|
-
mkdirSync(contents, { recursive: true });
|
|
88
86
|
// `awsMutate` rather than a plain read, only so a dry run prints the copy
|
|
89
87
|
// instead of performing it.
|
|
90
88
|
await awsMutate(ctx, ["s3", "cp", `s3://${release.bucket}/${key}`, tarball]);
|
|
91
|
-
await
|
|
89
|
+
return await extractSkillsTarball(tarball, dir, { dryRun: ctx.dryRun });
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Unpack a release's `skills.tar.gz` and return the directory holding the
|
|
94
|
+
* skills themselves.
|
|
95
|
+
*
|
|
96
|
+
* `release-build` runs `tar -czf skills.tar.gz skills`, so the archive's top
|
|
97
|
+
* level is a `skills/` directory. It is extracted INTO `dir`, landing at
|
|
98
|
+
* `dir/skills`. v0.1.0 and v0.1.1 extracted into `dir/skills` instead, which
|
|
99
|
+
* produced `dir/skills/skills/…` and synced every product skill to
|
|
100
|
+
* `s3://…/skills/skills/`, one level below where the agent looks — so a release
|
|
101
|
+
* deploy silently shipped no product skills at all.
|
|
102
|
+
*/
|
|
103
|
+
export async function extractSkillsTarball(
|
|
104
|
+
tarball: string,
|
|
105
|
+
dir: string,
|
|
106
|
+
opts: { dryRun?: boolean } = {},
|
|
107
|
+
): Promise<string> {
|
|
108
|
+
const contents = join(dir, "skills");
|
|
109
|
+
await run(["tar", "-xzf", tarball, "-C", dir], { dryRun: opts.dryRun });
|
|
110
|
+
if (opts.dryRun !== true && !existsSync(contents))
|
|
111
|
+
throw new Error(`${tarball} has no top-level skills/ directory`);
|
|
112
|
+
if (opts.dryRun === true) mkdirSync(contents, { recursive: true });
|
|
92
113
|
return contents;
|
|
93
114
|
}
|
package/src/deploy/endpoint.ts
CHANGED
|
@@ -140,11 +140,25 @@ export async function ensureEndpoint(
|
|
|
140
140
|
return "created";
|
|
141
141
|
}
|
|
142
142
|
|
|
143
|
-
/**
|
|
143
|
+
/**
|
|
144
|
+
* Point the endpoint at `version` and wait for it to be READY there, creating
|
|
145
|
+
* it at that version when it does not exist yet.
|
|
146
|
+
*
|
|
147
|
+
* Only `setup` used to create `live`; `deploy` and `post-deploy` could only
|
|
148
|
+
* update it. An instance brought up the documented way, `foundation-deploy
|
|
149
|
+
* deploy` from npm, therefore reached promotion with no `live` to update, and
|
|
150
|
+
* the gateway's invoker, which calls `live`, had nothing to call: the first
|
|
151
|
+
* Slack message after a fresh install would have failed. Found by migrating
|
|
152
|
+
* Olivia.
|
|
153
|
+
*/
|
|
144
154
|
export async function promoteEndpoint(
|
|
145
155
|
runner: EndpointRunner,
|
|
146
156
|
opts: EndpointOptions,
|
|
147
157
|
): Promise<void> {
|
|
158
|
+
if (opts.dryRun !== true && (await endpointState(runner, opts.id, opts.name)) === undefined) {
|
|
159
|
+
await ensureEndpoint(runner, opts);
|
|
160
|
+
return;
|
|
161
|
+
}
|
|
148
162
|
await runner.mutate([
|
|
149
163
|
"bedrock-agentcore-control",
|
|
150
164
|
"update-agent-runtime-endpoint",
|