@herdctl/core 5.5.0 → 5.6.0
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/config/index.d.ts +1 -1
- package/dist/config/index.d.ts.map +1 -1
- package/dist/config/index.js +3 -1
- package/dist/config/index.js.map +1 -1
- package/dist/distribution/__tests__/agent-discovery.test.d.ts +7 -0
- package/dist/distribution/__tests__/agent-discovery.test.d.ts.map +1 -0
- package/dist/distribution/__tests__/agent-discovery.test.js +443 -0
- package/dist/distribution/__tests__/agent-discovery.test.js.map +1 -0
- package/dist/distribution/__tests__/agent-info.test.d.ts +7 -0
- package/dist/distribution/__tests__/agent-info.test.d.ts.map +1 -0
- package/dist/distribution/__tests__/agent-info.test.js +568 -0
- package/dist/distribution/__tests__/agent-info.test.js.map +1 -0
- package/dist/distribution/__tests__/agent-remover.test.d.ts +7 -0
- package/dist/distribution/__tests__/agent-remover.test.d.ts.map +1 -0
- package/dist/distribution/__tests__/agent-remover.test.js +498 -0
- package/dist/distribution/__tests__/agent-remover.test.js.map +1 -0
- package/dist/distribution/__tests__/agent-repo-metadata.test.d.ts +5 -0
- package/dist/distribution/__tests__/agent-repo-metadata.test.d.ts.map +1 -0
- package/dist/distribution/__tests__/agent-repo-metadata.test.js +500 -0
- package/dist/distribution/__tests__/agent-repo-metadata.test.js.map +1 -0
- package/dist/distribution/__tests__/env-scanner.test.d.ts +5 -0
- package/dist/distribution/__tests__/env-scanner.test.d.ts.map +1 -0
- package/dist/distribution/__tests__/env-scanner.test.js +576 -0
- package/dist/distribution/__tests__/env-scanner.test.js.map +1 -0
- package/dist/distribution/__tests__/file-installer.test.d.ts +7 -0
- package/dist/distribution/__tests__/file-installer.test.d.ts.map +1 -0
- package/dist/distribution/__tests__/file-installer.test.js +714 -0
- package/dist/distribution/__tests__/file-installer.test.js.map +1 -0
- package/dist/distribution/__tests__/fleet-config-updater.test.d.ts +7 -0
- package/dist/distribution/__tests__/fleet-config-updater.test.d.ts.map +1 -0
- package/dist/distribution/__tests__/fleet-config-updater.test.js +531 -0
- package/dist/distribution/__tests__/fleet-config-updater.test.js.map +1 -0
- package/dist/distribution/__tests__/installation-metadata.test.d.ts +2 -0
- package/dist/distribution/__tests__/installation-metadata.test.d.ts.map +1 -0
- package/dist/distribution/__tests__/installation-metadata.test.js +292 -0
- package/dist/distribution/__tests__/installation-metadata.test.js.map +1 -0
- package/dist/distribution/__tests__/integration.test.d.ts +10 -0
- package/dist/distribution/__tests__/integration.test.d.ts.map +1 -0
- package/dist/distribution/__tests__/integration.test.js +522 -0
- package/dist/distribution/__tests__/integration.test.js.map +1 -0
- package/dist/distribution/__tests__/repository-fetcher.test.d.ts +5 -0
- package/dist/distribution/__tests__/repository-fetcher.test.d.ts.map +1 -0
- package/dist/distribution/__tests__/repository-fetcher.test.js +386 -0
- package/dist/distribution/__tests__/repository-fetcher.test.js.map +1 -0
- package/dist/distribution/__tests__/repository-validator.test.d.ts +7 -0
- package/dist/distribution/__tests__/repository-validator.test.d.ts.map +1 -0
- package/dist/distribution/__tests__/repository-validator.test.js +447 -0
- package/dist/distribution/__tests__/repository-validator.test.js.map +1 -0
- package/dist/distribution/__tests__/source-specifier.test.d.ts +5 -0
- package/dist/distribution/__tests__/source-specifier.test.d.ts.map +1 -0
- package/dist/distribution/__tests__/source-specifier.test.js +533 -0
- package/dist/distribution/__tests__/source-specifier.test.js.map +1 -0
- package/dist/distribution/agent-discovery.d.ts +81 -0
- package/dist/distribution/agent-discovery.d.ts.map +1 -0
- package/dist/distribution/agent-discovery.js +264 -0
- package/dist/distribution/agent-discovery.js.map +1 -0
- package/dist/distribution/agent-info.d.ts +86 -0
- package/dist/distribution/agent-info.d.ts.map +1 -0
- package/dist/distribution/agent-info.js +225 -0
- package/dist/distribution/agent-info.js.map +1 -0
- package/dist/distribution/agent-remover.d.ts +83 -0
- package/dist/distribution/agent-remover.d.ts.map +1 -0
- package/dist/distribution/agent-remover.js +222 -0
- package/dist/distribution/agent-remover.js.map +1 -0
- package/dist/distribution/agent-repo-metadata.d.ts +181 -0
- package/dist/distribution/agent-repo-metadata.d.ts.map +1 -0
- package/dist/distribution/agent-repo-metadata.js +143 -0
- package/dist/distribution/agent-repo-metadata.js.map +1 -0
- package/dist/distribution/env-scanner.d.ts +78 -0
- package/dist/distribution/env-scanner.d.ts.map +1 -0
- package/dist/distribution/env-scanner.js +144 -0
- package/dist/distribution/env-scanner.js.map +1 -0
- package/dist/distribution/file-installer.d.ts +80 -0
- package/dist/distribution/file-installer.d.ts.map +1 -0
- package/dist/distribution/file-installer.js +268 -0
- package/dist/distribution/file-installer.js.map +1 -0
- package/dist/distribution/fleet-config-updater.d.ts +96 -0
- package/dist/distribution/fleet-config-updater.d.ts.map +1 -0
- package/dist/distribution/fleet-config-updater.js +266 -0
- package/dist/distribution/fleet-config-updater.js.map +1 -0
- package/dist/distribution/index.d.ts +23 -0
- package/dist/distribution/index.d.ts.map +1 -0
- package/dist/distribution/index.js +42 -0
- package/dist/distribution/index.js.map +1 -0
- package/dist/distribution/installation-metadata.d.ts +191 -0
- package/dist/distribution/installation-metadata.d.ts.map +1 -0
- package/dist/distribution/installation-metadata.js +100 -0
- package/dist/distribution/installation-metadata.js.map +1 -0
- package/dist/distribution/repository-fetcher.d.ts +104 -0
- package/dist/distribution/repository-fetcher.d.ts.map +1 -0
- package/dist/distribution/repository-fetcher.js +246 -0
- package/dist/distribution/repository-fetcher.js.map +1 -0
- package/dist/distribution/repository-validator.d.ts +86 -0
- package/dist/distribution/repository-validator.d.ts.map +1 -0
- package/dist/distribution/repository-validator.js +296 -0
- package/dist/distribution/repository-validator.js.map +1 -0
- package/dist/distribution/source-specifier.d.ts +106 -0
- package/dist/distribution/source-specifier.d.ts.map +1 -0
- package/dist/distribution/source-specifier.js +247 -0
- package/dist/distribution/source-specifier.js.map +1 -0
- package/dist/fleet-manager/errors.d.ts +15 -0
- package/dist/fleet-manager/errors.d.ts.map +1 -1
- package/dist/fleet-manager/errors.js +16 -0
- package/dist/fleet-manager/errors.js.map +1 -1
- package/dist/fleet-manager/fleet-manager.d.ts.map +1 -1
- package/dist/fleet-manager/fleet-manager.js +31 -9
- package/dist/fleet-manager/fleet-manager.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/runner/message-processor.d.ts.map +1 -1
- package/dist/runner/message-processor.js +7 -2
- package/dist/runner/message-processor.js.map +1 -1
- package/dist/runner/runtime/container-manager.js +1 -1
- package/dist/runner/runtime/container-manager.js.map +1 -1
- package/dist/scheduler/errors.d.ts +15 -0
- package/dist/scheduler/errors.d.ts.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,533 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tests for Source Specifier Parser
|
|
3
|
+
*/
|
|
4
|
+
import * as path from "path";
|
|
5
|
+
import { describe, expect, it } from "vitest";
|
|
6
|
+
import { isGitHubSource, isLocalSource, parseSourceSpecifier, SourceParseError, stringifySourceSpecifier, } from "../source-specifier.js";
|
|
7
|
+
// =============================================================================
|
|
8
|
+
// GitHub Source Tests
|
|
9
|
+
// =============================================================================
|
|
10
|
+
describe("parseSourceSpecifier - GitHub sources", () => {
|
|
11
|
+
describe("basic GitHub sources", () => {
|
|
12
|
+
it("should parse basic github:owner/repo format", () => {
|
|
13
|
+
const result = parseSourceSpecifier("github:user/repo");
|
|
14
|
+
expect(result.type).toBe("github");
|
|
15
|
+
expect(isGitHubSource(result)).toBe(true);
|
|
16
|
+
if (isGitHubSource(result)) {
|
|
17
|
+
expect(result.owner).toBe("user");
|
|
18
|
+
expect(result.repo).toBe("repo");
|
|
19
|
+
expect(result.ref).toBeUndefined();
|
|
20
|
+
}
|
|
21
|
+
});
|
|
22
|
+
it("should parse GitHub source with organization owner", () => {
|
|
23
|
+
const result = parseSourceSpecifier("github:herdctl-examples/website-monitor-agent");
|
|
24
|
+
expect(result.type).toBe("github");
|
|
25
|
+
if (isGitHubSource(result)) {
|
|
26
|
+
expect(result.owner).toBe("herdctl-examples");
|
|
27
|
+
expect(result.repo).toBe("website-monitor-agent");
|
|
28
|
+
}
|
|
29
|
+
});
|
|
30
|
+
it("should parse GitHub source with underscores in names", () => {
|
|
31
|
+
const result = parseSourceSpecifier("github:my_org/my_repo");
|
|
32
|
+
expect(result.type).toBe("github");
|
|
33
|
+
if (isGitHubSource(result)) {
|
|
34
|
+
expect(result.owner).toBe("my_org");
|
|
35
|
+
expect(result.repo).toBe("my_repo");
|
|
36
|
+
}
|
|
37
|
+
});
|
|
38
|
+
it("should parse GitHub source with dots in names", () => {
|
|
39
|
+
const result = parseSourceSpecifier("github:user.name/repo.name");
|
|
40
|
+
expect(result.type).toBe("github");
|
|
41
|
+
if (isGitHubSource(result)) {
|
|
42
|
+
expect(result.owner).toBe("user.name");
|
|
43
|
+
expect(result.repo).toBe("repo.name");
|
|
44
|
+
}
|
|
45
|
+
});
|
|
46
|
+
it("should parse GitHub source with numeric names", () => {
|
|
47
|
+
const result = parseSourceSpecifier("github:user123/repo456");
|
|
48
|
+
expect(result.type).toBe("github");
|
|
49
|
+
if (isGitHubSource(result)) {
|
|
50
|
+
expect(result.owner).toBe("user123");
|
|
51
|
+
expect(result.repo).toBe("repo456");
|
|
52
|
+
}
|
|
53
|
+
});
|
|
54
|
+
it("should parse GitHub source with single character names", () => {
|
|
55
|
+
const result = parseSourceSpecifier("github:a/b");
|
|
56
|
+
expect(result.type).toBe("github");
|
|
57
|
+
if (isGitHubSource(result)) {
|
|
58
|
+
expect(result.owner).toBe("a");
|
|
59
|
+
expect(result.repo).toBe("b");
|
|
60
|
+
}
|
|
61
|
+
});
|
|
62
|
+
});
|
|
63
|
+
describe("GitHub sources with tag ref", () => {
|
|
64
|
+
it("should parse GitHub source with semver tag", () => {
|
|
65
|
+
const result = parseSourceSpecifier("github:user/repo@v1.0.0");
|
|
66
|
+
expect(result.type).toBe("github");
|
|
67
|
+
if (isGitHubSource(result)) {
|
|
68
|
+
expect(result.owner).toBe("user");
|
|
69
|
+
expect(result.repo).toBe("repo");
|
|
70
|
+
expect(result.ref).toBe("v1.0.0");
|
|
71
|
+
}
|
|
72
|
+
});
|
|
73
|
+
it("should parse GitHub source with tag without v prefix", () => {
|
|
74
|
+
const result = parseSourceSpecifier("github:user/repo@1.2.3");
|
|
75
|
+
expect(result.type).toBe("github");
|
|
76
|
+
if (isGitHubSource(result)) {
|
|
77
|
+
expect(result.ref).toBe("1.2.3");
|
|
78
|
+
}
|
|
79
|
+
});
|
|
80
|
+
it("should parse GitHub source with prerelease tag", () => {
|
|
81
|
+
const result = parseSourceSpecifier("github:user/repo@v2.0.0-beta.1");
|
|
82
|
+
expect(result.type).toBe("github");
|
|
83
|
+
if (isGitHubSource(result)) {
|
|
84
|
+
expect(result.ref).toBe("v2.0.0-beta.1");
|
|
85
|
+
}
|
|
86
|
+
});
|
|
87
|
+
});
|
|
88
|
+
describe("GitHub sources with branch ref", () => {
|
|
89
|
+
it("should parse GitHub source with main branch", () => {
|
|
90
|
+
const result = parseSourceSpecifier("github:user/repo@main");
|
|
91
|
+
expect(result.type).toBe("github");
|
|
92
|
+
if (isGitHubSource(result)) {
|
|
93
|
+
expect(result.ref).toBe("main");
|
|
94
|
+
}
|
|
95
|
+
});
|
|
96
|
+
it("should parse GitHub source with feature branch", () => {
|
|
97
|
+
const result = parseSourceSpecifier("github:user/repo@feature/new-feature");
|
|
98
|
+
expect(result.type).toBe("github");
|
|
99
|
+
if (isGitHubSource(result)) {
|
|
100
|
+
expect(result.ref).toBe("feature/new-feature");
|
|
101
|
+
}
|
|
102
|
+
});
|
|
103
|
+
it("should parse GitHub source with branch containing hyphens", () => {
|
|
104
|
+
const result = parseSourceSpecifier("github:user/repo@fix-bug-123");
|
|
105
|
+
expect(result.type).toBe("github");
|
|
106
|
+
if (isGitHubSource(result)) {
|
|
107
|
+
expect(result.ref).toBe("fix-bug-123");
|
|
108
|
+
}
|
|
109
|
+
});
|
|
110
|
+
it("should parse GitHub source with branch containing dots", () => {
|
|
111
|
+
const result = parseSourceSpecifier("github:user/repo@release.2024.01");
|
|
112
|
+
expect(result.type).toBe("github");
|
|
113
|
+
if (isGitHubSource(result)) {
|
|
114
|
+
expect(result.ref).toBe("release.2024.01");
|
|
115
|
+
}
|
|
116
|
+
});
|
|
117
|
+
});
|
|
118
|
+
describe("GitHub sources with commit SHA ref", () => {
|
|
119
|
+
it("should parse GitHub source with short commit SHA", () => {
|
|
120
|
+
const result = parseSourceSpecifier("github:user/repo@abc1234");
|
|
121
|
+
expect(result.type).toBe("github");
|
|
122
|
+
if (isGitHubSource(result)) {
|
|
123
|
+
expect(result.ref).toBe("abc1234");
|
|
124
|
+
}
|
|
125
|
+
});
|
|
126
|
+
it("should parse GitHub source with full commit SHA", () => {
|
|
127
|
+
const result = parseSourceSpecifier("github:user/repo@abc1234567890def1234567890abc1234567890de");
|
|
128
|
+
expect(result.type).toBe("github");
|
|
129
|
+
if (isGitHubSource(result)) {
|
|
130
|
+
expect(result.ref).toBe("abc1234567890def1234567890abc1234567890de");
|
|
131
|
+
}
|
|
132
|
+
});
|
|
133
|
+
});
|
|
134
|
+
describe("GitHub source error cases", () => {
|
|
135
|
+
it("should throw for github: with no repo", () => {
|
|
136
|
+
expect(() => parseSourceSpecifier("github:")).toThrow(SourceParseError);
|
|
137
|
+
expect(() => parseSourceSpecifier("github:")).toThrow("owner/repo");
|
|
138
|
+
});
|
|
139
|
+
it("should throw for github:owner/ missing repo", () => {
|
|
140
|
+
expect(() => parseSourceSpecifier("github:owner/")).toThrow(SourceParseError);
|
|
141
|
+
expect(() => parseSourceSpecifier("github:owner/")).toThrow("cannot be empty");
|
|
142
|
+
});
|
|
143
|
+
it("should throw for github:/repo missing owner", () => {
|
|
144
|
+
expect(() => parseSourceSpecifier("github:/repo")).toThrow(SourceParseError);
|
|
145
|
+
expect(() => parseSourceSpecifier("github:/repo")).toThrow("cannot be empty");
|
|
146
|
+
});
|
|
147
|
+
it("should throw for github:owner (no slash)", () => {
|
|
148
|
+
expect(() => parseSourceSpecifier("github:owner")).toThrow(SourceParseError);
|
|
149
|
+
expect(() => parseSourceSpecifier("github:owner")).toThrow("owner/repo");
|
|
150
|
+
});
|
|
151
|
+
it("should throw for github:owner/repo@ with empty ref", () => {
|
|
152
|
+
expect(() => parseSourceSpecifier("github:owner/repo@")).toThrow(SourceParseError);
|
|
153
|
+
expect(() => parseSourceSpecifier("github:owner/repo@")).toThrow('cannot be empty after "@"');
|
|
154
|
+
});
|
|
155
|
+
it("should throw for nested paths (github:owner/repo/subdir)", () => {
|
|
156
|
+
expect(() => parseSourceSpecifier("github:owner/repo/subdir")).toThrow(SourceParseError);
|
|
157
|
+
expect(() => parseSourceSpecifier("github:owner/repo/subdir")).toThrow("Nested paths are not supported");
|
|
158
|
+
});
|
|
159
|
+
it("should throw for owner starting with dot", () => {
|
|
160
|
+
expect(() => parseSourceSpecifier("github:.hidden/repo")).toThrow(SourceParseError);
|
|
161
|
+
expect(() => parseSourceSpecifier("github:.hidden/repo")).toThrow("cannot start with a dot");
|
|
162
|
+
});
|
|
163
|
+
it("should throw for repo starting with dot", () => {
|
|
164
|
+
expect(() => parseSourceSpecifier("github:owner/.hidden")).toThrow(SourceParseError);
|
|
165
|
+
});
|
|
166
|
+
it("should throw for owner ending with .git", () => {
|
|
167
|
+
expect(() => parseSourceSpecifier("github:owner.git/repo")).toThrow(SourceParseError);
|
|
168
|
+
expect(() => parseSourceSpecifier("github:owner.git/repo")).toThrow('cannot end with ".git"');
|
|
169
|
+
});
|
|
170
|
+
it("should throw for repo ending with .git", () => {
|
|
171
|
+
expect(() => parseSourceSpecifier("github:owner/repo.git")).toThrow(SourceParseError);
|
|
172
|
+
expect(() => parseSourceSpecifier("github:owner/repo.git")).toThrow('cannot end with ".git"');
|
|
173
|
+
});
|
|
174
|
+
it("should throw for owner with invalid characters", () => {
|
|
175
|
+
expect(() => parseSourceSpecifier("github:owner!/repo")).toThrow(SourceParseError);
|
|
176
|
+
expect(() => parseSourceSpecifier("github:owner@name/repo")).toThrow(SourceParseError);
|
|
177
|
+
expect(() => parseSourceSpecifier("github:owner name/repo")).toThrow(SourceParseError);
|
|
178
|
+
});
|
|
179
|
+
it("should throw for repo with invalid characters", () => {
|
|
180
|
+
expect(() => parseSourceSpecifier("github:owner/repo!")).toThrow(SourceParseError);
|
|
181
|
+
expect(() => parseSourceSpecifier("github:owner/repo name")).toThrow(SourceParseError);
|
|
182
|
+
});
|
|
183
|
+
});
|
|
184
|
+
});
|
|
185
|
+
// =============================================================================
|
|
186
|
+
// Local Source Tests
|
|
187
|
+
// =============================================================================
|
|
188
|
+
describe("parseSourceSpecifier - Local sources", () => {
|
|
189
|
+
describe("relative paths", () => {
|
|
190
|
+
it("should parse ./ relative path", () => {
|
|
191
|
+
const result = parseSourceSpecifier("./local/path");
|
|
192
|
+
expect(result.type).toBe("local");
|
|
193
|
+
expect(isLocalSource(result)).toBe(true);
|
|
194
|
+
if (isLocalSource(result)) {
|
|
195
|
+
expect(result.path).toBe(path.resolve("./local/path"));
|
|
196
|
+
expect(path.isAbsolute(result.path)).toBe(true);
|
|
197
|
+
}
|
|
198
|
+
});
|
|
199
|
+
it("should parse ../ relative path", () => {
|
|
200
|
+
const result = parseSourceSpecifier("../parent/path");
|
|
201
|
+
expect(result.type).toBe("local");
|
|
202
|
+
if (isLocalSource(result)) {
|
|
203
|
+
expect(result.path).toBe(path.resolve("../parent/path"));
|
|
204
|
+
expect(path.isAbsolute(result.path)).toBe(true);
|
|
205
|
+
}
|
|
206
|
+
});
|
|
207
|
+
it("should parse path with multiple ../", () => {
|
|
208
|
+
const result = parseSourceSpecifier("../../grandparent/path");
|
|
209
|
+
expect(result.type).toBe("local");
|
|
210
|
+
if (isLocalSource(result)) {
|
|
211
|
+
expect(result.path).toBe(path.resolve("../../grandparent/path"));
|
|
212
|
+
}
|
|
213
|
+
});
|
|
214
|
+
it("should resolve . in path components", () => {
|
|
215
|
+
const result = parseSourceSpecifier("./a/./b/./c");
|
|
216
|
+
expect(result.type).toBe("local");
|
|
217
|
+
if (isLocalSource(result)) {
|
|
218
|
+
// path.resolve normalizes away the . components
|
|
219
|
+
expect(result.path).toContain("a");
|
|
220
|
+
expect(result.path).toContain("b");
|
|
221
|
+
expect(result.path).toContain("c");
|
|
222
|
+
}
|
|
223
|
+
});
|
|
224
|
+
it("should resolve .. in path components", () => {
|
|
225
|
+
const result = parseSourceSpecifier("./a/b/../c");
|
|
226
|
+
expect(result.type).toBe("local");
|
|
227
|
+
if (isLocalSource(result)) {
|
|
228
|
+
// path.resolve normalizes a/b/../c to a/c
|
|
229
|
+
expect(result.path).toContain("a");
|
|
230
|
+
expect(result.path).toContain("c");
|
|
231
|
+
expect(result.path).not.toMatch(/a[/\\]b[/\\]c/); // Should not have a/b/c
|
|
232
|
+
}
|
|
233
|
+
});
|
|
234
|
+
});
|
|
235
|
+
describe("absolute paths", () => {
|
|
236
|
+
it("should parse Unix absolute path", () => {
|
|
237
|
+
const result = parseSourceSpecifier("/absolute/path/to/agent");
|
|
238
|
+
expect(result.type).toBe("local");
|
|
239
|
+
if (isLocalSource(result)) {
|
|
240
|
+
expect(result.path).toBe("/absolute/path/to/agent");
|
|
241
|
+
expect(path.isAbsolute(result.path)).toBe(true);
|
|
242
|
+
}
|
|
243
|
+
});
|
|
244
|
+
it("should parse root path", () => {
|
|
245
|
+
const result = parseSourceSpecifier("/");
|
|
246
|
+
expect(result.type).toBe("local");
|
|
247
|
+
if (isLocalSource(result)) {
|
|
248
|
+
expect(result.path).toBe("/");
|
|
249
|
+
}
|
|
250
|
+
});
|
|
251
|
+
});
|
|
252
|
+
describe("edge cases", () => {
|
|
253
|
+
it("should handle path with spaces", () => {
|
|
254
|
+
const result = parseSourceSpecifier("./path with spaces/agent");
|
|
255
|
+
expect(result.type).toBe("local");
|
|
256
|
+
if (isLocalSource(result)) {
|
|
257
|
+
expect(result.path).toContain("path with spaces");
|
|
258
|
+
}
|
|
259
|
+
});
|
|
260
|
+
it("should handle path with special characters", () => {
|
|
261
|
+
const result = parseSourceSpecifier("./path-with_special.chars/agent");
|
|
262
|
+
expect(result.type).toBe("local");
|
|
263
|
+
if (isLocalSource(result)) {
|
|
264
|
+
expect(result.path).toContain("path-with_special.chars");
|
|
265
|
+
}
|
|
266
|
+
});
|
|
267
|
+
it("should handle deeply nested path", () => {
|
|
268
|
+
const result = parseSourceSpecifier("./a/b/c/d/e/f/g/agent");
|
|
269
|
+
expect(result.type).toBe("local");
|
|
270
|
+
if (isLocalSource(result)) {
|
|
271
|
+
expect(result.path).toContain("a");
|
|
272
|
+
expect(result.path).toContain("agent");
|
|
273
|
+
}
|
|
274
|
+
});
|
|
275
|
+
});
|
|
276
|
+
});
|
|
277
|
+
// =============================================================================
|
|
278
|
+
// GitHub Shorthand Tests
|
|
279
|
+
// =============================================================================
|
|
280
|
+
describe("parseSourceSpecifier - GitHub shorthand", () => {
|
|
281
|
+
describe("valid owner/repo shorthand", () => {
|
|
282
|
+
it("should parse owner/repo as GitHub source", () => {
|
|
283
|
+
const result = parseSourceSpecifier("user/repo");
|
|
284
|
+
expect(result.type).toBe("github");
|
|
285
|
+
expect(isGitHubSource(result)).toBe(true);
|
|
286
|
+
if (isGitHubSource(result)) {
|
|
287
|
+
expect(result.owner).toBe("user");
|
|
288
|
+
expect(result.repo).toBe("repo");
|
|
289
|
+
expect(result.ref).toBeUndefined();
|
|
290
|
+
}
|
|
291
|
+
});
|
|
292
|
+
it("should parse owner/repo with ref", () => {
|
|
293
|
+
const result = parseSourceSpecifier("user/repo@v1.0.0");
|
|
294
|
+
expect(result.type).toBe("github");
|
|
295
|
+
if (isGitHubSource(result)) {
|
|
296
|
+
expect(result.owner).toBe("user");
|
|
297
|
+
expect(result.repo).toBe("repo");
|
|
298
|
+
expect(result.ref).toBe("v1.0.0");
|
|
299
|
+
}
|
|
300
|
+
});
|
|
301
|
+
it("should parse owner/repo with branch ref", () => {
|
|
302
|
+
const result = parseSourceSpecifier("user/repo@main");
|
|
303
|
+
expect(result.type).toBe("github");
|
|
304
|
+
if (isGitHubSource(result)) {
|
|
305
|
+
expect(result.owner).toBe("user");
|
|
306
|
+
expect(result.repo).toBe("repo");
|
|
307
|
+
expect(result.ref).toBe("main");
|
|
308
|
+
}
|
|
309
|
+
});
|
|
310
|
+
it("should parse org/repo with hyphens", () => {
|
|
311
|
+
const result = parseSourceSpecifier("herdctl-examples/website-monitor-agent");
|
|
312
|
+
expect(result.type).toBe("github");
|
|
313
|
+
if (isGitHubSource(result)) {
|
|
314
|
+
expect(result.owner).toBe("herdctl-examples");
|
|
315
|
+
expect(result.repo).toBe("website-monitor-agent");
|
|
316
|
+
}
|
|
317
|
+
});
|
|
318
|
+
it("should parse owner/repo with underscores", () => {
|
|
319
|
+
const result = parseSourceSpecifier("my_org/my_repo");
|
|
320
|
+
expect(result.type).toBe("github");
|
|
321
|
+
if (isGitHubSource(result)) {
|
|
322
|
+
expect(result.owner).toBe("my_org");
|
|
323
|
+
expect(result.repo).toBe("my_repo");
|
|
324
|
+
}
|
|
325
|
+
});
|
|
326
|
+
it("should be equivalent to github: prefix form", () => {
|
|
327
|
+
const shorthand = parseSourceSpecifier("user/repo@v1.0.0");
|
|
328
|
+
const explicit = parseSourceSpecifier("github:user/repo@v1.0.0");
|
|
329
|
+
expect(shorthand).toEqual(explicit);
|
|
330
|
+
});
|
|
331
|
+
});
|
|
332
|
+
describe("unrecognized bare names", () => {
|
|
333
|
+
it("should throw for bare name without slash", () => {
|
|
334
|
+
expect(() => parseSourceSpecifier("competitive-analysis")).toThrow(SourceParseError);
|
|
335
|
+
expect(() => parseSourceSpecifier("competitive-analysis")).toThrow("Unrecognized source format");
|
|
336
|
+
});
|
|
337
|
+
it("should throw for single word", () => {
|
|
338
|
+
expect(() => parseSourceSpecifier("myagent")).toThrow(SourceParseError);
|
|
339
|
+
expect(() => parseSourceSpecifier("myagent")).toThrow("Unrecognized source format");
|
|
340
|
+
});
|
|
341
|
+
it("should throw for name with special characters", () => {
|
|
342
|
+
expect(() => parseSourceSpecifier("invalid!name")).toThrow(SourceParseError);
|
|
343
|
+
expect(() => parseSourceSpecifier("invalid@name")).toThrow(SourceParseError);
|
|
344
|
+
});
|
|
345
|
+
it("should throw for backslash-separated names", () => {
|
|
346
|
+
expect(() => parseSourceSpecifier("invalid\\name")).toThrow(SourceParseError);
|
|
347
|
+
});
|
|
348
|
+
});
|
|
349
|
+
});
|
|
350
|
+
// =============================================================================
|
|
351
|
+
// General Error Cases
|
|
352
|
+
// =============================================================================
|
|
353
|
+
describe("parseSourceSpecifier - Error cases", () => {
|
|
354
|
+
it("should throw for empty string", () => {
|
|
355
|
+
expect(() => parseSourceSpecifier("")).toThrow(SourceParseError);
|
|
356
|
+
expect(() => parseSourceSpecifier("")).toThrow("cannot be empty");
|
|
357
|
+
});
|
|
358
|
+
it("should throw for whitespace-only string", () => {
|
|
359
|
+
expect(() => parseSourceSpecifier(" ")).toThrow(SourceParseError);
|
|
360
|
+
expect(() => parseSourceSpecifier(" ")).toThrow("cannot be empty");
|
|
361
|
+
});
|
|
362
|
+
it("should throw for null-like values", () => {
|
|
363
|
+
expect(() => parseSourceSpecifier(null)).toThrow(SourceParseError);
|
|
364
|
+
expect(() => parseSourceSpecifier(undefined)).toThrow(SourceParseError);
|
|
365
|
+
});
|
|
366
|
+
it("should trim whitespace from input", () => {
|
|
367
|
+
const result = parseSourceSpecifier(" github:user/repo ");
|
|
368
|
+
expect(result.type).toBe("github");
|
|
369
|
+
if (isGitHubSource(result)) {
|
|
370
|
+
expect(result.owner).toBe("user");
|
|
371
|
+
expect(result.repo).toBe("repo");
|
|
372
|
+
}
|
|
373
|
+
});
|
|
374
|
+
it("should include source in error for debugging", () => {
|
|
375
|
+
try {
|
|
376
|
+
parseSourceSpecifier("github:invalid!");
|
|
377
|
+
}
|
|
378
|
+
catch (error) {
|
|
379
|
+
expect(error).toBeInstanceOf(SourceParseError);
|
|
380
|
+
if (error instanceof SourceParseError) {
|
|
381
|
+
expect(error.source).toBe("github:invalid!");
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
});
|
|
385
|
+
});
|
|
386
|
+
// =============================================================================
|
|
387
|
+
// Type Guard Tests
|
|
388
|
+
// =============================================================================
|
|
389
|
+
describe("Type guards", () => {
|
|
390
|
+
describe("isGitHubSource", () => {
|
|
391
|
+
it("should return true for GitHub source", () => {
|
|
392
|
+
const specifier = parseSourceSpecifier("github:user/repo");
|
|
393
|
+
expect(isGitHubSource(specifier)).toBe(true);
|
|
394
|
+
});
|
|
395
|
+
it("should return true for GitHub shorthand", () => {
|
|
396
|
+
const specifier = parseSourceSpecifier("user/repo");
|
|
397
|
+
expect(isGitHubSource(specifier)).toBe(true);
|
|
398
|
+
});
|
|
399
|
+
it("should return false for local source", () => {
|
|
400
|
+
const specifier = parseSourceSpecifier("./local/path");
|
|
401
|
+
expect(isGitHubSource(specifier)).toBe(false);
|
|
402
|
+
});
|
|
403
|
+
});
|
|
404
|
+
describe("isLocalSource", () => {
|
|
405
|
+
it("should return true for local source", () => {
|
|
406
|
+
const specifier = parseSourceSpecifier("./local/path");
|
|
407
|
+
expect(isLocalSource(specifier)).toBe(true);
|
|
408
|
+
});
|
|
409
|
+
it("should return false for GitHub source", () => {
|
|
410
|
+
const specifier = parseSourceSpecifier("github:user/repo");
|
|
411
|
+
expect(isLocalSource(specifier)).toBe(false);
|
|
412
|
+
});
|
|
413
|
+
it("should return false for GitHub shorthand", () => {
|
|
414
|
+
const specifier = parseSourceSpecifier("user/repo");
|
|
415
|
+
expect(isLocalSource(specifier)).toBe(false);
|
|
416
|
+
});
|
|
417
|
+
});
|
|
418
|
+
});
|
|
419
|
+
// =============================================================================
|
|
420
|
+
// stringifySourceSpecifier Tests
|
|
421
|
+
// =============================================================================
|
|
422
|
+
describe("stringifySourceSpecifier", () => {
|
|
423
|
+
describe("GitHub sources", () => {
|
|
424
|
+
it("should stringify basic GitHub source", () => {
|
|
425
|
+
const specifier = {
|
|
426
|
+
type: "github",
|
|
427
|
+
owner: "user",
|
|
428
|
+
repo: "repo",
|
|
429
|
+
};
|
|
430
|
+
expect(stringifySourceSpecifier(specifier)).toBe("github:user/repo");
|
|
431
|
+
});
|
|
432
|
+
it("should stringify GitHub source with ref", () => {
|
|
433
|
+
const specifier = {
|
|
434
|
+
type: "github",
|
|
435
|
+
owner: "user",
|
|
436
|
+
repo: "repo",
|
|
437
|
+
ref: "v1.0.0",
|
|
438
|
+
};
|
|
439
|
+
expect(stringifySourceSpecifier(specifier)).toBe("github:user/repo@v1.0.0");
|
|
440
|
+
});
|
|
441
|
+
it("should stringify GitHub source with branch ref", () => {
|
|
442
|
+
const specifier = {
|
|
443
|
+
type: "github",
|
|
444
|
+
owner: "user",
|
|
445
|
+
repo: "repo",
|
|
446
|
+
ref: "feature/new-feature",
|
|
447
|
+
};
|
|
448
|
+
expect(stringifySourceSpecifier(specifier)).toBe("github:user/repo@feature/new-feature");
|
|
449
|
+
});
|
|
450
|
+
});
|
|
451
|
+
describe("Local sources", () => {
|
|
452
|
+
it("should stringify local source", () => {
|
|
453
|
+
const specifier = {
|
|
454
|
+
type: "local",
|
|
455
|
+
path: "/absolute/path/to/agent",
|
|
456
|
+
};
|
|
457
|
+
expect(stringifySourceSpecifier(specifier)).toBe("/absolute/path/to/agent");
|
|
458
|
+
});
|
|
459
|
+
});
|
|
460
|
+
describe("Round-trip", () => {
|
|
461
|
+
it("should round-trip GitHub source", () => {
|
|
462
|
+
const original = "github:user/repo@v1.0.0";
|
|
463
|
+
const parsed = parseSourceSpecifier(original);
|
|
464
|
+
const stringified = stringifySourceSpecifier(parsed);
|
|
465
|
+
expect(stringified).toBe(original);
|
|
466
|
+
});
|
|
467
|
+
it("should round-trip GitHub shorthand via explicit form", () => {
|
|
468
|
+
const parsed = parseSourceSpecifier("user/repo@v1.0.0");
|
|
469
|
+
const stringified = stringifySourceSpecifier(parsed);
|
|
470
|
+
// Shorthand round-trips to the explicit github: form
|
|
471
|
+
expect(stringified).toBe("github:user/repo@v1.0.0");
|
|
472
|
+
});
|
|
473
|
+
// Note: Local paths don't round-trip exactly because they're resolved to absolute
|
|
474
|
+
it("should produce valid specifier on local source round-trip", () => {
|
|
475
|
+
const original = "./local/path";
|
|
476
|
+
const parsed = parseSourceSpecifier(original);
|
|
477
|
+
const stringified = stringifySourceSpecifier(parsed);
|
|
478
|
+
// The stringified version is absolute, but should parse back to same path
|
|
479
|
+
const reparsed = parseSourceSpecifier(stringified);
|
|
480
|
+
expect(reparsed.type).toBe("local");
|
|
481
|
+
if (isLocalSource(parsed) && isLocalSource(reparsed)) {
|
|
482
|
+
expect(reparsed.path).toBe(parsed.path);
|
|
483
|
+
}
|
|
484
|
+
});
|
|
485
|
+
});
|
|
486
|
+
});
|
|
487
|
+
// =============================================================================
|
|
488
|
+
// SourceSpecifier Type Tests (compile-time)
|
|
489
|
+
// =============================================================================
|
|
490
|
+
describe("SourceSpecifier types", () => {
|
|
491
|
+
it("should have correct type structure for GitHubSource", () => {
|
|
492
|
+
const specifier = {
|
|
493
|
+
type: "github",
|
|
494
|
+
owner: "user",
|
|
495
|
+
repo: "repo",
|
|
496
|
+
ref: "v1.0.0",
|
|
497
|
+
};
|
|
498
|
+
// Type assertions - these are compile-time checks
|
|
499
|
+
const _type = specifier.type;
|
|
500
|
+
const _owner = specifier.owner;
|
|
501
|
+
const _repo = specifier.repo;
|
|
502
|
+
const _ref = specifier.ref;
|
|
503
|
+
expect(_type).toBe("github");
|
|
504
|
+
expect(_owner).toBe("user");
|
|
505
|
+
expect(_repo).toBe("repo");
|
|
506
|
+
expect(_ref).toBe("v1.0.0");
|
|
507
|
+
});
|
|
508
|
+
it("should have correct type structure for LocalSource", () => {
|
|
509
|
+
const specifier = {
|
|
510
|
+
type: "local",
|
|
511
|
+
path: "/some/path",
|
|
512
|
+
};
|
|
513
|
+
const _type = specifier.type;
|
|
514
|
+
const _path = specifier.path;
|
|
515
|
+
expect(_type).toBe("local");
|
|
516
|
+
expect(_path).toBe("/some/path");
|
|
517
|
+
});
|
|
518
|
+
it("should allow discrimination via type field", () => {
|
|
519
|
+
const specifier = parseSourceSpecifier("github:user/repo");
|
|
520
|
+
// This tests that the type discriminator works correctly
|
|
521
|
+
switch (specifier.type) {
|
|
522
|
+
case "github":
|
|
523
|
+
expect(specifier.owner).toBe("user");
|
|
524
|
+
expect(specifier.repo).toBe("repo");
|
|
525
|
+
break;
|
|
526
|
+
case "local":
|
|
527
|
+
// TypeScript knows specifier.path exists here
|
|
528
|
+
expect(specifier.path).toBeDefined();
|
|
529
|
+
break;
|
|
530
|
+
}
|
|
531
|
+
});
|
|
532
|
+
});
|
|
533
|
+
//# sourceMappingURL=source-specifier.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"source-specifier.test.js","sourceRoot":"","sources":["../../../src/distribution/__tests__/source-specifier.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Agent Discovery for herdctl
|
|
3
|
+
*
|
|
4
|
+
* Scans the filesystem to discover agents referenced in herdctl.yaml.
|
|
5
|
+
* Identifies which agents were installed via `herdctl agent add` (have metadata.json)
|
|
6
|
+
* vs manually created agents.
|
|
7
|
+
*/
|
|
8
|
+
import { FleetManagerError, type FleetManagerErrorCode } from "../fleet-manager/errors.js";
|
|
9
|
+
import { type InstallationMetadata } from "./installation-metadata.js";
|
|
10
|
+
/**
|
|
11
|
+
* Information about a discovered agent
|
|
12
|
+
*/
|
|
13
|
+
export interface DiscoveredAgent {
|
|
14
|
+
/** Agent name (from agent.yaml or directory name) */
|
|
15
|
+
name: string;
|
|
16
|
+
/** Whether this agent was installed via herdctl agent add (has metadata.json) */
|
|
17
|
+
installed: boolean;
|
|
18
|
+
/** Installation metadata (only for installed agents) */
|
|
19
|
+
metadata?: InstallationMetadata;
|
|
20
|
+
/** Absolute path to the agent directory */
|
|
21
|
+
path: string;
|
|
22
|
+
/** Relative path to agent.yaml (as referenced in fleet config) */
|
|
23
|
+
configPath: string;
|
|
24
|
+
/** Agent description (from agent.yaml if available) */
|
|
25
|
+
description?: string;
|
|
26
|
+
/** Agent version (from metadata.json source, or herdctl.json) */
|
|
27
|
+
version?: string;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Options for discovering agents
|
|
31
|
+
*/
|
|
32
|
+
export interface DiscoveryOptions {
|
|
33
|
+
/** Path to herdctl.yaml */
|
|
34
|
+
configPath: string;
|
|
35
|
+
/** Base directory of the project (defaults to dirname of configPath) */
|
|
36
|
+
baseDir?: string;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Result of agent discovery
|
|
40
|
+
*/
|
|
41
|
+
export interface DiscoveryResult {
|
|
42
|
+
/** All discovered agents (installed + manual) */
|
|
43
|
+
agents: DiscoveredAgent[];
|
|
44
|
+
}
|
|
45
|
+
/** Error code: herdctl.yaml doesn't exist */
|
|
46
|
+
export declare const DISCOVERY_CONFIG_NOT_FOUND: FleetManagerErrorCode;
|
|
47
|
+
/** Error code: herdctl.yaml is invalid */
|
|
48
|
+
export declare const DISCOVERY_CONFIG_INVALID: FleetManagerErrorCode;
|
|
49
|
+
/**
|
|
50
|
+
* Error thrown when agent discovery fails
|
|
51
|
+
*/
|
|
52
|
+
export declare class AgentDiscoveryError extends FleetManagerError {
|
|
53
|
+
constructor(message: string, code: FleetManagerErrorCode);
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Discover agents referenced in the fleet configuration
|
|
57
|
+
*
|
|
58
|
+
* This function:
|
|
59
|
+
* 1. Reads herdctl.yaml and extracts agent references
|
|
60
|
+
* 2. For each reference, checks if the agent directory exists
|
|
61
|
+
* 3. Reads agent.yaml to get name and description
|
|
62
|
+
* 4. Checks for metadata.json to determine if installed via herdctl
|
|
63
|
+
* 5. Returns all discovered agents sorted by name
|
|
64
|
+
*
|
|
65
|
+
* @param options - Discovery options including config path
|
|
66
|
+
* @returns Discovery result with list of agents
|
|
67
|
+
* @throws {AgentDiscoveryError} When discovery fails
|
|
68
|
+
*
|
|
69
|
+
* @example
|
|
70
|
+
* ```typescript
|
|
71
|
+
* const result = await discoverAgents({
|
|
72
|
+
* configPath: "/path/to/herdctl.yaml"
|
|
73
|
+
* });
|
|
74
|
+
*
|
|
75
|
+
* for (const agent of result.agents) {
|
|
76
|
+
* console.log(`${agent.name}: ${agent.installed ? 'installed' : 'manual'}`);
|
|
77
|
+
* }
|
|
78
|
+
* ```
|
|
79
|
+
*/
|
|
80
|
+
export declare function discoverAgents(options: DiscoveryOptions): Promise<DiscoveryResult>;
|
|
81
|
+
//# sourceMappingURL=agent-discovery.d.ts.map
|