Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(cli): deployment after reloading config #917

Merged
merged 2 commits into from
Nov 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 7 additions & 9 deletions src/meta-cli/src/deploy/actors/task_manager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -284,16 +284,14 @@ impl<A: TaskAction + 'static> Actor for TaskManager<A> {

fn stopping(&mut self, ctx: &mut Self::Context) -> Running {
match &self.stop_reason {
Some(reason) => {
if matches!(reason, StopReason::Restart) {
self.watcher_addr = self
.init_params
.start_source(ctx.address(), self.task_generator.clone());
Running::Continue
} else {
Running::Stop
}
Some(StopReason::Restart) => {
self.stop_reason.take();
self.watcher_addr = self
.init_params
.start_source(ctx.address(), self.task_generator.clone());
Running::Continue
}
Some(_) => Running::Stop,
None => Running::Continue,
}
}
Expand Down
135 changes: 102 additions & 33 deletions tests/e2e/cli/watch_test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,75 +2,144 @@
// SPDX-License-Identifier: MPL-2.0

import * as path from "@std/path";
import { assert } from "@std/assert";
import { Meta } from "test-utils/mod.ts";
import { MetaTest } from "test-utils/test.ts";
import { killProcess, Lines } from "test-utils/process.ts";
import { makeMetaCliTest } from "test-utils/meta.ts";

const typegraphConfig = `
typegraphs:
typescript:
include: "api/example.ts"`;
include: "api/deps.ts"`;

async function setupDirectory(t: MetaTest, dir: string) {
console.log("Preparing test directory...");

await t.shell([
"bash",
"-c",
`
rm -rf ./tmp && mkdir -p tmp/deps
meta new --template deno ${dir}
cp ./e2e/cli/typegraphs/deps.ts ${path.join(dir, "api", "example.ts")}
meta new --template python ${dir}
cp ./e2e/cli/typegraphs/deps.ts ${path.join(dir, "api")}
cp ./e2e/cli/typegraphs/deps.ts ${path.join(dir, "api", "excluded.ts")}
cp ./e2e/cli/artifacts/ops.ts ${path.join(dir, "deps", "ops.ts")}
echo "${typegraphConfig}" >> ${path.join(dir, "metatype.yaml")}
`,
]);
}

Meta.test({ name: "meta dev: watch artifacts" }, async (t) => {
Meta.test({ name: "meta dev: watch typegraphs" }, async (t) => {
const targetDir = path.join(t.workingDir, "tmp");

console.log("Preparing test directory...");

await setupDirectory(t, targetDir);

const metadev = new Deno.Command("meta", {
cwd: targetDir,
args: ["dev", `--gate=http://localhost:${t.port}`],
stderr: "piped",
}).spawn();
const { expectStderr, stderr } = makeMetaCliTest(t, targetDir, [
"dev",
`--gate=http://localhost:${t.port}`,
]);

await t.should("deploy typegraphs", async () => {
// order is not deterministic but there should be two
await expectStderr("successfully deployed typegraph");
await expectStderr("successfully deployed typegraph");
});

const stderr = new Lines(metadev.stderr);
await t.should("watch modified typegraph", async () => {
await t.shell(["bash", "-c", "echo '' >> api/example.py"], {
currentDir: targetDir,
});

await t.should("upload artifact", async () => {
await stderr.readWhile((line) => !line.includes("artifact uploaded"));
await expectStderr('File modified: "api/example.py"');
});

await t.should("deploy typegraph", async () => {
await stderr.readWhile(
(line) => !line.includes("successfully deployed typegraph"),
);
await t.should("re-deploy typegraph", () =>
expectStderr("successfully deployed typegraph example"),
);

await t.should("ignore excluded typegraph", async () => {
await t.shell(["bash", "-c", "echo '' >> api/excluded.ts"], {
currentDir: targetDir,
});

const lines: string[] = [];

try {
await stderr.readWhile((line) => {
lines.push(line);
return true;
}, 3000);
} catch (_) {
// timeout error
} finally {
assert(!lines.join("\n").includes("api/excluded.ts"));
}
});
});

Meta.test({ name: "meta dev: watch metatype.yaml" }, async (t) => {
const targetDir = path.join(t.workingDir, "tmp");

await t.shell(["bash", "-c", "echo '' >> deps/ops.ts"], {
currentDir: targetDir,
const { expectStderr } = makeMetaCliTest(t, targetDir, [
"dev",
`--gate=http://localhost:${t.port}`,
]);

await t.should("deploy typegraphs", async () => {
await expectStderr("successfully deployed typegraph");
await expectStderr("successfully deployed typegraph");
});

await t.should("watch modified file", async () => {
await stderr.readWhile((line) => !line.includes("File modified"));
await t.should("watch modified configuration", async () => {
await t.shell(["bash", "-c", "echo '' >> metatype.yaml"], {
currentDir: targetDir,
});

await expectStderr("metatype configuration file changed");
});

await t.should("re-upload artifact", async () => {
await stderr.readWhile((line) => !line.includes("artifact uploaded"));
await t.should("start restart process", async () => {
await expectStderr("reloading all the typegraphs");
await expectStderr("force stopping active tasks");
await expectStderr("starting discovery");
});

await t.should("re-deploy typegraph", async () => {
await stderr.readWhile(
(line) => !line.includes("successfully deployed typegraph"),
);
await t.should("re-deploy all typegraphs", async () => {
await expectStderr("successfully deployed typegraph");
await expectStderr("successfully deployed typegraph");
});
});

Meta.test({ name: "meta dev: watch artifacts" }, async (t) => {
const targetDir = path.join(t.workingDir, "tmp");

t.addCleanup(async () => {
await stderr.close();
await killProcess(metadev);
await t.shell(["rm", "-rf", targetDir]);
const { expectStderr } = makeMetaCliTest(t, targetDir, [
"dev",
`--gate=http://localhost:${t.port}`,
]);

await t.should("upload artifact", () =>
expectStderr("artifact uploaded: ../deps/ops.ts"),
);
await t.should("deploy typegraph", () =>
expectStderr("successfully deployed typegraph deps"),
);
await t.should("watch modified artifact", async () => {
await t.shell(["bash", "-c", "echo '' >> deps/ops.ts"], {
currentDir: targetDir,
});

await expectStderr('File modified: "deps/ops.ts"');
await expectStderr("-> api/deps.ts");
});

await t.should("re-upload artifact", () =>
expectStderr("artifact uploaded: ../deps/ops.ts"),
);

await t.should("re-deploy typegraph", () =>
expectStderr("successfully deployed typegraph deps"),
);

await t.shell(["rm", "-rf", targetDir]);
});
38 changes: 34 additions & 4 deletions tests/utils/meta.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
// Copyright Metatype OÜ, licensed under the Mozilla Public License Version 2.0.
// SPDX-License-Identifier: MPL-2.0

import { $ } from "@david/dax";
import { killProcess, Lines } from "./process.ts";
import { MetaTest } from "./test.ts";
import { shell, ShellOptions, ShellOutput } from "./shell.ts";

// added to path in dev/test.ts
Expand All @@ -15,10 +18,9 @@
first: string | ShellOptions,
...input: string[]
): Promise<ShellOutput> {
const res =
await (typeof first === "string"
? shell([metaCliExe, first, ...input])
: shell([metaCliExe, ...input], first));
const res = await (typeof first === "string"
? shell([metaCliExe, first, ...input])
: shell([metaCliExe, ...input], first));

return res;
}
Expand Down Expand Up @@ -53,3 +55,31 @@
const res = await shell(cmd);
return res.stdout;
}

export function makeMetaCliTest(t: MetaTest, cwd: string, args: string[]) {
const meta = new Deno.Command("meta", {
cwd,
args,
stdout: "piped",
stderr: "piped",
}).spawn();

const stdout = new Lines(meta.stdout);
const stderr = new Lines(meta.stderr);

const expectStdout = async (str: string) => {
await stdout.readWhile((line) => !$.stripAnsi(line).includes(str));
};

Check warning on line 72 in tests/utils/meta.ts

View check run for this annotation

Codecov / codecov/patch

tests/utils/meta.ts#L70-L72

Added lines #L70 - L72 were not covered by tests

const expectStderr = async (str: string) => {
await stderr.readWhile((line) => !$.stripAnsi(line).includes(str));
};

t.addCleanup(async () => {
await stdout.close();
await stderr.close();
await killProcess(meta);
});

return { meta, stdout, stderr, expectStdout, expectStderr };
}
Loading