@rudderhq/agent-runtime-utils 0.2.0-canary.8 → 0.2.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/git-identity.d.ts +28 -0
- package/dist/git-identity.d.ts.map +1 -0
- package/dist/git-identity.js +220 -0
- package/dist/git-identity.js.map +1 -0
- package/dist/git-identity.test.d.ts +2 -0
- package/dist/git-identity.test.d.ts.map +1 -0
- package/dist/git-identity.test.js +307 -0
- package/dist/git-identity.test.js.map +1 -0
- package/dist/server-utils.d.ts +15 -0
- package/dist/server-utils.d.ts.map +1 -1
- package/dist/server-utils.js +198 -14
- package/dist/server-utils.js.map +1 -1
- package/dist/server-utils.test.js +191 -9
- package/dist/server-utils.test.js.map +1 -1
- package/dist/types.d.ts +8 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
export type GitIdentitySource = "environment" | "repository" | "global";
|
|
2
|
+
export type GitIdentity = {
|
|
3
|
+
name: string;
|
|
4
|
+
email: string;
|
|
5
|
+
source: GitIdentitySource;
|
|
6
|
+
};
|
|
7
|
+
export type GitIdentityPreparationResult = {
|
|
8
|
+
identity: GitIdentity | null;
|
|
9
|
+
configTarget: string;
|
|
10
|
+
configuredUseConfigOnly: boolean;
|
|
11
|
+
warnings: string[];
|
|
12
|
+
};
|
|
13
|
+
type LogFn = (stream: "stdout" | "stderr", chunk: string) => Promise<void>;
|
|
14
|
+
export declare function isUnsafeGitIdentityEmail(email: string | null | undefined): boolean;
|
|
15
|
+
export declare function applyGitIdentityPreparationEnv(env: Record<string, string>, preparation: GitIdentityPreparationResult): void;
|
|
16
|
+
export declare function ensureGitIdentityFileConfig(input: {
|
|
17
|
+
cwd: string;
|
|
18
|
+
home: string;
|
|
19
|
+
sourceEnv?: NodeJS.ProcessEnv;
|
|
20
|
+
onLog?: LogFn | null;
|
|
21
|
+
}): Promise<GitIdentityPreparationResult>;
|
|
22
|
+
export declare function ensureGitRepositoryIdentityConfig(input: {
|
|
23
|
+
cwd: string;
|
|
24
|
+
sourceEnv?: NodeJS.ProcessEnv;
|
|
25
|
+
onLog?: LogFn | null;
|
|
26
|
+
}): Promise<GitIdentityPreparationResult>;
|
|
27
|
+
export {};
|
|
28
|
+
//# sourceMappingURL=git-identity.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"git-identity.d.ts","sourceRoot":"","sources":["../src/git-identity.ts"],"names":[],"mappings":"AAIA,MAAM,MAAM,iBAAiB,GAAG,aAAa,GAAG,YAAY,GAAG,QAAQ,CAAC;AAExE,MAAM,MAAM,WAAW,GAAG;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,iBAAiB,CAAC;CAC3B,CAAC;AAEF,MAAM,MAAM,4BAA4B,GAAG;IACzC,QAAQ,EAAE,WAAW,GAAG,IAAI,CAAC;IAC7B,YAAY,EAAE,MAAM,CAAC;IACrB,uBAAuB,EAAE,OAAO,CAAC;IACjC,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB,CAAC;AASF,KAAK,KAAK,GAAG,CAAC,MAAM,EAAE,QAAQ,GAAG,QAAQ,EAAE,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;AAkB3E,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,OAAO,CAKlF;AAED,wBAAgB,8BAA8B,CAC5C,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAC3B,WAAW,EAAE,4BAA4B,GACxC,IAAI,CAIN;AAuKD,wBAAsB,2BAA2B,CAAC,KAAK,EAAE;IACvD,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;IAC9B,KAAK,CAAC,EAAE,KAAK,GAAG,IAAI,CAAC;CACtB,GAAG,OAAO,CAAC,4BAA4B,CAAC,CA0CxC;AAED,wBAAsB,iCAAiC,CAAC,KAAK,EAAE;IAC7D,GAAG,EAAE,MAAM,CAAC;IACZ,SAAS,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;IAC9B,KAAK,CAAC,EAAE,KAAK,GAAG,IAAI,CAAC;CACtB,GAAG,OAAO,CAAC,4BAA4B,CAAC,CA4BxC"}
|
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
import { spawn } from "node:child_process";
|
|
2
|
+
import fs from "node:fs/promises";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
const LOCAL_EMAIL_RE = /@[^@\s<>]+\.local$/i;
|
|
5
|
+
const EMAIL_RE = /^[^@\s<>]+@[^@\s<>]+\.[^@\s<>]+$/;
|
|
6
|
+
function normalizeEnv(env) {
|
|
7
|
+
return Object.fromEntries(Object.entries(env ?? process.env).filter((entry) => typeof entry[1] === "string"));
|
|
8
|
+
}
|
|
9
|
+
function nonEmpty(value) {
|
|
10
|
+
const normalized = value?.trim() ?? "";
|
|
11
|
+
return normalized.length > 0 ? normalized : null;
|
|
12
|
+
}
|
|
13
|
+
export function isUnsafeGitIdentityEmail(email) {
|
|
14
|
+
const normalized = nonEmpty(email);
|
|
15
|
+
if (!normalized)
|
|
16
|
+
return true;
|
|
17
|
+
if (!EMAIL_RE.test(normalized))
|
|
18
|
+
return true;
|
|
19
|
+
return LOCAL_EMAIL_RE.test(normalized);
|
|
20
|
+
}
|
|
21
|
+
export function applyGitIdentityPreparationEnv(env, preparation) {
|
|
22
|
+
env.GIT_CONFIG_GLOBAL = preparation.configTarget;
|
|
23
|
+
clearUnsafeIdentityEnvPair(env, "GIT_AUTHOR_NAME", "GIT_AUTHOR_EMAIL");
|
|
24
|
+
clearUnsafeIdentityEnvPair(env, "GIT_COMMITTER_NAME", "GIT_COMMITTER_EMAIL");
|
|
25
|
+
}
|
|
26
|
+
function buildIdentity(name, email, source) {
|
|
27
|
+
const normalizedName = nonEmpty(name);
|
|
28
|
+
const normalizedEmail = nonEmpty(email);
|
|
29
|
+
if (!normalizedName || !normalizedEmail)
|
|
30
|
+
return null;
|
|
31
|
+
if (isUnsafeGitIdentityEmail(normalizedEmail))
|
|
32
|
+
return null;
|
|
33
|
+
return {
|
|
34
|
+
name: normalizedName,
|
|
35
|
+
email: normalizedEmail,
|
|
36
|
+
source,
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
function identityFromEnv(env) {
|
|
40
|
+
return (buildIdentity(env.GIT_AUTHOR_NAME, env.GIT_AUTHOR_EMAIL, "environment") ??
|
|
41
|
+
buildIdentity(env.GIT_COMMITTER_NAME, env.GIT_COMMITTER_EMAIL, "environment"));
|
|
42
|
+
}
|
|
43
|
+
function clearUnsafeIdentityEnvPair(env, nameKey, emailKey) {
|
|
44
|
+
const hasValue = nonEmpty(env[nameKey]) || nonEmpty(env[emailKey]);
|
|
45
|
+
if (!hasValue) {
|
|
46
|
+
delete env[nameKey];
|
|
47
|
+
delete env[emailKey];
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
if (buildIdentity(env[nameKey], env[emailKey], "environment"))
|
|
51
|
+
return;
|
|
52
|
+
delete env[nameKey];
|
|
53
|
+
delete env[emailKey];
|
|
54
|
+
}
|
|
55
|
+
async function runGit(args, opts = {}) {
|
|
56
|
+
const env = normalizeEnv(opts.env);
|
|
57
|
+
return await new Promise((resolve) => {
|
|
58
|
+
const child = spawn("git", args, {
|
|
59
|
+
cwd: opts.cwd ?? process.cwd(),
|
|
60
|
+
env,
|
|
61
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
62
|
+
});
|
|
63
|
+
let stdout = "";
|
|
64
|
+
let stderr = "";
|
|
65
|
+
child.stdout?.on("data", (chunk) => {
|
|
66
|
+
stdout += String(chunk);
|
|
67
|
+
});
|
|
68
|
+
child.stderr?.on("data", (chunk) => {
|
|
69
|
+
stderr += String(chunk);
|
|
70
|
+
});
|
|
71
|
+
child.on("error", (error) => {
|
|
72
|
+
resolve({ code: null, stdout, stderr, error });
|
|
73
|
+
});
|
|
74
|
+
child.on("close", (code) => {
|
|
75
|
+
resolve({ code, stdout, stderr, error: null });
|
|
76
|
+
});
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
async function readGitConfigValue(args, key, opts = {}) {
|
|
80
|
+
const result = await runGit([...args, "--get", key], opts);
|
|
81
|
+
if (result.code !== 0)
|
|
82
|
+
return null;
|
|
83
|
+
return nonEmpty(result.stdout);
|
|
84
|
+
}
|
|
85
|
+
async function readIdentityFromGitConfig(args, source, opts = {}) {
|
|
86
|
+
const [name, email] = await Promise.all([
|
|
87
|
+
readGitConfigValue(args, "user.name", opts),
|
|
88
|
+
readGitConfigValue(args, "user.email", opts),
|
|
89
|
+
]);
|
|
90
|
+
return buildIdentity(name, email, source);
|
|
91
|
+
}
|
|
92
|
+
async function setGitConfigValue(args, key, value, opts) {
|
|
93
|
+
const result = await runGit([...args, key, value], opts);
|
|
94
|
+
if (result.code === 0)
|
|
95
|
+
return;
|
|
96
|
+
const details = [result.stderr.trim(), result.stdout.trim(), result.error?.message]
|
|
97
|
+
.filter(Boolean)
|
|
98
|
+
.join("\n");
|
|
99
|
+
throw new Error(details || `git config ${key} failed`);
|
|
100
|
+
}
|
|
101
|
+
async function unsetGitConfigValue(args, key, opts) {
|
|
102
|
+
await runGit([...args, "--unset-all", key], opts);
|
|
103
|
+
}
|
|
104
|
+
async function existingGitConfigPaths(candidates) {
|
|
105
|
+
const seen = new Set();
|
|
106
|
+
const existing = [];
|
|
107
|
+
for (const candidate of candidates) {
|
|
108
|
+
const normalized = nonEmpty(candidate);
|
|
109
|
+
if (!normalized)
|
|
110
|
+
continue;
|
|
111
|
+
const resolved = path.resolve(normalized);
|
|
112
|
+
if (seen.has(resolved))
|
|
113
|
+
continue;
|
|
114
|
+
const stat = await fs.stat(resolved).catch(() => null);
|
|
115
|
+
if (!stat?.isFile())
|
|
116
|
+
continue;
|
|
117
|
+
seen.add(resolved);
|
|
118
|
+
existing.push(resolved);
|
|
119
|
+
}
|
|
120
|
+
return existing;
|
|
121
|
+
}
|
|
122
|
+
async function resolveHostGlobalGitConfigIncludes(sourceEnv, targetConfigPath) {
|
|
123
|
+
const home = nonEmpty(sourceEnv.HOME);
|
|
124
|
+
const xdgConfigHome = nonEmpty(sourceEnv.XDG_CONFIG_HOME);
|
|
125
|
+
const candidates = [
|
|
126
|
+
nonEmpty(sourceEnv.GIT_CONFIG_GLOBAL) ?? "",
|
|
127
|
+
home ? path.join(home, ".gitconfig") : "",
|
|
128
|
+
xdgConfigHome ? path.join(xdgConfigHome, "git", "config") : "",
|
|
129
|
+
home ? path.join(home, ".config", "git", "config") : "",
|
|
130
|
+
].filter(Boolean);
|
|
131
|
+
const target = path.resolve(targetConfigPath);
|
|
132
|
+
return (await existingGitConfigPaths(candidates)).filter((candidate) => candidate !== target);
|
|
133
|
+
}
|
|
134
|
+
function renderGitConfigIncludes(includePaths) {
|
|
135
|
+
if (includePaths.length === 0)
|
|
136
|
+
return [];
|
|
137
|
+
return ["[include]", ...includePaths.map((includePath) => `\tpath = ${includePath}`), ""];
|
|
138
|
+
}
|
|
139
|
+
async function writeGitConfigSeed(configPath, includePaths) {
|
|
140
|
+
await fs.mkdir(path.dirname(configPath), { recursive: true });
|
|
141
|
+
const lines = renderGitConfigIncludes(includePaths);
|
|
142
|
+
await fs.writeFile(configPath, lines.length > 0 ? `${lines.join("\n")}\n` : "", "utf8");
|
|
143
|
+
}
|
|
144
|
+
async function writeFallbackGitConfigFile(configPath, identity, includePaths = []) {
|
|
145
|
+
const lines = [...renderGitConfigIncludes(includePaths), "[user]", "\tuseConfigOnly = true"];
|
|
146
|
+
await fs.mkdir(path.dirname(configPath), { recursive: true });
|
|
147
|
+
await fs.writeFile(configPath, `${lines.join("\n")}\n`, "utf8");
|
|
148
|
+
}
|
|
149
|
+
async function resolveBestGitIdentity(input) {
|
|
150
|
+
return (identityFromEnv(input.sourceEnv) ??
|
|
151
|
+
(await readIdentityFromGitConfig(["config", "--local"], "repository", {
|
|
152
|
+
cwd: input.cwd,
|
|
153
|
+
env: input.sourceEnv,
|
|
154
|
+
})) ??
|
|
155
|
+
(await readIdentityFromGitConfig(["config", "--global"], "global", {
|
|
156
|
+
cwd: input.cwd,
|
|
157
|
+
env: input.sourceEnv,
|
|
158
|
+
})));
|
|
159
|
+
}
|
|
160
|
+
export async function ensureGitIdentityFileConfig(input) {
|
|
161
|
+
const sourceEnv = normalizeEnv(input.sourceEnv);
|
|
162
|
+
const home = path.resolve(input.home);
|
|
163
|
+
const gitConfigPath = path.join(home, ".gitconfig");
|
|
164
|
+
await fs.mkdir(home, { recursive: true });
|
|
165
|
+
const configArgs = ["config", "--file", gitConfigPath];
|
|
166
|
+
const identity = await resolveBestGitIdentity({
|
|
167
|
+
cwd: input.cwd,
|
|
168
|
+
sourceEnv,
|
|
169
|
+
});
|
|
170
|
+
const includePaths = identity
|
|
171
|
+
? await resolveHostGlobalGitConfigIncludes(sourceEnv, gitConfigPath)
|
|
172
|
+
: [];
|
|
173
|
+
const warnings = [];
|
|
174
|
+
try {
|
|
175
|
+
await writeGitConfigSeed(gitConfigPath, includePaths);
|
|
176
|
+
await setGitConfigValue(configArgs, "user.useConfigOnly", "true", { cwd: input.cwd, env: sourceEnv });
|
|
177
|
+
await unsetGitConfigValue(configArgs, "user.name", { cwd: input.cwd, env: sourceEnv });
|
|
178
|
+
await unsetGitConfigValue(configArgs, "user.email", { cwd: input.cwd, env: sourceEnv });
|
|
179
|
+
}
|
|
180
|
+
catch (error) {
|
|
181
|
+
warnings.push(error instanceof Error ? error.message : String(error));
|
|
182
|
+
await writeFallbackGitConfigFile(gitConfigPath, identity, includePaths);
|
|
183
|
+
}
|
|
184
|
+
if (input.onLog) {
|
|
185
|
+
const detail = identity
|
|
186
|
+
? `using ${identity.source} Git identity ${identity.name} <${identity.email}>`
|
|
187
|
+
: "without a usable Git identity; commits will fail until user.name and user.email are configured";
|
|
188
|
+
await input.onLog("stdout", `[rudder] Prepared isolated Git config at ${gitConfigPath} with user.useConfigOnly=true (${detail}).\n`);
|
|
189
|
+
}
|
|
190
|
+
return {
|
|
191
|
+
identity,
|
|
192
|
+
configTarget: gitConfigPath,
|
|
193
|
+
configuredUseConfigOnly: true,
|
|
194
|
+
warnings,
|
|
195
|
+
};
|
|
196
|
+
}
|
|
197
|
+
export async function ensureGitRepositoryIdentityConfig(input) {
|
|
198
|
+
const sourceEnv = normalizeEnv(input.sourceEnv);
|
|
199
|
+
const cwd = path.resolve(input.cwd);
|
|
200
|
+
const configArgs = ["config", "--local"];
|
|
201
|
+
const identity = await resolveBestGitIdentity({
|
|
202
|
+
cwd,
|
|
203
|
+
sourceEnv,
|
|
204
|
+
});
|
|
205
|
+
const warnings = [];
|
|
206
|
+
await setGitConfigValue(configArgs, "user.useConfigOnly", "true", { cwd, env: sourceEnv });
|
|
207
|
+
if (input.onLog) {
|
|
208
|
+
const detail = identity
|
|
209
|
+
? `using ${identity.source} Git identity ${identity.name} <${identity.email}>`
|
|
210
|
+
: "without a usable Git identity; commits will fail until user.name and user.email are configured";
|
|
211
|
+
await input.onLog("stdout", `[rudder] Prepared repository Git config in ${cwd} with user.useConfigOnly=true (${detail}).\n`);
|
|
212
|
+
}
|
|
213
|
+
return {
|
|
214
|
+
identity,
|
|
215
|
+
configTarget: cwd,
|
|
216
|
+
configuredUseConfigOnly: true,
|
|
217
|
+
warnings,
|
|
218
|
+
};
|
|
219
|
+
}
|
|
220
|
+
//# sourceMappingURL=git-identity.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"git-identity.js","sourceRoot":"","sources":["../src/git-identity.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"git-identity.test.d.ts","sourceRoot":"","sources":["../src/git-identity.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,307 @@
|
|
|
1
|
+
import { execFile } from "node:child_process";
|
|
2
|
+
import fs from "node:fs/promises";
|
|
3
|
+
import os from "node:os";
|
|
4
|
+
import path from "node:path";
|
|
5
|
+
import { promisify } from "node:util";
|
|
6
|
+
import { describe, expect, it } from "vitest";
|
|
7
|
+
import { applyGitIdentityPreparationEnv, ensureGitIdentityFileConfig, ensureGitRepositoryIdentityConfig, isUnsafeGitIdentityEmail, } from "./git-identity.js";
|
|
8
|
+
const execFileAsync = promisify(execFile);
|
|
9
|
+
function baseGitTestEnv(env) {
|
|
10
|
+
const base = { ...process.env };
|
|
11
|
+
for (const key of [
|
|
12
|
+
"GIT_AUTHOR_NAME",
|
|
13
|
+
"GIT_AUTHOR_EMAIL",
|
|
14
|
+
"GIT_COMMITTER_NAME",
|
|
15
|
+
"GIT_COMMITTER_EMAIL",
|
|
16
|
+
"GIT_CONFIG_GLOBAL",
|
|
17
|
+
"XDG_CONFIG_HOME",
|
|
18
|
+
]) {
|
|
19
|
+
delete base[key];
|
|
20
|
+
}
|
|
21
|
+
return {
|
|
22
|
+
...base,
|
|
23
|
+
...env,
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
async function runGit(cwd, args, env) {
|
|
27
|
+
return execFileAsync("git", args, {
|
|
28
|
+
cwd,
|
|
29
|
+
env: baseGitTestEnv(env),
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
async function createRepoWithoutStoredIdentity(root) {
|
|
33
|
+
const repo = path.join(root, "repo");
|
|
34
|
+
await fs.mkdir(repo, { recursive: true });
|
|
35
|
+
await runGit(repo, ["init"]);
|
|
36
|
+
await fs.writeFile(path.join(repo, "README.md"), "hello\n", "utf8");
|
|
37
|
+
await runGit(repo, ["add", "README.md"]);
|
|
38
|
+
await runGit(repo, [
|
|
39
|
+
"-c",
|
|
40
|
+
"user.name=Setup User",
|
|
41
|
+
"-c",
|
|
42
|
+
"user.email=setup@example.com",
|
|
43
|
+
"commit",
|
|
44
|
+
"-m",
|
|
45
|
+
"Initial commit",
|
|
46
|
+
]);
|
|
47
|
+
await runGit(repo, ["checkout", "-B", "main"]);
|
|
48
|
+
return repo;
|
|
49
|
+
}
|
|
50
|
+
async function gitAuthorIdent(cwd, env) {
|
|
51
|
+
return execFileAsync("git", ["var", "GIT_AUTHOR_IDENT"], {
|
|
52
|
+
cwd,
|
|
53
|
+
env: baseGitTestEnv(env),
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
describe("git identity guard", () => {
|
|
57
|
+
it("rejects local-host fallback emails as unsafe identities", () => {
|
|
58
|
+
expect(isUnsafeGitIdentityEmail("zeeland@ZeelanddeMacBook-Pro.local")).toBe(true);
|
|
59
|
+
expect(isUnsafeGitIdentityEmail("72488598+Undertone0809@users.noreply.github.com")).toBe(false);
|
|
60
|
+
});
|
|
61
|
+
it("seeds isolated HOME Git config from repository identity", async () => {
|
|
62
|
+
const root = await fs.mkdtemp(path.join(os.tmpdir(), "rudder-git-identity-repo-"));
|
|
63
|
+
try {
|
|
64
|
+
const repo = await createRepoWithoutStoredIdentity(root);
|
|
65
|
+
const isolatedHome = path.join(root, "agent-home");
|
|
66
|
+
await runGit(repo, ["config", "user.name", "Rudder Agent"]);
|
|
67
|
+
await runGit(repo, ["config", "user.email", "rudder-agent@example.com"]);
|
|
68
|
+
const result = await ensureGitIdentityFileConfig({
|
|
69
|
+
cwd: repo,
|
|
70
|
+
home: isolatedHome,
|
|
71
|
+
sourceEnv: baseGitTestEnv({
|
|
72
|
+
HOME: path.join(root, "empty-home"),
|
|
73
|
+
GIT_CONFIG_NOSYSTEM: "1",
|
|
74
|
+
}),
|
|
75
|
+
});
|
|
76
|
+
expect(result.identity).toMatchObject({
|
|
77
|
+
name: "Rudder Agent",
|
|
78
|
+
email: "rudder-agent@example.com",
|
|
79
|
+
source: "repository",
|
|
80
|
+
});
|
|
81
|
+
await expect(fs.readFile(path.join(isolatedHome, ".gitconfig"), "utf8")).resolves.toContain("useConfigOnly = true");
|
|
82
|
+
const ident = await gitAuthorIdent(repo, {
|
|
83
|
+
HOME: isolatedHome,
|
|
84
|
+
GIT_CONFIG_NOSYSTEM: "1",
|
|
85
|
+
});
|
|
86
|
+
expect(ident.stdout).toContain("Rudder Agent <rudder-agent@example.com>");
|
|
87
|
+
expect(ident.stdout).not.toContain(".local");
|
|
88
|
+
}
|
|
89
|
+
finally {
|
|
90
|
+
await fs.rm(root, { recursive: true, force: true });
|
|
91
|
+
}
|
|
92
|
+
});
|
|
93
|
+
it("includes host global Git config when a safe identity is resolved", async () => {
|
|
94
|
+
const root = await fs.mkdtemp(path.join(os.tmpdir(), "rudder-git-identity-include-"));
|
|
95
|
+
try {
|
|
96
|
+
const repo = await createRepoWithoutStoredIdentity(root);
|
|
97
|
+
const hostHome = path.join(root, "host-home");
|
|
98
|
+
const isolatedHome = path.join(root, "agent-home");
|
|
99
|
+
await fs.mkdir(hostHome, { recursive: true });
|
|
100
|
+
await fs.writeFile(path.join(hostHome, ".gitconfig"), [
|
|
101
|
+
"[user]",
|
|
102
|
+
"\tname = Host Operator",
|
|
103
|
+
"\temail = operator@example.com",
|
|
104
|
+
"[credential]",
|
|
105
|
+
"\thelper = store",
|
|
106
|
+
].join("\n") + "\n", "utf8");
|
|
107
|
+
const result = await ensureGitIdentityFileConfig({
|
|
108
|
+
cwd: repo,
|
|
109
|
+
home: isolatedHome,
|
|
110
|
+
sourceEnv: baseGitTestEnv({
|
|
111
|
+
HOME: hostHome,
|
|
112
|
+
GIT_CONFIG_NOSYSTEM: "1",
|
|
113
|
+
}),
|
|
114
|
+
});
|
|
115
|
+
expect(result.identity).toMatchObject({
|
|
116
|
+
name: "Host Operator",
|
|
117
|
+
email: "operator@example.com",
|
|
118
|
+
source: "global",
|
|
119
|
+
});
|
|
120
|
+
await expect(runGit(repo, [
|
|
121
|
+
"config",
|
|
122
|
+
"--get",
|
|
123
|
+
"credential.helper",
|
|
124
|
+
], {
|
|
125
|
+
HOME: isolatedHome,
|
|
126
|
+
GIT_CONFIG_GLOBAL: path.join(isolatedHome, ".gitconfig"),
|
|
127
|
+
GIT_CONFIG_NOSYSTEM: "1",
|
|
128
|
+
})).resolves.toMatchObject({ stdout: "store\n" });
|
|
129
|
+
await expect(runGit(repo, [
|
|
130
|
+
"config",
|
|
131
|
+
"--get",
|
|
132
|
+
"user.email",
|
|
133
|
+
], {
|
|
134
|
+
HOME: isolatedHome,
|
|
135
|
+
GIT_CONFIG_GLOBAL: path.join(isolatedHome, ".gitconfig"),
|
|
136
|
+
GIT_CONFIG_NOSYSTEM: "1",
|
|
137
|
+
})).resolves.toMatchObject({ stdout: "operator@example.com\n" });
|
|
138
|
+
}
|
|
139
|
+
finally {
|
|
140
|
+
await fs.rm(root, { recursive: true, force: true });
|
|
141
|
+
}
|
|
142
|
+
});
|
|
143
|
+
it("prevents Git fallback commits when isolated HOME has no usable identity", async () => {
|
|
144
|
+
const root = await fs.mkdtemp(path.join(os.tmpdir(), "rudder-git-identity-missing-"));
|
|
145
|
+
try {
|
|
146
|
+
const repo = await createRepoWithoutStoredIdentity(root);
|
|
147
|
+
const isolatedHome = path.join(root, "agent-home");
|
|
148
|
+
const result = await ensureGitIdentityFileConfig({
|
|
149
|
+
cwd: repo,
|
|
150
|
+
home: isolatedHome,
|
|
151
|
+
sourceEnv: baseGitTestEnv({
|
|
152
|
+
HOME: path.join(root, "empty-home"),
|
|
153
|
+
GIT_CONFIG_NOSYSTEM: "1",
|
|
154
|
+
}),
|
|
155
|
+
});
|
|
156
|
+
expect(result.identity).toBeNull();
|
|
157
|
+
await expect(gitAuthorIdent(repo, {
|
|
158
|
+
HOME: isolatedHome,
|
|
159
|
+
GIT_CONFIG_NOSYSTEM: "1",
|
|
160
|
+
})).rejects.toMatchObject({
|
|
161
|
+
stderr: expect.not.stringContaining(".local"),
|
|
162
|
+
});
|
|
163
|
+
await expect(execFileAsync("git", ["commit", "--allow-empty", "-m", "agent commit"], {
|
|
164
|
+
cwd: repo,
|
|
165
|
+
env: baseGitTestEnv({
|
|
166
|
+
HOME: isolatedHome,
|
|
167
|
+
GIT_CONFIG_NOSYSTEM: "1",
|
|
168
|
+
}),
|
|
169
|
+
})).rejects.toMatchObject({
|
|
170
|
+
stderr: expect.stringContaining("auto-detection is disabled"),
|
|
171
|
+
});
|
|
172
|
+
const count = await runGit(repo, ["rev-list", "--count", "HEAD"]);
|
|
173
|
+
expect(count.stdout.trim()).toBe("1");
|
|
174
|
+
}
|
|
175
|
+
finally {
|
|
176
|
+
await fs.rm(root, { recursive: true, force: true });
|
|
177
|
+
}
|
|
178
|
+
});
|
|
179
|
+
it("does not reuse stale managed HOME Git identity when current sources are missing", async () => {
|
|
180
|
+
const root = await fs.mkdtemp(path.join(os.tmpdir(), "rudder-git-identity-stale-managed-"));
|
|
181
|
+
try {
|
|
182
|
+
const repo = await createRepoWithoutStoredIdentity(root);
|
|
183
|
+
const isolatedHome = path.join(root, "agent-home");
|
|
184
|
+
await fs.mkdir(isolatedHome, { recursive: true });
|
|
185
|
+
await fs.writeFile(path.join(isolatedHome, ".gitconfig"), [
|
|
186
|
+
"[user]",
|
|
187
|
+
"\tname = Old Operator",
|
|
188
|
+
"\temail = old@example.com",
|
|
189
|
+
"\tuseConfigOnly = true",
|
|
190
|
+
].join("\n") + "\n", "utf8");
|
|
191
|
+
const result = await ensureGitIdentityFileConfig({
|
|
192
|
+
cwd: repo,
|
|
193
|
+
home: isolatedHome,
|
|
194
|
+
sourceEnv: baseGitTestEnv({
|
|
195
|
+
HOME: path.join(root, "empty-home"),
|
|
196
|
+
GIT_CONFIG_NOSYSTEM: "1",
|
|
197
|
+
}),
|
|
198
|
+
});
|
|
199
|
+
expect(result.identity).toBeNull();
|
|
200
|
+
const managedConfig = await fs.readFile(path.join(isolatedHome, ".gitconfig"), "utf8");
|
|
201
|
+
expect(managedConfig).toContain("useConfigOnly = true");
|
|
202
|
+
expect(managedConfig).not.toContain("old@example.com");
|
|
203
|
+
await expect(gitAuthorIdent(repo, {
|
|
204
|
+
HOME: isolatedHome,
|
|
205
|
+
GIT_CONFIG_NOSYSTEM: "1",
|
|
206
|
+
})).rejects.toMatchObject({
|
|
207
|
+
stderr: expect.not.stringContaining("old@example.com"),
|
|
208
|
+
});
|
|
209
|
+
}
|
|
210
|
+
finally {
|
|
211
|
+
await fs.rm(root, { recursive: true, force: true });
|
|
212
|
+
}
|
|
213
|
+
});
|
|
214
|
+
it("applies an isolated Git config and clears unsafe inherited identity env", async () => {
|
|
215
|
+
const env = {
|
|
216
|
+
GIT_AUTHOR_NAME: "Host User",
|
|
217
|
+
GIT_AUTHOR_EMAIL: "host@machine.local",
|
|
218
|
+
GIT_COMMITTER_NAME: "Host User",
|
|
219
|
+
GIT_COMMITTER_EMAIL: "host@machine.local",
|
|
220
|
+
};
|
|
221
|
+
applyGitIdentityPreparationEnv(env, {
|
|
222
|
+
identity: null,
|
|
223
|
+
configTarget: "/tmp/rudder-agent-home/.gitconfig",
|
|
224
|
+
configuredUseConfigOnly: true,
|
|
225
|
+
warnings: [],
|
|
226
|
+
});
|
|
227
|
+
expect(env).toMatchObject({
|
|
228
|
+
GIT_CONFIG_GLOBAL: "/tmp/rudder-agent-home/.gitconfig",
|
|
229
|
+
});
|
|
230
|
+
expect(env.GIT_AUTHOR_NAME).toBeUndefined();
|
|
231
|
+
expect(env.GIT_AUTHOR_EMAIL).toBeUndefined();
|
|
232
|
+
expect(env.GIT_COMMITTER_NAME).toBeUndefined();
|
|
233
|
+
expect(env.GIT_COMMITTER_EMAIL).toBeUndefined();
|
|
234
|
+
});
|
|
235
|
+
it("applies isolated Git config without injecting resolved identity env", async () => {
|
|
236
|
+
const env = {};
|
|
237
|
+
applyGitIdentityPreparationEnv(env, {
|
|
238
|
+
identity: {
|
|
239
|
+
name: "Rudder Operator",
|
|
240
|
+
email: "operator@example.com",
|
|
241
|
+
source: "global",
|
|
242
|
+
},
|
|
243
|
+
configTarget: "/tmp/rudder-agent-home/.gitconfig",
|
|
244
|
+
configuredUseConfigOnly: true,
|
|
245
|
+
warnings: [],
|
|
246
|
+
});
|
|
247
|
+
expect(env).toMatchObject({
|
|
248
|
+
GIT_CONFIG_GLOBAL: "/tmp/rudder-agent-home/.gitconfig",
|
|
249
|
+
});
|
|
250
|
+
expect(env.GIT_AUTHOR_NAME).toBeUndefined();
|
|
251
|
+
expect(env.GIT_AUTHOR_EMAIL).toBeUndefined();
|
|
252
|
+
expect(env.GIT_COMMITTER_NAME).toBeUndefined();
|
|
253
|
+
expect(env.GIT_COMMITTER_EMAIL).toBeUndefined();
|
|
254
|
+
});
|
|
255
|
+
it("preserves explicit safe inherited identity env", async () => {
|
|
256
|
+
const env = {
|
|
257
|
+
GIT_AUTHOR_NAME: "Rudder Operator",
|
|
258
|
+
GIT_AUTHOR_EMAIL: "operator@example.com",
|
|
259
|
+
GIT_COMMITTER_NAME: "Rudder Operator",
|
|
260
|
+
GIT_COMMITTER_EMAIL: "operator@example.com",
|
|
261
|
+
};
|
|
262
|
+
applyGitIdentityPreparationEnv(env, {
|
|
263
|
+
identity: {
|
|
264
|
+
name: "Rudder Operator",
|
|
265
|
+
email: "operator@example.com",
|
|
266
|
+
source: "environment",
|
|
267
|
+
},
|
|
268
|
+
configTarget: "/tmp/rudder-agent-home/.gitconfig",
|
|
269
|
+
configuredUseConfigOnly: true,
|
|
270
|
+
warnings: [],
|
|
271
|
+
});
|
|
272
|
+
expect(env).toMatchObject({
|
|
273
|
+
GIT_CONFIG_GLOBAL: "/tmp/rudder-agent-home/.gitconfig",
|
|
274
|
+
GIT_AUTHOR_NAME: "Rudder Operator",
|
|
275
|
+
GIT_AUTHOR_EMAIL: "operator@example.com",
|
|
276
|
+
GIT_COMMITTER_NAME: "Rudder Operator",
|
|
277
|
+
GIT_COMMITTER_EMAIL: "operator@example.com",
|
|
278
|
+
});
|
|
279
|
+
});
|
|
280
|
+
it("configures repository useConfigOnly without inventing a fallback identity", async () => {
|
|
281
|
+
const root = await fs.mkdtemp(path.join(os.tmpdir(), "rudder-git-identity-worktree-"));
|
|
282
|
+
try {
|
|
283
|
+
const repo = await createRepoWithoutStoredIdentity(root);
|
|
284
|
+
const result = await ensureGitRepositoryIdentityConfig({
|
|
285
|
+
cwd: repo,
|
|
286
|
+
sourceEnv: baseGitTestEnv({
|
|
287
|
+
HOME: path.join(root, "empty-home"),
|
|
288
|
+
GIT_CONFIG_NOSYSTEM: "1",
|
|
289
|
+
}),
|
|
290
|
+
});
|
|
291
|
+
expect(result.identity).toBeNull();
|
|
292
|
+
await expect(runGit(repo, ["config", "--local", "--get", "user.useConfigOnly"])).resolves.toMatchObject({
|
|
293
|
+
stdout: "true\n",
|
|
294
|
+
});
|
|
295
|
+
await expect(gitAuthorIdent(repo, {
|
|
296
|
+
HOME: path.join(root, "empty-home"),
|
|
297
|
+
GIT_CONFIG_NOSYSTEM: "1",
|
|
298
|
+
})).rejects.toMatchObject({
|
|
299
|
+
stderr: expect.not.stringContaining(".local"),
|
|
300
|
+
});
|
|
301
|
+
}
|
|
302
|
+
finally {
|
|
303
|
+
await fs.rm(root, { recursive: true, force: true });
|
|
304
|
+
}
|
|
305
|
+
});
|
|
306
|
+
});
|
|
307
|
+
//# sourceMappingURL=git-identity.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"git-identity.test.js","sourceRoot":"","sources":["../src/git-identity.test.ts"],"names":[],"mappings":"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"}
|
package/dist/server-utils.d.ts
CHANGED
|
@@ -78,6 +78,7 @@ export declare const DEFAULT_AGENT_PROMPT_TEMPLATE = "You are agent {{agent.id}}
|
|
|
78
78
|
export declare const ISSUE_ASSIGN_PROMPT_TEMPLATE = "You are agent {{agent.id}} ({{agent.name}}). You have been assigned to work on an issue.\n\n{{context.rudderWorkspace.orgResourcesPrompt}}\n\n## Task Context\n\n**Issue:** {{issue.title}}\n**ID:** {{issue.id}}\n**Status:** {{issue.status}}\n**Priority:** {{issue.priority}}\n\n**Description:**\n{{issue.description}}\n\n{{context.issueDocumentsPrompt}}\n\nYour task is to review this issue and begin working on it. Use the available tools to explore the codebase, understand the requirements, and implement a solution.";
|
|
79
79
|
export declare const COMMENT_MENTION_PROMPT_TEMPLATE = "You are agent {{agent.id}} ({{agent.name}}). You were mentioned in a comment and your attention is needed.\n\n{{context.rudderWorkspace.orgResourcesPrompt}}\n\n## Context\n\n**Issue:** {{issue.title}}\n**ID:** {{issue.id}}\n\n**Issue Description:**\n{{issue.description}}\n\n{{context.issueDocumentsPrompt}}\n\n**Comment:**\n{{comment.body}}\n\nPlease review the comment above and respond or take action as appropriate.";
|
|
80
80
|
export declare const ISSUE_COMMENTED_PROMPT_TEMPLATE = "You are agent {{agent.id}} ({{agent.name}}). There is a new comment on an issue you own.\n\n{{context.rudderWorkspace.orgResourcesPrompt}}\n\n## Context\n\n**Issue:** {{issue.title}}\n**ID:** {{issue.id}}\n**Status:** {{issue.status}}\n\n**Issue Description:**\n{{issue.description}}\n\n{{context.issueDocumentsPrompt}}\n\n**Latest Comment:**\n{{comment.body}}\n\nReview the new comment and continue the issue from the current state. Respond or take action as needed.";
|
|
81
|
+
export declare const ISSUE_CHANGES_REQUESTED_PROMPT_TEMPLATE = "You are agent {{agent.id}} ({{agent.name}}). A reviewer requested changes on an issue you own.\n\n{{context.rudderWorkspace.orgResourcesPrompt}}\n\n## Context\n\n**Issue:** {{issue.title}}\n**ID:** {{issue.id}}\n**Status:** {{issue.status}}\n\n**Issue Description:**\n{{issue.description}}\n\n{{context.issueDocumentsPrompt}}\n\n**Reviewer Comment:**\n{{comment.body}}\n\nReview the requested changes and continue the issue from the current state. Address the reviewer feedback before handing it back for review.";
|
|
81
82
|
export declare const ISSUE_RECOVERY_PROMPT_TEMPLATE = "You are agent {{agent.id}} ({{agent.name}}). This is a recovery run, not a fresh task.\n\n{{context.rudderWorkspace.orgResourcesPrompt}}\n\n## Recovery Context\n\n- Original Run ID: {{context.recovery.originalRunId}}\n- Failure Kind: {{context.recovery.failureKind}}\n- Failure Summary: {{context.recovery.failureSummary}}\n- Recovery Trigger: {{context.recovery.recoveryTrigger}}\n- Recovery Mode: {{context.recovery.recoveryMode}}\n\n## Current Issue Context\n\n- Issue: {{issue.title}}\n- ID: {{issue.id}}\n- Status: {{issue.status}}\n- Priority: {{issue.priority}}\n\n- Description:\n{{issue.description}}\n\n{{context.issueDocumentsPrompt}}\n\nBefore doing anything else, inspect what the previous run already completed and any side effects it may have caused. Continue the remaining work from the current state. Avoid blindly re-running the whole task.";
|
|
82
83
|
export declare const RECOVERY_PROMPT_TEMPLATE = "You are agent {{agent.id}} ({{agent.name}}). This is a recovery run, not a fresh task.\n\n{{context.rudderWorkspace.orgResourcesPrompt}}\n\n## Recovery Context\n\n- Original Run ID: {{context.recovery.originalRunId}}\n- Failure Kind: {{context.recovery.failureKind}}\n- Failure Summary: {{context.recovery.failureSummary}}\n- Recovery Trigger: {{context.recovery.recoveryTrigger}}\n- Recovery Mode: {{context.recovery.recoveryMode}}\n\nBefore doing anything else, inspect what the previous run already completed and any side effects it may have caused. Continue the remaining work from the current state. Avoid blindly re-running the whole task.";
|
|
83
84
|
export declare const ISSUE_PASSIVE_FOLLOWUP_PROMPT_TEMPLATE = "You are agent {{agent.id}} ({{agent.name}}). This is a passive issue follow-up, not a fresh assignment and not a failure recovery.\n\n{{context.rudderWorkspace.orgResourcesPrompt}}\n\n## Why You Were Woken\n\nThe previous run ended without sufficient issue close-out.\n\n- Origin Run ID: {{context.passiveFollowup.originRunId}}\n- Previous Run ID: {{context.passiveFollowup.previousRunId}}\n- Attempt: {{context.passiveFollowup.attempt}} / {{context.passiveFollowup.maxAttempts}}\nReason: {{context.passiveFollowup.reason}}\n\n## Current Issue Context\n\n- Issue: {{issue.title}}\n- ID: {{issue.id}}\n- Status: {{issue.status}}\n- Priority: {{issue.priority}}\n\n- Description:\n{{issue.description}}\n\n{{context.issueDocumentsPrompt}}\n\nBefore changing the issue, inspect the current issue state and any side effects from the previous run. Then do exactly one close-out action: add a progress comment, mark the issue done, block it with a reason, or hand it off explicitly with explanation.";
|
|
@@ -91,6 +92,9 @@ export declare const ISSUE_PASSIVE_FOLLOWUP_PROMPT_TEMPLATE = "You are agent {{a
|
|
|
91
92
|
* - comment.mention:
|
|
92
93
|
* "You were mentioned in a comment ..."
|
|
93
94
|
* Includes issue summary plus mention comment body so the agent can respond without extra fetches.
|
|
95
|
+
* - issue_changes_requested:
|
|
96
|
+
* "A reviewer requested changes on an issue you own ..."
|
|
97
|
+
* Includes issue summary plus reviewer comment body so the assignee can act on feedback immediately.
|
|
94
98
|
* - issue_commented:
|
|
95
99
|
* "There is a new comment on an issue you own ..."
|
|
96
100
|
* Includes issue summary plus the newest comment body so the assignee can continue immediately.
|
|
@@ -170,6 +174,17 @@ export declare function resolveRudderDesiredSkillNames(config: Record<string, un
|
|
|
170
174
|
runtimeName?: string | null;
|
|
171
175
|
}>): string[];
|
|
172
176
|
export declare function writeRudderSkillSyncPreference(config: Record<string, unknown>, desiredSkills: string[]): Record<string, unknown>;
|
|
177
|
+
export declare function resolveLocalOperatorHome(sourceEnv?: NodeJS.ProcessEnv): string;
|
|
178
|
+
export declare function applyLocalCliHomeEnv(targetEnv: Record<string, string>, sourceEnv?: NodeJS.ProcessEnv): void;
|
|
179
|
+
export declare function syncLocalCliCredentialHomeEntries(input: {
|
|
180
|
+
sourceHome?: string | null;
|
|
181
|
+
targetHome: string;
|
|
182
|
+
entries?: readonly string[];
|
|
183
|
+
onLog?: ((stream: "stdout" | "stderr", chunk: string) => Promise<void>) | null;
|
|
184
|
+
}): Promise<{
|
|
185
|
+
linked: string[];
|
|
186
|
+
skipped: string[];
|
|
187
|
+
}>;
|
|
173
188
|
export declare function ensureRudderSkillSymlink(source: string, target: string, linkSkill?: (source: string, target: string) => Promise<void>): Promise<"created" | "repaired" | "skipped">;
|
|
174
189
|
export declare function removeMaintainerOnlySkillSymlinks(skillsHome: string, allowedSkillNames: Iterable<string>): Promise<string[]>;
|
|
175
190
|
export declare function ensureCommandResolvable(command: string, cwd: string, env: NodeJS.ProcessEnv): Promise<void>;
|