Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
125 changes: 111 additions & 14 deletions experiments/g01-scaleset/livecanary/ack_command_fixture_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -298,7 +298,11 @@ func (f *ackCommandFixture) brokerWire(r *http.Request) {
}
key := r.Method + " " + r.URL.Path
f.brokerAttempts = append(f.brokerAttempts, key) // count before body drain or dispatch
v3 := f.base.a.GroupPolicy.Version == 2
primary := []string{"GET " + workflowRunFixturePath(f.transport), "GET /app", "GET /orgs/fixture-org/installation", "GET " + workflowRunFixturePath(f.transport), "POST /app/installations/12/access_tokens", "GET /installation/repositories", "GET /repos/fixture-org/canary", "GET /orgs/fixture-org/actions/runner-groups/3", "GET /orgs/fixture-org/actions/runner-groups/3/repositories"}
if v3 {
primary = []string{"GET " + workflowRunFixturePath(f.transport), "GET /app", "GET /orgs/fixture-org/installation", "POST /app/installations/12/access_tokens", "GET /installation/repositories", "GET /repos/fixture-org/canary", "GET /orgs/fixture-org/actions/runner-groups/3", "GET /orgs/fixture-org/actions/runner-groups/3/repositories", "DELETE /installation/token", "GET " + workflowRunFixturePath(f.transport), "POST /app/installations/12/access_tokens", "GET /installation/repositories", "GET /repos/fixture-org/canary", "GET /orgs/fixture-org/actions/runner-groups/3", "GET /orgs/fixture-org/actions/runner-groups/3/repositories", "GET " + workflowRunFixturePath(f.transport)}
}
position := len(f.brokerAttempts) - 1 // shared lock held; already counted before drain
fresh := f.transport.attempt == f.attempt+"-fresh"
if fresh {
Expand Down Expand Up @@ -351,13 +355,21 @@ func (f *ackCommandFixture) brokerWire(r *http.Request) {
if position == 0 || fresh {
token = "synthetic-observation-credential"
}
} else if v3 && position >= 4 && position <= 7 {
token = "synthetic-process-read-installation-token"
} else if v3 && r.URL.Path == "/installation/token" {
token = "synthetic-process-read-installation-token"
}
if auth != "Bearer "+token {
t.Error("ACK broker distinct observation/verification/installation authority differs")
}
}
if key == "POST /app/installations/12/access_tokens" {
if string(data) != `{"repository_ids":[42],"permissions":{"metadata":"read","organization_self_hosted_runners":"write"}}` {
want := `{"repository_ids":[42],"permissions":{"metadata":"read","organization_self_hosted_runners":"write"}}`
if v3 && position == 3 {
want = `{"repository_ids":[42],"permissions":{"metadata":"read","organization_self_hosted_runners":"read"}}`
}
if string(data) != want {
t.Error("ACK broker exact scoped mint body differs")
}
} else if len(data) != 0 {
Expand Down Expand Up @@ -423,7 +435,7 @@ func (f *ackCommandFixture) consumption() *controllerHandoffConsumption {
}
if event.Kind == "claim" && event.Slot == f.phase && event.Provenance != nil {
p := event.Provenance
if found != nil || p.Source != "github-rest-workflow-v1" || len(p.Digest) != 64 || len(p.Nonce) != 32 {
if found != nil || p.Source != originalContextClaimSource(f.base.a) || len(p.Digest) != 64 || len(p.Nonce) != 32 {
f.t.Error("ACK original claim provenance differs")
}
found = &controllerHandoffConsumption{ReceiptNonce: p.Nonce, Phase: f.phase, ApprovalSHA256: handoff.Digest(f.raw), ReceiptSHA256: p.Digest, KeyID: "fixture-ed25519-v1"}
Expand Down Expand Up @@ -588,11 +600,22 @@ func (f *ackCommandFixture) assertBroker() {
f.brokerMu.Lock()
defer f.brokerMu.Unlock()
want := []string{"GET " + workflowRunFixturePath(f.transport), "GET /app", "GET /orgs/fixture-org/installation", "GET " + workflowRunFixturePath(f.transport), "POST /app/installations/12/access_tokens", "GET /installation/repositories", "GET /repos/fixture-org/canary", "GET /orgs/fixture-org/actions/runner-groups/3", "GET /orgs/fixture-org/actions/runner-groups/3/repositories"}
v3 := f.base.a.GroupPolicy.Version == 2
if v3 {
want = []string{"GET " + workflowRunFixturePath(f.transport), "GET /app", "GET /orgs/fixture-org/installation", "POST /app/installations/12/access_tokens", "GET /installation/repositories", "GET /repos/fixture-org/canary", "GET /orgs/fixture-org/actions/runner-groups/3", "GET /orgs/fixture-org/actions/runner-groups/3/repositories", "DELETE /installation/token", "GET " + workflowRunFixturePath(f.transport), "POST /app/installations/12/access_tokens", "GET /installation/repositories", "GET /repos/fixture-org/canary", "GET /orgs/fixture-org/actions/runner-groups/3", "GET /orgs/fixture-org/actions/runner-groups/3/repositories", "GET " + workflowRunFixturePath(f.transport)}
}
if !reflect.DeepEqual(f.brokerAttempts, f.transport.calls) {
f.t.Error("ACK broker server-entry counts differ from dispatched calls")
}
if f.transport.mints != 1 || !reflect.DeepEqual(f.transport.calls, want) {
f.t.Errorf("ACK actual broker exact trace differs: calls=%v mints=%d", f.transport.calls, f.transport.mints)
if !reflect.DeepEqual(f.transport.calls, want) {
f.t.Errorf("ACK actual broker exact trace differs: calls=%v want=%v", f.transport.calls, want)
}
if v3 {
if f.transport.mints != 2 || f.transport.readOnlyMints != 1 || f.transport.managementMints != 1 || f.transport.revocations != 1 {
f.t.Errorf("ACK actual broker issuance lifecycle differs: mints=%d read-only=%d management=%d revocations=%d", f.transport.mints, f.transport.readOnlyMints, f.transport.managementMints, f.transport.revocations)
}
} else if f.transport.mints != 1 {
f.t.Errorf("ACK actual broker issuance lifecycle differs: mints=%d", f.transport.mints)
}
raw := f.read(filepath.Join(f.attempt, "broker.jsonl"))
completed := 0
Expand Down Expand Up @@ -624,16 +647,76 @@ func (f *ackCommandFixture) assertBroker() {
}
// Completion preserves the permanent occupied claim and all its provenance.
ledger := bytes.Split(bytes.TrimSpace(f.read(filepath.Join(f.admission, "broker-admission.jsonl"))), []byte{'\n'})
if len(ledger) != 2+wantComplete {
f.t.Error("ACK exact broker claim/completion count differs")
} else if wantComplete == 1 {
var claim, completion map[string]any
if json.Unmarshal(ledger[1], &claim) != nil || json.Unmarshal(ledger[2], &completion) != nil || claim["kind"] != "claim" || completion["kind"] != "complete" {
f.t.Error("ACK durable broker claim/completion unavailable")
workflowEvents := 0
claimIndex := 1
for claimIndex < len(ledger) {
var event struct {
Kind string `json:"kind"`
}
if json.Unmarshal(ledger[claimIndex], &event) != nil {
f.t.Error("ACK admission event decode differs")
break
}
if event.Kind == "claim" {
break
}
completion["kind"] = "claim"
if !reflect.DeepEqual(claim, completion) {
f.t.Error("ACK completion changed occupied claim/provenance")
if strings.HasPrefix(event.Kind, "workflow_provenance_get_") {
workflowEvents++
}
claimIndex++
}
wantLedger := 2 + workflowEvents + wantComplete
if workflowEvents != 0 && workflowEvents != 2 {
f.t.Errorf("ACK workflow provenance lifecycle events=%d, want none or a start/confirmation pair", workflowEvents)
}
if v3 {
wantLedger += 2 // read-token lifecycle start and confirmation surround completion.
}
completionIndex := claimIndex + 1
if v3 {
completionIndex += 2
}
if len(ledger) != wantLedger || claimIndex >= len(ledger) {
f.t.Errorf("ACK exact broker claim/completion count differs: events=%d want=%d claim-index=%d", len(ledger), wantLedger, claimIndex)
} else {
var claimIdentity struct {
Kind string `json:"kind"`
Slot string `json:"slot"`
Attempt json.RawMessage `json:"attempt"`
Journal json.RawMessage `json:"journal"`
Provenance struct {
Source string `json:"source"`
} `json:"provenance"`
}
if json.Unmarshal(ledger[claimIndex], &claimIdentity) != nil || claimIdentity.Kind != "claim" {
f.t.Error("ACK durable broker claim unavailable")
}
if workflowEvents == 2 {
if !workflowProvenancePairMatchesClaim(ledger[1], ledger[2], ledger[claimIndex]) {
f.t.Error("ACK workflow provenance lifecycle claim identity differs")
}
}
if v3 {
var started, confirmed struct {
Kind string `json:"kind"`
Slot string `json:"slot"`
Attempt json.RawMessage `json:"attempt"`
Journal json.RawMessage `json:"journal"`
}
readTokenStartIndex := claimIndex + 1
if json.Unmarshal(ledger[readTokenStartIndex], &started) != nil || json.Unmarshal(ledger[readTokenStartIndex+1], &confirmed) != nil || started.Kind != "read_token_lifecycle_started" || confirmed.Kind != "read_token_lifecycle_confirmed" || started.Slot != claimIdentity.Slot || confirmed.Slot != claimIdentity.Slot || !bytes.Equal(started.Attempt, claimIdentity.Attempt) || !bytes.Equal(started.Journal, claimIdentity.Journal) || !bytes.Equal(confirmed.Attempt, claimIdentity.Attempt) || !bytes.Equal(confirmed.Journal, claimIdentity.Journal) {
f.t.Error("ACK read-token lifecycle claim identity differs")
}
}
if wantComplete == 1 {
var claim, completion map[string]any
if json.Unmarshal(ledger[claimIndex], &claim) != nil || json.Unmarshal(ledger[completionIndex], &completion) != nil || claim["kind"] != "claim" || completion["kind"] != "complete" {
f.t.Error("ACK durable broker claim/completion unavailable")
}
completion["kind"] = "claim"
if !reflect.DeepEqual(claim, completion) {
f.t.Error("ACK completion changed occupied claim/provenance")
}
}
}
snapshot := f.read(filepath.Join(f.attempt, "controller-approval.json"))
Expand All @@ -652,7 +735,21 @@ func (f *ackCommandFixture) validatePreparation(receipt PreparationReceipt, phas
return preparedIdentity(info)
}
claimPath := f.base.j.claim.file.Name()
want := PreparationReceipt{Version: 1, Status: "controller_journal_prepared", Phase: phase, ApprovalDigest: approvalDigest(f.base.a), State: identity(f.base.j.directory), Journal: identity(filepath.Join(f.base.j.directory, "journal.jsonl")), Claim: identity(claimPath), AdmissionDirectory: identity(f.admission), JournalDigest: handoff.Digest(journal), ClaimDigest: handoff.Digest(f.read(claimPath))}
var rootBinding *handoff.RootBinding
if f.base.a.GroupPolicy.Version == 2 && phase == f.phase {
_, workflow, issuer, e := handoff.DecodePublicPolicy([]byte(experimentalPolicy(f.t, f.base.a, f.raw, "controller", phase, "controller")), "controller", time.Now())
if e != nil {
f.t.Error("ACK reusable-callee policy decode differs")
} else {
binding, e := handoff.NewRootBinding(workflow, issuer)
if e != nil {
f.t.Error("ACK reusable-callee root binding unavailable")
} else {
rootBinding = &binding
}
}
}
want := PreparationReceipt{Version: 1, Status: "controller_journal_prepared", Phase: phase, ApprovalDigest: approvalDigest(f.base.a), State: identity(f.base.j.directory), Journal: identity(filepath.Join(f.base.j.directory, "journal.jsonl")), Claim: identity(claimPath), AdmissionDirectory: identity(f.admission), JournalDigest: handoff.Digest(journal), ClaimDigest: handoff.Digest(f.read(claimPath)), RootBinding: rootBinding}
if !reflect.DeepEqual(receipt, want) {
f.t.Error("ACK actual preparation full concrete receipt differs")
}
Expand Down
Loading