Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 9 additions & 1 deletion docfx/docs/shallow-cloning-agents.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,15 @@ A few caveats with this:

## GitHub Copilot Coding Agent

To configure the Copilot Coding Agent to set this environment variable, follow these steps to set environment variables for the `copilot` environment:
**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.

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.

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.

### Manual configuration (optional)

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:

1. Navigate to your GitHub repo's Settings tab.
1. Select Environments from the list on the left.
Expand Down
21 changes: 19 additions & 2 deletions src/NerdBank.GitVersioning/GitContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ public string RepoRelativeProjectDirectory
protected string? DotGitPath { get; }

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

// If we're in a GitHub Copilot environment and NBGV_GitEngine is not set, automatically disable the git engine
if (IsGitHubCopilotEnvironment())
{
return Engine.Disabled;
}

// Otherwise, use the default engine
return defaultEngine;
}
Expand Down Expand Up @@ -398,4 +405,14 @@ private static bool IsDependabotEnvironment()
string? dependabotEnvVar = Environment.GetEnvironmentVariable("DEPENDABOT");
return string.Equals(dependabotEnvVar, "true", StringComparison.OrdinalIgnoreCase);
}

/// <summary>
/// Determines whether the current environment is running under GitHub Copilot.
/// </summary>
/// <returns><see langword="true"/> if GITHUB_ACTOR environment variable is set to "copilot-swe-agent[bot]"; otherwise, <see langword="false"/>.</returns>
private static bool IsGitHubCopilotEnvironment()
{
string? githubActorEnvVar = Environment.GetEnvironmentVariable("GITHUB_ACTOR");
return string.Equals(githubActorEnvVar, "copilot-swe-agent[bot]", StringComparison.Ordinal);
}
}
100 changes: 96 additions & 4 deletions test/Nerdbank.GitVersioning.Tests/GitContextTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -193,13 +193,15 @@ public void HeadCanonicalName_PackedHead()
[Fact]
public void GetEffectiveGitEngine_DefaultBehavior()
{
// Arrange: Clear both environment variables
// Arrange: Clear all environment variables
var originalDependabot = Environment.GetEnvironmentVariable("DEPENDABOT");
var originalNbgvGitEngine = Environment.GetEnvironmentVariable("NBGV_GitEngine");
var originalGitHubActor = Environment.GetEnvironmentVariable("GITHUB_ACTOR");
try
{
Environment.SetEnvironmentVariable("DEPENDABOT", null);
Environment.SetEnvironmentVariable("NBGV_GitEngine", null);
Environment.SetEnvironmentVariable("GITHUB_ACTOR", null);

// Act & Assert: With no environment variables, should return default ReadOnly
Assert.Equal(GitContext.Engine.ReadOnly, GitContext.GetEffectiveGitEngine());
Expand All @@ -209,6 +211,7 @@ public void GetEffectiveGitEngine_DefaultBehavior()
{
Environment.SetEnvironmentVariable("DEPENDABOT", originalDependabot);
Environment.SetEnvironmentVariable("NBGV_GitEngine", originalNbgvGitEngine);
Environment.SetEnvironmentVariable("GITHUB_ACTOR", originalGitHubActor);
}
}

Expand All @@ -218,13 +221,15 @@ public void GetEffectiveGitEngine_DefaultBehavior()
[InlineData("True")]
public void GetEffectiveGitEngine_DependabotEnvironment_DisablesEngine(string dependabotValue)
{
// Arrange: Set DEPENDABOT=true and clear NBGV_GitEngine
// Arrange: Set DEPENDABOT=true and clear NBGV_GitEngine and GITHUB_ACTOR
var originalDependabot = Environment.GetEnvironmentVariable("DEPENDABOT");
var originalNbgvGitEngine = Environment.GetEnvironmentVariable("NBGV_GitEngine");
var originalGitHubActor = Environment.GetEnvironmentVariable("GITHUB_ACTOR");
try
{
Environment.SetEnvironmentVariable("DEPENDABOT", dependabotValue);
Environment.SetEnvironmentVariable("NBGV_GitEngine", null);
Environment.SetEnvironmentVariable("GITHUB_ACTOR", null);

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

Expand All @@ -245,13 +251,15 @@ public void GetEffectiveGitEngine_DependabotEnvironment_DisablesEngine(string de
[InlineData("")]
public void GetEffectiveGitEngine_DependabotNotTrue_UsesDefault(string dependabotValue)
{
// Arrange: Set DEPENDABOT to non-true value and clear NBGV_GitEngine
// Arrange: Set DEPENDABOT to non-true value and clear NBGV_GitEngine and GITHUB_ACTOR
var originalDependabot = Environment.GetEnvironmentVariable("DEPENDABOT");
var originalNbgvGitEngine = Environment.GetEnvironmentVariable("NBGV_GitEngine");
var originalGitHubActor = Environment.GetEnvironmentVariable("GITHUB_ACTOR");
try
{
Environment.SetEnvironmentVariable("DEPENDABOT", dependabotValue);
Environment.SetEnvironmentVariable("NBGV_GitEngine", null);
Environment.SetEnvironmentVariable("GITHUB_ACTOR", null);

// Act & Assert: Should use default behavior
Assert.Equal(GitContext.Engine.ReadOnly, GitContext.GetEffectiveGitEngine());
Expand All @@ -261,6 +269,7 @@ public void GetEffectiveGitEngine_DependabotNotTrue_UsesDefault(string dependabo
{
Environment.SetEnvironmentVariable("DEPENDABOT", originalDependabot);
Environment.SetEnvironmentVariable("NBGV_GitEngine", originalNbgvGitEngine);
Environment.SetEnvironmentVariable("GITHUB_ACTOR", originalGitHubActor);
}
}

Expand All @@ -270,13 +279,15 @@ public void GetEffectiveGitEngine_DependabotNotTrue_UsesDefault(string dependabo
[InlineData("Disabled", GitContext.Engine.Disabled)]
public void GetEffectiveGitEngine_NbgvGitEngineOverridesDependabot(string nbgvValue, GitContext.Engine expectedEngine)
{
// Arrange: Set both DEPENDABOT and NBGV_GitEngine
// Arrange: Set both DEPENDABOT and NBGV_GitEngine, clear GITHUB_ACTOR
var originalDependabot = Environment.GetEnvironmentVariable("DEPENDABOT");
var originalNbgvGitEngine = Environment.GetEnvironmentVariable("NBGV_GitEngine");
var originalGitHubActor = Environment.GetEnvironmentVariable("GITHUB_ACTOR");
try
{
Environment.SetEnvironmentVariable("DEPENDABOT", "true");
Environment.SetEnvironmentVariable("NBGV_GitEngine", nbgvValue);
Environment.SetEnvironmentVariable("GITHUB_ACTOR", null);

// Act & Assert: NBGV_GitEngine should take precedence and be parsed correctly
Assert.Equal(expectedEngine, GitContext.GetEffectiveGitEngine());
Expand All @@ -285,6 +296,87 @@ public void GetEffectiveGitEngine_NbgvGitEngineOverridesDependabot(string nbgvVa
{
Environment.SetEnvironmentVariable("DEPENDABOT", originalDependabot);
Environment.SetEnvironmentVariable("NBGV_GitEngine", originalNbgvGitEngine);
Environment.SetEnvironmentVariable("GITHUB_ACTOR", originalGitHubActor);
}
}

[Fact]
public void GetEffectiveGitEngine_GitHubCopilotEnvironment_DisablesEngine()
{
// Arrange: Set GITHUB_ACTOR to copilot-swe-agent[bot] and clear NBGV_GitEngine and DEPENDABOT
var originalGitHubActor = Environment.GetEnvironmentVariable("GITHUB_ACTOR");
var originalNbgvGitEngine = Environment.GetEnvironmentVariable("NBGV_GitEngine");
var originalDependabot = Environment.GetEnvironmentVariable("DEPENDABOT");
try
{
Environment.SetEnvironmentVariable("GITHUB_ACTOR", "copilot-swe-agent[bot]");
Environment.SetEnvironmentVariable("NBGV_GitEngine", null);
Environment.SetEnvironmentVariable("DEPENDABOT", null);

// Act & Assert: Should return Disabled regardless of requested engine
Assert.Equal(GitContext.Engine.Disabled, GitContext.GetEffectiveGitEngine());
Assert.Equal(GitContext.Engine.Disabled, GitContext.GetEffectiveGitEngine(GitContext.Engine.ReadOnly));
Assert.Equal(GitContext.Engine.Disabled, GitContext.GetEffectiveGitEngine(GitContext.Engine.ReadWrite));
}
finally
{
Environment.SetEnvironmentVariable("GITHUB_ACTOR", originalGitHubActor);
Environment.SetEnvironmentVariable("NBGV_GitEngine", originalNbgvGitEngine);
Environment.SetEnvironmentVariable("DEPENDABOT", originalDependabot);
}
}

[Theory]
[InlineData("user")]
[InlineData("dependabot[bot]")]
[InlineData("copilot-swe-agent")]
[InlineData("COPILOT-SWE-AGENT[BOT]")]
[InlineData("")]
public void GetEffectiveGitEngine_GitHubActorNotCopilot_UsesDefault(string gitHubActorValue)
{
// Arrange: Set GITHUB_ACTOR to non-copilot value and clear NBGV_GitEngine and DEPENDABOT
var originalGitHubActor = Environment.GetEnvironmentVariable("GITHUB_ACTOR");
var originalNbgvGitEngine = Environment.GetEnvironmentVariable("NBGV_GitEngine");
var originalDependabot = Environment.GetEnvironmentVariable("DEPENDABOT");
try
{
Environment.SetEnvironmentVariable("GITHUB_ACTOR", gitHubActorValue);
Environment.SetEnvironmentVariable("NBGV_GitEngine", null);
Environment.SetEnvironmentVariable("DEPENDABOT", null);

// Act & Assert: Should use default behavior
Assert.Equal(GitContext.Engine.ReadOnly, GitContext.GetEffectiveGitEngine());
Assert.Equal(GitContext.Engine.ReadWrite, GitContext.GetEffectiveGitEngine(GitContext.Engine.ReadWrite));
}
finally
{
Environment.SetEnvironmentVariable("GITHUB_ACTOR", originalGitHubActor);
Environment.SetEnvironmentVariable("NBGV_GitEngine", originalNbgvGitEngine);
Environment.SetEnvironmentVariable("DEPENDABOT", originalDependabot);
}
}

[Theory]
[InlineData("LibGit2", GitContext.Engine.ReadWrite)]
[InlineData("Managed", GitContext.Engine.ReadOnly)]
[InlineData("Disabled", GitContext.Engine.Disabled)]
public void GetEffectiveGitEngine_NbgvGitEngineOverridesGitHubCopilot(string nbgvValue, GitContext.Engine expectedEngine)
{
// Arrange: Set both GITHUB_ACTOR=copilot-swe-agent[bot] and NBGV_GitEngine
var originalGitHubActor = Environment.GetEnvironmentVariable("GITHUB_ACTOR");
var originalNbgvGitEngine = Environment.GetEnvironmentVariable("NBGV_GitEngine");
try
{
Environment.SetEnvironmentVariable("GITHUB_ACTOR", "copilot-swe-agent[bot]");
Environment.SetEnvironmentVariable("NBGV_GitEngine", nbgvValue);

// Act & Assert: NBGV_GitEngine should take precedence and be parsed correctly
Assert.Equal(expectedEngine, GitContext.GetEffectiveGitEngine());
}
finally
{
Environment.SetEnvironmentVariable("GITHUB_ACTOR", originalGitHubActor);
Environment.SetEnvironmentVariable("NBGV_GitEngine", originalNbgvGitEngine);
}
}
}
Loading