Skip to content

Commit 9373184

Browse files
ganhammarnickfloyd
andauthored
feat: add additional configuration option (#568)
* feat: add additional configuration option * chore: add tests for github webhooks azure functions host builder extensions --------- Co-authored-by: Nick Floyd <[email protected]>
1 parent e03d9ce commit 9373184

File tree

5 files changed

+128
-5
lines changed

5 files changed

+128
-5
lines changed

Octokit.Webhooks.sln

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,9 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{E1B24F25-B
3131
EndProjectSection
3232
EndProject
3333
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "images", "images", "{26F71F5B-2940-4FB0-9681-A76060CBCEF9}"
34-
ProjectSection(SolutionItems) = preProject
35-
images\Icon.png = images\Icon.png
36-
EndProjectSection
34+
ProjectSection(SolutionItems) = preProject
35+
images\Icon.png = images\Icon.png
36+
EndProjectSection
3737
EndProject
3838
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "ISSUE_TEMPLATE", "ISSUE_TEMPLATE", "{566DF0E2-1288-4083-9B55-4C8B69BB1432}"
3939
ProjectSection(SolutionItems) = preProject
@@ -70,6 +70,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AzureFunctions", "samples\A
7070
EndProject
7171
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Octokit.Webhooks.AzureFunctions", "src\Octokit.Webhooks.AzureFunctions\Octokit.Webhooks.AzureFunctions.csproj", "{E7A3E0C8-CE8E-434D-8E97-723F9D5206FA}"
7272
EndProject
73+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Octokit.Webhooks.AzureFunctions.Test", "test\Octokit.Webhooks.AzureFunctions.Test\Octokit.Webhooks.AzureFunctions.Test.csproj", "{7B30ABC3-C016-4EA5-81C1-A51C28580D36}"
74+
EndProject
7375
Global
7476
GlobalSection(SolutionConfigurationPlatforms) = preSolution
7577
Debug|Any CPU = Debug|Any CPU
@@ -104,6 +106,10 @@ Global
104106
{E7A3E0C8-CE8E-434D-8E97-723F9D5206FA}.Debug|Any CPU.Build.0 = Debug|Any CPU
105107
{E7A3E0C8-CE8E-434D-8E97-723F9D5206FA}.Release|Any CPU.ActiveCfg = Release|Any CPU
106108
{E7A3E0C8-CE8E-434D-8E97-723F9D5206FA}.Release|Any CPU.Build.0 = Release|Any CPU
109+
{7B30ABC3-C016-4EA5-81C1-A51C28580D36}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
110+
{7B30ABC3-C016-4EA5-81C1-A51C28580D36}.Debug|Any CPU.Build.0 = Debug|Any CPU
111+
{7B30ABC3-C016-4EA5-81C1-A51C28580D36}.Release|Any CPU.ActiveCfg = Release|Any CPU
112+
{7B30ABC3-C016-4EA5-81C1-A51C28580D36}.Release|Any CPU.Build.0 = Release|Any CPU
107113
EndGlobalSection
108114
GlobalSection(SolutionProperties) = preSolution
109115
HideSolutionNode = FALSE
@@ -119,6 +125,7 @@ Global
119125
{48EB4752-1A23-4DD2-AF86-21ED12475F8B} = {E1B24F25-B8A4-46EE-B7EB-7803DCFC543F}
120126
{8731AAA1-8F8D-441A-BD61-6CA3A16A805B} = {174C8B3B-E8D3-4845-AE7C-8C0DEC43354F}
121127
{E7A3E0C8-CE8E-434D-8E97-723F9D5206FA} = {719809C2-A551-4C4A-9EFD-B10FB5E35BC0}
128+
{7B30ABC3-C016-4EA5-81C1-A51C28580D36} = {E1B24F25-B8A4-46EE-B7EB-7803DCFC543F}
122129
EndGlobalSection
123130
GlobalSection(ExtensibilityGlobals) = postSolution
124131
SolutionGuid = {73F36209-F8D6-4066-8951-D97729F773CF}

README.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,10 +84,14 @@ Libraries to handle GitHub Webhooks in .NET applications.
8484
.Build();
8585
```
8686

87-
`ConfigureGitHubWebhooks()` takes one optional parameter:
87+
`ConfigureGitHubWebhooks()` either takes an optional parameter:
8888

8989
* `secret`. The secret you have configured in GitHub, if you have set this up.
9090

91+
or:
92+
93+
* `configure`. A function that takes an IConfiguration instance and expects the secret you have configured in GitHub in return.
94+
9195
The function is available on the `/api/github/webhooks` endpoint.
9296

9397
## Thanks

src/Octokit.Webhooks.AzureFunctions/GithubWebhookHostBuilderExtensions.cs

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
1-
namespace Octokit.Webhooks.AzureFunctions;
1+
namespace Octokit.Webhooks.AzureFunctions;
22

3+
using System;
4+
using Microsoft.Extensions.Configuration;
35
using Microsoft.Extensions.DependencyInjection;
46
using Microsoft.Extensions.Hosting;
57

@@ -14,4 +16,18 @@ public static class GithubWebhookHostBuilderExtensions
1416
public static IHostBuilder ConfigureGitHubWebhooks(this IHostBuilder hostBuilder, string? secret = null) =>
1517
hostBuilder.ConfigureServices(services =>
1618
services.AddOptions<GitHubWebhooksOptions>().Configure(options => options.Secret = secret));
19+
20+
/// <summary>
21+
/// Configures GitHub webhook function.
22+
/// </summary>
23+
/// <param name="hostBuilder"><see cref="IHostBuilder" /> instance.</param>
24+
/// <param name="configure">A function that takes an <see cref="IConfiguration" /> instance and expects the secret you have configured in GitHub in return.</param>
25+
/// <returns>Returns <see cref="IHostBuilder" /> instance.</returns>
26+
public static IHostBuilder ConfigureGitHubWebhooks(this IHostBuilder hostBuilder, Func<IConfiguration, string> configure)
27+
{
28+
ArgumentNullException.ThrowIfNull(configure);
29+
30+
return hostBuilder.ConfigureServices((context, services) =>
31+
services.AddOptions<GitHubWebhooksOptions>().Configure(options => options.Secret = configure(context.Configuration)));
32+
}
1733
}
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
namespace Octokit.Webhooks.AzureFunctions.Test;
2+
3+
using System;
4+
using System.Collections.Generic;
5+
using FluentAssertions;
6+
using Microsoft.Extensions.Configuration;
7+
using Microsoft.Extensions.DependencyInjection;
8+
using Microsoft.Extensions.Hosting;
9+
using Microsoft.Extensions.Options;
10+
using Moq;
11+
using Xunit;
12+
13+
public class GithubWebhookHostBuilderExtensionsTests
14+
{
15+
[Fact]
16+
public void CanConfigureSecretUsingPlainText()
17+
{
18+
// Arrange
19+
var mockHostBuilder = new Mock<IHostBuilder>();
20+
var services = new ServiceCollection();
21+
var testSecret = "test-secret";
22+
23+
mockHostBuilder
24+
.Setup(hb => hb.ConfigureServices(It.IsAny<Action<HostBuilderContext, IServiceCollection>>()))
25+
.Callback<Action<HostBuilderContext, IServiceCollection>>((action) =>
26+
{
27+
var context = new HostBuilderContext(new Dictionary<object, object>());
28+
action(context, services);
29+
})
30+
.Returns(mockHostBuilder.Object);
31+
32+
// Act
33+
mockHostBuilder.Object.ConfigureGitHubWebhooks(testSecret);
34+
35+
// Assert
36+
var serviceProvider = services.BuildServiceProvider();
37+
var options = serviceProvider.GetRequiredService<IOptions<GitHubWebhooksOptions>>().Value;
38+
Assert.Equal(testSecret, options.Secret);
39+
}
40+
41+
[Fact]
42+
public void CanConfigureSecretUsingConfigurationInstance()
43+
{
44+
// Arrange
45+
var mockHostBuilder = new Mock<IHostBuilder>();
46+
var services = new ServiceCollection();
47+
var testSecret = "test-secret";
48+
var configuration = new ConfigurationBuilder()
49+
.AddInMemoryCollection(new Dictionary<string, string?>
50+
{
51+
["GitHubSecret"] = testSecret,
52+
})
53+
.Build();
54+
55+
mockHostBuilder
56+
.Setup(hb => hb.ConfigureServices(It.IsAny<Action<HostBuilderContext, IServiceCollection>>()))
57+
.Callback<Action<HostBuilderContext, IServiceCollection>>((action) =>
58+
{
59+
var context = new HostBuilderContext(new Dictionary<object, object>())
60+
{
61+
Configuration = configuration,
62+
};
63+
action(context, services);
64+
})
65+
.Returns(mockHostBuilder.Object);
66+
67+
static string Configure(IConfiguration config) => config.GetValue<string>("GitHubSecret")
68+
?? throw new ArgumentNullException();
69+
70+
// Act
71+
mockHostBuilder.Object.ConfigureGitHubWebhooks(Configure);
72+
73+
// Assert
74+
var serviceProvider = services.BuildServiceProvider();
75+
var options = serviceProvider.GetRequiredService<IOptions<GitHubWebhooksOptions>>().Value;
76+
Assert.Equal(testSecret, options.Secret);
77+
}
78+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
3+
<PropertyGroup Label="Build">
4+
<TargetFramework>net6.0</TargetFramework>
5+
</PropertyGroup>
6+
7+
<ItemGroup Label="Project References">
8+
<ProjectReference Include="..\..\src\Octokit.Webhooks.AzureFunctions\Octokit.Webhooks.AzureFunctions.csproj" />
9+
<ProjectReference Include="..\Octokit.Webhooks.TestUtils\Octokit.Webhooks.TestUtils.csproj" />
10+
</ItemGroup>
11+
12+
<ItemGroup>
13+
<Content Include="Resources\**">
14+
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
15+
</Content>
16+
</ItemGroup>
17+
18+
</Project>

0 commit comments

Comments
 (0)