The operator, 2026-11-04: logic one module owns lives inside that module as a package of its own, so the take-in step changes no mesh-sdk. TakeIn, its keys and event names, PendingWait and PendingAnswer move to modules/mesh-delivery-indexer/takein (its merges a takein.Merge of its own); Forge whole, with its group fields, ForgeGroupEnd and GroupMerge, moves to modules/mesh-delivery-forge-bridge/forgemsg. Both are nested Go modules that their readers take by replace, as buildrun is. Every importer moves in this commit: the indexer, the bridge, the watchman and the view. Forge's private checks (the repository name, the version) are copied small; mesh-sdk main still holds an unused Forge until its own fold removes it. The indexer, bridge, watchman, view and checker pin mesh-sdk 5a38a12 (origin/main), no feat/take-in commit. The bridge's integration bus now grants the state end-asks that bridge_group_end_again added: without it every test of the package failed on a permissions violation. Test budget: two new test functions (TestForge, TestTakeInEvents) and the two the join added are paid by merging four pairs in internal/bridge; the repository stays at 806 unit tests. Claude-Session: https://claude.ai/code/session_01JG73KG7AfSdh6FP8VrBqCn
79 lines
2.6 KiB
Go
79 lines
2.6 KiB
Go
package forgemsg
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"reflect"
|
|
)
|
|
|
|
// ForgeGroupEndEvent is the name of a delivery group's end on the forge bridge's stream (novox/hq ADR 0633 §4): the
|
|
// bridge publishes it once every approved member of the group is merged, after the last member's merged message. It
|
|
// has three parts, so no repository's forge event (`forge.<owner>.<name>.<kind>`) is ever this name.
|
|
const ForgeGroupEndEvent = "forge.group.merged"
|
|
|
|
// GroupMerge is one merged member of a delivery group: the repository as `<owner>/<name>`, its pull request and the
|
|
// merge commit the forge made of it.
|
|
type GroupMerge struct {
|
|
Repository string `json:"repository"`
|
|
Number int `json:"number"`
|
|
Merge string `json:"merge"`
|
|
}
|
|
|
|
// ForgeGroupEnd is the body of ForgeGroupEndEvent: the group and every member merged in it, with its merge commit.
|
|
// The indexer takes the members it holds in as one source revision once it hears it (ADR 0633 §4).
|
|
type ForgeGroupEnd struct {
|
|
V int `json:"v"`
|
|
Group string `json:"group"`
|
|
Members []GroupMerge `json:"members"`
|
|
}
|
|
|
|
func (e ForgeGroupEnd) check() error {
|
|
if e.Group == "" {
|
|
return fmt.Errorf("delivery: a group's end names its group")
|
|
}
|
|
if len(e.Members) == 0 {
|
|
return fmt.Errorf("delivery: the end of the group %q names no member merged in it", e.Group)
|
|
}
|
|
seen := map[string]bool{}
|
|
for _, m := range e.Members {
|
|
if err := checkRepository(m.Repository); err != nil {
|
|
return err
|
|
}
|
|
if m.Number <= 0 || m.Merge == "" {
|
|
return fmt.Errorf("delivery: the member %s of the group %q's end needs its pull request number and merge commit", m.Repository, e.Group)
|
|
}
|
|
k := fmt.Sprintf("%s#%d", m.Repository, m.Number)
|
|
if seen[k] {
|
|
return fmt.Errorf("delivery: the end of the group %q names its member %s twice", e.Group, k)
|
|
}
|
|
seen[k] = true
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// EncodeForgeGroupEnd is e as JSON at Version; it refuses an end with no group or no member, and a member without its
|
|
// pull request or merge commit.
|
|
func EncodeForgeGroupEnd(e ForgeGroupEnd) ([]byte, error) {
|
|
if err := e.check(); err != nil {
|
|
return nil, err
|
|
}
|
|
e.V = Version
|
|
return json.Marshal(e)
|
|
}
|
|
|
|
// DecodeForgeGroupEnd reads a group's end; it refuses an unknown version (ErrUnknownVersion) and what
|
|
// EncodeForgeGroupEnd refuses.
|
|
func DecodeForgeGroupEnd(data []byte) (ForgeGroupEnd, error) {
|
|
var e ForgeGroupEnd
|
|
if err := decode(data, &e); err != nil {
|
|
return ForgeGroupEnd{}, err
|
|
}
|
|
if err := e.check(); err != nil {
|
|
return ForgeGroupEnd{}, err
|
|
}
|
|
return e, nil
|
|
}
|
|
|
|
// SameForgeGroupEnd says whether two group ends are the same value.
|
|
func SameForgeGroupEnd(a, b ForgeGroupEnd) bool { return reflect.DeepEqual(a, b) }
|