Skip to content

Commit 8ae0336

Browse files
JusterZhuclaude
andcommitted
fix: address Copilot review feedback
- Remove 'retry' from HttpRangeDownloader summary (no retry impl) - Fix auth precedence: per-package AuthScheme fully overrides global - Remove unimplented properties from HttpDownloadOptions (RequestTimeout, MaxRetryAttempts, RetryBaseDelay) - Document httpClient vs httpOptions mutual exclusivity in CreateDefault - Replace --force-with-lease with safe tag-creation check in CI Co-Authored-By: Claude <noreply@anthropic.com>
1 parent bcf4daa commit 8ae0336

4 files changed

Lines changed: 29 additions & 25 deletions

File tree

.github/workflows/publish-nuget.yml

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,11 @@ jobs:
6666
git config user.name "github-actions"
6767
git config user.email "github-actions@github.com"
6868
TAG="v${{ inputs.version }}"
69-
git tag --force "$TAG"
69+
if git rev-parse "$TAG" >/dev/null 2>&1; then
70+
echo "::error::Tag $TAG already exists. Use a different version or delete the existing tag first."
71+
exit 1
72+
fi
73+
git tag "$TAG"
7074
git push --force-with-lease origin "$TAG"
7175
7276
- name: Create GitHub Release

src/GeneralUpdate.Maui.Android/Models/HttpDownloadOptions.cs

Lines changed: 3 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ namespace GeneralUpdate.Maui.Android.Models;
55

66
/// <summary>
77
/// Configures HTTP transport behavior for update downloads:
8-
/// SSL/TLS certificate validation, timeouts, proxy, retry, and authentication.
8+
/// SSL/TLS certificate validation, proxy, timeouts, and authentication.
99
/// <para>
1010
/// When provided to <see cref="Services.GeneralUpdateBootstrap.CreateDefault"/>,
1111
/// the library constructs an internal <see cref="HttpClient"/> from these settings.
@@ -22,12 +22,6 @@ public sealed record HttpDownloadOptions
2222
/// </summary>
2323
public ISslValidationPolicy? SslValidationPolicy { get; init; }
2424

25-
/// <summary>
26-
/// Timeout for individual HTTP requests (HEAD probes, etc.).
27-
/// Default is 30 seconds.
28-
/// </summary>
29-
public TimeSpan RequestTimeout { get; init; } = TimeSpan.FromSeconds(30);
30-
3125
/// <summary>
3226
/// Overall timeout for the entire download operation.
3327
/// Default is 10 minutes.
@@ -46,23 +40,11 @@ public sealed record HttpDownloadOptions
4640
/// </summary>
4741
public bool UseProxy { get; init; }
4842

49-
/// <summary>
50-
/// Maximum number of retry attempts for transient failures.
51-
/// Default is 3 (meaning 1 initial attempt + 2 retries).
52-
/// Set to 1 to disable retry.
53-
/// </summary>
54-
public int MaxRetryAttempts { get; init; } = 3;
55-
56-
/// <summary>
57-
/// Base delay for exponential backoff retry.
58-
/// Actual delays are: baseDelay * 2^attempt.
59-
/// Default is 1 second.
60-
/// </summary>
61-
public TimeSpan RetryBaseDelay { get; init; } = TimeSpan.FromSeconds(1);
62-
6343
/// <summary>
6444
/// Global authentication provider applied to all download requests.
6545
/// Per-package authentication on <see cref="UpdatePackageInfo"/> takes precedence.
46+
/// When <see cref="UpdatePackageInfo.AuthScheme"/> is explicitly set,
47+
/// per-package credentials are used exclusively (no fallback to global).
6648
/// </summary>
6749
public IHttpAuthProvider? AuthProvider { get; init; }
6850

src/GeneralUpdate.Maui.Android/Services/GeneralUpdateBootstrap.cs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,16 @@ public static IServiceCollection AddGeneralUpdateMauiAndroid(
3434
return services;
3535
}
3636

37+
/// <summary>
38+
/// Creates a default <see cref="IAndroidBootstrap"/> with built-in service implementations.
39+
/// </summary>
40+
/// <param name="httpClient">Optional external HttpClient. Ignored when <paramref name="httpOptions"/> is provided.</param>
41+
/// <param name="logger">Optional logger.</param>
42+
/// <param name="httpOptions">
43+
/// Optional HTTP configuration (SSL, proxy, auth, timeouts).
44+
/// When set, an internal HttpClient is constructed from these options
45+
/// and <paramref name="httpClient"/> is not used.
46+
/// </param>
3747
public static IAndroidBootstrap CreateDefault(
3848
HttpClient? httpClient = null,
3949
IUpdateLogger? logger = null,
@@ -42,6 +52,7 @@ public static IAndroidBootstrap CreateDefault(
4252
if (httpOptions != null)
4353
{
4454
// Build HttpClient from HttpDownloadOptions (SSL, proxy, auth, timeouts)
55+
// Note: when httpOptions is provided, the httpClient parameter is NOT used.
4556
var handler = httpOptions.BuildHandler();
4657
var client = new HttpClient(handler, disposeHandler: true)
4758
{

src/GeneralUpdate.Maui.Android/Services/HttpRangeDownloader.cs

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
namespace GeneralUpdate.Maui.Android.Services;
88

99
/// <summary>
10-
/// HTTP downloader that supports range-based resume, authentication, retry, and progress statistics.
10+
/// HTTP downloader that supports range-based resume, authentication, and progress statistics.
1111
/// </summary>
1212
public sealed class HttpRangeDownloader : IUpdateDownloader, IDisposable
1313
{
@@ -135,11 +135,15 @@ public async Task<DownloadResult> DownloadAsync(
135135
/// <summary>
136136
/// Applies authentication to the HTTP request.
137137
/// Per-package auth takes precedence over global auth.
138+
/// When <see cref="UpdatePackageInfo.AuthScheme"/> is explicitly set,
139+
/// only per-package credentials are used (no fallback to global).
140+
/// When AuthScheme is null, the global provider is used if configured.
138141
/// </summary>
139142
private async Task ApplyAuthAsync(HttpRequestMessage request, UpdatePackageInfo packageInfo, CancellationToken cancellationToken)
140143
{
141144
IHttpAuthProvider? provider = null;
142145

146+
// Per-package auth takes full precedence when explicitly set
143147
if (packageInfo.AuthScheme.HasValue)
144148
{
145149
provider = HttpAuthProviderFactory.Create(
@@ -148,10 +152,13 @@ private async Task ApplyAuthAsync(HttpRequestMessage request, UpdatePackageInfo
148152
packageInfo.AuthSecretKey,
149153
packageInfo.BasicUsername,
150154
packageInfo.BasicPassword);
151-
}
152155

153-
if ((provider is null || provider is NoOpAuthProvider) && _globalAuthProvider != null)
156+
// When per-package scheme is set, do NOT fall back to global,
157+
// even if credentials are missing (NoOpAuthProvider).
158+
}
159+
else
154160
{
161+
// Only fall back to global when no per-package scheme is specified
155162
provider = _globalAuthProvider;
156163
}
157164

0 commit comments

Comments
 (0)