GitRoot
craft your forge, build your project, grow your community freely
1// SPDX-FileCopyrightText: 2025 Romain Maneschi <romain@gitroot.dev>
2//
3// SPDX-License-Identifier: EUPL-1.2
4
5package main
6
7// compile cmd
8// tinygo build -o ladybug-0.0.1.wasm -scheduler=none --no-debug -target=wasi ./
9
10import (
11 "bytes"
12 _ "embed"
13 "fmt"
14 "io/fs"
15
16 "github.com/sigurn/crc16"
17 "github.com/tidwall/gjson"
18 gitroot "gitroot.dev/libs/golang/plugin"
19)
20
21type MyConf struct {
22 Name string `json:"name"`
23 Type string `json:"type"`
24 Mandatory bool `json:"mandatory"`
25 Default any `json:"default"`
26}
27
28var defaultConf = map[string]any{"metadata": []MyConf{
29 {Name: "id", Type: "crc16", Mandatory: true, Default: "autogenerated"},
30 {Name: "priority", Type: "int", Mandatory: true, Default: 50},
31 {Name: "assignee", Type: "user", Mandatory: false, Default: nil},
32 {Name: "status", Type: "string", Mandatory: false, Default: "triage"},
33 {Name: "kind", Type: "string", Mandatory: false, Default: "issue"},
34}}
35
36var defaultRun = []gitroot.PluginRun{{
37 Path: "issues/**/*.md",
38 Branch: []string{"*"},
39 When: []gitroot.PluginRunWhen{gitroot.PluginRunWhenAdd, gitroot.PluginRunWhenMod},
40 Write: gitroot.PluginWrite{
41 Git: []gitroot.PluginWriteRight{{
42 Path: "issues/**/*.md",
43 Can: []gitroot.PluginWriteRightCan{gitroot.PluginWriteRightCanMod},
44 }},
45 Web: []gitroot.PluginWriteRight{},
46 },
47 Configuration: defaultConf,
48}}
49
50var table = crc16.MakeTable(crc16.CRC16_MAXIM)
51
52type Plugin struct {
53 server gitroot.Server
54 conf []MyConf
55}
56
57func (p *Plugin) Init(repoName string, confHasChanged bool, serializedConf string) error {
58 p.conf = []MyConf{}
59 for _, meta := range gjson.Parse(serializedConf).Get("metadata").Array() {
60 myConf := MyConf{
61 Name: meta.Get("name").String(),
62 Type: meta.Get("type").String(),
63 Mandatory: meta.Get("mandatory").Bool(),
64 Default: meta.Get("default").Value(),
65 }
66 p.conf = append(p.conf, myConf)
67 }
68 return nil
69}
70
71func (p *Plugin) StartCommit(commit gitroot.Commit) error {
72 return nil
73}
74
75func (p *Plugin) AddFile(filepath string) error {
76 content, err := fs.ReadFile(p.server.Worktree(), filepath)
77 if err != nil {
78 p.server.LogError("AddFile ReadFile "+filepath, err)
79 return nil
80 }
81 if !bytes.HasPrefix(content, []byte("---")) {
82 header := ""
83 for _, props := range p.conf {
84 if props.Name != "" {
85 if props.Mandatory {
86 if props.Default != nil {
87 def := props.Default
88 if props.Default == "autogenerated" && props.Type == "crc16" {
89 def = fmt.Sprintf("%X", crc16.Checksum([]byte(filepath), table))
90 }
91 header += fmt.Sprintf("%s: %v\n", props.Name, def)
92 }
93 } else {
94 if props.Default != nil {
95 header += fmt.Sprintf("%s: %v\n", props.Name, props.Default)
96 } else {
97 header += fmt.Sprintf("%s: null\n", props.Name)
98 }
99 }
100 }
101 }
102 newContent := fmt.Sprintf("---\n%s---\n\n%s", header, string(content))
103 p.server.ModifyContent(filepath, newContent)
104 } else {
105 metas := bytes.Split(content, []byte("---"))
106 meta := bytes.Trim(metas[1], "\n")
107 header := ""
108 for _, props := range p.conf {
109 if props.Name != "" {
110 if !bytes.Contains(meta, []byte(props.Name)) {
111 if props.Mandatory {
112 if props.Default != "" {
113 def := props.Default
114 if props.Default == "autogenerated" && props.Type == "crc16" {
115 def = fmt.Sprintf("%X", crc16.Checksum([]byte(filepath), table))
116 }
117 header += fmt.Sprintf("%s: %s\n", props.Name, def)
118 }
119 } else {
120 if props.Default != nil && props.Default != "" {
121 header += fmt.Sprintf("%s: %s\n", props.Name, props.Default)
122 } else {
123 header += fmt.Sprintf("%s: null\n", props.Name)
124 }
125 }
126 }
127 }
128 }
129 newContent := fmt.Sprintf("---\n%s\n%s---%s", meta, header, bytes.Join(metas[2:], []byte("\n")))
130 p.server.ModifyContent(filepath, newContent)
131 }
132 return nil
133}
134
135func (p *Plugin) ModFile(fromPath string, toPath string) error {
136 return p.AddFile(toPath)
137}
138
139func (p *Plugin) DelFile(path string) error {
140 return nil
141}
142
143func (p *Plugin) EndCommit(commit gitroot.Commit) error {
144 return nil
145}
146
147func (p *Plugin) Finish() error {
148 p.server.CommitAllIfNeeded("issue metadata added")
149 return nil
150}
151
152func Build(server gitroot.Server) gitroot.Plugin {
153 return &Plugin{
154 server: server,
155 }
156}
157
158//go:wasmexport install
159func main() {
160 gitroot.Register(defaultRun, Build)
161}