OPC # 0006: OPC Git Trunk-Based management
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
using ControlPlane.Core.Models;
|
||||
using ControlPlane.Core.Services;
|
||||
using LibGit2Sharp;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using System.Diagnostics;
|
||||
@@ -24,9 +25,14 @@ public class ProjectBuildService(
|
||||
|
||||
return
|
||||
[
|
||||
new("Clarity.Server", BuildKind.DotnetProject, "Clarity.Server/Clarity.Server.csproj"),
|
||||
new("Clarity.ServiceDefaults", BuildKind.DotnetProject, "Clarity.ServiceDefaults/Clarity.ServiceDefaults.csproj"),
|
||||
new("frontend (Clarity.Server)", BuildKind.NpmProject, "frontend"),
|
||||
// ── Solution-level builds (primary targets) ──────────────────────
|
||||
new("Clarity Solution", BuildKind.SolutionBuild, "Clarity/Clarity.slnx"),
|
||||
new("ControlPlane Solution", BuildKind.SolutionBuild, "OPC/ControlPlane.slnx"),
|
||||
|
||||
// ── Individual Clarity projects ───────────────────────────────────
|
||||
new("Clarity.Server", BuildKind.DotnetProject, "Clarity/Clarity.Server/Clarity.Server.csproj"),
|
||||
new("Clarity.ServiceDefaults", BuildKind.DotnetProject, "Clarity/Clarity.ServiceDefaults/Clarity.ServiceDefaults.csproj"),
|
||||
new("frontend (Clarity.Server)", BuildKind.NpmProject, "Clarity/frontend"),
|
||||
];
|
||||
}
|
||||
|
||||
@@ -53,6 +59,16 @@ public class ProjectBuildService(
|
||||
record.Log.Add("──────────────────────────────────────");
|
||||
onLine($"▶ Building {def.Name}");
|
||||
|
||||
// Capture HEAD SHA so the build is traceable to a specific commit
|
||||
try
|
||||
{
|
||||
using var gitRepo = new Repository(RepoRoot);
|
||||
record.CommitSha = gitRepo.Head.Tip?.Sha;
|
||||
if (record.CommitSha is not null)
|
||||
record.Log.Add($" Commit: {record.CommitSha[..8]}");
|
||||
}
|
||||
catch { /* not a git repo or no commits yet */ }
|
||||
|
||||
try
|
||||
{
|
||||
var (exe, args, workDir) = def.Kind == BuildKind.NpmProject
|
||||
|
||||
@@ -4,7 +4,7 @@ using System.Text.Json.Serialization;
|
||||
namespace ControlPlane.Core.Models;
|
||||
|
||||
public enum BuildStatus { Running, Succeeded, Failed }
|
||||
public enum BuildKind { DockerImage, DotnetProject, NpmProject }
|
||||
public enum BuildKind { DockerImage, DotnetProject, NpmProject, SolutionBuild }
|
||||
|
||||
/// <summary>
|
||||
/// Persisted record of a single build run — image build, dotnet build, or npm build.
|
||||
|
||||
@@ -64,7 +64,7 @@ function GitHistoryPanel({ relativePath }: { relativePath: string }) {
|
||||
<p style={{ fontSize: '0.75rem', color: '#8f99a8', marginTop: '0.5rem' }}>No commits found for this path.</p>
|
||||
)}
|
||||
{commits.length > 0 && (
|
||||
<HTMLTable className="bp5-html-table-condensed bp5-html-table-striped" style={{ width: '100%', marginTop: '0.5rem', fontSize: '0.72rem' }}>
|
||||
<HTMLTable className="bp6-html-table-condensed bp6-html-table-striped" style={{ width: '100%', marginTop: '0.5rem', fontSize: '0.72rem' }}>
|
||||
<thead>
|
||||
<tr>
|
||||
<th style={{ width: 60 }}>Commit</th>
|
||||
@@ -250,9 +250,9 @@ export default function BuildMonitorPage() {
|
||||
|
||||
useEffect(() => { (async () => { await load(); })(); }, []);
|
||||
|
||||
// Find latest build per project
|
||||
const lastBuildFor = (name: string): BuildRecord | undefined =>
|
||||
history.find((b) => b.target.includes(name.split(' ')[0]) || b.target.endsWith(name));
|
||||
// Find latest build per project — match exactly by relativePath (= build target)
|
||||
const lastBuildFor = (project: ProjectDefinition): BuildRecord | undefined =>
|
||||
history.find((b) => b.target === project.relativePath);
|
||||
|
||||
return (
|
||||
<>
|
||||
@@ -292,7 +292,7 @@ export default function BuildMonitorPage() {
|
||||
<ProjectCard
|
||||
key={p.name}
|
||||
project={p}
|
||||
lastBuild={lastBuildFor(p.name)}
|
||||
lastBuild={lastBuildFor(p)}
|
||||
onBuilt={load}
|
||||
/>
|
||||
))}
|
||||
|
||||
@@ -226,7 +226,7 @@ export default function PipelinesPage() {
|
||||
try {
|
||||
const [r, b] = await Promise.all([getReleaseHistory(), getBuildHistory()]);
|
||||
setReleases(r);
|
||||
setBuilds(b.filter((b) => b.kind === 'DockerImage'));
|
||||
setBuilds(b.filter((b) => b.kind === 'SolutionBuild'));
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
@@ -252,7 +252,7 @@ export default function PipelinesPage() {
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h3 style={{ margin: '0 0 0.5rem' }}>Image Build History</h3>
|
||||
<h3 style={{ margin: '0 0 0.5rem' }}>Solution Build History</h3>
|
||||
{loading ? <Spinner size={20} /> : <BuildHistoryTable records={builds} />}
|
||||
</section>
|
||||
</>
|
||||
|
||||
Reference in New Issue
Block a user