@rudderhq/agent-runtime-utils 0.2.0-canary.9 → 0.2.1
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 +32 -0
- package/dist/git-identity.d.ts.map +1 -0
- package/dist/git-identity.js +207 -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 +327 -0
- package/dist/git-identity.test.js.map +1 -0
- package/dist/server-utils.d.ts +28 -0
- package/dist/server-utils.d.ts.map +1 -1
- package/dist/server-utils.js +362 -21
- package/dist/server-utils.js.map +1 -1
- package/dist/server-utils.test.js +337 -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,32 @@
|
|
|
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 applyGitCredentialHelperPolicyEnv(env: Record<string, string>, options?: {
|
|
23
|
+
helper?: string;
|
|
24
|
+
resetExistingHelpers?: boolean;
|
|
25
|
+
}): void;
|
|
26
|
+
export declare function ensureGitRepositoryIdentityConfig(input: {
|
|
27
|
+
cwd: string;
|
|
28
|
+
sourceEnv?: NodeJS.ProcessEnv;
|
|
29
|
+
onLog?: LogFn | null;
|
|
30
|
+
}): Promise<GitIdentityPreparationResult>;
|
|
31
|
+
export {};
|
|
32
|
+
//# 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;AAuID,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,CA2CxC;AAgBD,wBAAgB,iCAAiC,CAC/C,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAC3B,OAAO,GAAE;IACP,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,oBAAoB,CAAC,EAAE,OAAO,CAAC;CAC3B,GACL,IAAI,CAKN;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,207 @@
|
|
|
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 writeGitConfigSeed(configPath) {
|
|
105
|
+
await fs.mkdir(path.dirname(configPath), { recursive: true });
|
|
106
|
+
await fs.writeFile(configPath, "", "utf8");
|
|
107
|
+
}
|
|
108
|
+
async function writeFallbackGitConfigFile(configPath, identity) {
|
|
109
|
+
const lines = ["[user]", "\tuseConfigOnly = true"];
|
|
110
|
+
if (identity?.source === "global") {
|
|
111
|
+
lines.push(`\tname = ${identity.name}`, `\temail = ${identity.email}`);
|
|
112
|
+
}
|
|
113
|
+
await fs.mkdir(path.dirname(configPath), { recursive: true });
|
|
114
|
+
await fs.writeFile(configPath, `${lines.join("\n")}\n`, "utf8");
|
|
115
|
+
}
|
|
116
|
+
async function resolveBestGitIdentity(input) {
|
|
117
|
+
return (identityFromEnv(input.sourceEnv) ??
|
|
118
|
+
(await readIdentityFromGitConfig(["config", "--local"], "repository", {
|
|
119
|
+
cwd: input.cwd,
|
|
120
|
+
env: input.sourceEnv,
|
|
121
|
+
})) ??
|
|
122
|
+
(await readIdentityFromGitConfig(["config", "--global"], "global", {
|
|
123
|
+
cwd: input.cwd,
|
|
124
|
+
env: input.sourceEnv,
|
|
125
|
+
})));
|
|
126
|
+
}
|
|
127
|
+
export async function ensureGitIdentityFileConfig(input) {
|
|
128
|
+
const sourceEnv = normalizeEnv(input.sourceEnv);
|
|
129
|
+
const home = path.resolve(input.home);
|
|
130
|
+
const gitConfigPath = path.join(home, ".gitconfig");
|
|
131
|
+
await fs.mkdir(home, { recursive: true });
|
|
132
|
+
const configArgs = ["config", "--file", gitConfigPath];
|
|
133
|
+
const identity = await resolveBestGitIdentity({
|
|
134
|
+
cwd: input.cwd,
|
|
135
|
+
sourceEnv,
|
|
136
|
+
});
|
|
137
|
+
const warnings = [];
|
|
138
|
+
try {
|
|
139
|
+
await writeGitConfigSeed(gitConfigPath);
|
|
140
|
+
await setGitConfigValue(configArgs, "user.useConfigOnly", "true", { cwd: input.cwd, env: sourceEnv });
|
|
141
|
+
await unsetGitConfigValue(configArgs, "user.name", { cwd: input.cwd, env: sourceEnv });
|
|
142
|
+
await unsetGitConfigValue(configArgs, "user.email", { cwd: input.cwd, env: sourceEnv });
|
|
143
|
+
if (identity?.source === "global") {
|
|
144
|
+
await setGitConfigValue(configArgs, "user.name", identity.name, { cwd: input.cwd, env: sourceEnv });
|
|
145
|
+
await setGitConfigValue(configArgs, "user.email", identity.email, { cwd: input.cwd, env: sourceEnv });
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
catch (error) {
|
|
149
|
+
warnings.push(error instanceof Error ? error.message : String(error));
|
|
150
|
+
await writeFallbackGitConfigFile(gitConfigPath, identity);
|
|
151
|
+
}
|
|
152
|
+
if (input.onLog) {
|
|
153
|
+
const detail = identity
|
|
154
|
+
? `using ${identity.source} Git identity ${identity.name} <${identity.email}>`
|
|
155
|
+
: "without a usable Git identity; commits will fail until user.name and user.email are configured";
|
|
156
|
+
await input.onLog("stdout", `[rudder] Prepared isolated Git config at ${gitConfigPath} with user.useConfigOnly=true (${detail}).\n`);
|
|
157
|
+
}
|
|
158
|
+
return {
|
|
159
|
+
identity,
|
|
160
|
+
configTarget: gitConfigPath,
|
|
161
|
+
configuredUseConfigOnly: true,
|
|
162
|
+
warnings,
|
|
163
|
+
};
|
|
164
|
+
}
|
|
165
|
+
function readGitConfigEnvCount(env) {
|
|
166
|
+
const raw = nonEmpty(env.GIT_CONFIG_COUNT);
|
|
167
|
+
if (!raw)
|
|
168
|
+
return 0;
|
|
169
|
+
const parsed = Number.parseInt(raw, 10);
|
|
170
|
+
return Number.isSafeInteger(parsed) && parsed >= 0 ? parsed : 0;
|
|
171
|
+
}
|
|
172
|
+
function appendGitConfigEnvValue(env, key, value) {
|
|
173
|
+
const index = readGitConfigEnvCount(env);
|
|
174
|
+
env[`GIT_CONFIG_KEY_${index}`] = key;
|
|
175
|
+
env[`GIT_CONFIG_VALUE_${index}`] = value;
|
|
176
|
+
env.GIT_CONFIG_COUNT = String(index + 1);
|
|
177
|
+
}
|
|
178
|
+
export function applyGitCredentialHelperPolicyEnv(env, options = {}) {
|
|
179
|
+
if (options.resetExistingHelpers ?? true) {
|
|
180
|
+
appendGitConfigEnvValue(env, "credential.helper", "");
|
|
181
|
+
}
|
|
182
|
+
appendGitConfigEnvValue(env, "credential.helper", options.helper ?? "!gh auth git-credential");
|
|
183
|
+
}
|
|
184
|
+
export async function ensureGitRepositoryIdentityConfig(input) {
|
|
185
|
+
const sourceEnv = normalizeEnv(input.sourceEnv);
|
|
186
|
+
const cwd = path.resolve(input.cwd);
|
|
187
|
+
const configArgs = ["config", "--local"];
|
|
188
|
+
const identity = await resolveBestGitIdentity({
|
|
189
|
+
cwd,
|
|
190
|
+
sourceEnv,
|
|
191
|
+
});
|
|
192
|
+
const warnings = [];
|
|
193
|
+
await setGitConfigValue(configArgs, "user.useConfigOnly", "true", { cwd, env: sourceEnv });
|
|
194
|
+
if (input.onLog) {
|
|
195
|
+
const detail = identity
|
|
196
|
+
? `using ${identity.source} Git identity ${identity.name} <${identity.email}>`
|
|
197
|
+
: "without a usable Git identity; commits will fail until user.name and user.email are configured";
|
|
198
|
+
await input.onLog("stdout", `[rudder] Prepared repository Git config in ${cwd} with user.useConfigOnly=true (${detail}).\n`);
|
|
199
|
+
}
|
|
200
|
+
return {
|
|
201
|
+
identity,
|
|
202
|
+
configTarget: cwd,
|
|
203
|
+
configuredUseConfigOnly: true,
|
|
204
|
+
warnings,
|
|
205
|
+
};
|
|
206
|
+
}
|
|
207
|
+
//# 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,327 @@
|
|
|
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 { applyGitCredentialHelperPolicyEnv, 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("copies only safe host global Git identity into the isolated config", 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-all",
|
|
123
|
+
"credential.helper",
|
|
124
|
+
], {
|
|
125
|
+
HOME: isolatedHome,
|
|
126
|
+
GIT_CONFIG_GLOBAL: path.join(isolatedHome, ".gitconfig"),
|
|
127
|
+
GIT_CONFIG_NOSYSTEM: "1",
|
|
128
|
+
})).rejects.toMatchObject({ stdout: "" });
|
|
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
|
+
const managedConfig = await fs.readFile(path.join(isolatedHome, ".gitconfig"), "utf8");
|
|
139
|
+
expect(managedConfig).not.toContain("[include]");
|
|
140
|
+
expect(managedConfig).not.toContain("helper = store");
|
|
141
|
+
}
|
|
142
|
+
finally {
|
|
143
|
+
await fs.rm(root, { recursive: true, force: true });
|
|
144
|
+
}
|
|
145
|
+
});
|
|
146
|
+
it("injects a narrow gh-backed Git credential helper policy through env config", async () => {
|
|
147
|
+
const env = {
|
|
148
|
+
GIT_CONFIG_COUNT: "1",
|
|
149
|
+
GIT_CONFIG_KEY_0: "protocol.version",
|
|
150
|
+
GIT_CONFIG_VALUE_0: "2",
|
|
151
|
+
};
|
|
152
|
+
applyGitCredentialHelperPolicyEnv(env);
|
|
153
|
+
expect(env).toMatchObject({
|
|
154
|
+
GIT_CONFIG_COUNT: "3",
|
|
155
|
+
GIT_CONFIG_KEY_0: "protocol.version",
|
|
156
|
+
GIT_CONFIG_VALUE_0: "2",
|
|
157
|
+
GIT_CONFIG_KEY_1: "credential.helper",
|
|
158
|
+
GIT_CONFIG_VALUE_1: "",
|
|
159
|
+
GIT_CONFIG_KEY_2: "credential.helper",
|
|
160
|
+
GIT_CONFIG_VALUE_2: "!gh auth git-credential",
|
|
161
|
+
});
|
|
162
|
+
});
|
|
163
|
+
it("prevents Git fallback commits when isolated HOME has no usable identity", async () => {
|
|
164
|
+
const root = await fs.mkdtemp(path.join(os.tmpdir(), "rudder-git-identity-missing-"));
|
|
165
|
+
try {
|
|
166
|
+
const repo = await createRepoWithoutStoredIdentity(root);
|
|
167
|
+
const isolatedHome = path.join(root, "agent-home");
|
|
168
|
+
const result = await ensureGitIdentityFileConfig({
|
|
169
|
+
cwd: repo,
|
|
170
|
+
home: isolatedHome,
|
|
171
|
+
sourceEnv: baseGitTestEnv({
|
|
172
|
+
HOME: path.join(root, "empty-home"),
|
|
173
|
+
GIT_CONFIG_NOSYSTEM: "1",
|
|
174
|
+
}),
|
|
175
|
+
});
|
|
176
|
+
expect(result.identity).toBeNull();
|
|
177
|
+
await expect(gitAuthorIdent(repo, {
|
|
178
|
+
HOME: isolatedHome,
|
|
179
|
+
GIT_CONFIG_NOSYSTEM: "1",
|
|
180
|
+
})).rejects.toMatchObject({
|
|
181
|
+
stderr: expect.not.stringContaining(".local"),
|
|
182
|
+
});
|
|
183
|
+
await expect(execFileAsync("git", ["commit", "--allow-empty", "-m", "agent commit"], {
|
|
184
|
+
cwd: repo,
|
|
185
|
+
env: baseGitTestEnv({
|
|
186
|
+
HOME: isolatedHome,
|
|
187
|
+
GIT_CONFIG_NOSYSTEM: "1",
|
|
188
|
+
}),
|
|
189
|
+
})).rejects.toMatchObject({
|
|
190
|
+
stderr: expect.stringContaining("auto-detection is disabled"),
|
|
191
|
+
});
|
|
192
|
+
const count = await runGit(repo, ["rev-list", "--count", "HEAD"]);
|
|
193
|
+
expect(count.stdout.trim()).toBe("1");
|
|
194
|
+
}
|
|
195
|
+
finally {
|
|
196
|
+
await fs.rm(root, { recursive: true, force: true });
|
|
197
|
+
}
|
|
198
|
+
});
|
|
199
|
+
it("does not reuse stale managed HOME Git identity when current sources are missing", async () => {
|
|
200
|
+
const root = await fs.mkdtemp(path.join(os.tmpdir(), "rudder-git-identity-stale-managed-"));
|
|
201
|
+
try {
|
|
202
|
+
const repo = await createRepoWithoutStoredIdentity(root);
|
|
203
|
+
const isolatedHome = path.join(root, "agent-home");
|
|
204
|
+
await fs.mkdir(isolatedHome, { recursive: true });
|
|
205
|
+
await fs.writeFile(path.join(isolatedHome, ".gitconfig"), [
|
|
206
|
+
"[user]",
|
|
207
|
+
"\tname = Old Operator",
|
|
208
|
+
"\temail = old@example.com",
|
|
209
|
+
"\tuseConfigOnly = true",
|
|
210
|
+
].join("\n") + "\n", "utf8");
|
|
211
|
+
const result = await ensureGitIdentityFileConfig({
|
|
212
|
+
cwd: repo,
|
|
213
|
+
home: isolatedHome,
|
|
214
|
+
sourceEnv: baseGitTestEnv({
|
|
215
|
+
HOME: path.join(root, "empty-home"),
|
|
216
|
+
GIT_CONFIG_NOSYSTEM: "1",
|
|
217
|
+
}),
|
|
218
|
+
});
|
|
219
|
+
expect(result.identity).toBeNull();
|
|
220
|
+
const managedConfig = await fs.readFile(path.join(isolatedHome, ".gitconfig"), "utf8");
|
|
221
|
+
expect(managedConfig).toContain("useConfigOnly = true");
|
|
222
|
+
expect(managedConfig).not.toContain("old@example.com");
|
|
223
|
+
await expect(gitAuthorIdent(repo, {
|
|
224
|
+
HOME: isolatedHome,
|
|
225
|
+
GIT_CONFIG_NOSYSTEM: "1",
|
|
226
|
+
})).rejects.toMatchObject({
|
|
227
|
+
stderr: expect.not.stringContaining("old@example.com"),
|
|
228
|
+
});
|
|
229
|
+
}
|
|
230
|
+
finally {
|
|
231
|
+
await fs.rm(root, { recursive: true, force: true });
|
|
232
|
+
}
|
|
233
|
+
});
|
|
234
|
+
it("applies an isolated Git config and clears unsafe inherited identity env", async () => {
|
|
235
|
+
const env = {
|
|
236
|
+
GIT_AUTHOR_NAME: "Host User",
|
|
237
|
+
GIT_AUTHOR_EMAIL: "host@machine.local",
|
|
238
|
+
GIT_COMMITTER_NAME: "Host User",
|
|
239
|
+
GIT_COMMITTER_EMAIL: "host@machine.local",
|
|
240
|
+
};
|
|
241
|
+
applyGitIdentityPreparationEnv(env, {
|
|
242
|
+
identity: null,
|
|
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("applies isolated Git config without injecting resolved identity env", async () => {
|
|
256
|
+
const env = {};
|
|
257
|
+
applyGitIdentityPreparationEnv(env, {
|
|
258
|
+
identity: {
|
|
259
|
+
name: "Rudder Operator",
|
|
260
|
+
email: "operator@example.com",
|
|
261
|
+
source: "global",
|
|
262
|
+
},
|
|
263
|
+
configTarget: "/tmp/rudder-agent-home/.gitconfig",
|
|
264
|
+
configuredUseConfigOnly: true,
|
|
265
|
+
warnings: [],
|
|
266
|
+
});
|
|
267
|
+
expect(env).toMatchObject({
|
|
268
|
+
GIT_CONFIG_GLOBAL: "/tmp/rudder-agent-home/.gitconfig",
|
|
269
|
+
});
|
|
270
|
+
expect(env.GIT_AUTHOR_NAME).toBeUndefined();
|
|
271
|
+
expect(env.GIT_AUTHOR_EMAIL).toBeUndefined();
|
|
272
|
+
expect(env.GIT_COMMITTER_NAME).toBeUndefined();
|
|
273
|
+
expect(env.GIT_COMMITTER_EMAIL).toBeUndefined();
|
|
274
|
+
});
|
|
275
|
+
it("preserves explicit safe inherited identity env", async () => {
|
|
276
|
+
const env = {
|
|
277
|
+
GIT_AUTHOR_NAME: "Rudder Operator",
|
|
278
|
+
GIT_AUTHOR_EMAIL: "operator@example.com",
|
|
279
|
+
GIT_COMMITTER_NAME: "Rudder Operator",
|
|
280
|
+
GIT_COMMITTER_EMAIL: "operator@example.com",
|
|
281
|
+
};
|
|
282
|
+
applyGitIdentityPreparationEnv(env, {
|
|
283
|
+
identity: {
|
|
284
|
+
name: "Rudder Operator",
|
|
285
|
+
email: "operator@example.com",
|
|
286
|
+
source: "environment",
|
|
287
|
+
},
|
|
288
|
+
configTarget: "/tmp/rudder-agent-home/.gitconfig",
|
|
289
|
+
configuredUseConfigOnly: true,
|
|
290
|
+
warnings: [],
|
|
291
|
+
});
|
|
292
|
+
expect(env).toMatchObject({
|
|
293
|
+
GIT_CONFIG_GLOBAL: "/tmp/rudder-agent-home/.gitconfig",
|
|
294
|
+
GIT_AUTHOR_NAME: "Rudder Operator",
|
|
295
|
+
GIT_AUTHOR_EMAIL: "operator@example.com",
|
|
296
|
+
GIT_COMMITTER_NAME: "Rudder Operator",
|
|
297
|
+
GIT_COMMITTER_EMAIL: "operator@example.com",
|
|
298
|
+
});
|
|
299
|
+
});
|
|
300
|
+
it("configures repository useConfigOnly without inventing a fallback identity", async () => {
|
|
301
|
+
const root = await fs.mkdtemp(path.join(os.tmpdir(), "rudder-git-identity-worktree-"));
|
|
302
|
+
try {
|
|
303
|
+
const repo = await createRepoWithoutStoredIdentity(root);
|
|
304
|
+
const result = await ensureGitRepositoryIdentityConfig({
|
|
305
|
+
cwd: repo,
|
|
306
|
+
sourceEnv: baseGitTestEnv({
|
|
307
|
+
HOME: path.join(root, "empty-home"),
|
|
308
|
+
GIT_CONFIG_NOSYSTEM: "1",
|
|
309
|
+
}),
|
|
310
|
+
});
|
|
311
|
+
expect(result.identity).toBeNull();
|
|
312
|
+
await expect(runGit(repo, ["config", "--local", "--get", "user.useConfigOnly"])).resolves.toMatchObject({
|
|
313
|
+
stdout: "true\n",
|
|
314
|
+
});
|
|
315
|
+
await expect(gitAuthorIdent(repo, {
|
|
316
|
+
HOME: path.join(root, "empty-home"),
|
|
317
|
+
GIT_CONFIG_NOSYSTEM: "1",
|
|
318
|
+
})).rejects.toMatchObject({
|
|
319
|
+
stderr: expect.not.stringContaining(".local"),
|
|
320
|
+
});
|
|
321
|
+
}
|
|
322
|
+
finally {
|
|
323
|
+
await fs.rm(root, { recursive: true, force: true });
|
|
324
|
+
}
|
|
325
|
+
});
|
|
326
|
+
});
|
|
327
|
+
//# 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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"}
|