Skip to content

Commit

Permalink
feat: add additional configuration option (#568)
Browse files Browse the repository at this point in the history
* feat: add additional configuration option

* chore: add tests for github webhooks azure functions host builder extensions

---------

Co-authored-by: Nick Floyd <[email protected]>
  • Loading branch information
ganhammar and nickfloyd authored Oct 8, 2024
1 parent e03d9ce commit 9373184
Show file tree
Hide file tree
Showing 5 changed files with 128 additions and 5 deletions.
13 changes: 10 additions & 3 deletions Octokit.Webhooks.sln
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,9 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{E1B24F25-B
EndProjectSection
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "images", "images", "{26F71F5B-2940-4FB0-9681-A76060CBCEF9}"
ProjectSection(SolutionItems) = preProject
images\Icon.png = images\Icon.png
EndProjectSection
ProjectSection(SolutionItems) = preProject
images\Icon.png = images\Icon.png
EndProjectSection
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "ISSUE_TEMPLATE", "ISSUE_TEMPLATE", "{566DF0E2-1288-4083-9B55-4C8B69BB1432}"
ProjectSection(SolutionItems) = preProject
Expand Down Expand Up @@ -70,6 +70,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AzureFunctions", "samples\A
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Octokit.Webhooks.AzureFunctions", "src\Octokit.Webhooks.AzureFunctions\Octokit.Webhooks.AzureFunctions.csproj", "{E7A3E0C8-CE8E-434D-8E97-723F9D5206FA}"
EndProject
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}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -104,6 +106,10 @@ Global
{E7A3E0C8-CE8E-434D-8E97-723F9D5206FA}.Debug|Any CPU.Build.0 = Debug|Any CPU
{E7A3E0C8-CE8E-434D-8E97-723F9D5206FA}.Release|Any CPU.ActiveCfg = Release|Any CPU
{E7A3E0C8-CE8E-434D-8E97-723F9D5206FA}.Release|Any CPU.Build.0 = Release|Any CPU
{7B30ABC3-C016-4EA5-81C1-A51C28580D36}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{7B30ABC3-C016-4EA5-81C1-A51C28580D36}.Debug|Any CPU.Build.0 = Debug|Any CPU
{7B30ABC3-C016-4EA5-81C1-A51C28580D36}.Release|Any CPU.ActiveCfg = Release|Any CPU
{7B30ABC3-C016-4EA5-81C1-A51C28580D36}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand All @@ -119,6 +125,7 @@ Global
{48EB4752-1A23-4DD2-AF86-21ED12475F8B} = {E1B24F25-B8A4-46EE-B7EB-7803DCFC543F}
{8731AAA1-8F8D-441A-BD61-6CA3A16A805B} = {174C8B3B-E8D3-4845-AE7C-8C0DEC43354F}
{E7A3E0C8-CE8E-434D-8E97-723F9D5206FA} = {719809C2-A551-4C4A-9EFD-B10FB5E35BC0}
{7B30ABC3-C016-4EA5-81C1-A51C28580D36} = {E1B24F25-B8A4-46EE-B7EB-7803DCFC543F}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {73F36209-F8D6-4066-8951-D97729F773CF}
Expand Down
6 changes: 5 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -84,10 +84,14 @@ Libraries to handle GitHub Webhooks in .NET applications.
.Build();
```

`ConfigureGitHubWebhooks()` takes one optional parameter:
`ConfigureGitHubWebhooks()` either takes an optional parameter:

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

or:

* `configure`. A function that takes an IConfiguration instance and expects the secret you have configured in GitHub in return.

The function is available on the `/api/github/webhooks` endpoint.

## Thanks
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
namespace Octokit.Webhooks.AzureFunctions;
namespace Octokit.Webhooks.AzureFunctions;

using System;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;

Expand All @@ -14,4 +16,18 @@ public static class GithubWebhookHostBuilderExtensions
public static IHostBuilder ConfigureGitHubWebhooks(this IHostBuilder hostBuilder, string? secret = null) =>
hostBuilder.ConfigureServices(services =>
services.AddOptions<GitHubWebhooksOptions>().Configure(options => options.Secret = secret));

/// <summary>
/// Configures GitHub webhook function.
/// </summary>
/// <param name="hostBuilder"><see cref="IHostBuilder" /> instance.</param>
/// <param name="configure">A function that takes an <see cref="IConfiguration" /> instance and expects the secret you have configured in GitHub in return.</param>
/// <returns>Returns <see cref="IHostBuilder" /> instance.</returns>
public static IHostBuilder ConfigureGitHubWebhooks(this IHostBuilder hostBuilder, Func<IConfiguration, string> configure)
{
ArgumentNullException.ThrowIfNull(configure);

return hostBuilder.ConfigureServices((context, services) =>
services.AddOptions<GitHubWebhooksOptions>().Configure(options => options.Secret = configure(context.Configuration)));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
namespace Octokit.Webhooks.AzureFunctions.Test;

using System;
using System.Collections.Generic;
using FluentAssertions;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Options;
using Moq;
using Xunit;

public class GithubWebhookHostBuilderExtensionsTests
{
[Fact]
public void CanConfigureSecretUsingPlainText()
{
// Arrange
var mockHostBuilder = new Mock<IHostBuilder>();
var services = new ServiceCollection();
var testSecret = "test-secret";

mockHostBuilder
.Setup(hb => hb.ConfigureServices(It.IsAny<Action<HostBuilderContext, IServiceCollection>>()))
.Callback<Action<HostBuilderContext, IServiceCollection>>((action) =>
{
var context = new HostBuilderContext(new Dictionary<object, object>());
action(context, services);
})
.Returns(mockHostBuilder.Object);

// Act
mockHostBuilder.Object.ConfigureGitHubWebhooks(testSecret);

// Assert
var serviceProvider = services.BuildServiceProvider();
var options = serviceProvider.GetRequiredService<IOptions<GitHubWebhooksOptions>>().Value;
Assert.Equal(testSecret, options.Secret);
}

[Fact]
public void CanConfigureSecretUsingConfigurationInstance()
{
// Arrange
var mockHostBuilder = new Mock<IHostBuilder>();
var services = new ServiceCollection();
var testSecret = "test-secret";
var configuration = new ConfigurationBuilder()
.AddInMemoryCollection(new Dictionary<string, string?>
{
["GitHubSecret"] = testSecret,
})
.Build();

mockHostBuilder
.Setup(hb => hb.ConfigureServices(It.IsAny<Action<HostBuilderContext, IServiceCollection>>()))
.Callback<Action<HostBuilderContext, IServiceCollection>>((action) =>
{
var context = new HostBuilderContext(new Dictionary<object, object>())
{
Configuration = configuration,
};
action(context, services);
})
.Returns(mockHostBuilder.Object);

static string Configure(IConfiguration config) => config.GetValue<string>("GitHubSecret")
?? throw new ArgumentNullException();

// Act
mockHostBuilder.Object.ConfigureGitHubWebhooks(Configure);

// Assert
var serviceProvider = services.BuildServiceProvider();
var options = serviceProvider.GetRequiredService<IOptions<GitHubWebhooksOptions>>().Value;
Assert.Equal(testSecret, options.Secret);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup Label="Build">
<TargetFramework>net6.0</TargetFramework>
</PropertyGroup>

<ItemGroup Label="Project References">
<ProjectReference Include="..\..\src\Octokit.Webhooks.AzureFunctions\Octokit.Webhooks.AzureFunctions.csproj" />
<ProjectReference Include="..\Octokit.Webhooks.TestUtils\Octokit.Webhooks.TestUtils.csproj" />
</ItemGroup>

<ItemGroup>
<Content Include="Resources\**">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
</ItemGroup>

</Project>

0 comments on commit 9373184

Please sign in to comment.