Skip to content

Commit

Permalink
Adding In Basic GitLab Support (#34)
Browse files Browse the repository at this point in the history
* basic template for gitlab

* readme update

* Pull request and pipelines for gitlab

* GitLab repository feature

* global json serialiser convert for enums

* Vulnerability checking and caching in pipeline

* retrigger for cache test

* name change
  • Loading branch information
james-d12 authored Mar 1, 2025
1 parent 83db593 commit cea7432
Show file tree
Hide file tree
Showing 30 changed files with 567 additions and 50 deletions.
22 changes: 18 additions & 4 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,13 @@ on:
branches:
- main

env:
SOLUTION_FILE: CodeHub.sln

jobs:
build:
name: "Build and Check"
runs-on: ubuntu-latest

steps:
- name: Checkout repository
uses: actions/checkout@v4
Expand All @@ -21,17 +24,28 @@ jobs:
with:
dotnet-version: '9.0.x'

- name: Cache NuGet packages
uses: actions/cache@v4
env:
cache-name: nuget-package-cache
with:
path: ~/.nuget/packages
key: ${{ runner.os }}-${{ env.cache-name }}

- name: Restore dependencies
run: dotnet restore CodeHub.sln
run: dotnet restore ${{ env.SOLUTION_FILE }}

- name: Build API
run: dotnet build CodeHub.sln --configuration Release --no-restore
run: dotnet build ${{ env.SOLUTION_FILE }} --configuration Release --no-restore

- name: Check For Vulnerabilities
run: dotnet list ${{ env.SOLUTION_FILE }} package --vulnerable

- name: Format Check
run: dotnet format --verify-no-changes --verbosity diagnostic

- name: Run tests
run: dotnet test CodeHub.sln --configuration Release --no-build --collect:"XPlat Code Coverage"
run: dotnet test ${{ env.SOLUTION_FILE }} --configuration Release --no-build --collect:"XPlat Code Coverage"

- name: Build Docker
run: docker compose build
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,4 @@ riderModule.iml
*.user
/src/frontend/CodeHub.Portal/CodeHub.Portal.csproj.user
/src/backend/CodeHub.Api/CodeHub.Api.csproj.user
coverage-report
7 changes: 7 additions & 0 deletions CodeHub.sln
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CodeHub.Platform.Azure.Test
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CodeHub.Platform.GitHub", "src\backend\CodeHub.Platform.GitHub\CodeHub.Platform.GitHub.csproj", "{8AFCA3A8-0CDB-4FF7-B484-803EA74E94D5}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CodeHub.Platform.GitLab", "src\backend\CodeHub.Platform.GitLab\CodeHub.Platform.GitLab.csproj", "{7014F74C-506D-4DC3-85DC-DF14EC446FB4}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -96,6 +98,10 @@ Global
{8AFCA3A8-0CDB-4FF7-B484-803EA74E94D5}.Debug|Any CPU.Build.0 = Debug|Any CPU
{8AFCA3A8-0CDB-4FF7-B484-803EA74E94D5}.Release|Any CPU.ActiveCfg = Release|Any CPU
{8AFCA3A8-0CDB-4FF7-B484-803EA74E94D5}.Release|Any CPU.Build.0 = Release|Any CPU
{7014F74C-506D-4DC3-85DC-DF14EC446FB4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{7014F74C-506D-4DC3-85DC-DF14EC446FB4}.Debug|Any CPU.Build.0 = Debug|Any CPU
{7014F74C-506D-4DC3-85DC-DF14EC446FB4}.Release|Any CPU.ActiveCfg = Release|Any CPU
{7014F74C-506D-4DC3-85DC-DF14EC446FB4}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand All @@ -113,5 +119,6 @@ Global
{58014886-DBFC-4D3B-9EA3-03B8A228B601} = {6BBAFA79-C6EC-4415-8249-3AF0BF69A8F8}
{4D69214A-521E-413C-8732-A228A50753DD} = {3AC7FEA5-756C-45E1-8988-16170C26B898}
{8AFCA3A8-0CDB-4FF7-B484-803EA74E94D5} = {6BBAFA79-C6EC-4415-8249-3AF0BF69A8F8}
{7014F74C-506D-4DC3-85DC-DF14EC446FB4} = {6BBAFA79-C6EC-4415-8249-3AF0BF69A8F8}
EndGlobalSection
EndGlobal
1 change: 1 addition & 0 deletions src/backend/CodeHub.Api/CodeHub.Api.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
<ProjectReference Include="..\CodeHub.Platform.AzureDevOps\CodeHub.Platform.AzureDevOps.csproj"/>
<ProjectReference Include="..\CodeHub.Platform.Azure\CodeHub.Platform.Azure.csproj"/>
<ProjectReference Include="..\CodeHub.Platform.GitHub\CodeHub.Platform.GitHub.csproj" />
<ProjectReference Include="..\CodeHub.Platform.GitLab\CodeHub.Platform.GitLab.csproj" />
</ItemGroup>

<ItemGroup>
Expand Down
3 changes: 3 additions & 0 deletions src/backend/CodeHub.Api/Controllers/ResourceController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ public ResourceDevOpsController(IEnumerable<IQueryService> queryServices)
}

[HttpGet, Route("pipelines")]
[ProducesResponseType(StatusCodes.Status200OK)]
public List<Pipeline> GetPipelines([FromQuery] PipelineQueryRequest request)
{
var pipelines = new List<Pipeline>();
Expand All @@ -30,6 +31,7 @@ public List<Pipeline> GetPipelines([FromQuery] PipelineQueryRequest request)
}

[HttpGet, Route("repositories")]
[ProducesResponseType(StatusCodes.Status200OK)]
public List<Repository> GetRepositories([FromQuery] RepositoryQueryRequest request)
{
var repositories = new List<Repository>();
Expand All @@ -42,6 +44,7 @@ public List<Repository> GetRepositories([FromQuery] RepositoryQueryRequest reque
}

[HttpGet, Route("pull-requests")]
[ProducesResponseType(StatusCodes.Status200OK)]
public List<PullRequest> GetPullRequests([FromQuery] PullRequestQueryRequest request)
{
var pullRequests = new List<PullRequest>();
Expand Down
11 changes: 9 additions & 2 deletions src/backend/CodeHub.Api/Program.cs
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
using System.Text.Json;
using System.Text.Json.Serialization;
using CodeHub.Api.Jobs;
using CodeHub.Api.Settings;
using CodeHub.Platform.Azure.Extensions;
using CodeHub.Platform.AzureDevOps.Extensions;
using CodeHub.Platform.GitHub.Extensions;
using CodeHub.Platform.GitLab.Extensions;
using Microsoft.VisualStudio.Services.Common;

var builder = WebApplication.CreateBuilder(args);
Expand All @@ -20,18 +22,23 @@

try
{
logger.LogDebug("Configuration: {Config}", JsonSerializer.Serialize(builder.Configuration.GetSection("CorsSettings").Value));
logger.LogDebug("Configuration: {Config}",
JsonSerializer.Serialize(builder.Configuration.GetSection("CorsSettings").Value));
logger.LogInformation("Starting up: {ApplicationName}", applicationName);

builder.Services.AddLogging();
builder.Services.AddControllers();
builder.Services.AddControllers().AddJsonOptions(options =>
{
options.JsonSerializerOptions.Converters.Add(new JsonStringEnumConverter());
});
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
builder.Services.AddHostedService<DiscoveryHostedService>();

builder.Services.RegisterAzure(builder.Configuration);
builder.Services.RegisterAzureDevOps(builder.Configuration);
builder.Services.RegisterGitHub(builder.Configuration);
builder.Services.RegisterGitLab(builder.Configuration);

var corsSettings = builder.Configuration.GetSection(nameof(CorsSettings)).Get<CorsSettings>();

Expand Down
5 changes: 5 additions & 0 deletions src/backend/CodeHub.Api/appsettings.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,11 @@
"Token": "",
"IsEnabled": false
},
"GitLabSettings": {
"HostUrl": "",
"Token": "",
"IsEnabled": false
},
"CorsSettings": {
"AllowedFrontend": ""
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ public List<Pipeline> QueryPipelines(PipelineQueryRequest request)
{
_logger.LogInformation("Querying pipelines from Azure DevOps");
var azureDevOpsPipelines = _memoryCache.Get<List<AzureDevOpsPipeline>>(CacheConstants.PipelineCacheKey) ?? [];
var pipelines = azureDevOpsPipelines.ConvertAll(p => (Pipeline)p);
var pipelines = azureDevOpsPipelines.ConvertAll<Pipeline>(p => p);

if (azureDevOpsPipelines.Count <= 0)
{
Expand All @@ -43,7 +43,7 @@ public List<Repository> QueryRepositories(RepositoryQueryRequest request)
_logger.LogInformation("Querying repositories from Azure DevOps");
var azureDevOpsRepositories =
_memoryCache.Get<List<AzureDevOpsRepository>>(CacheConstants.RepositoryCacheKey) ?? [];
var repositories = azureDevOpsRepositories.ConvertAll(p => (Repository)p);
var repositories = azureDevOpsRepositories.ConvertAll<Repository>(p => p);

if (repositories.Count <= 0)
{
Expand All @@ -62,7 +62,7 @@ public List<PullRequest> QueryPullRequests(PullRequestQueryRequest request)
_logger.LogInformation("Querying pull requests from Azure DevOps");
var azureDevOpsPullRequests =
_memoryCache.Get<List<AzureDevOpsPullRequest>>(CacheConstants.PullRequestCacheKey) ?? [];
var pullRequests = azureDevOpsPullRequests.ConvertAll(p => (PullRequest)p);
var pullRequests = azureDevOpsPullRequests.ConvertAll<PullRequest>(p => p);

if (pullRequests.Count <= 0)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,13 @@ namespace CodeHub.Platform.GitHub.Services;

internal sealed class GitHubConnectionService : IGitHubConnectionService
{
private readonly GitHubClient _client;
public GitHubClient Client { get; }

public GitHubConnectionService(IOptions<GitHubSettings> options)
{
_client = new GitHubClient(new ProductHeaderValue(options.Value.AgentName))
Client = new GitHubClient(new ProductHeaderValue(options.Value.AgentName))
{
Credentials = new Credentials(options.Value.Token)
};
}

public GitHubClient Client()
{
return _client;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,6 @@ public List<Repository> QueryRepositories(RepositoryQueryRequest request)

public List<PullRequest> QueryPullRequests(PullRequestQueryRequest request)
{
return [];
throw new NotImplementedException();
}
}
6 changes: 3 additions & 3 deletions src/backend/CodeHub.Platform.GitHub/Services/GitHubService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,15 @@ public GitHubService(IGitHubConnectionService gitHubConnectionService)
public async Task<List<Repository>> GetRepositoriesAsync(CancellationToken cancellationToken)
{
var repositories =
await _gitHubConnectionService.Client().Repository.GetAllForCurrent().WaitAsync(cancellationToken) ?? [];
await _gitHubConnectionService.Client.Repository.GetAllForCurrent().WaitAsync(cancellationToken) ?? [];
return repositories.Select(r => r.MapToRepository()).ToList();
}

public async Task<List<Pipeline>> GetActionsAsync(string owner, string repository,
CancellationToken cancellationToken)
{
var pipelines = await _gitHubConnectionService.Client().Actions.Workflows.List(owner, repository);
var jobs = await _gitHubConnectionService.Client().Actions.Workflows.Runs.List(owner, repository);
var pipelines = await _gitHubConnectionService.Client.Actions.Workflows.List(owner, repository);
var jobs = await _gitHubConnectionService.Client.Actions.Workflows.Runs.List(owner, repository);

var workflows = pipelines.Workflows.GroupJoin(jobs.WorkflowRuns,
workflow => workflow.Id,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,5 @@ namespace CodeHub.Platform.GitHub.Services;

internal interface IGitHubConnectionService
{
GitHubClient Client();
GitHubClient Client { get; }
}
10 changes: 10 additions & 0 deletions src/backend/CodeHub.Platform.GitLab/CodeHub.Platform.GitLab.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<Project Sdk="Microsoft.NET.Sdk">
<ItemGroup>
<PackageReference Include="NGitLab"/>
<PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions"/>
<PackageReference Include="Microsoft.Extensions.Caching.Memory"/>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\CodeHub.Shared\CodeHub.Shared.csproj"/>
</ItemGroup>
</Project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
namespace CodeHub.Platform.GitLab.Constants;

internal static class CacheConstants
{
internal const string PipelineCacheKey = "gitlab-pipelines";
internal const string PullRequestCacheKey = "gitlab-pullrequests";
internal const string RepositoryCacheKey = "gitlab-repositories";
}
48 changes: 48 additions & 0 deletions src/backend/CodeHub.Platform.GitLab/Extensions/GitLabExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
using CodeHub.Platform.GitLab.Models;
using CodeHub.Platform.GitLab.Services;
using CodeHub.Platform.GitLab.Validator;
using CodeHub.Shared.Query;
using CodeHub.Shared.Services;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;

namespace CodeHub.Platform.GitLab.Extensions;

public static class GitLabExtensions
{
public static IServiceCollection RegisterGitLab(this IServiceCollection services,
IConfiguration configuration)
{
var settings = GitLabSettingsValidator.GetValidSettings(configuration);

if (!settings.IsEnabled)
{
return services;
}

services.RegisterCache();
services.RegisterServices();
services.RegisterOptions(configuration);
return services;
}

private static void RegisterCache(this IServiceCollection services)
{
services.AddMemoryCache(options => options.TrackStatistics = true);
}

private static void RegisterServices(this IServiceCollection services)
{
services.TryAddSingleton<IGitLabConnectionService, GitLabConnectionService>();
services.TryAddSingleton<IGitLabService, GitLabService>();
services.AddScoped<IQueryService, GitLabQueryService>();
services.AddSingleton<IDiscoveryService, GitLabDiscoveryService>();
}

private static void RegisterOptions(this IServiceCollection services, IConfiguration configuration)
{
services.AddOptions<GitLabSettings>()
.Bind(configuration.GetRequiredSection(nameof(GitLabSettings)));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
using System.Collections.Immutable;
using CodeHub.Platform.GitLab.Models;
using CodeHub.Shared.Models;
using NGitLab.Models;
using Commit = CodeHub.Shared.Models.Commit;

namespace CodeHub.Platform.GitLab.Extensions;

internal static class GitLabMapperExtensions
{
internal static GitLabPullRequest MapToGitLabPullRequest(this MergeRequest mergeRequest)
{
return new GitLabPullRequest
{
Id = new PullRequestId(mergeRequest.Id.ToString()),
Name = mergeRequest.Title,
Description = mergeRequest.Description,
Url = new Uri(mergeRequest.WebUrl),
Labels = mergeRequest.Labels.ToImmutableHashSet(),
Reviewers = mergeRequest.Reviewers.Select(r => r.Name).ToImmutableHashSet(),
Status = PullRequestStatus.Draft,
Platform = PullRequestPlatform.GitLab,
LastCommit = new Commit
{
Id = new CommitId(""),
Url = new Uri(mergeRequest.WebUrl),
Committer = string.Empty,
Comment = string.Empty,
ChangeCount = 0
},
RepositoryUrl = new Uri(mergeRequest.WebUrl),
RepositoryName = string.Empty,
CreatedOnDate = DateOnly.FromDateTime(mergeRequest.CreatedAt)
};
}

internal static GitLabPipeline MapToGitLabPipeline(this PipelineBasic pipeline)
{
return new GitLabPipeline
{
Id = new PipelineId(pipeline.Id.ToString()),
Name = pipeline.Name,
Url = new Uri(pipeline.WebUrl),
Owner = Owner.CreateEmptyOwner(),
Platform = PipelinePlatform.GitLab
};
}

internal static GitLabRepository MapToGitLabRepository(this Project project)
{
return new GitLabRepository
{
Id = new RepositoryId(project.Id.ToString()),
Name = project.Name,
Url = new Uri(project.WebUrl),
DefaultBranch = project.DefaultBranch,
Owner = new Owner
{
Id = new OwnerId(project.Owner.Id.ToString()),
Name = project.Owner.Name,
Description = project.Owner.Bio,
Url = new Uri(project.Owner.WebURL),
Platform = OwnerPlatform.AzureDevOps
},
Platform = RepositoryPlatform.GitLab
};
}
}
7 changes: 7 additions & 0 deletions src/backend/CodeHub.Platform.GitLab/Models/GitLabPipeline.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
using CodeHub.Shared.Models;

namespace CodeHub.Platform.GitLab.Models;

public sealed record GitLabPipeline : Pipeline
{
}
Loading

0 comments on commit cea7432

Please sign in to comment.