OPC # 0006: OPC Git Trunk-Based management
Co-authored-by: Copilot <copilot@github.com>
This commit is contained in:
@@ -138,7 +138,7 @@ public class PromotionService(IConfiguration config, ILogger<PromotionService> l
|
||||
}
|
||||
|
||||
result.Add(new BranchStatus(branchName, true, tip.Sha[..7], summary,
|
||||
ahead, behind, unreleasedCommits));
|
||||
ahead, behind, unreleasedCommits, tip.Sha));
|
||||
}
|
||||
|
||||
return result;
|
||||
@@ -716,6 +716,49 @@ public class PromotionService(IConfiguration config, ILogger<PromotionService> l
|
||||
try { return JsonSerializer.Deserialize<List<PromotionRequest>>(File.ReadAllText(HistoryPath), JsonOpts) ?? []; }
|
||||
catch { return []; }
|
||||
}
|
||||
|
||||
// ── OPC number extraction ─────────────────────────────────────────────
|
||||
|
||||
private static readonly System.Text.RegularExpressions.Regex OpcTagPattern =
|
||||
new(@"OPC\s*#\s*(\d+)", System.Text.RegularExpressions.RegexOptions.IgnoreCase
|
||||
| System.Text.RegularExpressions.RegexOptions.Compiled);
|
||||
|
||||
/// <summary>
|
||||
/// Scans the most recent <paramref name="limit"/> commits on <paramref name="branch"/> and
|
||||
/// returns a distinct, sorted list of OPC numbers referenced in commit messages (e.g. "OPC # 0042").
|
||||
/// Safe to call when git is not configured — returns an empty list on any error.
|
||||
/// </summary>
|
||||
public Task<List<string>> ExtractOpcNumbersAsync(
|
||||
string repoName = "Clarity",
|
||||
string branch = "main",
|
||||
int limit = 50,
|
||||
CancellationToken ct = default) =>
|
||||
Task.Run(() => ExtractOpcNumbersCore(repoName, branch, limit), ct);
|
||||
|
||||
private List<string> ExtractOpcNumbersCore(string repoName, string branch, int limit)
|
||||
{
|
||||
var repoPath = GetRepoPath(repoName);
|
||||
if (string.IsNullOrWhiteSpace(repoPath) || !Directory.Exists(repoPath))
|
||||
return [];
|
||||
try
|
||||
{
|
||||
using var repo = new Repository(repoPath);
|
||||
var b = repo.Branches[branch] ?? repo.Branches[$"origin/{branch}"];
|
||||
if (b is null) return [];
|
||||
|
||||
var set = new HashSet<string>(StringComparer.Ordinal);
|
||||
foreach (var commit in b.Commits.Take(limit))
|
||||
foreach (System.Text.RegularExpressions.Match m in OpcTagPattern.Matches(commit.Message))
|
||||
set.Add($"OPC # {m.Groups[1].Value.PadLeft(4, '0')}");
|
||||
|
||||
return [.. set.OrderBy(x => x)];
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
logger.LogWarning(ex, "ExtractOpcNumbers failed for {Repo}/{Branch}", repoName, branch);
|
||||
return [];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>A single unreleased commit — carries full SHA for cherry-pick operations.</summary>
|
||||
@@ -729,5 +772,6 @@ public record BranchStatus(
|
||||
string? LastCommitSummary,
|
||||
int AheadOfNext, // commits this branch has that the next doesn't
|
||||
int BehindNext, // commits next has that this branch doesn't (diverged)
|
||||
CommitInfo[] UnreleasedCommits // rich commit objects for cherry-pick UI
|
||||
CommitInfo[] UnreleasedCommits, // rich commit objects for cherry-pick UI
|
||||
string? TipSha = null // full 40-char SHA for build-gate checks
|
||||
);
|
||||
|
||||
@@ -17,6 +17,7 @@ public class ReleaseService(
|
||||
IConfiguration config,
|
||||
TenantRegistryService registry,
|
||||
BuildHistoryService history,
|
||||
PromotionService promotions,
|
||||
ILogger<ReleaseService> logger)
|
||||
{
|
||||
private static readonly SemaphoreSlim _lock = new(1, 1);
|
||||
@@ -182,6 +183,11 @@ public class ReleaseService(
|
||||
}
|
||||
finally
|
||||
{
|
||||
// Stamp OPC ticket numbers from recent commits on the target branch.
|
||||
var branch = targetEnv switch { "fdev" => "develop", "staging" => "staging", "uat" => "uat", _ => "main" };
|
||||
try { record.OpcNumbers = await promotions.ExtractOpcNumbersAsync("Clarity", branch, 50, ct); }
|
||||
catch { /* git not configured — continue without OPC stamp */ }
|
||||
|
||||
await history.UpdateReleaseAsync(record);
|
||||
_lock.Release();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user