Skip to content

Commit a10a0bb

Browse files
author
Arin Ghazarian
authored
Add CLI's root and executing commands to user-agent header (#377)
1 parent 9f95edb commit a10a0bb

File tree

10 files changed

+161
-4
lines changed

10 files changed

+161
-4
lines changed

src/Octoshift/AdoClient.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,10 @@ public AdoClient(OctoLogger log, HttpClient httpClient, IVersionProvider version
2626
var authToken = Convert.ToBase64String(Encoding.ASCII.GetBytes($":{personalAccessToken}"));
2727
_httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", authToken);
2828
_httpClient.DefaultRequestHeaders.UserAgent.Add(new ProductInfoHeaderValue("OctoshiftCLI", versionProvider?.GetCurrentVersion()));
29+
if (versionProvider?.GetVersionComments() is { } comments)
30+
{
31+
_httpClient.DefaultRequestHeaders.UserAgent.Add(new ProductInfoHeaderValue(comments));
32+
}
2933
}
3034
}
3135

src/Octoshift/CliContext.cs

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
using System;
2+
3+
namespace OctoshiftCLI
4+
{
5+
public static class CliContext
6+
{
7+
private static string _rootCommand;
8+
private static string _executingCommand;
9+
10+
public static string RootCommand
11+
{
12+
set => _rootCommand = _rootCommand is null
13+
? value
14+
: throw new InvalidOperationException("Value can only be set once.");
15+
get => _rootCommand;
16+
}
17+
18+
public static string ExecutingCommand
19+
{
20+
set => _executingCommand = _executingCommand is null
21+
? value
22+
: throw new InvalidOperationException("Value can only be set once.");
23+
get => _executingCommand;
24+
}
25+
}
26+
}

src/Octoshift/GithubClient.cs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,13 @@ public GithubClient(OctoLogger log, HttpClient httpClient, IVersionProvider vers
2525
if (_httpClient != null)
2626
{
2727
_httpClient.DefaultRequestHeaders.Add("Accept", "application/vnd.github.v3+json");
28-
_httpClient.DefaultRequestHeaders.UserAgent.Add(new ProductInfoHeaderValue("OctoshiftCLI", versionProvider?.GetCurrentVersion()));
2928
_httpClient.DefaultRequestHeaders.Add("GraphQL-Features", "import_api,mannequin_claiming");
3029
_httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", personalAccessToken);
30+
_httpClient.DefaultRequestHeaders.UserAgent.Add(new ProductInfoHeaderValue("OctoshiftCLI", versionProvider?.GetCurrentVersion()));
31+
if (versionProvider?.GetVersionComments() is { } comments)
32+
{
33+
_httpClient.DefaultRequestHeaders.UserAgent.Add(new ProductInfoHeaderValue(comments));
34+
}
3135
}
3236
}
3337

src/Octoshift/IVersionProvider.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,6 @@
33
public interface IVersionProvider
44
{
55
string GetCurrentVersion();
6+
string GetVersionComments();
67
}
78
}

src/Octoshift/VersionChecker.cs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,14 +29,23 @@ public string GetCurrentVersion()
2929
return Assembly.GetExecutingAssembly().GetName().Version.ToString();
3030
}
3131

32+
public string GetVersionComments() =>
33+
CliContext.RootCommand.HasValue() && CliContext.ExecutingCommand.HasValue()
34+
? $"({CliContext.RootCommand}/{CliContext.ExecutingCommand})"
35+
: null;
36+
3237
public async Task<string> GetLatestVersion()
3338
{
3439
if (_latestVersion.IsNullOrWhiteSpace())
3540
{
3641
_httpClient.DefaultRequestHeaders.Add("Accept", "application/vnd.github.v3+json");
3742
_httpClient.DefaultRequestHeaders.UserAgent.Add(new ProductInfoHeaderValue("OctoshiftCLI", GetCurrentVersion()));
43+
if (GetVersionComments() is { } comments)
44+
{
45+
_httpClient.DefaultRequestHeaders.UserAgent.Add(new ProductInfoHeaderValue(comments));
46+
}
3847

39-
var url = "https://api.github.com/repos/github/gh-gei/releases/latest";
48+
const string url = "https://api.github.com/repos/github/gh-gei/releases/latest";
4049

4150
var response = await _httpClient.GetAsync(url);
4251
response.EnsureSuccessStatusCode();

src/OctoshiftCLI.Tests/AdoClientTests.cs

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -990,6 +990,41 @@ public async Task GetWithPagingAsync_Gets_All_Pages()
990990
ItExpr.IsAny<CancellationToken>());
991991
}
992992

993+
[Fact]
994+
public void It_Sets_User_Agent_Header_With_Comments()
995+
{
996+
// Arrange
997+
const string currentVersion = "1.1.1.1";
998+
const string versionComments = "(COMMENTS)";
999+
1000+
using var httpClient = new HttpClient();
1001+
1002+
var mockVersionProvider = new Mock<IVersionProvider>();
1003+
mockVersionProvider.Setup(m => m.GetCurrentVersion()).Returns("1.1.1.1");
1004+
mockVersionProvider.Setup(m => m.GetVersionComments()).Returns(versionComments);
1005+
1006+
// Act
1007+
_ = new AdoClient(null, httpClient, mockVersionProvider.Object, PERSONAL_ACCESS_TOKEN);
1008+
1009+
// Assert
1010+
httpClient.DefaultRequestHeaders.UserAgent.Should().HaveCount(2);
1011+
httpClient.DefaultRequestHeaders.UserAgent.ToString().Should().Be($"OctoshiftCLI/{currentVersion} {versionComments}");
1012+
}
1013+
1014+
[Fact]
1015+
public void It_Only_Sets_The_Product_Name_In_User_Agent_Header_When_Version_Provider_Is_Null()
1016+
{
1017+
// Arrange
1018+
using var httpClient = new HttpClient();
1019+
1020+
// Act
1021+
_ = new AdoClient(null, httpClient, null, PERSONAL_ACCESS_TOKEN);
1022+
1023+
// Assert
1024+
httpClient.DefaultRequestHeaders.UserAgent.Should().HaveCount(1);
1025+
httpClient.DefaultRequestHeaders.UserAgent.ToString().Should().Be("OctoshiftCLI");
1026+
}
1027+
9931028
private Mock<HttpMessageHandler> MockHttpHandlerForGet() =>
9941029
MockHttpHandler(req => req.Method == HttpMethod.Get);
9951030

src/OctoshiftCLI.Tests/GithubClientTests.cs

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1440,6 +1440,41 @@ await githubClient
14401440
.WithParameterName("pageInfoSelector");
14411441
}
14421442

1443+
[Fact]
1444+
public void It_Sets_User_Agent_Header_With_Comments()
1445+
{
1446+
// Arrange
1447+
const string currentVersion = "1.1.1.1";
1448+
const string versionComments = "(COMMENTS)";
1449+
1450+
using var httpClient = new HttpClient();
1451+
1452+
var mockVersionProvider = new Mock<IVersionProvider>();
1453+
mockVersionProvider.Setup(m => m.GetCurrentVersion()).Returns("1.1.1.1");
1454+
mockVersionProvider.Setup(m => m.GetVersionComments()).Returns(versionComments);
1455+
1456+
// Act
1457+
_ = new GithubClient(null, httpClient, mockVersionProvider.Object, PERSONAL_ACCESS_TOKEN);
1458+
1459+
// Assert
1460+
httpClient.DefaultRequestHeaders.UserAgent.Should().HaveCount(2);
1461+
httpClient.DefaultRequestHeaders.UserAgent.ToString().Should().Be($"OctoshiftCLI/{currentVersion} {versionComments}");
1462+
}
1463+
1464+
[Fact]
1465+
public void It_Only_Sets_The_Product_Name_In_User_Agent_Header_When_Version_Provider_Is_Null()
1466+
{
1467+
// Arrange
1468+
using var httpClient = new HttpClient();
1469+
1470+
// Act
1471+
_ = new GithubClient(null, httpClient, null, PERSONAL_ACCESS_TOKEN);
1472+
1473+
// Assert
1474+
httpClient.DefaultRequestHeaders.UserAgent.Should().HaveCount(1);
1475+
httpClient.DefaultRequestHeaders.UserAgent.ToString().Should().Be("OctoshiftCLI");
1476+
}
1477+
14431478
private object CreateRepositoryMigration(string migrationId = null, string state = RepositoryMigrationStatus.Succeeded) => new
14441479
{
14451480
id = migrationId ?? Guid.NewGuid().ToString(),
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
using FluentAssertions;
2+
using Xunit;
3+
4+
namespace OctoshiftCLI.Tests
5+
{
6+
public class VersionCheckerTests
7+
{
8+
[Fact]
9+
public void GetVersionComments_Returns_Root_And_Executing_Commands()
10+
{
11+
// Arrange
12+
const string rootCommand = "ROOT_COMMAND";
13+
const string executingCommand = "EXECUTING_COMMAND";
14+
15+
CliContext.RootCommand = rootCommand;
16+
CliContext.ExecutingCommand = executingCommand;
17+
18+
var versionChecker = new VersionChecker(null);
19+
20+
// Act
21+
var comments = versionChecker.GetVersionComments();
22+
23+
// Assert
24+
comments.Should().Be($"({rootCommand}/{executingCommand})");
25+
}
26+
}
27+
}

src/ado2gh/Program.cs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,19 +32,27 @@ public static async Task Main(string[] args)
3232
var serviceProvider = serviceCollection.BuildServiceProvider();
3333
var parser = BuildParser(serviceProvider);
3434

35+
SetContext(parser.Parse(args));
36+
3537
try
3638
{
3739
await LatestVersionCheck(serviceProvider);
3840
}
3941
catch (Exception ex)
4042
{
41-
Logger.LogWarning($"Could not retrieve latest ado2gh version from github.com, please ensure you are using the latest version by downloading it from https://github.com/github/gh-gei/releases/latest");
43+
Logger.LogWarning("Could not retrieve latest ado2gh version from github.com, please ensure you are using the latest version by downloading it from https://github.com/github/gh-gei/releases/latest");
4244
Logger.LogVerbose(ex.ToString());
4345
}
4446

4547
await parser.InvokeAsync(args);
4648
}
4749

50+
private static void SetContext(ParseResult parseResult)
51+
{
52+
CliContext.RootCommand = parseResult.RootCommandResult.Command.Name;
53+
CliContext.ExecutingCommand = parseResult.CommandResult.Command.Name;
54+
}
55+
4856
private static async Task LatestVersionCheck(ServiceProvider sp)
4957
{
5058
var versionChecker = sp.GetRequiredService<VersionChecker>();

src/gei/Program.cs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,19 +49,27 @@ public static async Task Main(string[] args)
4949
var serviceProvider = serviceCollection.BuildServiceProvider();
5050
var parser = BuildParser(serviceProvider);
5151

52+
SetContext(parser.Parse(args));
53+
5254
try
5355
{
5456
await LatestVersionCheck(serviceProvider);
5557
}
5658
catch (Exception ex)
5759
{
58-
Logger.LogWarning($"Could not retrieve latest gei CLI version from github.com, please ensure you are using the latest version by running: gh extension upgrade gei");
60+
Logger.LogWarning("Could not retrieve latest gei CLI version from github.com, please ensure you are using the latest version by running: gh extension upgrade gei");
5961
Logger.LogVerbose(ex.ToString());
6062
}
6163

6264
await parser.InvokeAsync(args);
6365
}
6466

67+
private static void SetContext(ParseResult parseResult)
68+
{
69+
CliContext.RootCommand = parseResult.RootCommandResult.Command.Name;
70+
CliContext.ExecutingCommand = parseResult.CommandResult.Command.Name;
71+
}
72+
6573
private static async Task LatestVersionCheck(ServiceProvider sp)
6674
{
6775
var versionChecker = sp.GetRequiredService<VersionChecker>();

0 commit comments

Comments
 (0)