ci_ingo/ci_ingo.go
2021-10-14 07:55:28 +02:00

136 lines
2.8 KiB
Go

package ci_ingo
import (
"os"
"strings"
)
// CI holds information about the current CI environment.
type CI struct {
Name string
Constant string
IsPR bool
}
type vendorCI struct {
name string
constant string
env envMatcher
pr envMatcher
}
var genericCIMatcher = simpleEnvMatcher{"CI"}
type envMatcher interface {
matchEnv(env map[string]string) bool
}
// simpleEnvMatcher Test if the specified environment variable is set.
type simpleEnvMatcher struct {
envvar string
}
func (m simpleEnvMatcher) matchEnv(env map[string]string) bool {
_, exists := env[m.envvar]
return exists
}
// anyEnvMatcher Test if any of the specified environment variables is set.
type anyEnvMatcher struct {
envvars []string
}
func (m anyEnvMatcher) matchEnv(env map[string]string) bool {
for _, v := range m.envvars {
if _, exists := env[v]; exists {
return true
}
}
return false
}
// allEnvMatcher Test if all of the specified environment variables are set.
type allEnvMatcher struct {
envvars []string
}
func (m allEnvMatcher) matchEnv(env map[string]string) bool {
for _, v := range m.envvars {
if _, exists := env[v]; !exists {
return false
}
}
return true
}
// kvEnvMatcher Test if all specified environment variables are set to the
// specified values.
type kvEnvMatcher struct {
envvars map[string]string
}
func (m kvEnvMatcher) matchEnv(env map[string]string) bool {
for key, value := range m.envvars {
if env[key] != value {
return false
}
}
return true
}
// neEnvMatcher Test if the specified environment variable is set, but not
// to the specified value.
type neEnvMatcher struct {
envvar string
ne string
}
func (m neEnvMatcher) matchEnv(env map[string]string) bool {
if val, exists := env[m.envvar]; exists {
return val != m.ne
}
return false
}
func getEnvironment() map[string]string {
getenvironment := func(
data []string, getkeyval func(item string) (key, val string)) map[string]string {
items := make(map[string]string)
for _, item := range data {
key, val := getkeyval(item)
items[key] = val
}
return items
}
return getenvironment(os.Environ(), func(item string) (key, val string) {
splits := strings.Split(item, "=")
key = splits[0]
val = splits[1]
return
})
}
// GetCI returns information about the CI system the program is running in
// or a nil pointer if the program is not running in a CI environment.
func GetCI() *CI {
env := getEnvironment()
for _, ci := range vendors {
if ci.env != nil && ci.env.matchEnv(env) {
isPR := ci.pr != nil && ci.pr.matchEnv(env)
return &CI{ci.name, ci.constant, isPR}
}
}
if genericCIMatcher.matchEnv(env) {
return &CI{"Unknown CI", "CI", false}
}
return nil
}
// IsCI returns true if the program is running in any CI environment.
func IsCI() bool {
return GetCI() != nil
}