feat: refactor HTTP client setup for Github and Forgejo services

- Centralized HTTP client configuration for `GithubService` and `ForgejoService` using `AddHttpClient`.
- Enhanced maintainability by moving Forgejo token and base URL setup into DI-configured HTTP clients.
- Fixed `forgejoInstance` validation logic and adjusted release selection to prioritize the first non-prerelease.
This commit is contained in:
mahdium committed 2026-11-04 16:55:58 +03:30
1 parent 7ac8a5af62
commit 3b644de2d5
5 files changed
+20 -15

No files matched your search

+1
View File
@@ -13,6 +13,7 @@
<ItemGroup> <ItemGroup>
<PackageReference Include="DotNetEnv" Version="3.2.0" /> <PackageReference Include="DotNetEnv" Version="3.2.0" />
<PackageReference Include="Microsoft.Extensions.Hosting" Version="10.0.14" /> <PackageReference Include="Microsoft.Extensions.Hosting" Version="10.0.14" />
<PackageReference Include="Microsoft.Extensions.Http" Version="10.0.14" />
<PackageReference Include="RStein.TOML" Version="1.0.0" /> <PackageReference Include="RStein.TOML" Version="1.0.0" />
</ItemGroup> </ItemGroup>
+16 -10
View File
@@ -1,4 +1,5 @@
using ForgejoReleaseSync.Services; using System.Net.Http.Headers;
using ForgejoReleaseSync.Services;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Hosting;
@@ -11,12 +12,19 @@ var repositoryConfig = await RepoConfigLoader.LoadConfigAsync(
config.RepositoryConfigFilePath); config.RepositoryConfigFilePath);
builder.Services.AddSingleton(repositoryConfig); builder.Services.AddSingleton(repositoryConfig);
var client = new HttpClient(); builder.Services.AddHttpClient<GithubService>(client =>
client.DefaultRequestHeaders.Add("User-Agent", "ForgejoReleaseSync"); {
client.DefaultRequestHeaders.Add("Accept", "application/json"); client.BaseAddress = new Uri("https://api.github.com/");
client.Timeout = TimeSpan.FromMinutes(3); client.DefaultRequestHeaders.UserAgent.ParseAdd("ForgejoReleaseSync");
client.MaxResponseContentBufferSize = 1024 * 1024 * 1; client.DefaultRequestHeaders.Accept.ParseAdd("application/vnd.github+json");
builder.Services.AddSingleton(client); });
builder.Services.AddHttpClient<ForgejoService>(client =>
{
client.BaseAddress = new Uri(config.ForgejoInstacne);
client.DefaultRequestHeaders.UserAgent.ParseAdd("ForgejoReleaseSync");
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("token", config.ForgejoToken);
});
builder.Services.AddSingleton<ReleaseAssetDownloadService>(); builder.Services.AddSingleton<ReleaseAssetDownloadService>();
builder.Services.AddSingleton<GithubService>(); builder.Services.AddSingleton<GithubService>();
@@ -29,6 +37,4 @@ using var scope = app.Services.CreateScope();
await scope.ServiceProvider await scope.ServiceProvider
.GetRequiredService<SyncService>() .GetRequiredService<SyncService>()
.Sync(); .Sync();
await app.RunAsync();
+1 -1
View File
@@ -24,7 +24,7 @@ public static class AppConfigLoader
if (string.IsNullOrEmpty(forgejoInstance)) if (string.IsNullOrEmpty(forgejoInstance))
throw new Exception("FORGEJO_INSTANCE environment variable is required"); throw new Exception("FORGEJO_INSTANCE environment variable is required");
if (!string.IsNullOrEmpty(forgejoToken) && forgejoInstance.EndsWith('/')) if (!string.IsNullOrEmpty(forgejoInstance) && forgejoInstance.EndsWith('/'))
forgejoInstance = forgejoInstance[..^1]; forgejoInstance = forgejoInstance[..^1];
if (string.IsNullOrEmpty(forgejoToken)) if (string.IsNullOrEmpty(forgejoToken))
-2
View File
@@ -20,7 +20,6 @@ public class ForgejoService(HttpClient httpClient, AppConfig config, ILogger<For
HttpMethod.Post, HttpMethod.Post,
new Uri($"{config.ForgejoInstacne}/api/v1/repos/{owner}/{repo}/releases")); new Uri($"{config.ForgejoInstacne}/api/v1/repos/{owner}/{repo}/releases"));
request.Content = new StringContent(json, Encoding.UTF8, "application/json"); request.Content = new StringContent(json, Encoding.UTF8, "application/json");
request.Headers.Authorization = new AuthenticationHeaderValue("token", config.ForgejoToken);
using var response = await httpClient.SendAsync(request, token); using var response = await httpClient.SendAsync(request, token);
response.EnsureSuccessStatusCode(); response.EnsureSuccessStatusCode();
@@ -79,7 +78,6 @@ public class ForgejoService(HttpClient httpClient, AppConfig config, ILogger<For
HttpMethod.Post, HttpMethod.Post,
new Uri($"{config.ForgejoInstacne}/api/v1/repos/{owner}/{repo}/releases/{releaseId}/assets")); new Uri($"{config.ForgejoInstacne}/api/v1/repos/{owner}/{repo}/releases/{releaseId}/assets"));
request.Content = formData; request.Content = formData;
request.Headers.Authorization = new AuthenticationHeaderValue("token", config.ForgejoToken);
using var response = await httpClient.SendAsync( using var response = await httpClient.SendAsync(
request, HttpCompletionOption.ResponseHeadersRead, token); request, HttpCompletionOption.ResponseHeadersRead, token);
+2 -2
View File
@@ -36,7 +36,7 @@ public class SyncService(
var (owner, name) = ParseGithubUrl(repo.GithubUrl); var (owner, name) = ParseGithubUrl(repo.GithubUrl);
var githubReleases = await githubService.FetchRepoReleasesAsync(owner, name, token); var githubReleases = await githubService.FetchRepoReleasesAsync(owner, name, token);
var githubRelease = githubReleases.LastOrDefault(r => !r.Prerelease); var githubRelease = githubReleases.FirstOrDefault(r => !r.Prerelease);
if (githubRelease is null) if (githubRelease is null)
{ {
logger.LogWarning("{Owner}/{Name}: no GitHub release found, skipping", owner, name); logger.LogWarning("{Owner}/{Name}: no GitHub release found, skipping", owner, name);
@@ -44,7 +44,7 @@ public class SyncService(
} }
var forgejoReleases = await forgejoService.FetchRepoReleasesAsync(owner, name, token); var forgejoReleases = await forgejoService.FetchRepoReleasesAsync(owner, name, token);
var forgejoRelease = forgejoReleases.LastOrDefault(r => !r.Prerelease); var forgejoRelease = forgejoReleases.FirstOrDefault(r => !r.Prerelease);
var releaseId = await ResolveReleaseIdAsync(owner, name, githubRelease, forgejoRelease, token); var releaseId = await ResolveReleaseIdAsync(owner, name, githubRelease, forgejoRelease, token);