107 lines
3.9 KiB
Go
107 lines
3.9 KiB
Go
package bridge
|
|
|
|
import (
|
|
"fmt"
|
|
"strings"
|
|
|
|
"git.novox.be/novox/mesh-sdk/go/delivery"
|
|
)
|
|
|
|
// Call is a call of a forge tool: the tool by its manifest key and its arguments.
|
|
type Call struct {
|
|
Tool string
|
|
Args map[string]any
|
|
}
|
|
|
|
// Act is one thing the bridge does on the forge for a key of the gate: the act's name (an owed key's act, `status=<context>`,
|
|
// `view`, `note`, `comment.<seq>`), the pull request and head it is on (Number 0 for a commit no pull
|
|
// request names) and the forge call that performs it.
|
|
type Act struct {
|
|
Name string
|
|
Repository string
|
|
Number int
|
|
Head string
|
|
Call Call
|
|
}
|
|
|
|
// The forge's tools, by manifest key; their arguments are the ones of mesh-catalog modules/gitea: delivery.ts
|
|
// commitStatusTool (owner, repo, sha, context, state, description, target_url), tools/index.ts gitea_delivery_view
|
|
// (owner, repo, number, body), gitea_note_append (owner, repo, sha, ref, line), gitea_add_comment (owner, repo,
|
|
// number, body).
|
|
const (
|
|
commitStatusTool = "gitea.gitea_commit_status"
|
|
deliveryViewTool = "gitea.gitea_delivery_view"
|
|
noteAppendTool = "gitea.gitea_note_append"
|
|
addCommentTool = "gitea.gitea_add_comment"
|
|
)
|
|
|
|
func ownerRepo(repository string) (owner, repo string) {
|
|
owner, repo, _ = strings.Cut(repository, "/")
|
|
return owner, repo
|
|
}
|
|
|
|
// OwedAct turns an owed key and its value (mesh-sdk go/delivery OwedKey, EncodeOwed) into the forge call that performs
|
|
// it. A key that is no owed key, a value that is no owed act, a value whose act is not the key's, and a view or a comment
|
|
// on no pull request are errors, each saying why.
|
|
func OwedAct(key string, value []byte) (Act, error) {
|
|
repository, number, head, name, err := delivery.ParseOwedKey(key)
|
|
if err != nil {
|
|
return Act{}, err
|
|
}
|
|
o, err := delivery.DecodeOwed(value)
|
|
if err != nil {
|
|
return Act{}, fmt.Errorf("the owed act %s: %w", key, err)
|
|
}
|
|
kind, context, err := delivery.ParseOwedAct(name)
|
|
if err != nil {
|
|
return Act{}, err
|
|
}
|
|
if o.Act != kind {
|
|
return Act{}, fmt.Errorf("the owed act %s says %q, not the %q its key names", key, o.Act, kind)
|
|
}
|
|
owner, repo := ownerRepo(repository)
|
|
a := Act{Name: name, Repository: repository, Number: number, Head: head}
|
|
needsPull := func() error {
|
|
if number <= 0 {
|
|
return fmt.Errorf("the owed %s %s is on a commit no pull request names, and it needs the pull request", kind, key)
|
|
}
|
|
return nil
|
|
}
|
|
switch kind {
|
|
case delivery.OwedStatus:
|
|
if o.Context != context {
|
|
return Act{}, fmt.Errorf("the owed status %s says the context %q, not the %q its key names", key, o.Context, context)
|
|
}
|
|
a.Call = Call{Tool: commitStatusTool, Args: map[string]any{"owner": owner, "repo": repo, "sha": head, "context": o.Context,
|
|
"state": o.State, "description": o.Text, "target_url": o.Target}}
|
|
case delivery.OwedView:
|
|
if err := needsPull(); err != nil {
|
|
return Act{}, err
|
|
}
|
|
a.Call = Call{Tool: deliveryViewTool, Args: map[string]any{"owner": owner, "repo": repo, "number": number, "body": o.Text}}
|
|
case delivery.OwedNote:
|
|
a.Call = Call{Tool: noteAppendTool, Args: map[string]any{"owner": owner, "repo": repo, "sha": head, "ref": o.Ref, "line": o.Text}}
|
|
case delivery.OwedComment:
|
|
if err := needsPull(); err != nil {
|
|
return Act{}, err
|
|
}
|
|
a.Call = Call{Tool: addCommentTool, Args: map[string]any{"owner": owner, "repo": repo, "number": number, "body": o.Text}}
|
|
}
|
|
return a, nil
|
|
}
|
|
|
|
// RefusedMessage is the refused message the bridge writes on FORGE when the forge refuses an act: the act, the pull
|
|
// request and head it was on, and the forge's own words.
|
|
func RefusedMessage(a Act, words string) (Message, error) {
|
|
event, err := delivery.ForgeEvent(a.Repository, delivery.ForgeRefused)
|
|
if err != nil {
|
|
return Message{}, err
|
|
}
|
|
body, err := delivery.EncodeForge(delivery.Forge{Kind: delivery.ForgeRefused, Repository: a.Repository, Number: a.Number,
|
|
Head: a.Head, Act: a.Name, Words: words})
|
|
if err != nil {
|
|
return Message{}, err
|
|
}
|
|
return Message{Event: event, Data: body}, nil
|
|
}
|