2023-12-20 13:26:57 +00:00
|
|
|
package addon
|
|
|
|
|
|
|
|
import (
|
|
|
|
"errors"
|
|
|
|
"plugin"
|
|
|
|
|
|
|
|
"github.com/rs/zerolog"
|
|
|
|
"github.com/rs/zerolog/log"
|
|
|
|
|
|
|
|
"go.woodpecker-ci.org/woodpecker/v2/shared/addon/types"
|
|
|
|
)
|
|
|
|
|
|
|
|
var pluginCache = map[string]*plugin.Plugin{}
|
|
|
|
|
|
|
|
type Addon[T any] struct {
|
|
|
|
Type types.Type
|
|
|
|
Value T
|
|
|
|
}
|
|
|
|
|
|
|
|
func Load[T any](files []string, t types.Type) (*Addon[T], error) {
|
|
|
|
for _, file := range files {
|
|
|
|
if _, has := pluginCache[file]; !has {
|
|
|
|
p, err := plugin.Open(file)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
pluginCache[file] = p
|
|
|
|
}
|
|
|
|
|
|
|
|
typeLookup, err := pluginCache[file].Lookup("Type")
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
if addonType, is := typeLookup.(*types.Type); !is {
|
|
|
|
return nil, errors.New("addon type is incorrect")
|
|
|
|
} else if *addonType != t {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
|
|
|
mainLookup, err := pluginCache[file].Lookup("Addon")
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
2024-01-02 18:54:34 +00:00
|
|
|
main, is := mainLookup.(func(zerolog.Logger) (T, error))
|
2023-12-20 13:26:57 +00:00
|
|
|
if !is {
|
|
|
|
return nil, errors.New("addon main function has incorrect type")
|
|
|
|
}
|
|
|
|
|
|
|
|
logger := log.Logger.With().Str("addon", file).Logger()
|
|
|
|
|
2024-01-02 18:54:34 +00:00
|
|
|
mainOut, err := main(logger)
|
2023-12-20 13:26:57 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
return &Addon[T]{
|
|
|
|
Type: t,
|
|
|
|
Value: mainOut,
|
|
|
|
}, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil, nil
|
|
|
|
}
|