func (cfg *Config) Validation() error {
	switch strings.ToLower(cfg.CI) {
	case "":
		return errors.New("ci: need to be set")
	case "circleci", "circle-ci":
	case "gitlabci", "gitlab-ci":
	case "travis", "travisci", "travis-ci":
	case "codebuild":
	case "teamcity":
	case "drone":
	case "jenkins":
	case "github-actions":
	case "cloud-build", "cloudbuild":
	default:
		return fmt.Errorf("%s: not supported yet", cfg.CI)
	}
	if cfg.isDefinedGithub() {
		if cfg.Notifier.Github.Repository.Owner == "" {
			return fmt.Errorf("repository owner is missing")
		}
		if cfg.Notifier.Github.Repository.Name == "" {
			return fmt.Errorf("repository name is missing")
		}
	}
	if cfg.isDefinedGitlab() {
		if cfg.Notifier.Gitlab.Repository.Owner == "" {
			return fmt.Errorf("repository owner is missing")
		}
		if cfg.Notifier.Gitlab.Repository.Name == "" {
			return fmt.Errorf("repository name is missing")
		}
	}
	if cfg.isDefinedSlack() {
		if cfg.Notifier.Slack.Channel == "" {
			return fmt.Errorf("slack channel id is missing")
		}
	}
	if cfg.isDefinedTypetalk() {
		if cfg.Notifier.Typetalk.TopicID == "" {
			return fmt.Errorf("Typetalk topic id is missing")
		}
	}
	notifier := cfg.GetNotifierType()
	if notifier == "" {
		return fmt.Errorf("notifier is missing")
	}
	return nil
}
Validation validates config file
package config
import (
	"errors"
	"fmt"
	"io/ioutil"
	"os"
	"strings"
	"gopkg.in/yaml.v2"
)
type Config struct {
	CI        string    `yaml:"ci"`
	Notifier  Notifier  `yaml:"notifier"`
	Terraform Terraform `yaml:"terraform"`
	path string
}
type Notifier struct {
	Github   GithubNotifier   `yaml:"github"`
	Gitlab   GitlabNotifier   `yaml:"gitlab"`
	Slack    SlackNotifier    `yaml:"slack"`
	Typetalk TypetalkNotifier `yaml:"typetalk"`
}
type GithubNotifier struct {
	Token      string     `yaml:"token"`
	BaseURL    string     `yaml:"base_url"`
	Repository Repository `yaml:"repository"`
}
type GitlabNotifier struct {
	Token      string     `yaml:"token"`
	BaseURL    string     `yaml:"base_url"`
	Repository Repository `yaml:"repository"`
}
type Repository struct {
	Owner string `yaml:"owner"`
	Name  string `yaml:"name"`
}
type SlackNotifier struct {
	Token   string `yaml:"token"`
	Channel string `yaml:"channel"`
	Bot     string `yaml:"bot"`
}
type TypetalkNotifier struct {
	Token   string `yaml:"token"`
	TopicID string `yaml:"topic_id"`
}
type Terraform struct {
	Default      Default `yaml:"default"`
	Fmt          Fmt     `yaml:"fmt"`
	Plan         Plan    `yaml:"plan"`
	Apply        Apply   `yaml:"apply"`
	UseRawOutput bool    `yaml:"use_raw_output,omitempty"`
}
type Default struct {
	Template string `yaml:"template"`
}
type Fmt struct {
	Template string `yaml:"template"`
}
type Plan struct {
	Template            string              `yaml:"template"`
	WhenAddOrUpdateOnly WhenAddOrUpdateOnly `yaml:"when_add_or_update_only,omitempty"`
	WhenDestroy         WhenDestroy         `yaml:"when_destroy,omitempty"`
	WhenNoChanges       WhenNoChanges       `yaml:"when_no_changes,omitempty"`
	WhenPlanError       WhenPlanError       `yaml:"when_plan_error,omitempty"`
}
type WhenAddOrUpdateOnly struct {
	Label string `yaml:"label,omitempty"`
}
type WhenDestroy struct {
	Label    string `yaml:"label,omitempty"`
	Template string `yaml:"template,omitempty"`
}
type WhenNoChanges struct {
	Label string `yaml:"label,omitempty"`
}
type WhenPlanError struct {
	Label string `yaml:"label,omitempty"`
}
type Apply struct {
	Template string `yaml:"template"`
}
func (cfg *Config) LoadFile(path string) error {
	cfg.path = path
	_, err := os.Stat(cfg.path)
	if err != nil {
		return fmt.Errorf("%s: no config file", cfg.path)
	}
	raw, _ := ioutil.ReadFile(cfg.path)
	return yaml.Unmarshal(raw, cfg)
}