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 }