Compare commits

...
Author SHA1 Message Date
mesh-admin 4d9b4fdfa6 Merge pull request 'The catalogue declares the event it emits on starting' (#129) from fix/the-catalogue-declares-the-event-it-emits into main 2026-09-28 07:49:06 +00:00
jschoubben eff11b1d4d The catalogue declares the event it emits on starting
Its runtime announces that it has just started and may have missed builds — the event the control
plane follows to replay them — and its manifest did not declare it. A module's authority on the bus
is derived from what it declares, so the publish was refused and the runtime died on start, in a
loop, with the mesh's graph never catching up.
2026-09-28 09:49:03 +02:00
mesh-admin 4ead13d4d4 Merge pull request 'A merge says which files it changed' (#128) from feat/a-merge-rebuilds-what-it-changed into main 2026-09-28 07:20:05 +00:00
jschoubben 3b77dde666 A merge says which files it changed
Every module built from a repository was rebuilt for a change to any of them: one merge in this
repository meant twenty-six builds, which is what exhausted a public registry's pull limit. The
forge lists the files a merge changed and the event carries them, from the watcher and from the
merge tool alike; a merge that changed more files than were asked for says so, and the mesh then
treats the whole repository as changed rather than guessing.
2026-09-28 09:17:38 +02:00
mesh-admin 5ea4961980 Merge pull request 'A merge older than the watching is history, not news' (#127) from fix/a-merge-older-than-the-watching-is-history into main 2026-09-28 03:08:22 +00:00
mesh-admin 719fb1e025 Merge pull request 'A merge the forge announces is said in its log' (#126) from fix/a-merge-announced-is-said into main 2026-09-28 02:44:19 +00:00
jschoubben ac5630bee2 A merge the forge announces is said in its log
A trigger that fires silently is indistinguishable from one that did not fire (novox/hq issue
131); the announcement is now one line an operator can read.
2026-09-28 04:44:17 +02:00
4 changed files with 27 additions and 1 deletions
+11
View File
@@ -229,6 +229,17 @@ export class GiteaClient {
return GiteaClient.mapPull(await this.request<any>(`/repos/${owner}/${repo}/pulls/${index}`));
}
/** The files a merged pull request changed, as paths from the repository's root.
*
* `limit` is what is asked for, and a merge that changed more says so rather than being read
* page by page: what the mesh does with a partial list is treat the whole repository as changed,
* so more pages would buy nothing. */
async listPullFiles(owner: string, repo: string, index: number, limit = 100): Promise<{ paths: string[]; truncated: boolean }> {
const files = await this.request<any[]>(`/repos/${owner}/${repo}/pulls/${index}/files?limit=${limit}`);
const paths = (files ?? []).map((f) => String(f?.filename ?? "")).filter((p) => p !== "");
return { paths, truncated: paths.length >= limit };
}
async createPullRequest(
owner: string,
repo: string,
+9
View File
@@ -95,6 +95,10 @@ async function pollMerged(client: GiteaClient): Promise<void> {
// at once.
const fresh = !!pull.merged_at && !!since && pull.merged_at > since;
if (primedMerges && fresh) {
// What it changed, asked for only now: a module is rebuilt because a file inside its own
// directory moved, and without this every module built from a repository is rebuilt for a
// change to any of them (novox/hq 04-ISSUES/131).
const changed = await client.listPullFiles(repo.owner, repo.name, pull.number);
await emit("pull.merged", {
owner: repo.owner,
repo: repo.name,
@@ -106,7 +110,12 @@ async function pollMerged(client: GiteaClient): Promise<void> {
merged_at: pull.merged_at,
clone_url: repo.clone_url,
html_url: pull.html_url,
paths: changed.paths,
paths_truncated: changed.truncated,
});
// Said, because a trigger that fires silently is indistinguishable from one that did not
// fire (novox/hq 04-ISSUES/131) — this line is how an operator knows the mesh was told.
console.log(`[gitea] announced merge ${repo.full_name}#${pull.number} (${pull.merge_commit_sha.slice(0, 8)}) into ${pull.base}`);
}
announced.add(pull.merge_commit_sha);
changed = true;
+5
View File
@@ -233,6 +233,9 @@ export function getGiteaTools(gitea: GiteaClient): ToolDefinition[] {
await gitea.mergePullRequest(owner, repo, number, method, deleteBranch);
// Read it again: the merge commit only exists now, and it is what a build is made from.
const merged = await gitea.getPullRequest(owner, repo, number);
// And what it changed, so the mesh rebuilds the modules whose own files moved rather than
// every module built from the repository (novox/hq 04-ISSUES/131).
const changed = await gitea.listPullFiles(owner, repo, number);
await emit("pull.merged", {
owner,
repo,
@@ -244,6 +247,8 @@ export function getGiteaTools(gitea: GiteaClient): ToolDefinition[] {
merged_at: merged.merged_at,
method,
html_url: pull.html_url,
paths: changed.paths,
paths_truncated: changed.truncated,
});
return { merged: true, number, method, deleted_branch: deleteBranch };
},
+2 -1
View File
@@ -34,7 +34,8 @@
"emits": [
"registered",
"upgraded",
"rebuild-needed"
"rebuild-needed",
"catching-up"
],
"resources": [
{