Skip to content

Commit 44c7f5b

Browse files
authored
Merge pull request #1291 from dotnet/copilot/fix-nbgv-gitengine-issue
Auto-disable git engine for GitHub Copilot environments
2 parents c996125 + b8efd46 commit 44c7f5b

File tree

3 files changed

+124
-7
lines changed

3 files changed

+124
-7
lines changed

docfx/docs/shallow-cloning-agents.md

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,15 @@ A few caveats with this:
1515

1616
## GitHub Copilot Coding Agent
1717

18-
To configure the Copilot Coding Agent to set this environment variable, follow these steps to set environment variables for the `copilot` environment:
18+
**As of Nerdbank.GitVersioning v3.9, the git engine is automatically disabled when running under GitHub Copilot**, eliminating the need for manual configuration in most cases.
19+
20+
Specifically, when the `GITHUB_ACTOR` environment variable is set to `copilot-swe-agent[bot]` and the `NBGV_GitEngine` environment variable is **not** set, Nerdbank.GitVersioning automatically behaves as if `NBGV_GitEngine=Disabled`. This ensures that GitHub Copilot runs succeed without any additional setup.
21+
22+
If you need to override this behavior for any reason, you can explicitly set the `NBGV_GitEngine` environment variable to your desired value, which will take precedence over the automatic GitHub Copilot detection.
23+
24+
### Manual configuration (optional)
25+
26+
If automatic detection doesn't work for your scenario, you can manually configure the Copilot Coding Agent to set the environment variable by following these steps to set environment variables for the `copilot` environment:
1927

2028
1. Navigate to your GitHub repo's Settings tab.
2129
1. Select Environments from the list on the left.

src/NerdBank.GitVersioning/GitContext.cs

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,7 @@ public string RepoRelativeProjectDirectory
134134
protected string? DotGitPath { get; }
135135

136136
/// <summary>
137-
/// Gets the effective git engine to use, taking into account automatic disabling for Dependabot.
137+
/// Gets the effective git engine to use, taking into account automatic disabling for Dependabot and GitHub Copilot.
138138
/// This overload checks the NBGV_GitEngine environment variable and parses it automatically.
139139
/// </summary>
140140
/// <param name="defaultEngine">The engine to use if no environment variables dictate otherwise.</param>
@@ -144,11 +144,12 @@ public string RepoRelativeProjectDirectory
144144
/// Valid values are "LibGit2", "Managed", and "Disabled" (case-sensitive).
145145
/// Unrecognized values are treated as if the variable was not set, maintaining backward compatibility.
146146
/// Otherwise, if the DEPENDABOT environment variable is set to "true" (case-insensitive), returns <see cref="Engine.Disabled"/>.
147+
/// Otherwise, if the GITHUB_ACTOR environment variable is set to "copilot-swe-agent[bot]", returns <see cref="Engine.Disabled"/>.
147148
/// Otherwise, returns <paramref name="defaultEngine"/>.
148149
/// </remarks>
149150
public static Engine GetEffectiveGitEngine(Engine defaultEngine = Engine.ReadOnly)
150151
{
151-
// If NBGV_GitEngine is set, respect that setting regardless of Dependabot
152+
// If NBGV_GitEngine is set, respect that setting regardless of Dependabot or GitHub Copilot
152153
string? nbgvGitEngine = Environment.GetEnvironmentVariable("NBGV_GitEngine");
153154
if (!string.IsNullOrEmpty(nbgvGitEngine))
154155
{
@@ -177,6 +178,12 @@ public static Engine GetEffectiveGitEngine(Engine defaultEngine = Engine.ReadOnl
177178
return Engine.Disabled;
178179
}
179180

181+
// If we're in a GitHub Copilot environment and NBGV_GitEngine is not set, automatically disable the git engine
182+
if (IsGitHubCopilotEnvironment())
183+
{
184+
return Engine.Disabled;
185+
}
186+
180187
// Otherwise, use the default engine
181188
return defaultEngine;
182189
}
@@ -398,4 +405,14 @@ private static bool IsDependabotEnvironment()
398405
string? dependabotEnvVar = Environment.GetEnvironmentVariable("DEPENDABOT");
399406
return string.Equals(dependabotEnvVar, "true", StringComparison.OrdinalIgnoreCase);
400407
}
408+
409+
/// <summary>
410+
/// Determines whether the current environment is running under GitHub Copilot.
411+
/// </summary>
412+
/// <returns><see langword="true"/> if GITHUB_ACTOR environment variable is set to "copilot-swe-agent[bot]"; otherwise, <see langword="false"/>.</returns>
413+
private static bool IsGitHubCopilotEnvironment()
414+
{
415+
string? githubActorEnvVar = Environment.GetEnvironmentVariable("GITHUB_ACTOR");
416+
return string.Equals(githubActorEnvVar, "copilot-swe-agent[bot]", StringComparison.Ordinal);
417+
}
401418
}

test/Nerdbank.GitVersioning.Tests/GitContextTests.cs

Lines changed: 96 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -193,13 +193,15 @@ public void HeadCanonicalName_PackedHead()
193193
[Fact]
194194
public void GetEffectiveGitEngine_DefaultBehavior()
195195
{
196-
// Arrange: Clear both environment variables
196+
// Arrange: Clear all environment variables
197197
var originalDependabot = Environment.GetEnvironmentVariable("DEPENDABOT");
198198
var originalNbgvGitEngine = Environment.GetEnvironmentVariable("NBGV_GitEngine");
199+
var originalGitHubActor = Environment.GetEnvironmentVariable("GITHUB_ACTOR");
199200
try
200201
{
201202
Environment.SetEnvironmentVariable("DEPENDABOT", null);
202203
Environment.SetEnvironmentVariable("NBGV_GitEngine", null);
204+
Environment.SetEnvironmentVariable("GITHUB_ACTOR", null);
203205

204206
// Act & Assert: With no environment variables, should return default ReadOnly
205207
Assert.Equal(GitContext.Engine.ReadOnly, GitContext.GetEffectiveGitEngine());
@@ -209,6 +211,7 @@ public void GetEffectiveGitEngine_DefaultBehavior()
209211
{
210212
Environment.SetEnvironmentVariable("DEPENDABOT", originalDependabot);
211213
Environment.SetEnvironmentVariable("NBGV_GitEngine", originalNbgvGitEngine);
214+
Environment.SetEnvironmentVariable("GITHUB_ACTOR", originalGitHubActor);
212215
}
213216
}
214217

@@ -218,13 +221,15 @@ public void GetEffectiveGitEngine_DefaultBehavior()
218221
[InlineData("True")]
219222
public void GetEffectiveGitEngine_DependabotEnvironment_DisablesEngine(string dependabotValue)
220223
{
221-
// Arrange: Set DEPENDABOT=true and clear NBGV_GitEngine
224+
// Arrange: Set DEPENDABOT=true and clear NBGV_GitEngine and GITHUB_ACTOR
222225
var originalDependabot = Environment.GetEnvironmentVariable("DEPENDABOT");
223226
var originalNbgvGitEngine = Environment.GetEnvironmentVariable("NBGV_GitEngine");
227+
var originalGitHubActor = Environment.GetEnvironmentVariable("GITHUB_ACTOR");
224228
try
225229
{
226230
Environment.SetEnvironmentVariable("DEPENDABOT", dependabotValue);
227231
Environment.SetEnvironmentVariable("NBGV_GitEngine", null);
232+
Environment.SetEnvironmentVariable("GITHUB_ACTOR", null);
228233

229234
// Act & Assert: Should return Disabled regardless of requested engine
230235
Assert.Equal(GitContext.Engine.Disabled, GitContext.GetEffectiveGitEngine());
@@ -235,6 +240,7 @@ public void GetEffectiveGitEngine_DependabotEnvironment_DisablesEngine(string de
235240
{
236241
Environment.SetEnvironmentVariable("DEPENDABOT", originalDependabot);
237242
Environment.SetEnvironmentVariable("NBGV_GitEngine", originalNbgvGitEngine);
243+
Environment.SetEnvironmentVariable("GITHUB_ACTOR", originalGitHubActor);
238244
}
239245
}
240246

@@ -245,13 +251,15 @@ public void GetEffectiveGitEngine_DependabotEnvironment_DisablesEngine(string de
245251
[InlineData("")]
246252
public void GetEffectiveGitEngine_DependabotNotTrue_UsesDefault(string dependabotValue)
247253
{
248-
// Arrange: Set DEPENDABOT to non-true value and clear NBGV_GitEngine
254+
// Arrange: Set DEPENDABOT to non-true value and clear NBGV_GitEngine and GITHUB_ACTOR
249255
var originalDependabot = Environment.GetEnvironmentVariable("DEPENDABOT");
250256
var originalNbgvGitEngine = Environment.GetEnvironmentVariable("NBGV_GitEngine");
257+
var originalGitHubActor = Environment.GetEnvironmentVariable("GITHUB_ACTOR");
251258
try
252259
{
253260
Environment.SetEnvironmentVariable("DEPENDABOT", dependabotValue);
254261
Environment.SetEnvironmentVariable("NBGV_GitEngine", null);
262+
Environment.SetEnvironmentVariable("GITHUB_ACTOR", null);
255263

256264
// Act & Assert: Should use default behavior
257265
Assert.Equal(GitContext.Engine.ReadOnly, GitContext.GetEffectiveGitEngine());
@@ -261,6 +269,7 @@ public void GetEffectiveGitEngine_DependabotNotTrue_UsesDefault(string dependabo
261269
{
262270
Environment.SetEnvironmentVariable("DEPENDABOT", originalDependabot);
263271
Environment.SetEnvironmentVariable("NBGV_GitEngine", originalNbgvGitEngine);
272+
Environment.SetEnvironmentVariable("GITHUB_ACTOR", originalGitHubActor);
264273
}
265274
}
266275

@@ -270,13 +279,15 @@ public void GetEffectiveGitEngine_DependabotNotTrue_UsesDefault(string dependabo
270279
[InlineData("Disabled", GitContext.Engine.Disabled)]
271280
public void GetEffectiveGitEngine_NbgvGitEngineOverridesDependabot(string nbgvValue, GitContext.Engine expectedEngine)
272281
{
273-
// Arrange: Set both DEPENDABOT and NBGV_GitEngine
282+
// Arrange: Set both DEPENDABOT and NBGV_GitEngine, clear GITHUB_ACTOR
274283
var originalDependabot = Environment.GetEnvironmentVariable("DEPENDABOT");
275284
var originalNbgvGitEngine = Environment.GetEnvironmentVariable("NBGV_GitEngine");
285+
var originalGitHubActor = Environment.GetEnvironmentVariable("GITHUB_ACTOR");
276286
try
277287
{
278288
Environment.SetEnvironmentVariable("DEPENDABOT", "true");
279289
Environment.SetEnvironmentVariable("NBGV_GitEngine", nbgvValue);
290+
Environment.SetEnvironmentVariable("GITHUB_ACTOR", null);
280291

281292
// Act & Assert: NBGV_GitEngine should take precedence and be parsed correctly
282293
Assert.Equal(expectedEngine, GitContext.GetEffectiveGitEngine());
@@ -285,6 +296,87 @@ public void GetEffectiveGitEngine_NbgvGitEngineOverridesDependabot(string nbgvVa
285296
{
286297
Environment.SetEnvironmentVariable("DEPENDABOT", originalDependabot);
287298
Environment.SetEnvironmentVariable("NBGV_GitEngine", originalNbgvGitEngine);
299+
Environment.SetEnvironmentVariable("GITHUB_ACTOR", originalGitHubActor);
300+
}
301+
}
302+
303+
[Fact]
304+
public void GetEffectiveGitEngine_GitHubCopilotEnvironment_DisablesEngine()
305+
{
306+
// Arrange: Set GITHUB_ACTOR to copilot-swe-agent[bot] and clear NBGV_GitEngine and DEPENDABOT
307+
var originalGitHubActor = Environment.GetEnvironmentVariable("GITHUB_ACTOR");
308+
var originalNbgvGitEngine = Environment.GetEnvironmentVariable("NBGV_GitEngine");
309+
var originalDependabot = Environment.GetEnvironmentVariable("DEPENDABOT");
310+
try
311+
{
312+
Environment.SetEnvironmentVariable("GITHUB_ACTOR", "copilot-swe-agent[bot]");
313+
Environment.SetEnvironmentVariable("NBGV_GitEngine", null);
314+
Environment.SetEnvironmentVariable("DEPENDABOT", null);
315+
316+
// Act & Assert: Should return Disabled regardless of requested engine
317+
Assert.Equal(GitContext.Engine.Disabled, GitContext.GetEffectiveGitEngine());
318+
Assert.Equal(GitContext.Engine.Disabled, GitContext.GetEffectiveGitEngine(GitContext.Engine.ReadOnly));
319+
Assert.Equal(GitContext.Engine.Disabled, GitContext.GetEffectiveGitEngine(GitContext.Engine.ReadWrite));
320+
}
321+
finally
322+
{
323+
Environment.SetEnvironmentVariable("GITHUB_ACTOR", originalGitHubActor);
324+
Environment.SetEnvironmentVariable("NBGV_GitEngine", originalNbgvGitEngine);
325+
Environment.SetEnvironmentVariable("DEPENDABOT", originalDependabot);
326+
}
327+
}
328+
329+
[Theory]
330+
[InlineData("user")]
331+
[InlineData("dependabot[bot]")]
332+
[InlineData("copilot-swe-agent")]
333+
[InlineData("COPILOT-SWE-AGENT[BOT]")]
334+
[InlineData("")]
335+
public void GetEffectiveGitEngine_GitHubActorNotCopilot_UsesDefault(string gitHubActorValue)
336+
{
337+
// Arrange: Set GITHUB_ACTOR to non-copilot value and clear NBGV_GitEngine and DEPENDABOT
338+
var originalGitHubActor = Environment.GetEnvironmentVariable("GITHUB_ACTOR");
339+
var originalNbgvGitEngine = Environment.GetEnvironmentVariable("NBGV_GitEngine");
340+
var originalDependabot = Environment.GetEnvironmentVariable("DEPENDABOT");
341+
try
342+
{
343+
Environment.SetEnvironmentVariable("GITHUB_ACTOR", gitHubActorValue);
344+
Environment.SetEnvironmentVariable("NBGV_GitEngine", null);
345+
Environment.SetEnvironmentVariable("DEPENDABOT", null);
346+
347+
// Act & Assert: Should use default behavior
348+
Assert.Equal(GitContext.Engine.ReadOnly, GitContext.GetEffectiveGitEngine());
349+
Assert.Equal(GitContext.Engine.ReadWrite, GitContext.GetEffectiveGitEngine(GitContext.Engine.ReadWrite));
350+
}
351+
finally
352+
{
353+
Environment.SetEnvironmentVariable("GITHUB_ACTOR", originalGitHubActor);
354+
Environment.SetEnvironmentVariable("NBGV_GitEngine", originalNbgvGitEngine);
355+
Environment.SetEnvironmentVariable("DEPENDABOT", originalDependabot);
356+
}
357+
}
358+
359+
[Theory]
360+
[InlineData("LibGit2", GitContext.Engine.ReadWrite)]
361+
[InlineData("Managed", GitContext.Engine.ReadOnly)]
362+
[InlineData("Disabled", GitContext.Engine.Disabled)]
363+
public void GetEffectiveGitEngine_NbgvGitEngineOverridesGitHubCopilot(string nbgvValue, GitContext.Engine expectedEngine)
364+
{
365+
// Arrange: Set both GITHUB_ACTOR=copilot-swe-agent[bot] and NBGV_GitEngine
366+
var originalGitHubActor = Environment.GetEnvironmentVariable("GITHUB_ACTOR");
367+
var originalNbgvGitEngine = Environment.GetEnvironmentVariable("NBGV_GitEngine");
368+
try
369+
{
370+
Environment.SetEnvironmentVariable("GITHUB_ACTOR", "copilot-swe-agent[bot]");
371+
Environment.SetEnvironmentVariable("NBGV_GitEngine", nbgvValue);
372+
373+
// Act & Assert: NBGV_GitEngine should take precedence and be parsed correctly
374+
Assert.Equal(expectedEngine, GitContext.GetEffectiveGitEngine());
375+
}
376+
finally
377+
{
378+
Environment.SetEnvironmentVariable("GITHUB_ACTOR", originalGitHubActor);
379+
Environment.SetEnvironmentVariable("NBGV_GitEngine", originalNbgvGitEngine);
288380
}
289381
}
290382
}

0 commit comments

Comments
 (0)