package main import ( "os" "os/exec" "strconv" "strings" "github.com/sethvargo/go-githubactions" "go.uber.org/zap" "go.uber.org/zap/zapcore" ) type pluginConfig struct { check_syntax bool check bool diff bool verbosity int64 limit *string tags *string privateKey *string vaultToken *string galaxyFile *string playbook *string } func runCommand(sugar *zap.SugaredLogger, args ...string) { sugar.Infof("➡️ %s", args) cmd := exec.Command(args[0], args[1:]...) cmd.Env = os.Environ() cmd.Stdout = os.Stdout cmd.Stderr = os.Stderr err := cmd.Run() if err != nil { os.Exit(1) } } func getPluginConfig(sugar *zap.SugaredLogger) pluginConfig { config := pluginConfig{} check_syntax := githubactions.GetInput("check_syntax") if check_syntax == "" { config.check_syntax = false } else { converted, err := strconv.ParseBool(check_syntax) if err != nil { sugar.Fatal(err) } config.check_syntax = converted } check := githubactions.GetInput("check") if check == "" { config.check = false } else { converted, err := strconv.ParseBool(check) if err != nil { sugar.Fatal(err) } config.check = converted } diff := githubactions.GetInput("diff") if diff == "" { config.diff = false } else { converted, err := strconv.ParseBool(diff) if err != nil { sugar.Fatal(err) } config.diff = converted } verbosity := githubactions.GetInput("verbosity") if verbosity == "" { config.verbosity = 0 } else { converted, err := strconv.ParseInt(verbosity, 10, 0) if err != nil { sugar.Fatal(err) } config.verbosity = converted } limit := githubactions.GetInput("limit") if limit == "" { config.limit = nil } else { config.limit = &limit } tags := githubactions.GetInput("tags") if tags == "" { config.tags = nil } else { config.tags = &tags } privateKey := githubactions.GetInput("private_key") if privateKey == "" { sugar.Warn("⚠️ 'private_key' setting not defined !") config.privateKey = nil } else { config.privateKey = &privateKey } vaultToken := githubactions.GetInput("vault_token") if vaultToken == "" { config.vaultToken = nil } else { config.vaultToken = &vaultToken } galaxyFile := githubactions.GetInput("galaxy_file") if galaxyFile == "" { config.galaxyFile = nil } else { config.galaxyFile = &galaxyFile } playbook := githubactions.GetInput("playbook") if playbook == "" { sugar.Fatal("⚠️ 'playbook' setting not defined, ABORT!") } else { config.playbook = &playbook } return config } func main() { // encoderConfig := zapcore.EncoderConfig{ // MessageKey: "message", // LevelKey: "level", // EncodeLevel: zapcore.CapitalColorLevelEncoder, // EncodeDuration: zapcore.StringDurationEncoder, // EncodeCaller: zapcore.ShortCallerEncoder, // } // encoder := zapcore.NewConsoleEncoder(encoderConfig) // core := zapcore.NewCore(encoder, os.Stdout, zapcore.InfoLevel) config := zap.NewProductionConfig() config.EncoderConfig.EncodeLevel = zapcore.CapitalColorLevelEncoder config.EncoderConfig.TimeKey = "" config.Encoding = "console" config.DisableCaller = true config.DisableStacktrace = true logger, _ := config.Build() defer logger.Sync() sugar := logger.Sugar() sugar.Info("Woodpecker Ansible Runner") pluginConfig := getPluginConfig(sugar) if pluginConfig.privateKey != nil { sugar.Info("🔑 Adding ssh key to .ssh/id_ed25519") os.MkdirAll("/root/.ssh", 0700) if !strings.HasSuffix(*pluginConfig.privateKey, "\n") { *pluginConfig.privateKey = *pluginConfig.privateKey + "\n" } err := os.WriteFile("/root/.ssh/id_ed25519", []byte(*pluginConfig.privateKey), 0400) if err != nil { sugar.Fatal(err) } } args := []string{*pluginConfig.playbook} if pluginConfig.vaultToken != nil { sugar.Info("💼 Adding vault token to 'credentials/ci_vault_token'") os.MkdirAll("credentials", 0755) err := os.WriteFile("credentials/ci_vault_token", []byte(*pluginConfig.vaultToken), 0644) if err != nil { sugar.Fatal(err) } args = append(args, "--vault-password-file=credentials/ci_vault_token") sugar.Info("⚙️ Clean ansible.cfg") runCommand(sugar, "sed", "-i", "/vault_password_file.*/d", "./ansible.cfg") } if _, err := os.Stat("ansible-ci.cfg"); err == nil { sugar.Info("⚙️ ansible-ci.cfg is present, using it.") os.Remove("ansible.cfg") os.Rename("ansible-ci.cfg", "ansible.cfg") } if pluginConfig.galaxyFile != nil { sugar.Infof("🚀 Installing Galaxy dependencies (%s)", *pluginConfig.galaxyFile) runCommand(sugar, "ansible-galaxy", "install", "-r", *pluginConfig.galaxyFile, "--force") } if pluginConfig.check_syntax { args = append(args, "--syntax-check") } if pluginConfig.check { args = append(args, "--check") } if pluginConfig.diff { args = append(args, "--diff") } if pluginConfig.verbosity != 0 { verb := "-" for i := 0; i < int(pluginConfig.verbosity); i++ { verb += "v" } args = append(args, verb) } if pluginConfig.limit != nil { args = append(args, "--limit", *pluginConfig.limit) } if pluginConfig.tags != nil { args = append(args, "--tags", *pluginConfig.tags) } command := append([]string{"ansible-playbook"}, args...) runCommand(sugar, command...) }