alpic 0.0.0-dev.f7aa18c → 0.0.0-dev.f7c0e62

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.
Files changed (54) hide show
  1. package/dist/__tests__/deployment-inspect.e2e.test.d.ts +1 -0
  2. package/dist/__tests__/deployment-inspect.e2e.test.js +113 -0
  3. package/dist/__tests__/deployment-inspect.e2e.test.js.map +1 -0
  4. package/dist/__tests__/deployment-list.e2e.test.d.ts +1 -0
  5. package/dist/__tests__/deployment-list.e2e.test.js +108 -0
  6. package/dist/__tests__/deployment-list.e2e.test.js.map +1 -0
  7. package/dist/__tests__/deployment-logs.e2e.test.d.ts +1 -0
  8. package/dist/__tests__/deployment-logs.e2e.test.js +180 -0
  9. package/dist/__tests__/deployment-logs.e2e.test.js.map +1 -0
  10. package/dist/__tests__/mock-server.d.ts +12 -0
  11. package/dist/__tests__/mock-server.js +80 -5
  12. package/dist/__tests__/mock-server.js.map +1 -1
  13. package/dist/__tests__/publish.e2e.test.d.ts +1 -0
  14. package/dist/__tests__/publish.e2e.test.js +485 -0
  15. package/dist/__tests__/publish.e2e.test.js.map +1 -0
  16. package/dist/__tests__/tunnel.e2e.test.d.ts +1 -0
  17. package/dist/__tests__/tunnel.e2e.test.js +64 -0
  18. package/dist/__tests__/tunnel.e2e.test.js.map +1 -0
  19. package/dist/__tests__/utils.d.ts +5 -0
  20. package/dist/__tests__/utils.js +19 -2
  21. package/dist/__tests__/utils.js.map +1 -1
  22. package/dist/commands/deployment/inspect.d.ts +11 -0
  23. package/dist/commands/deployment/inspect.js +68 -0
  24. package/dist/commands/deployment/inspect.js.map +1 -0
  25. package/dist/commands/deployment/list.d.ts +11 -0
  26. package/dist/commands/deployment/list.js +85 -0
  27. package/dist/commands/deployment/list.js.map +1 -0
  28. package/dist/commands/deployment/logs.d.ts +12 -0
  29. package/dist/commands/deployment/logs.js +48 -0
  30. package/dist/commands/deployment/logs.js.map +1 -0
  31. package/dist/commands/publish.d.ts +15 -0
  32. package/dist/commands/publish.js +51 -0
  33. package/dist/commands/publish.js.map +1 -0
  34. package/dist/commands/tunnel.d.ts +9 -0
  35. package/dist/commands/tunnel.js +53 -0
  36. package/dist/commands/tunnel.js.map +1 -0
  37. package/dist/lib/deployment.d.ts +68 -0
  38. package/dist/lib/deployment.js +102 -1
  39. package/dist/lib/deployment.js.map +1 -1
  40. package/dist/lib/logs.d.ts +1 -0
  41. package/dist/lib/logs.js +6 -3
  42. package/dist/lib/logs.js.map +1 -1
  43. package/dist/lib/project.d.ts +3 -0
  44. package/dist/lib/project.js +11 -0
  45. package/dist/lib/project.js.map +1 -1
  46. package/dist/lib/publish.d.ts +22 -0
  47. package/dist/lib/publish.js +181 -0
  48. package/dist/lib/publish.js.map +1 -0
  49. package/dist/lib/utils.d.ts +4 -1
  50. package/dist/lib/utils.js +16 -12
  51. package/dist/lib/utils.js.map +1 -1
  52. package/dist/lib/utils.test.js +13 -6
  53. package/dist/lib/utils.test.js.map +1 -1
  54. package/package.json +17 -14
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,113 @@
1
+ import { rmSync } from "node:fs";
2
+ import { afterEach, beforeEach, describe, expect, it } from "vitest";
3
+ import { MockApiServer } from "./mock-server.js";
4
+ import { buildMockDeployment, buildMockProject, cliSession, expectSuccessfulApiCall, setupTestDirectory, } from "./utils.js";
5
+ describe("alpic deployment inspect (E2E)", () => {
6
+ let mockServer;
7
+ let serverUrl;
8
+ let cwd;
9
+ let binPath;
10
+ const projectId = "test-project-id";
11
+ const teamId = "mock-team-id";
12
+ const environmentId = "test-env-id";
13
+ const environmentName = "production";
14
+ beforeEach(async () => {
15
+ mockServer = new MockApiServer();
16
+ serverUrl = await mockServer.start();
17
+ const setup = await setupTestDirectory();
18
+ cwd = setup.cwd;
19
+ binPath = setup.binPath;
20
+ mockServer.addProject(buildMockProject({
21
+ projectId,
22
+ teamId,
23
+ projectName: "test-project",
24
+ environmentId,
25
+ environmentName,
26
+ }));
27
+ });
28
+ afterEach(async () => {
29
+ await mockServer.stop();
30
+ if (cwd) {
31
+ rmSync(cwd, { recursive: true, force: true });
32
+ }
33
+ });
34
+ it("displays deployment details with --deployment-id", async () => {
35
+ const deploymentId = "dpl_inspect_test";
36
+ const startedAt = new Date(Date.now() - 120_000);
37
+ mockServer.addDeployments([
38
+ buildMockDeployment({
39
+ id: deploymentId,
40
+ sourceCommitMessage: "Fix production bug",
41
+ startedAt,
42
+ completedAt: new Date(startedAt.getTime() + 60_000),
43
+ environmentId,
44
+ environmentName,
45
+ }),
46
+ ]);
47
+ const { exitCode, output } = await cliSession(process.execPath, [binPath, "deployment", "inspect", "--deployment-id", deploymentId], {
48
+ cwd,
49
+ env: { ALPIC_API_BASE_URL: serverUrl, ALPIC_API_KEY: "test-api-key" },
50
+ }, async (cli) => {
51
+ await cli.expect("deployed");
52
+ });
53
+ expect(exitCode).toBe(0);
54
+ const startIdx = output.indexOf("Deployment found");
55
+ expect(startIdx).toBeGreaterThanOrEqual(0);
56
+ expect(output.slice(startIdx)).toMatchSnapshot();
57
+ const getCall = mockServer.getLastCall("GET", `/v1/deployments/${deploymentId}`);
58
+ expectSuccessfulApiCall(getCall);
59
+ });
60
+ it("resolves latest deployment with --environment-id", async () => {
61
+ const deploymentId = "dpl_env_lookup";
62
+ mockServer.addDeployments([
63
+ buildMockDeployment({
64
+ id: deploymentId,
65
+ authorUsername: "bob",
66
+ environmentId,
67
+ environmentName,
68
+ }),
69
+ ]);
70
+ const { exitCode, output } = await cliSession(process.execPath, [binPath, "deployment", "inspect", "--environment-id", environmentId], {
71
+ cwd,
72
+ env: { ALPIC_API_BASE_URL: serverUrl, ALPIC_API_KEY: "test-api-key" },
73
+ }, async (cli) => {
74
+ await cli.expect("deployed");
75
+ });
76
+ expect(exitCode).toBe(0);
77
+ expect(output).toContain(deploymentId);
78
+ expect(output).toContain(environmentName);
79
+ expect(output).toContain("bob");
80
+ });
81
+ it("waits for an ongoing deployment with --wait", async () => {
82
+ const deploymentId = "dpl_ongoing";
83
+ mockServer.addDeployments([
84
+ buildMockDeployment({
85
+ id: deploymentId,
86
+ status: "ongoing",
87
+ startedAt: new Date(),
88
+ completedAt: null,
89
+ isCurrent: false,
90
+ environmentId,
91
+ environmentName,
92
+ }),
93
+ ]);
94
+ const { exitCode, output } = await cliSession(process.execPath, [binPath, "deployment", "inspect", "--deployment-id", deploymentId, "--wait"], {
95
+ cwd,
96
+ env: { ALPIC_API_BASE_URL: serverUrl, ALPIC_API_KEY: "test-api-key" },
97
+ }, async (cli) => {
98
+ await cli.expect("deployed");
99
+ });
100
+ expect(exitCode).toBe(0);
101
+ expect(output).toContain("deployed");
102
+ });
103
+ it("exits with error when deployment is not found", async () => {
104
+ const { exitCode } = await cliSession(process.execPath, [binPath, "deployment", "inspect", "--deployment-id", "dpl_does_not_exist"], {
105
+ cwd,
106
+ env: { ALPIC_API_BASE_URL: serverUrl, ALPIC_API_KEY: "test-api-key" },
107
+ }, async (cli) => {
108
+ await cli.expect(/error|not found/i);
109
+ });
110
+ expect(exitCode).not.toBe(0);
111
+ });
112
+ }, 15_000);
113
+ //# sourceMappingURL=deployment-inspect.e2e.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"deployment-inspect.e2e.test.js","sourceRoot":"","sources":["../../src/__tests__/deployment-inspect.e2e.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,108 @@
1
+ import { rmSync } from "node:fs";
2
+ import { afterEach, beforeEach, describe, expect, it } from "vitest";
3
+ import { MockApiServer } from "./mock-server.js";
4
+ import { buildMockDeployment, buildMockProject, cliSession, expectSuccessfulApiCall, setupTestDirectory, } from "./utils.js";
5
+ describe("alpic deployment list (E2E)", () => {
6
+ let mockServer;
7
+ let serverUrl;
8
+ let cwd;
9
+ let binPath;
10
+ const projectId = "test-project-id";
11
+ const teamId = "mock-team-id";
12
+ const environmentId = "test-env-id";
13
+ const environmentName = "production";
14
+ beforeEach(async () => {
15
+ mockServer = new MockApiServer();
16
+ serverUrl = await mockServer.start();
17
+ const setup = await setupTestDirectory();
18
+ cwd = setup.cwd;
19
+ binPath = setup.binPath;
20
+ mockServer.addProject(buildMockProject({
21
+ projectId,
22
+ teamId,
23
+ projectName: "test-project",
24
+ environmentId,
25
+ environmentName,
26
+ }));
27
+ });
28
+ afterEach(async () => {
29
+ await mockServer.stop();
30
+ if (cwd) {
31
+ rmSync(cwd, { recursive: true, force: true });
32
+ }
33
+ });
34
+ it("renders deployment rows correctly", async () => {
35
+ const sevenDaysAgo = new Date(Date.now() - 7 * 24 * 60 * 60 * 1000);
36
+ const thirteenDaysAgo = new Date(Date.now() - 13 * 24 * 60 * 60 * 1000);
37
+ mockServer.addDeployments([
38
+ buildMockDeployment({
39
+ id: "dpl_test_deployed",
40
+ startedAt: sevenDaysAgo,
41
+ completedAt: new Date(sevenDaysAgo.getTime() + 116_000),
42
+ environmentId,
43
+ environmentName,
44
+ }),
45
+ buildMockDeployment({
46
+ id: "dpl_test_canceled",
47
+ status: "canceled",
48
+ sourceCommitId: "def5678",
49
+ sourceCommitMessage: "Cancel deployment",
50
+ authorUsername: null,
51
+ startedAt: thirteenDaysAgo,
52
+ completedAt: new Date(thirteenDaysAgo.getTime() + 12_000),
53
+ isCurrent: false,
54
+ environmentId,
55
+ environmentName,
56
+ }),
57
+ ]);
58
+ const { exitCode, output } = await cliSession(process.execPath, [binPath, "deployment", "list", "--project-id", projectId], {
59
+ cwd,
60
+ env: {
61
+ ALPIC_API_BASE_URL: serverUrl,
62
+ ALPIC_API_KEY: "test-api-key",
63
+ },
64
+ }, async (cli) => {
65
+ await cli.expect("Found 2 deployments");
66
+ });
67
+ expect(exitCode).toBe(0);
68
+ const normalizedOutput = output.replace(/^.*Fetching deployments\.\.\.\r?\n?/gm, "");
69
+ expect(normalizedOutput).toMatchSnapshot();
70
+ const listCall = mockServer.getLastCall("GET", `/v1/projects/${projectId}/deployments`);
71
+ expectSuccessfulApiCall(listCall);
72
+ });
73
+ it("passes environment-id filter to the API server-side", async () => {
74
+ const otherEnvironmentId = "other-env-id";
75
+ mockServer.addDeployments([
76
+ buildMockDeployment({ environmentId, environmentName, id: "dpl_env_match" }),
77
+ buildMockDeployment({ environmentId: otherEnvironmentId, environmentName: "staging", id: "dpl_env_other" }),
78
+ ]);
79
+ const { exitCode, output } = await cliSession(process.execPath, [binPath, "deployment", "list", "--project-id", projectId, "--environment-id", environmentId], {
80
+ cwd,
81
+ env: { ALPIC_API_BASE_URL: serverUrl, ALPIC_API_KEY: "test-api-key" },
82
+ }, async (cli) => {
83
+ await cli.expect("Found 1 deployment");
84
+ });
85
+ expect(exitCode).toBe(0);
86
+ expect(output).toContain("dpl_env_match");
87
+ expect(output).not.toContain("dpl_env_other");
88
+ const listCall = mockServer.getLastCall("GET", `/v1/projects/${projectId}/deployments`);
89
+ expectSuccessfulApiCall(listCall);
90
+ expect(listCall?.input).toMatchObject({ environmentId });
91
+ });
92
+ it("passes status filter to the API", async () => {
93
+ const { exitCode } = await cliSession(process.execPath, [binPath, "deployment", "list", "--project-id", projectId, "--status", "deployed", "--status", "failed"], {
94
+ cwd,
95
+ env: { ALPIC_API_BASE_URL: serverUrl, ALPIC_API_KEY: "test-api-key" },
96
+ }, async (cli) => {
97
+ await cli.expect("Found 0 deployments");
98
+ });
99
+ expect(exitCode).toBe(0);
100
+ const listCall = mockServer.getLastCall("GET", `/v1/projects/${projectId}/deployments`);
101
+ expectSuccessfulApiCall(listCall);
102
+ expect(listCall?.input).toMatchObject({
103
+ "status[0]": "deployed",
104
+ "status[1]": "failed",
105
+ });
106
+ });
107
+ }, 15_000);
108
+ //# sourceMappingURL=deployment-list.e2e.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"deployment-list.e2e.test.js","sourceRoot":"","sources":["../../src/__tests__/deployment-list.e2e.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,180 @@
1
+ import { rmSync } from "node:fs";
2
+ import { afterEach, beforeEach, describe, expect, it } from "vitest";
3
+ import { MockApiServer } from "./mock-server.js";
4
+ import { buildMockDeployment, buildMockProject, cliSession, createConfigFile, expectSuccessfulApiCall, setupTestDirectory, } from "./utils.js";
5
+ const DEPLOYMENT_ID = "dpl_logs_test";
6
+ const PROJECT_ID = "prj-logs-test";
7
+ const TEAM_ID = "mock-team-id";
8
+ const ENVIRONMENT_ID = "env-logs-test";
9
+ describe("alpic deployment logs (E2E)", () => {
10
+ let mockServer;
11
+ let serverUrl;
12
+ let cwd;
13
+ let binPath;
14
+ beforeEach(async () => {
15
+ mockServer = new MockApiServer();
16
+ serverUrl = await mockServer.start();
17
+ const setup = await setupTestDirectory();
18
+ cwd = setup.cwd;
19
+ binPath = setup.binPath;
20
+ mockServer.addProject(buildMockProject({
21
+ projectId: PROJECT_ID,
22
+ teamId: TEAM_ID,
23
+ projectName: "logs-project",
24
+ environmentId: ENVIRONMENT_ID,
25
+ environmentName: "production",
26
+ }));
27
+ mockServer.addDeployments([
28
+ buildMockDeployment({
29
+ id: DEPLOYMENT_ID,
30
+ environmentId: ENVIRONMENT_ID,
31
+ environmentName: "production",
32
+ }),
33
+ ]);
34
+ });
35
+ afterEach(async () => {
36
+ await mockServer.stop();
37
+ if (cwd)
38
+ rmSync(cwd, { recursive: true, force: true });
39
+ });
40
+ it("fetches and prints logs for a given --deployment-id", async () => {
41
+ mockServer.setDeploymentLogPages(DEPLOYMENT_ID, [
42
+ {
43
+ logs: [
44
+ { timestamp: new Date("2024-06-01T12:00:00.000Z"), content: "Installing dependencies..." },
45
+ { timestamp: new Date("2024-06-01T12:00:01.000Z"), content: "Build succeeded" },
46
+ ],
47
+ hasMoreLogs: false,
48
+ },
49
+ ]);
50
+ const { exitCode, output } = await cliSession(process.execPath, [binPath, "deployment", "logs", "--deployment-id", DEPLOYMENT_ID], { cwd, env: { ALPIC_API_BASE_URL: serverUrl, ALPIC_API_KEY: "test-api-key" } });
51
+ expect(exitCode).toBe(0);
52
+ expect(output).toContain("Installing dependencies...");
53
+ expect(output).toContain("Build succeeded");
54
+ const call = mockServer.getLastCall("GET", /\/v1\/deployments\/.*\/logs/);
55
+ expectSuccessfulApiCall(call);
56
+ });
57
+ it("polls and streams new logs with --follow, stops when hasMoreLogs is false", async () => {
58
+ mockServer.setDeploymentLogPages(DEPLOYMENT_ID, [
59
+ {
60
+ logs: [{ timestamp: new Date("2024-06-01T12:00:00.000Z"), content: "Step 1" }],
61
+ hasMoreLogs: true,
62
+ },
63
+ {
64
+ logs: [
65
+ { timestamp: new Date("2024-06-01T12:00:00.000Z"), content: "Step 1" },
66
+ { timestamp: new Date("2024-06-01T12:00:01.000Z"), content: "Step 2" },
67
+ ],
68
+ hasMoreLogs: true,
69
+ },
70
+ {
71
+ logs: [
72
+ { timestamp: new Date("2024-06-01T12:00:00.000Z"), content: "Step 1" },
73
+ { timestamp: new Date("2024-06-01T12:00:01.000Z"), content: "Step 2" },
74
+ { timestamp: new Date("2024-06-01T12:00:02.000Z"), content: "Step 3 - done" },
75
+ ],
76
+ hasMoreLogs: false,
77
+ },
78
+ ]);
79
+ const { exitCode, output } = await cliSession(process.execPath, [binPath, "deployment", "logs", "--deployment-id", DEPLOYMENT_ID, "--follow"], { cwd, env: { ALPIC_API_BASE_URL: serverUrl, ALPIC_API_KEY: "test-api-key" }, timeoutMs: 15_000 });
80
+ expect(exitCode).toBe(0);
81
+ expect(output).toContain("Step 1");
82
+ expect(output).toContain("Step 2");
83
+ expect(output).toContain("Step 3 - done");
84
+ const calls = mockServer.getCalls("GET", /\/v1\/deployments\/.*\/logs/);
85
+ expect(calls.length).toBe(3);
86
+ });
87
+ it("does not duplicate logs when polling with --follow", async () => {
88
+ mockServer.setDeploymentLogPages(DEPLOYMENT_ID, [
89
+ {
90
+ logs: [{ timestamp: new Date("2024-06-01T12:00:00.000Z"), content: "Only once" }],
91
+ hasMoreLogs: true,
92
+ },
93
+ {
94
+ logs: [
95
+ { timestamp: new Date("2024-06-01T12:00:00.000Z"), content: "Only once" },
96
+ { timestamp: new Date("2024-06-01T12:00:01.000Z"), content: "Second entry" },
97
+ ],
98
+ hasMoreLogs: false,
99
+ },
100
+ ]);
101
+ const { exitCode, output } = await cliSession(process.execPath, [binPath, "deployment", "logs", "--deployment-id", DEPLOYMENT_ID, "--follow"], { cwd, env: { ALPIC_API_BASE_URL: serverUrl, ALPIC_API_KEY: "test-api-key" }, timeoutMs: 15_000 });
102
+ expect(exitCode).toBe(0);
103
+ const occurrences = (output.match(/Only once/g) ?? []).length;
104
+ expect(occurrences).toBe(1);
105
+ });
106
+ it("exits immediately without --follow when hasMoreLogs is true", async () => {
107
+ mockServer.setDeploymentLogPages(DEPLOYMENT_ID, [
108
+ {
109
+ logs: [{ timestamp: new Date("2024-06-01T12:00:00.000Z"), content: "Partial build log" }],
110
+ hasMoreLogs: true,
111
+ },
112
+ ]);
113
+ const { exitCode, output } = await cliSession(process.execPath, [binPath, "deployment", "logs", "--deployment-id", DEPLOYMENT_ID], { cwd, env: { ALPIC_API_BASE_URL: serverUrl, ALPIC_API_KEY: "test-api-key" } });
114
+ expect(exitCode).toBe(0);
115
+ expect(output).toContain("Partial build log");
116
+ const calls = mockServer.getCalls("GET", /\/v1\/deployments\/.*\/logs/);
117
+ expect(calls.length).toBe(1);
118
+ });
119
+ it("strips ANSI codes from log content with --no-color", async () => {
120
+ // Content contains ANSI escape codes as CodeBuild tools (npm, tsc, etc.) often emit
121
+ const redText = "\x1b[31mBuild failed\x1b[0m";
122
+ mockServer.setDeploymentLogPages(DEPLOYMENT_ID, [
123
+ {
124
+ logs: [{ timestamp: new Date("2024-06-01T12:00:00.000Z"), content: redText }],
125
+ hasMoreLogs: false,
126
+ },
127
+ ]);
128
+ const { exitCode, output } = await cliSession(process.execPath, [binPath, "deployment", "logs", "--deployment-id", DEPLOYMENT_ID, "--no-color"], { cwd, env: { ALPIC_API_BASE_URL: serverUrl, ALPIC_API_KEY: "test-api-key" } });
129
+ expect(exitCode).toBe(0);
130
+ expect(output).toContain("2024-06-01 12:00:00.000 Build failed");
131
+ expect(output).not.toContain("\x1b[31m");
132
+ });
133
+ it("exits with error when deployment is not found", async () => {
134
+ const { exitCode, output } = await cliSession(process.execPath, [binPath, "deployment", "logs", "--deployment-id", "dpl_does_not_exist"], { cwd, env: { ALPIC_API_BASE_URL: serverUrl, ALPIC_API_KEY: "test-api-key" } });
135
+ expect(exitCode).not.toBe(0);
136
+ expect(output).toMatch(/error|not found/i);
137
+ });
138
+ it("exits with error when not authenticated", async () => {
139
+ const { exitCode, output } = await cliSession(process.execPath, [binPath, "deployment", "logs", "--deployment-id", DEPLOYMENT_ID], { cwd, env: { ALPIC_API_BASE_URL: serverUrl } });
140
+ expect(exitCode).not.toBe(0);
141
+ expect(output).toMatch(/not authenticated|alpic login|ALPIC_API_KEY/i);
142
+ });
143
+ it("resolves deployment via --environment-id", async () => {
144
+ mockServer.setDeploymentLogPages(DEPLOYMENT_ID, [
145
+ {
146
+ logs: [{ timestamp: new Date("2024-06-01T12:00:00.000Z"), content: "Env lookup log" }],
147
+ hasMoreLogs: false,
148
+ },
149
+ ]);
150
+ const { exitCode, output } = await cliSession(process.execPath, [binPath, "deployment", "logs", "--environment-id", ENVIRONMENT_ID], { cwd, env: { ALPIC_API_BASE_URL: serverUrl, ALPIC_API_KEY: "test-api-key" } });
151
+ expect(exitCode).toBe(0);
152
+ expect(output).toContain("Env lookup log");
153
+ const call = mockServer.getLastCall("GET", /\/v1\/deployments\/.*\/logs/);
154
+ expectSuccessfulApiCall(call);
155
+ });
156
+ it("resolves deployment via environment-id from config file", async () => {
157
+ mockServer.setDeploymentLogPages(DEPLOYMENT_ID, [
158
+ {
159
+ logs: [{ timestamp: new Date("2024-06-01T12:00:00.000Z"), content: "Config file log" }],
160
+ hasMoreLogs: false,
161
+ },
162
+ ]);
163
+ createConfigFile(cwd, PROJECT_ID, TEAM_ID, "logs-project", ENVIRONMENT_ID, "production");
164
+ const { exitCode, output } = await cliSession(process.execPath, [binPath, "deployment", "logs"], {
165
+ cwd,
166
+ env: { ALPIC_API_BASE_URL: serverUrl, ALPIC_API_KEY: "test-api-key" },
167
+ });
168
+ expect(exitCode).toBe(0);
169
+ expect(output).toContain("Config file log");
170
+ });
171
+ it("exits with error when no deployment-id or environment-id provided", async () => {
172
+ const { exitCode, output } = await cliSession(process.execPath, [binPath, "deployment", "logs"], {
173
+ cwd,
174
+ env: { ALPIC_API_BASE_URL: serverUrl, ALPIC_API_KEY: "test-api-key" },
175
+ });
176
+ expect(exitCode).not.toBe(0);
177
+ expect(output).toMatch(/environment|deployment-id/i);
178
+ });
179
+ }, 30_000);
180
+ //# sourceMappingURL=deployment-logs.e2e.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"deployment-logs.e2e.test.js","sourceRoot":"","sources":["../../src/__tests__/deployment-logs.e2e.test.ts"],"names":[],"mappings":"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"}
@@ -1,5 +1,13 @@
1
1
  import { type RouterOutput } from "@alpic-ai/api";
2
2
  export type MockRuntimeLog = RouterOutput["environments"]["getLogs"]["v1"]["logs"][number];
3
+ type PublishedServer = RouterOutput["distribution"]["info"]["v1"]["serverFields"];
4
+ export type MockDeploymentLogPage = {
5
+ logs: {
6
+ timestamp?: Date;
7
+ content?: string;
8
+ }[];
9
+ hasMoreLogs: boolean;
10
+ };
3
11
  export type ApiCall = {
4
12
  method: string;
5
13
  path: string;
@@ -22,5 +30,9 @@ export declare class MockApiServer {
22
30
  addEnvironmentVariables(environmentId: string, variables: RouterOutput["environmentVariables"]["list"]["v1"]): void;
23
31
  setRuntimeLogs(environmentId: string, logs: MockRuntimeLog[]): void;
24
32
  setRuntimeLogPages(environmentId: string, pages: MockRuntimeLog[][]): void;
33
+ setPublishedServer(projectId: string, domain: string, server: PublishedServer): void;
34
+ addDeployments(deployments: RouterOutput["deployments"]["list"]["v1"]): void;
35
+ setDeploymentLogPages(deploymentId: string, pages: MockDeploymentLogPage[]): void;
25
36
  addProject(project: RouterOutput["projects"]["get"]["v1"]): void;
26
37
  }
38
+ export {};
@@ -6,6 +6,7 @@ import { randomUUID } from "node:crypto";
6
6
  import { readFileSync } from "node:fs";
7
7
  import { dirname, join } from "node:path";
8
8
  import { fileURLToPath } from "node:url";
9
+ import { inc as semverInc } from "semver";
9
10
  import { contract } from "@alpic-ai/api";
10
11
  const __testDirname = dirname(fileURLToPath(import.meta.url));
11
12
  const FIXTURE_CERT_PATH = join(__testDirname, "fixtures", "certs", "localhost-cert.pem");
@@ -32,6 +33,9 @@ export class MockApiServer {
32
33
  environmentVariables: new Map(),
33
34
  runtimeLogs: new Map(),
34
35
  runtimeLogPages: new Map(),
36
+ deploymentLogPages: new Map(),
37
+ deploymentLogCallCounts: new Map(),
38
+ publishedServers: new Map(),
35
39
  };
36
40
  }
37
41
  async start() {
@@ -337,9 +341,11 @@ export class MockApiServer {
337
341
  const allLogs = pagedLogs === undefined
338
342
  ? (this.mockData.runtimeLogs.get(input.environmentId) ?? [])
339
343
  : (pagedLogs[pageIndex] ?? []);
340
- const logs = input.level === undefined
341
- ? allLogs
342
- : allLogs.filter((log) => input.level.includes(log.type));
344
+ let logs = allLogs;
345
+ if (input.level !== undefined) {
346
+ const levels = input.level;
347
+ logs = allLogs.filter((log) => levels.includes(log.type));
348
+ }
343
349
  const nextToken = pagedLogs === undefined || pageIndex + 1 >= pagedLogs.length ? null : String(pageIndex + 1);
344
350
  return { logs, nextToken };
345
351
  }),
@@ -354,6 +360,9 @@ export class MockApiServer {
354
360
  const deployment = {
355
361
  id: deploymentId,
356
362
  status: "ongoing",
363
+ environmentId: environment.id,
364
+ environmentName: environment.name,
365
+ isCurrent: false,
357
366
  sourceRef: environment.sourceBranch,
358
367
  sourceCommitId: randomUUID().slice(0, 7),
359
368
  sourceCommitMessage: "Mock deployment",
@@ -431,6 +440,44 @@ export class MockApiServer {
431
440
  }),
432
441
  },
433
442
  },
443
+ distribution: {
444
+ info: {
445
+ v1: implement(contract.distribution.info.v1).handler(async ({ input }) => {
446
+ const existing = this.mockData.publishedServers.get(`${input.projectId}:${input.domain}`);
447
+ return {
448
+ serverFields: existing ?? {
449
+ $schema: "https://registry.modelcontextprotocol.io/schemas/1.0/server.json",
450
+ name: "",
451
+ description: "",
452
+ },
453
+ };
454
+ }),
455
+ },
456
+ publish: {
457
+ v1: implement(contract.distribution.publish.v1).handler(async ({ input }) => {
458
+ const project = this.mockData.projects.get(input.projectId);
459
+ if (!project) {
460
+ throw new ORPCError("NOT_FOUND", { message: "Project not found" });
461
+ }
462
+ const key = `${input.projectId}:${input.domain}`;
463
+ const existing = this.mockData.publishedServers.get(key);
464
+ const version = existing?.version ? (semverInc(existing.version, "patch") ?? "0.0.1") : "0.0.1";
465
+ const serverFields = {
466
+ $schema: "https://registry.modelcontextprotocol.io/schemas/1.0/server.json",
467
+ name: input.domain,
468
+ description: input.description,
469
+ title: input.title,
470
+ version,
471
+ ...(input.websiteUrl ? { websiteUrl: input.websiteUrl } : {}),
472
+ ...(input.iconSrc ? { icons: [{ src: input.iconSrc }] } : {}),
473
+ };
474
+ if (!input.dryRun) {
475
+ this.mockData.publishedServers.set(key, serverFields);
476
+ }
477
+ return { serverFields };
478
+ }),
479
+ },
480
+ },
434
481
  deployments: {
435
482
  list: {
436
483
  v1: implement(contract.deployments.list.v1).handler(async ({ input }) => {
@@ -438,10 +485,16 @@ export class MockApiServer {
438
485
  if (!project) {
439
486
  throw new ORPCError("NOT_FOUND", { message: "Project not found" });
440
487
  }
441
- return Array.from(this.mockData.deployments.values()).map((deployment) => ({
488
+ let deployments = Array.from(this.mockData.deployments.values());
489
+ if (input.environmentId) {
490
+ deployments = deployments.filter((deployment) => deployment.environmentId === input.environmentId);
491
+ }
492
+ if (input.status?.length) {
493
+ deployments = deployments.filter((deployment) => input.status.includes(deployment.status));
494
+ }
495
+ return deployments.map((deployment) => ({
442
496
  ...deployment,
443
497
  isCurrent: deployment.status === "deployed",
444
- environmentId: project.productionEnvironment?.id ?? "",
445
498
  }));
446
499
  }),
447
500
  },
@@ -470,6 +523,13 @@ export class MockApiServer {
470
523
  if (!deployment) {
471
524
  throw new ORPCError("NOT_FOUND", { message: "Deployment not found" });
472
525
  }
526
+ const pages = this.mockData.deploymentLogPages.get(input.deploymentId);
527
+ if (pages !== undefined) {
528
+ const callCount = this.mockData.deploymentLogCallCounts.get(input.deploymentId) ?? 0;
529
+ const pageIndex = Math.min(callCount, pages.length - 1);
530
+ this.mockData.deploymentLogCallCounts.set(input.deploymentId, callCount + 1);
531
+ return pages[pageIndex] ?? { logs: [], hasMoreLogs: false };
532
+ }
473
533
  return {
474
534
  logs: [{ timestamp: new Date(), content: "Mock log entry" }],
475
535
  hasMoreLogs: false,
@@ -585,6 +645,21 @@ export class MockApiServer {
585
645
  this.mockData.runtimeLogPages.set(environmentId, pages);
586
646
  this.mockData.runtimeLogs.delete(environmentId);
587
647
  }
648
+ setPublishedServer(projectId, domain, server) {
649
+ this.mockData.publishedServers.set(`${projectId}:${domain}`, server);
650
+ }
651
+ addDeployments(deployments) {
652
+ for (const deployment of deployments) {
653
+ this.mockData.deployments.set(deployment.id, {
654
+ ...deployment,
655
+ deploymentPageUrl: null,
656
+ });
657
+ }
658
+ }
659
+ setDeploymentLogPages(deploymentId, pages) {
660
+ this.mockData.deploymentLogPages.set(deploymentId, pages);
661
+ this.mockData.deploymentLogCallCounts.set(deploymentId, 0);
662
+ }
588
663
  addProject(project) {
589
664
  this.mockData.projects.set(project.id, project);
590
665
  if (project.productionEnvironment) {