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
2 changes: 2 additions & 0 deletions .github/workflows/dotnet-ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ run-name: Continuous Integration
on:
push:
branches: [ "feature/*" ]
paths-ignore:
- 'samples/**'
pull_request_target:
branches: [ "main" ]
types: [closed]
Expand Down
14 changes: 11 additions & 3 deletions .github/workflows/wf-build-test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,23 @@ jobs:
build-project:
name: Build Project & Test
runs-on: ubuntu-latest

env:
NUGET_PACKAGES: ${{ github.workspace }}/.nuget/packages

steps:
- name: Checkout Repository
uses: actions/checkout@v4

- name: Setup .NET Core SDK
uses: actions/setup-dotnet@v4.0.0
with:
dotnet-version: 8.0.x
dotnet-version: |
6.0.x
7.0.x
8.0.x
dotnet-quality: ga
cache: true
cache-dependency-path: src/**/packages.lock.json

- name: Create packages directory
run: mkdir -p packages
Expand All @@ -30,7 +38,7 @@ jobs:
run: dotnet restore

- name: Build
run: dotnet build --no-restore --configuration ${{ inputs.buildConfiguration }}
run: dotnet build --no-restore --configuration ${{ inputs.buildConfiguration }} -p:GeneratePackageOnBuild=false

- name: Test
run: dotnet test --no-build --verbosity normal --configuration ${{ inputs.buildConfiguration }}
2 changes: 1 addition & 1 deletion .github/workflows/wf-publish-nuget.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ jobs:
run: mkdir -p packages

- name: Pack
run: dotnet pack $GITHUB_WORKSPACE/InvvardDev.Ifttt.sln --output ${{ env.package_path }} --configuration ${{ inputs.build_configuration }} -p:GeneratePackageOnBuild=falsedot
run: dotnet pack $GITHUB_WORKSPACE/InvvardDev.Ifttt.sln --output ${{ env.package_path }} --configuration ${{ inputs.build_configuration }} -p:GeneratePackageOnBuild=false

- name: Upload Artifact
uses: actions/upload-artifact@v4
Expand Down
19 changes: 10 additions & 9 deletions InvvardDev.Ifttt.sln
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,13 @@ Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.8.34330.188
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "InvvardDev.Ifttt.Core", "src\InvvardDev.Ifttt.Core\InvvardDev.Ifttt.Core.csproj", "{2A300429-5FD8-40E3-BECD-6CDBE16F2CD6}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "InvvardDev.Ifttt.Trigger", "src\InvvardDev.Ifttt.Trigger\InvvardDev.Ifttt.Trigger.csproj", "{7A94E577-6B7C-4AC5-A602-01FC41ED4D84}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "InvvardDev.Ifttt", "src\InvvardDev.Ifttt.csproj", "{2A300429-5FD8-40E3-BECD-6CDBE16F2CD6}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{8217D2BC-C98F-444C-B8D7-47CB074F6A66}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "InvvardDev.Ifttt.Trigger.Tests", "tests\InvvardDev.Ifttt.Trigger.Tests\InvvardDev.Ifttt.Trigger.Tests.csproj", "{F94D7981-BB31-467B-AA87-8924964CA186}"
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "InvvardDev.Ifttt.Tests", "tests\InvvardDev.Ifttt.Tests\InvvardDev.Ifttt.Tests.csproj", "{F94D7981-BB31-467B-AA87-8924964CA186}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "InvvardDev.Ifttt.TestFactories", "tests\InvvardDev.Ifttt.TestFactories\InvvardDev.Ifttt.TestFactories.csproj", "{795D362E-5E0F-46A7-B833-D41706617FCC}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Expand All @@ -21,14 +21,14 @@ Global
{2A300429-5FD8-40E3-BECD-6CDBE16F2CD6}.Debug|Any CPU.Build.0 = Debug|Any CPU
{2A300429-5FD8-40E3-BECD-6CDBE16F2CD6}.Release|Any CPU.ActiveCfg = Release|Any CPU
{2A300429-5FD8-40E3-BECD-6CDBE16F2CD6}.Release|Any CPU.Build.0 = Release|Any CPU
{7A94E577-6B7C-4AC5-A602-01FC41ED4D84}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{7A94E577-6B7C-4AC5-A602-01FC41ED4D84}.Debug|Any CPU.Build.0 = Debug|Any CPU
{7A94E577-6B7C-4AC5-A602-01FC41ED4D84}.Release|Any CPU.ActiveCfg = Release|Any CPU
{7A94E577-6B7C-4AC5-A602-01FC41ED4D84}.Release|Any CPU.Build.0 = Release|Any CPU
{F94D7981-BB31-467B-AA87-8924964CA186}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{F94D7981-BB31-467B-AA87-8924964CA186}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F94D7981-BB31-467B-AA87-8924964CA186}.Release|Any CPU.ActiveCfg = Release|Any CPU
{F94D7981-BB31-467B-AA87-8924964CA186}.Release|Any CPU.Build.0 = Release|Any CPU
{F94D7981-BB31-467B-AA87-8924964CA186}.Debug|Any CPU.Build.0 = Debug|Any CPU
{795D362E-5E0F-46A7-B833-D41706617FCC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{795D362E-5E0F-46A7-B833-D41706617FCC}.Release|Any CPU.ActiveCfg = Release|Any CPU
{795D362E-5E0F-46A7-B833-D41706617FCC}.Release|Any CPU.Build.0 = Release|Any CPU
{795D362E-5E0F-46A7-B833-D41706617FCC}.Debug|Any CPU.Build.0 = Debug|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand All @@ -38,5 +38,6 @@ Global
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{F94D7981-BB31-467B-AA87-8924964CA186} = {8217D2BC-C98F-444C-B8D7-47CB074F6A66}
{795D362E-5E0F-46A7-B833-D41706617FCC} = {8217D2BC-C98F-444C-B8D7-47CB074F6A66}
EndGlobalSection
EndGlobal
3 changes: 3 additions & 0 deletions samples/InvvardDev.Ifttt.Trigger.UpdatedNuget/Program.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
using InvvardDev.Ifttt.Trigger;
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;

var builder = WebApplication.CreateBuilder(args);

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
using InvvardDev.Ifttt.Trigger.Attributes;
using System.Threading;
using System.Threading.Tasks;
using InvvardDev.Ifttt.Trigger.Attributes;
using InvvardDev.Ifttt.Trigger.Contracts;
using InvvardDev.Ifttt.Trigger.Models;
using InvvardDev.Ifttt.Trigger.UpdatedNuget.Models;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
using System.Reflection;

namespace InvvardDev.Ifttt.Trigger.Contracts;
namespace InvvardDev.Ifttt.Contracts;

public interface IAssemblyAccessor
{
Expand Down
6 changes: 6 additions & 0 deletions src/Contracts/IAttributeLookup.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
namespace InvvardDev.Ifttt.Contracts;

internal interface IAttributeLookup
{
IEnumerable<Type> GetAnnotatedTypes();
}
19 changes: 19 additions & 0 deletions src/Contracts/IProcessorRepository.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
using InvvardDev.Ifttt.Models.Core;
using InvvardDev.Ifttt.Models.Trigger;

namespace InvvardDev.Ifttt.Contracts;

public interface IProcessorRepository
{
Task AddProcessor(ProcessorTree processorTree);

Task UpdateProcessor(ProcessorTree processorTree);

Task<bool> Exists(string key);

Task<ProcessorTree?> GetProcessorByKey(string key);

Task<IEnumerable<ProcessorTree>> FilterProcessors(Func<ProcessorTree, bool> predicate);

Task<IEnumerable<ProcessorTree>> GetAllProcessors();
}
18 changes: 18 additions & 0 deletions src/Contracts/IProcessorService.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
using InvvardDev.Ifttt.Models.Trigger;

namespace InvvardDev.Ifttt.Contracts;

public interface IProcessorService
{
Task AddOrUpdateProcessor(ProcessorTree processorMap);

Task AddDataField(string processorSlug, string dataFieldSlug, Type dataFieldType);

Task<bool> Exists(string processorSlug);

Task<ProcessorTree?> GetProcessor(string processorSlug);

Task<Type?> GetDataFieldType(string processorSlug, string dataFieldSlug);

Task<TInterface?> GetProcessorInstance<TInterface>(string processorSlug);
}
8 changes: 8 additions & 0 deletions src/Contracts/ITestSetup.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
using InvvardDev.Ifttt.Toolkit.Models;

namespace InvvardDev.Ifttt.Contracts;

public interface ITestSetup
{
Task<ProcessorPayload> PrepareSetupListing();
}
8 changes: 8 additions & 0 deletions src/Contracts/ITriggerMapper.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
namespace InvvardDev.Ifttt.Contracts;

public interface ITriggerMapper
{
Task<ITriggerMapper> MapTriggerProcessors();

Task<ITriggerMapper> MapTriggerFields();
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
using InvvardDev.Ifttt.Core.Configuration;
using InvvardDev.Ifttt.Hosting.Models;
using Microsoft.AspNetCore.Mvc;

namespace InvvardDev.Ifttt.Core.Controllers;
namespace InvvardDev.Ifttt.Controllers;

[ApiController]
[Route(IftttConstants.StatusApiPath)]
Expand Down
44 changes: 44 additions & 0 deletions src/Controllers/TestSetupController.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
using InvvardDev.Ifttt.Contracts;
using InvvardDev.Ifttt.Hosting.Models;
using InvvardDev.Ifttt.Toolkit.Models;
using Microsoft.AspNetCore.Mvc;

namespace InvvardDev.Ifttt.Controllers;

[ApiController]
[Route(IftttConstants.TestingApiPath)]
[Consumes("application/json")]
[Produces("application/json")]
public class TestSetupController : ControllerBase
{
private readonly ITestSetup testSetup;
private readonly ILogger<TestSetupController> logger;

public TestSetupController(ITestSetup testSetup, ILogger<TestSetupController> logger)
{
ArgumentNullException.ThrowIfNull(testSetup);
this.testSetup = testSetup;
this.logger = logger;
}

[HttpPost]
public async Task<IActionResult> SetupTest()
{
try
{
var processors = await testSetup.PrepareSetupListing();

var payload = TopLevelMessageModel<SamplesPayload>.Serialize(new SamplesPayload(processors));

return Ok(payload);
}
catch (Exception ex)
{
logger.LogError(ex, "Error while setting up test");

var errorMessages = TopLevelErrorModel.Serialize(new[] { new ErrorMessage($"Error while setting up test: {ex.Message}") });

return Problem(errorMessages);
}
}
}
25 changes: 25 additions & 0 deletions src/Controllers/TriggerController.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
using InvvardDev.Ifttt.Contracts;
using InvvardDev.Ifttt.Hosting.Models;
using InvvardDev.Ifttt.Toolkit.Contracts;
using InvvardDev.Ifttt.Toolkit.Models;
using Microsoft.AspNetCore.Mvc;

namespace InvvardDev.Ifttt.Controllers;

[ApiController]
[Route(IftttConstants.BaseTriggersApiPath)]
public class TriggerController(IProcessorService triggerService) : ControllerBase
{
[HttpPost("{triggerSlug}")]
public async Task<IActionResult> ExecuteTrigger(string triggerSlug, TriggerRequest triggerRequest)
{
if (await triggerService.GetProcessorInstance<ITrigger>(triggerSlug) is not { } trigger)
{
return NotFound();
}

await trigger.ExecuteAsync(triggerRequest);

return Ok();
}
}
8 changes: 8 additions & 0 deletions src/Extensions/ProcessorKeyExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
using InvvardDev.Ifttt.Models.Core;

namespace InvvardDev.Ifttt;

internal static class ProcessorKeyExtensions
{
public static string GetProcessorKey(this ProcessorKind kind, string slug) => $"{kind}:{slug}";
}
6 changes: 6 additions & 0 deletions src/Hosting/Builders/DefaultIftttAppBuilder.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
namespace InvvardDev.Ifttt.Hosting;

public sealed class DefaultIftttAppBuilder(IApplicationBuilder app) : IIftttAppBuilder
{
public IApplicationBuilder App { get; } = app;
}
10 changes: 10 additions & 0 deletions src/Hosting/Builders/DefaultIftttServiceBuilder.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
namespace InvvardDev.Ifttt.Hosting;

public sealed class DefaultIftttServiceBuilder(IServiceCollection services, string? serviceKey, string realTimeBaseAddress) : IIftttServiceBuilder
{
public IServiceCollection Services { get; } = services;

public string? ServiceKey { get; set; } = serviceKey;

public string RealTimeBaseAddress { get; } = realTimeBaseAddress;
}
6 changes: 6 additions & 0 deletions src/Hosting/Builders/IIftttAppBuilder.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
namespace InvvardDev.Ifttt.Hosting;

public interface IIftttAppBuilder
{
IApplicationBuilder App { get; }
}
10 changes: 10 additions & 0 deletions src/Hosting/Builders/IIftttServiceBuilder.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
namespace InvvardDev.Ifttt.Hosting;

public interface IIftttServiceBuilder
{
IServiceCollection Services { get; }

string? ServiceKey { get; set; }

string RealTimeBaseAddress { get; }
}
76 changes: 76 additions & 0 deletions src/Hosting/IftttServiceHostingExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
using System.Reflection;
using InvvardDev.Ifttt.Contracts;
using InvvardDev.Ifttt.Controllers;
using InvvardDev.Ifttt.Hosting.Middleware;
using InvvardDev.Ifttt.Hosting.Models;
using InvvardDev.Ifttt.Reflection;
using InvvardDev.Ifttt.Services;

namespace InvvardDev.Ifttt.Hosting;

public static class IftttServiceHostingExtensions
{
public static IWebHostBuilder AddIftttToolkit(this IWebHostBuilder hostBuilder,
Action<IIftttServiceBuilder, IftttOptions> configureServicesDelegate)
{
ArgumentNullException.ThrowIfNull(hostBuilder);
ArgumentNullException.ThrowIfNull(configureServicesDelegate);

return hostBuilder.ConfigureServices((ctx, services) =>
{
var options = new IftttOptions();
configureServicesDelegate(AddIftttToolkit(services, options), options);
});
}

public static IWebHostBuilder ConfigureIftttToolkit(this IWebHostBuilder hostBuilder,
Action<IIftttAppBuilder> configureAppDelegate)
{
ArgumentNullException.ThrowIfNull(hostBuilder);
ArgumentNullException.ThrowIfNull(configureAppDelegate);

return hostBuilder.Configure((context, applicationBuilder) =>
{
configureAppDelegate(new DefaultIftttAppBuilder(applicationBuilder));
});
}

public static IIftttServiceBuilder UseServiceKeyAuthentication(this IIftttServiceBuilder builder, string serviceKey)
{
ArgumentNullException.ThrowIfNull(builder);
ArgumentNullException.ThrowIfNull(serviceKey);

builder.ServiceKey = serviceKey;

return builder;
}

public static IIftttAppBuilder UseAuthentication(this IIftttAppBuilder appBuilder)
{
ArgumentNullException.ThrowIfNull(appBuilder);

appBuilder.App.UseMiddleware<ServiceKeyMiddleware>();

return appBuilder;
}

private static IIftttServiceBuilder AddIftttToolkit(IServiceCollection services, IftttOptions options)
{
if (Uri.IsWellFormedUriString(options.RealTimeBaseAddress, UriKind.RelativeOrAbsolute))
{
throw new UriFormatException("The RealTimeBaseAddress is not a valid URI.");
}

var builder = new DefaultIftttServiceBuilder(services, options.ServiceKey, options.RealTimeBaseAddress);

var apiBuilder = builder.Services.AddControllers();

apiBuilder.AddApplicationPart(Assembly.GetAssembly(typeof(StatusController)) ?? throw new InvalidOperationException())
.AddControllersAsServices();

builder.Services.AddScoped<IAssemblyAccessor, AssemblyAccessor>();
builder.Services.AddSingleton<IProcessorRepository, ProcessorRepository>();

return builder;
}
}
Loading