Skip to content

Commit 76b29db

Browse files
committed
DEBUG: optionally avoid all actions
When debugging locally, say, a `/submit` command, it is incredibly not okay if emails are sent or if comments are added to the respective PR on GitHub. Setting the `GITGITGADGET_DEBUG` variable will now prevent all such things from happening. To avoid `git push` invocations accidentally succeeding because of, say, VS Code's `GIT_ASKPASS` support, let's also unset the `VSCODE_*` environment variables and override any credential helper when debugging locally. Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
1 parent 6fd8d01 commit 76b29db

File tree

6 files changed

+84
-0
lines changed

6 files changed

+84
-0
lines changed

.vscode/settings.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,8 @@
9898
"CIsmtphost",
9999
"CIsmtppass",
100100
"CIsmtpopts",
101+
"GIT_ASKPASS",
102+
"GIT_CONFIG_NOSYSTEM",
101103
"GITGIT_(|DIR|GIT_REMOTE|MAIL_REMOTE|MAIL_EPOCH)",
102104
"mailrepo",
103105
"parsePRURLInput",

lib/ci-helper.ts

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,23 @@ export class CIHelper {
8080
}
8181

8282
public constructor(workDir: string = "pr-repo.git", config?: IConfig, skipUpdate?: boolean, gggConfigDir = ".") {
83+
if (process.env.GITGITGADGET_DRY_RUN) {
84+
// Avoid letting VS Code's `GIT_ASKPASS` any push succeed
85+
Object.keys(process.env).forEach((key) => {
86+
if (key.startsWith("GIT_") || key.startsWith("VSCODE_")) {
87+
console.warn(`Deleting environment variable ${key}`);
88+
delete process.env[key];
89+
}
90+
});
91+
process.env.GIT_CONFIG_NOSYSTEM = "1";
92+
process.env.GIT_CONFIG_GLOBAL = "does-not-exist";
93+
94+
// Disable any credential helper
95+
process.env.GIT_CONFIG_PARAMETERS = [process.env.GIT_CONFIG_PARAMETERS, "'credential.helper='"]
96+
.filter((e) => e)
97+
.join(" ");
98+
}
99+
83100
this.config = config || CIHelper.getConfigAsGitHubActionInput();
84101
this.gggConfigDir = gggConfigDir;
85102
this.workDir = workDir;
@@ -132,6 +149,15 @@ export class CIHelper {
132149
// Ignore, for now
133150
}
134151

152+
if (!this.smtpOptions && process.env.GITGITGADGET_DRY_RUN) {
153+
this.smtpOptions = {
154+
smtpUser: "user@example.com",
155+
smtpHost: "smtp.example.com",
156+
smtpPass: "password",
157+
};
158+
console.log("Using debug SMTP options:", this.smtpOptions);
159+
}
160+
135161
if (setupOptions?.createOrUpdateCheckRun) {
136162
if (setupOptions?.createGitNotes) {
137163
throw new Error(`Cannot use createOrUpdateCheckRun and createGitNotes at the same time`);
@@ -147,12 +173,17 @@ export class CIHelper {
147173
.map((p) => path.normalize(`${p}${path.sep}${gitExecutable}`))
148174
// eslint-disable-next-line security/detect-non-literal-fs-filename
149175
.filter((p) => p.endsWith(`${path.sep}${stripSuffix}`) && fs.existsSync(p))) {
176+
if (process.env.GITGITGADGET_DRY_RUN) console.error(`Found Git at ${gitPath}`);
150177
process.env.LOCAL_GIT_DIRECTORY = gitPath.substring(0, gitPath.length - stripSuffix.length);
178+
if (process.env.GITGITGADGET_DRY_RUN) {
179+
console.error(`Setting LOCAL_GIT_DIRECTORY to ${process.env.LOCAL_GIT_DIRECTORY}`);
180+
}
151181
// need to override GIT_EXEC_PATH, so that Dugite can find the `git-remote-https` executable,
152182
// see https://github.com/desktop/dugite/blob/v2.7.1/lib/git-environment.ts#L44-L64
153183
// Also: We cannot use `await git(["--exec-path"]);` because that would use Dugite, which would
154184
// override `GIT_EXEC_PATH` and then `git --exec-path` would report _that_...
155185
process.env.GIT_EXEC_PATH = spawnSync(gitPath, ["--exec-path"]).stdout.toString("utf-8").trimEnd();
186+
if (process.env.GITGITGADGET_DRY_RUN) console.error(`GIT_EXEC_PATH: '${process.env.GIT_EXEC_PATH}'`);
156187
break;
157188
}
158189

lib/git-notes.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,10 @@ type TemporaryNoteIndex = {
2020

2121
export class GitNotes {
2222
public async push(url: string, token: string | undefined = undefined): Promise<void> {
23+
if (process.env.GITGITGADGET_DRY_RUN) {
24+
console.log(`Would push '${this.notesRef}' to ${url}`);
25+
return; // debug mode does not actually do anything
26+
}
2327
const auth = !token
2428
? []
2529
: [

lib/github-glue.ts

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,10 @@ export class GitHubGlue {
9090
const [, short, completedAt] = match;
9191
const url = `https://github.com/${baseOwner}/${this.repo}/commit/${gitGitCommit}`;
9292

93+
if (process.env.GITGITGADGET_DRY_RUN) {
94+
console.log(`Would annotate ${originalCommit}:\n${gitGitCommit} as ${short} at ${completedAt}\n${url}`);
95+
return -1; // debug mode does not actually do anything
96+
}
9397
await this.ensureAuthenticated(repositoryOwner);
9498
const checks = await this.client.rest.checks.create({
9599
completed_at: completedAt,
@@ -188,6 +192,10 @@ export class GitHubGlue {
188192
* @returns the comment ID and the URL to the comment
189193
*/
190194
public async addPRComment(pullRequest: pullRequestKeyInfo, comment: string): Promise<{ id: number; url: string }> {
195+
if (process.env.GITGITGADGET_DRY_RUN) {
196+
console.log(`Would add comment to ${JSON.stringify(pullRequest)}:\n${comment}`);
197+
return { id: -1, url: "" }; // debug mode does not actually do anything
198+
}
191199
const prKey = getPullRequestKey(pullRequest);
192200

193201
await this.ensureAuthenticated(prKey.owner);
@@ -219,6 +227,10 @@ export class GitHubGlue {
219227
comment: string,
220228
line?: number,
221229
): Promise<{ id: number; url: string }> {
230+
if (process.env.GITGITGADGET_DRY_RUN) {
231+
console.log(`Would add comment to ${JSON.stringify(pullRequest)}, commit ${commit}:\n${comment}`);
232+
return { id: -1, url: "" }; // debug mode does not actually do anything
233+
}
222234
const prKey = getPullRequestKey(pullRequest);
223235

224236
await this.ensureAuthenticated(prKey.owner);
@@ -252,6 +264,10 @@ export class GitHubGlue {
252264
id: number,
253265
comment: string,
254266
): Promise<{ id: number; url: string }> {
267+
if (process.env.GITGITGADGET_DRY_RUN) {
268+
console.log(`Would add reply to ${JSON.stringify(pullRequest)}, id ${id}:\n${comment}`);
269+
return { id: -1, url: "" }; // debug mode does not actually do anything
270+
}
255271
const prKey = getPullRequestKey(pullRequest);
256272

257273
await this.ensureAuthenticated(prKey.owner);
@@ -276,6 +292,10 @@ export class GitHubGlue {
276292
* @returns the PR number
277293
*/
278294
public async updatePR(prKey: pullRequestKey, body?: string, title?: string): Promise<number> {
295+
if (process.env.GITGITGADGET_DRY_RUN) {
296+
console.log(`Would add update ${JSON.stringify(prKey)}:\ntitle: ${title}\nbody: ${body}`);
297+
return prKey.pull_number; // debug mode does not actually do anything
298+
}
279299
await this.ensureAuthenticated(prKey.owner);
280300

281301
const result = await this.client.rest.pulls.update({
@@ -288,6 +308,10 @@ export class GitHubGlue {
288308
}
289309

290310
public async addPRLabels(pullRequest: pullRequestKeyInfo, labels: string[]): Promise<string[]> {
311+
if (process.env.GITGITGADGET_DRY_RUN) {
312+
console.log(`Would add labels to ${JSON.stringify(pullRequest)}:\n${labels.join(", ")}`);
313+
return labels; // debug mode does not actually do anything
314+
}
291315
const prKey = getPullRequestKey(pullRequest);
292316

293317
await this.ensureAuthenticated(prKey.owner);
@@ -301,6 +325,10 @@ export class GitHubGlue {
301325
}
302326

303327
public async closePR(pullRequest: pullRequestKeyInfo, viaMergeCommit: string): Promise<number> {
328+
if (process.env.GITGITGADGET_DRY_RUN) {
329+
console.log(`Would add close ${JSON.stringify(pullRequest)}:\n${viaMergeCommit}`);
330+
return -1; // debug mode does not actually do anything
331+
}
304332
const prKey = getPullRequestKey(pullRequest);
305333

306334
await this.ensureAuthenticated(prKey.owner);
@@ -465,6 +493,16 @@ export class GitHubGlue {
465493
* @param login the GitHub login
466494
*/
467495
public async getGitHubUserInfo(login: string): Promise<IGitHubUser> {
496+
if (process.env.GITGITGADGET_DRY_RUN) {
497+
if (login === "dscho")
498+
return {
499+
email: "dscho@me.com",
500+
login,
501+
name: "Ohai!",
502+
type: "user",
503+
};
504+
throw new Error(`Cannot mock getByUsername: ${login}`);
505+
}
468506
// required to get email
469507
await this.ensureAuthenticated(this.authenticated || this.owner);
470508

lib/patch-series.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,11 @@ export class PatchSeries {
152152
cc.push("Johannes Sixt <j6t@kdbg.org>");
153153
}
154154

155+
if (process.env.GITGITGADGET_DRY_RUN) {
156+
console.log(`Forcing Patch Series to use dry-run mode`);
157+
options = { ...(options || {}), dryRun: true }; // debug mode does not actually do anything
158+
}
159+
155160
return new PatchSeries(
156161
config,
157162
notes,

lib/send-mail.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,10 @@ export function parseMBoxMessageIDAndReferences(parsed: IParsedMBox): { messageI
157157
}
158158

159159
export async function sendMail(mail: IParsedMBox, smtpOptions: ISMTPOptions): Promise<string> {
160+
if (process.env.GITGITGADGET_DRY_RUN) {
161+
console.log(`Would send the email:\n${JSON.stringify(mail, null, 2)}`);
162+
return "<Message-ID>"; // debug mode does not actually do anything
163+
}
160164
const transportOpts: SMTPTransport.Options = {
161165
auth: {
162166
pass: smtpOptions.smtpPass,

0 commit comments

Comments
 (0)