From 8b1197128b2420d08ebee4e18645409dc2aabc9c Mon Sep 17 00:00:00 2001 From: Jared Patrick Date: Mon, 14 Oct 2024 15:52:04 -0400 Subject: [PATCH 1/3] refactor command, package, and internal layout --- Makefile | 11 +- cmd/telefonistka/bump-version-overwrite.go | 92 --------- cmd/telefonistka/bump-version-regex.go | 89 --------- cmd/telefonistka/bump-version-yaml.go | 107 ---------- cmd/telefonistka/bump_version_overwrite.go | 106 ++++++++++ cmd/telefonistka/bump_version_regex.go | 115 +++++++++++ cmd/telefonistka/bump_version_yaml.go | 117 +++++++++++ cmd/telefonistka/event.go | 49 ++--- cmd/telefonistka/root.go | 48 ----- cmd/telefonistka/server.go | 75 +------ internal/bumpversion/bumpversion.go | 187 ++++++++++++++++++ internal/github/client.go | 24 +++ internal/github/event.go | 13 ++ internal/logging/logging.go | 26 +++ internal/server/server.go | 52 +++++ main.go | 9 - {internal/pkg => pkg}/argocd/argocd.go | 2 +- .../argocd/argocd_copied_from_upstream.go | 0 {internal/pkg => pkg}/argocd/argocd_test.go | 2 +- {internal/pkg => pkg}/argocd/diff/README.md | 0 {internal/pkg => pkg}/argocd/diff/diff.go | 0 .../pkg => pkg}/argocd/diff/diff_test.go | 0 .../argocd/diff/testdata/allnew.txt | 0 .../argocd/diff/testdata/allold.txt | 0 .../argocd/diff/testdata/basic.txt | 0 .../pkg => pkg}/argocd/diff/testdata/dups.txt | 0 .../pkg => pkg}/argocd/diff/testdata/end.txt | 0 .../pkg => pkg}/argocd/diff/testdata/eof.txt | 0 .../pkg => pkg}/argocd/diff/testdata/eof1.txt | 0 .../pkg => pkg}/argocd/diff/testdata/eof2.txt | 0 .../pkg => pkg}/argocd/diff/testdata/long.txt | 0 .../pkg => pkg}/argocd/diff/testdata/same.txt | 0 .../argocd/diff/testdata/start.txt | 0 .../pkg => pkg}/argocd/diff/testdata/triv.txt | 0 .../TestDiffLiveVsTargetObject/1.live | 0 .../TestDiffLiveVsTargetObject/1.target | 0 .../TestDiffLiveVsTargetObject/1.want | 0 .../argocd/testdata/TestRenderDiff.live | 0 .../argocd/testdata/TestRenderDiff.md | 0 .../argocd/testdata/TestRenderDiff.target | 0 {internal/pkg => pkg}/configuration/config.go | 0 .../pkg => pkg}/configuration/config_test.go | 0 .../tests/testConfigurationParsing.yaml | 0 {internal/pkg => pkg}/githubapi/.tmpMJcSWN | 0 {internal/pkg => pkg}/githubapi/clients.go | 0 .../pkg => pkg}/githubapi/drift_detection.go | 2 +- .../githubapi/drift_detection_test.go | 0 {internal/pkg => pkg}/githubapi/github.go | 6 +- .../pkg => pkg}/githubapi/github_graphql.go | 0 .../pkg => pkg}/githubapi/github_test.go | 0 {internal/pkg => pkg}/githubapi/promotion.go | 4 +- .../pkg => pkg}/githubapi/promotion_test.go | 2 +- .../testdata/diff_comment_data_test.json | 0 .../githubapi/testdata/pr_body.golden.md | 0 .../pkg => pkg}/githubapi/webhook_proxy.go | 4 +- .../githubapi/webhook_proxy_test.go | 2 +- {internal/pkg => pkg}/mocks/.gitignore | 0 {internal/pkg => pkg}/mocks/mocks.go | 0 .../pkg => pkg}/prometheus/prometheus.go | 0 .../pkg => pkg}/prometheus/prometheus_test.go | 0 pkg/utils/utils.go | 35 ++++ .../utils/utils_test.go | 8 +- 62 files changed, 732 insertions(+), 455 deletions(-) delete mode 100644 cmd/telefonistka/bump-version-overwrite.go delete mode 100644 cmd/telefonistka/bump-version-regex.go delete mode 100644 cmd/telefonistka/bump-version-yaml.go create mode 100644 cmd/telefonistka/bump_version_overwrite.go create mode 100644 cmd/telefonistka/bump_version_regex.go create mode 100644 cmd/telefonistka/bump_version_yaml.go delete mode 100644 cmd/telefonistka/root.go create mode 100644 internal/bumpversion/bumpversion.go create mode 100644 internal/github/client.go create mode 100644 internal/github/event.go create mode 100644 internal/logging/logging.go create mode 100644 internal/server/server.go delete mode 100644 main.go rename {internal/pkg => pkg}/argocd/argocd.go (99%) rename {internal/pkg => pkg}/argocd/argocd_copied_from_upstream.go (100%) rename {internal/pkg => pkg}/argocd/argocd_test.go (99%) rename {internal/pkg => pkg}/argocd/diff/README.md (100%) rename {internal/pkg => pkg}/argocd/diff/diff.go (100%) rename {internal/pkg => pkg}/argocd/diff/diff_test.go (100%) rename {internal/pkg => pkg}/argocd/diff/testdata/allnew.txt (100%) rename {internal/pkg => pkg}/argocd/diff/testdata/allold.txt (100%) rename {internal/pkg => pkg}/argocd/diff/testdata/basic.txt (100%) rename {internal/pkg => pkg}/argocd/diff/testdata/dups.txt (100%) rename {internal/pkg => pkg}/argocd/diff/testdata/end.txt (100%) rename {internal/pkg => pkg}/argocd/diff/testdata/eof.txt (100%) rename {internal/pkg => pkg}/argocd/diff/testdata/eof1.txt (100%) rename {internal/pkg => pkg}/argocd/diff/testdata/eof2.txt (100%) rename {internal/pkg => pkg}/argocd/diff/testdata/long.txt (100%) rename {internal/pkg => pkg}/argocd/diff/testdata/same.txt (100%) rename {internal/pkg => pkg}/argocd/diff/testdata/start.txt (100%) rename {internal/pkg => pkg}/argocd/diff/testdata/triv.txt (100%) rename {internal/pkg => pkg}/argocd/testdata/TestDiffLiveVsTargetObject/1.live (100%) rename {internal/pkg => pkg}/argocd/testdata/TestDiffLiveVsTargetObject/1.target (100%) rename {internal/pkg => pkg}/argocd/testdata/TestDiffLiveVsTargetObject/1.want (100%) rename {internal/pkg => pkg}/argocd/testdata/TestRenderDiff.live (100%) rename {internal/pkg => pkg}/argocd/testdata/TestRenderDiff.md (100%) rename {internal/pkg => pkg}/argocd/testdata/TestRenderDiff.target (100%) rename {internal/pkg => pkg}/configuration/config.go (100%) rename {internal/pkg => pkg}/configuration/config_test.go (100%) rename {internal/pkg => pkg}/configuration/tests/testConfigurationParsing.yaml (100%) rename {internal/pkg => pkg}/githubapi/.tmpMJcSWN (100%) rename {internal/pkg => pkg}/githubapi/clients.go (100%) rename {internal/pkg => pkg}/githubapi/drift_detection.go (98%) rename {internal/pkg => pkg}/githubapi/drift_detection_test.go (100%) rename {internal/pkg => pkg}/githubapi/github.go (99%) rename {internal/pkg => pkg}/githubapi/github_graphql.go (100%) rename {internal/pkg => pkg}/githubapi/github_test.go (100%) rename {internal/pkg => pkg}/githubapi/promotion.go (98%) rename {internal/pkg => pkg}/githubapi/promotion_test.go (99%) rename {internal/pkg => pkg}/githubapi/testdata/diff_comment_data_test.json (100%) rename {internal/pkg => pkg}/githubapi/testdata/pr_body.golden.md (100%) rename {internal/pkg => pkg}/githubapi/webhook_proxy.go (96%) rename {internal/pkg => pkg}/githubapi/webhook_proxy_test.go (96%) rename {internal/pkg => pkg}/mocks/.gitignore (100%) rename {internal/pkg => pkg}/mocks/mocks.go (100%) rename {internal/pkg => pkg}/prometheus/prometheus.go (100%) rename {internal/pkg => pkg}/prometheus/prometheus_test.go (100%) create mode 100644 pkg/utils/utils.go rename cmd/telefonistka/bump-version-yaml_test.go => pkg/utils/utils_test.go (92%) diff --git a/Makefile b/Makefile index 7089aff2..fed92ab0 100644 --- a/Makefile +++ b/Makefile @@ -7,23 +7,24 @@ # @copyright 2019 Wayfair, LLC. -- All rights reserved. VENDOR_DIR = vendor +BUILD_VERSION ?= 0.0.0 .PHONY: get-deps get-deps: $(VENDOR_DIR) $(VENDOR_DIR): - go generate $$(go list ./internal/pkg/mocks/...) - GO111MODULE=on go mod vendor + @go generate $$(go list ./pkg/mocks/...) + @GO111MODULE=on go mod vendor .PHONY: build build: $(VENDOR_DIR) - GOOS=linux CGO_ENABLED=0 go build -a -ldflags '-extldflags "-static"' -o telefonistka . + @GOOS=linux CGO_ENABLED=0 go build -a -ldflags '-extldflags "-static" -X "main.version=${BUILD_VERSION}"' -o telefonistka ./cmd/telefonistka .PHONY: clean clean: - rm -f telefonistka + @rm -f telefonistka .PHONY: test test: $(VENDOR_DIR) - TEMPLATES_PATH=../../../templates/ go test -v -timeout 30s ./... + @TEMPLATES_PATH=${PWD}/templates/ go test -v -timeout 30s ./... diff --git a/cmd/telefonistka/bump-version-overwrite.go b/cmd/telefonistka/bump-version-overwrite.go deleted file mode 100644 index e2df86df..00000000 --- a/cmd/telefonistka/bump-version-overwrite.go +++ /dev/null @@ -1,92 +0,0 @@ -package telefonistka - -import ( - "context" - "os" - "strings" - - lru "github.com/hashicorp/golang-lru/v2" - "github.com/hexops/gotextdiff" - "github.com/hexops/gotextdiff/myers" - "github.com/hexops/gotextdiff/span" - log "github.com/sirupsen/logrus" - "github.com/spf13/cobra" - "github.com/wayfair-incubator/telefonistka/internal/pkg/githubapi" -) - -// This is still(https://github.com/spf13/cobra/issues/1862) the documented way to use cobra -func init() { //nolint:gochecknoinits - var targetRepo string - var targetFile string - var file string - var githubHost string - var triggeringRepo string - var triggeringRepoSHA string - var triggeringActor string - var autoMerge bool - eventCmd := &cobra.Command{ - Use: "bump-overwrite", - Short: "Bump artifact version based on provided file content.", - Long: "Bump artifact version based on provided file content.\nThis open a pull request in the target repo.", - Args: cobra.ExactArgs(0), - Run: func(cmd *cobra.Command, args []string) { - bumpVersionOverwrite(targetRepo, targetFile, file, githubHost, triggeringRepo, triggeringRepoSHA, triggeringActor, autoMerge) - }, - } - eventCmd.Flags().StringVarP(&targetRepo, "target-repo", "t", getEnv("TARGET_REPO", ""), "Target Git repository slug(e.g. org-name/repo-name), defaults to TARGET_REPO env var.") - eventCmd.Flags().StringVarP(&targetFile, "target-file", "f", getEnv("TARGET_FILE", ""), "Target file path(from repo root), defaults to TARGET_FILE env var.") - eventCmd.Flags().StringVarP(&file, "file", "c", "", "File that holds the content the target file will be overwritten with, like \"version.yaml\" or '<(echo -e \"image:\\n tag: ${VERSION}\")'.") - eventCmd.Flags().StringVarP(&githubHost, "github-host", "g", "", "GitHub instance HOSTNAME, defaults to \"github.com\". This is used for GitHub Enterprise Server instances.") - eventCmd.Flags().StringVarP(&triggeringRepo, "triggering-repo", "p", getEnv("GITHUB_REPOSITORY", ""), "Github repo triggering the version bump(e.g. `octocat/Hello-World`) defaults to GITHUB_REPOSITORY env var.") - eventCmd.Flags().StringVarP(&triggeringRepoSHA, "triggering-repo-sha", "s", getEnv("GITHUB_SHA", ""), "Git SHA of triggering repo, defaults to GITHUB_SHA env var.") - eventCmd.Flags().StringVarP(&triggeringActor, "triggering-actor", "a", getEnv("GITHUB_ACTOR", ""), "GitHub user of the person/bot who triggered the bump, defaults to GITHUB_ACTOR env var.") - eventCmd.Flags().BoolVar(&autoMerge, "auto-merge", false, "Automatically merges the created PR, defaults to false.") - rootCmd.AddCommand(eventCmd) -} - -func bumpVersionOverwrite(targetRepo string, targetFile string, file string, githubHost string, triggeringRepo string, triggeringRepoSHA string, triggeringActor string, autoMerge bool) { - b, err := os.ReadFile(file) - if err != nil { - log.Errorf("Failed to read file %s, %v", file, err) - os.Exit(1) - } - newFileContent := string(b) - - ctx := context.Background() - var githubRestAltURL string - - if githubHost != "" { - githubRestAltURL = "https://" + githubHost + "/api/v3" - log.Infof("Github REST API endpoint is configured to %s", githubRestAltURL) - } - var mainGithubClientPair githubapi.GhClientPair - mainGhClientCache, _ := lru.New[string, githubapi.GhClientPair](128) - - mainGithubClientPair.GetAndCache(mainGhClientCache, "GITHUB_APP_ID", "GITHUB_APP_PRIVATE_KEY_PATH", "GITHUB_OAUTH_TOKEN", strings.Split(targetRepo, "/")[0], ctx) - - var ghPrClientDetails githubapi.GhPrClientDetails - - ghPrClientDetails.GhClientPair = &mainGithubClientPair - ghPrClientDetails.Ctx = ctx - ghPrClientDetails.Owner = strings.Split(targetRepo, "/")[0] - ghPrClientDetails.Repo = strings.Split(targetRepo, "/")[1] - ghPrClientDetails.PrLogger = log.WithFields(log.Fields{}) // TODO what fields should be here? - - defaultBranch, _ := ghPrClientDetails.GetDefaultBranch() - initialFileContent, statusCode, err := githubapi.GetFileContent(ghPrClientDetails, defaultBranch, targetFile) - if statusCode == 404 { - ghPrClientDetails.PrLogger.Infof("File %s was not found\n", targetFile) - } else if err != nil { - ghPrClientDetails.PrLogger.Errorf("Fail to fetch file content:%s\n", err) - os.Exit(1) - } - - edits := myers.ComputeEdits(span.URIFromPath(""), initialFileContent, newFileContent) - ghPrClientDetails.PrLogger.Infof("Diff:\n%s", gotextdiff.ToUnified("Before", "After", initialFileContent, edits)) - - err = githubapi.BumpVersion(ghPrClientDetails, "main", targetFile, newFileContent, triggeringRepo, triggeringRepoSHA, triggeringActor, autoMerge) - if err != nil { - log.Errorf("Failed to bump version: %v", err) - os.Exit(1) - } -} diff --git a/cmd/telefonistka/bump-version-regex.go b/cmd/telefonistka/bump-version-regex.go deleted file mode 100644 index fc3d50f1..00000000 --- a/cmd/telefonistka/bump-version-regex.go +++ /dev/null @@ -1,89 +0,0 @@ -package telefonistka - -import ( - "context" - "os" - "regexp" - "strings" - - lru "github.com/hashicorp/golang-lru/v2" - "github.com/hexops/gotextdiff" - "github.com/hexops/gotextdiff/myers" - "github.com/hexops/gotextdiff/span" - log "github.com/sirupsen/logrus" - "github.com/spf13/cobra" - "github.com/wayfair-incubator/telefonistka/internal/pkg/githubapi" -) - -// This is still(https://github.com/spf13/cobra/issues/1862) the documented way to use cobra -func init() { //nolint:gochecknoinits - var targetRepo string - var targetFile string - var regex string - var replacement string - var githubHost string - var triggeringRepo string - var triggeringRepoSHA string - var triggeringActor string - var autoMerge bool - eventCmd := &cobra.Command{ - Use: "bump-regex", - Short: "Bump artifact version in a file using regex", - Long: "Bump artifact version in a file using regex.\nThis open a pull request in the target repo.\n", - Args: cobra.ExactArgs(0), - Run: func(cmd *cobra.Command, args []string) { - bumpVersionRegex(targetRepo, targetFile, regex, replacement, githubHost, triggeringRepo, triggeringRepoSHA, triggeringActor, autoMerge) - }, - } - eventCmd.Flags().StringVarP(&targetRepo, "target-repo", "t", getEnv("TARGET_REPO", ""), "Target Git repository slug(e.g. org-name/repo-name), defaults to TARGET_REPO env var.") - eventCmd.Flags().StringVarP(&targetFile, "target-file", "f", getEnv("TARGET_FILE", ""), "Target file path(from repo root), defaults to TARGET_FILE env var.") - eventCmd.Flags().StringVarP(®ex, "regex-string", "r", "", "Regex used to replace artifact version, e.g. 'tag:\\s*(\\S*)'.") - eventCmd.Flags().StringVarP(&replacement, "replacement-string", "n", "", "Replacement string that includes the version of new artifact, e.g. 'tag: v2.7.1'.") - eventCmd.Flags().StringVarP(&githubHost, "github-host", "g", "", "GitHub instance HOSTNAME, defaults to \"github.com\". This is used for GitHub Enterprise Server instances.") - eventCmd.Flags().StringVarP(&triggeringRepo, "triggering-repo", "p", getEnv("GITHUB_REPOSITORY", ""), "Github repo triggering the version bump(e.g. `octocat/Hello-World`) defaults to GITHUB_REPOSITORY env var.") - eventCmd.Flags().StringVarP(&triggeringRepoSHA, "triggering-repo-sha", "s", getEnv("GITHUB_SHA", ""), "Git SHA of triggering repo, defaults to GITHUB_SHA env var.") - eventCmd.Flags().StringVarP(&triggeringActor, "triggering-actor", "a", getEnv("GITHUB_ACTOR", ""), "GitHub user of the person/bot who triggered the bump, defaults to GITHUB_ACTOR env var.") - eventCmd.Flags().BoolVar(&autoMerge, "auto-merge", false, "Automatically merges the created PR, defaults to false.") - rootCmd.AddCommand(eventCmd) -} - -func bumpVersionRegex(targetRepo string, targetFile string, regex string, replacement string, githubHost string, triggeringRepo string, triggeringRepoSHA string, triggeringActor string, autoMerge bool) { - ctx := context.Background() - var githubRestAltURL string - - if githubHost != "" { - githubRestAltURL = "https://" + githubHost + "/api/v3" - log.Infof("Github REST API endpoint is configured to %s", githubRestAltURL) - } - var mainGithubClientPair githubapi.GhClientPair - mainGhClientCache, _ := lru.New[string, githubapi.GhClientPair](128) - - mainGithubClientPair.GetAndCache(mainGhClientCache, "GITHUB_APP_ID", "GITHUB_APP_PRIVATE_KEY_PATH", "GITHUB_OAUTH_TOKEN", strings.Split(targetRepo, "/")[0], ctx) - - var ghPrClientDetails githubapi.GhPrClientDetails - - ghPrClientDetails.GhClientPair = &mainGithubClientPair - ghPrClientDetails.Ctx = ctx - ghPrClientDetails.Owner = strings.Split(targetRepo, "/")[0] - ghPrClientDetails.Repo = strings.Split(targetRepo, "/")[1] - ghPrClientDetails.PrLogger = log.WithFields(log.Fields{}) // TODO what fields should be here? - - r := regexp.MustCompile(regex) - defaultBranch, _ := ghPrClientDetails.GetDefaultBranch() - - initialFileContent, _, err := githubapi.GetFileContent(ghPrClientDetails, defaultBranch, targetFile) - if err != nil { - ghPrClientDetails.PrLogger.Errorf("Fail to fetch file content:%s\n", err) - os.Exit(1) - } - newFileContent := r.ReplaceAllString(initialFileContent, replacement) - - edits := myers.ComputeEdits(span.URIFromPath(""), initialFileContent, newFileContent) - ghPrClientDetails.PrLogger.Infof("Diff:\n%s", gotextdiff.ToUnified("Before", "After", initialFileContent, edits)) - - err = githubapi.BumpVersion(ghPrClientDetails, "main", targetFile, newFileContent, triggeringRepo, triggeringRepoSHA, triggeringActor, autoMerge) - if err != nil { - log.Errorf("Failed to bump version: %v", err) - os.Exit(1) - } -} diff --git a/cmd/telefonistka/bump-version-yaml.go b/cmd/telefonistka/bump-version-yaml.go deleted file mode 100644 index c130b775..00000000 --- a/cmd/telefonistka/bump-version-yaml.go +++ /dev/null @@ -1,107 +0,0 @@ -package telefonistka - -import ( - "context" - "fmt" - "os" - "strings" - - lru "github.com/hashicorp/golang-lru/v2" - "github.com/hexops/gotextdiff" - "github.com/hexops/gotextdiff/myers" - "github.com/hexops/gotextdiff/span" - "github.com/mikefarah/yq/v4/pkg/yqlib" - log "github.com/sirupsen/logrus" - "github.com/spf13/cobra" - "github.com/wayfair-incubator/telefonistka/internal/pkg/githubapi" -) - -// This is still(https://github.com/spf13/cobra/issues/1862) the documented way to use cobra -func init() { //nolint:gochecknoinits - var targetRepo string - var targetFile string - var address string - var replacement string - var githubHost string - var triggeringRepo string - var triggeringRepoSHA string - var triggeringActor string - var autoMerge bool - eventCmd := &cobra.Command{ - Use: "bump-yaml", - Short: "Bump artifact version in a file using yaml selector", - Long: `Bump artifact version in a file using yaml selector. -This will open a pull request in the target repo. -This command uses yq selector to find the yaml value to replace. -`, - Args: cobra.ExactArgs(0), - Run: func(cmd *cobra.Command, args []string) { - bumpVersionYaml(targetRepo, targetFile, address, replacement, githubHost, triggeringRepo, triggeringRepoSHA, triggeringActor, autoMerge) - }, - } - eventCmd.Flags().StringVarP(&targetRepo, "target-repo", "t", getEnv("TARGET_REPO", ""), "Target Git repository slug(e.g. org-name/repo-name), defaults to TARGET_REPO env var.") - eventCmd.Flags().StringVarP(&targetFile, "target-file", "f", getEnv("TARGET_FILE", ""), "Target file path(from repo root), defaults to TARGET_FILE env var.") - eventCmd.Flags().StringVar(&address, "address", "", "Yaml value address described as a yq selector, e.g. '.db.[] | select(.name == \"postgres\").image.tag'.") - eventCmd.Flags().StringVarP(&replacement, "replacement-string", "n", "", "Replacement string that includes the version value of new artifact, e.g. 'v2.7.1'.") - eventCmd.Flags().StringVarP(&githubHost, "github-host", "g", "", "GitHub instance HOSTNAME, defaults to \"github.com\". This is used for GitHub Enterprise Server instances.") - eventCmd.Flags().StringVarP(&triggeringRepo, "triggering-repo", "p", getEnv("GITHUB_REPOSITORY", ""), "Github repo triggering the version bump(e.g. `octocat/Hello-World`) defaults to GITHUB_REPOSITORY env var.") - eventCmd.Flags().StringVarP(&triggeringRepoSHA, "triggering-repo-sha", "s", getEnv("GITHUB_SHA", ""), "Git SHA of triggering repo, defaults to GITHUB_SHA env var.") - eventCmd.Flags().StringVarP(&triggeringActor, "triggering-actor", "a", getEnv("GITHUB_ACTOR", ""), "GitHub user of the person/bot who triggered the bump, defaults to GITHUB_ACTOR env var.") - eventCmd.Flags().BoolVar(&autoMerge, "auto-merge", false, "Automatically merges the created PR, defaults to false.") - rootCmd.AddCommand(eventCmd) -} - -func bumpVersionYaml(targetRepo string, targetFile string, address string, value string, githubHost string, triggeringRepo string, triggeringRepoSHA string, triggeringActor string, autoMerge bool) { - ctx := context.Background() - var githubRestAltURL string - - if githubHost != "" { - githubRestAltURL = "https://" + githubHost + "/api/v3" - log.Infof("Github REST API endpoint is configured to %s", githubRestAltURL) - } - var mainGithubClientPair githubapi.GhClientPair - mainGhClientCache, _ := lru.New[string, githubapi.GhClientPair](128) - - mainGithubClientPair.GetAndCache(mainGhClientCache, "GITHUB_APP_ID", "GITHUB_APP_PRIVATE_KEY_PATH", "GITHUB_OAUTH_TOKEN", strings.Split(targetRepo, "/")[0], ctx) - - var ghPrClientDetails githubapi.GhPrClientDetails - - ghPrClientDetails.GhClientPair = &mainGithubClientPair - ghPrClientDetails.Ctx = ctx - ghPrClientDetails.Owner = strings.Split(targetRepo, "/")[0] - ghPrClientDetails.Repo = strings.Split(targetRepo, "/")[1] - ghPrClientDetails.PrLogger = log.WithFields(log.Fields{}) // TODO what fields should be here? - - defaultBranch, _ := ghPrClientDetails.GetDefaultBranch() - - initialFileContent, _, err := githubapi.GetFileContent(ghPrClientDetails, defaultBranch, targetFile) - if err != nil { - ghPrClientDetails.PrLogger.Errorf("Fail to fetch file content:%s\n", err) - os.Exit(1) - } - newFileContent, err := updateYaml(initialFileContent, address, value) - if err != nil { - ghPrClientDetails.PrLogger.Errorf("Fail to update yaml:%s\n", err) - os.Exit(1) - } - - edits := myers.ComputeEdits(span.URIFromPath(""), initialFileContent, newFileContent) - ghPrClientDetails.PrLogger.Infof("Diff:\n%s", gotextdiff.ToUnified("Before", "After", initialFileContent, edits)) - - err = githubapi.BumpVersion(ghPrClientDetails, "main", targetFile, newFileContent, triggeringRepo, triggeringRepoSHA, triggeringActor, autoMerge) - if err != nil { - log.Errorf("Failed to bump version: %v", err) - os.Exit(1) - } -} - -func updateYaml(yamlContent string, address string, value string) (string, error) { - yqExpression := fmt.Sprintf("(%s)=\"%s\"", address, value) - - preferences := yqlib.NewDefaultYamlPreferences() - evaluate, err := yqlib.NewStringEvaluator().Evaluate(yqExpression, yamlContent, yqlib.NewYamlEncoder(preferences), yqlib.NewYamlDecoder(preferences)) - if err != nil { - return "", err - } - return evaluate, nil -} diff --git a/cmd/telefonistka/bump_version_overwrite.go b/cmd/telefonistka/bump_version_overwrite.go new file mode 100644 index 00000000..33340fd3 --- /dev/null +++ b/cmd/telefonistka/bump_version_overwrite.go @@ -0,0 +1,106 @@ +package main + +import ( + "github.com/spf13/cobra" + "github.com/wayfair-incubator/telefonistka/internal/bumpversion" + "github.com/wayfair-incubator/telefonistka/pkg/utils" +) + +// This is still(https://github.com/spf13/cobra/issues/1862) the documented way to use cobra +func init() { //nolint:gochecknoinits + var ( + targetRepo string + targetFile string + file string + githubHost string + triggeringRepo string + triggeringRepoSHA string + triggeringActor string + autoMerge bool + ) + + var cmd = &cobra.Command{ + Use: "bump-overwrite", + Short: "Bump artifact version based on provided file content.", + Long: "Bump artifact version based on provided file content.\nThis open a pull request in the target repo.", + Args: cobra.ExactArgs(0), + Run: func(cmd *cobra.Command, args []string) { + params := bumpversion.OverwriteParams{ + TargetRepo: targetRepo, + TargetFile: targetFile, + File: file, + GithubHost: githubHost, + TriggeringRepo: triggeringRepo, + TriggeringRepoSHA: triggeringRepoSHA, + TriggeringActor: triggeringActor, + AutoMerge: autoMerge, + } + bumpversion.Overwrite(params) + }, + } + + cmd.Flags().StringVarP( + &targetRepo, + "target-repo", + "t", + utils.GetEnv("TARGET_REPO", ""), + "Target Git repository slug(e.g. org-name/repo-name), defaults to TARGET_REPO env var.", + ) + + cmd.Flags().StringVarP( + &targetFile, + "target-file", + "f", + utils.GetEnv("TARGET_FILE", ""), + "Target file path(from repo root), defaults to TARGET_FILE env var.", + ) + + cmd.Flags().StringVarP( + &file, + "file", + "c", + "", + "File that holds the content the target file will be overwritten with, like \"version.yaml\" or '<(echo -e \"image:\\n tag: ${VERSION}\")'.", + ) + + cmd.Flags().StringVarP( + &githubHost, + "github-host", + "g", + "", + "GitHub instance HOSTNAME, defaults to \"github.com\". This is used for GitHub Enterprise Server instances.", + ) + + cmd.Flags().StringVarP( + &triggeringRepo, + "triggering-repo", + "p", + utils.GetEnv("GITHUB_REPOSITORY", ""), + "Github repo triggering the version bump(e.g. `octocat/Hello-World`) defaults to GITHUB_REPOSITORY env var.", + ) + + cmd.Flags().StringVarP( + &triggeringRepoSHA, + "triggering-repo-sha", + "s", + utils.GetEnv("GITHUB_SHA", ""), + "Git SHA of triggering repo, defaults to GITHUB_SHA env var.", + ) + + cmd.Flags().StringVarP( + &triggeringActor, + "triggering-actor", + "a", + utils.GetEnv("GITHUB_ACTOR", ""), + "GitHub user of the person/bot who triggered the bump, defaults to GITHUB_ACTOR env var.", + ) + + cmd.Flags().BoolVar( + &autoMerge, + "auto-merge", + false, + "Automatically merges the created PR, defaults to false.", + ) + + rootCmd.AddCommand(cmd) +} diff --git a/cmd/telefonistka/bump_version_regex.go b/cmd/telefonistka/bump_version_regex.go new file mode 100644 index 00000000..a4d6b2fb --- /dev/null +++ b/cmd/telefonistka/bump_version_regex.go @@ -0,0 +1,115 @@ +package main + +import ( + "github.com/spf13/cobra" + "github.com/wayfair-incubator/telefonistka/internal/bumpversion" + "github.com/wayfair-incubator/telefonistka/pkg/utils" +) + +// This is still(https://github.com/spf13/cobra/issues/1862) the documented way to use cobra +func init() { //nolint:gochecknoinits + var ( + targetRepo string + targetFile string + regex string + replacement string + githubHost string + triggeringRepo string + triggeringRepoSHA string + triggeringActor string + autoMerge bool + ) + + var cmd = &cobra.Command{ + Use: "bump-regex", + Short: "Bump artifact version in a file using regex", + Long: "Bump artifact version in a file using regex.\nThis open a pull request in the target repo.\n", + Args: cobra.ExactArgs(0), + Run: func(cmd *cobra.Command, args []string) { + params := bumpversion.RegexParams{ + TargetRepo: targetRepo, + TargetFile: targetFile, + Regex: regex, + Replacement: replacement, + GithubHost: githubHost, + TriggeringRepo: triggeringRepo, + TriggeringRepoSHA: triggeringRepoSHA, + TriggeringActor: triggeringActor, + AutoMerge: autoMerge, + } + bumpversion.Regex(params) + }, + } + + cmd.Flags().StringVarP( + &targetRepo, + "target-repo", + "t", + utils.GetEnv("TARGET_REPO", ""), + "Target Git repository slug(e.g. org-name/repo-name), defaults to TARGET_REPO env var.", + ) + + cmd.Flags().StringVarP( + &targetFile, + "target-file", + "f", + utils.GetEnv("TARGET_FILE", ""), + "Target file path(from repo root), defaults to TARGET_FILE env var.", + ) + + cmd.Flags().StringVarP( + ®ex, + "regex-string", + "r", + "", + "Regex used to replace artifact version, e.g. 'tag:\\s*(\\S*)'.", + ) + + cmd.Flags().StringVarP( + &replacement, + "replacement-string", + "n", + "", + "Replacement string that includes the version of new artifact, e.g. 'tag: v2.7.1'.", + ) + + cmd.Flags().StringVarP( + &githubHost, + "github-host", + "g", + "", + "GitHub instance HOSTNAME, defaults to \"github.com\". This is used for GitHub Enterprise Server instances.", + ) + + cmd.Flags().StringVarP( + &triggeringRepo, + "triggering-repo", + "p", + utils.GetEnv("GITHUB_REPOSITORY", ""), + "Github repo triggering the version bump(e.g. `octocat/Hello-World`) defaults to GITHUB_REPOSITORY env var.", + ) + + cmd.Flags().StringVarP( + &triggeringRepoSHA, + "triggering-repo-sha", + "s", + utils.GetEnv("GITHUB_SHA", ""), + "Git SHA of triggering repo, defaults to GITHUB_SHA env var.", + ) + + cmd.Flags().StringVarP( + &triggeringActor, + "triggering-actor", + "a", + utils.GetEnv("GITHUB_ACTOR", ""), + "GitHub user of the person/bot who triggered the bump, defaults to GITHUB_ACTOR env var.", + ) + + cmd.Flags().BoolVar( + &autoMerge, + "auto-merge", false, + "Automatically merges the created PR, defaults to false.", + ) + + rootCmd.AddCommand(cmd) +} diff --git a/cmd/telefonistka/bump_version_yaml.go b/cmd/telefonistka/bump_version_yaml.go new file mode 100644 index 00000000..94580f38 --- /dev/null +++ b/cmd/telefonistka/bump_version_yaml.go @@ -0,0 +1,117 @@ +package main + +import ( + "github.com/spf13/cobra" + "github.com/wayfair-incubator/telefonistka/internal/bumpversion" + "github.com/wayfair-incubator/telefonistka/pkg/utils" +) + +// This is still(https://github.com/spf13/cobra/issues/1862) the documented way to use cobra +func init() { //nolint:gochecknoinits + var ( + targetRepo string + targetFile string + address string + replacement string + githubHost string + triggeringRepo string + triggeringRepoSHA string + triggeringActor string + autoMerge bool + ) + + var cmd = &cobra.Command{ + Use: "bump-yaml", + Short: "Bump artifact version in a file using yaml selector", + Long: `Bump artifact version in a file using yaml selector. + This will open a pull request in the target repo. + This command uses yq selector to find the yaml value to replace. + `, + Args: cobra.ExactArgs(0), + Run: func(cmd *cobra.Command, args []string) { + params := bumpversion.YamlParams{ + TargetRepo: targetRepo, + TargetFile: targetFile, + Address: address, + Value: replacement, + GithubHost: githubHost, + TriggeringRepo: triggeringRepo, + TriggeringRepoSHA: triggeringRepoSHA, + TriggeringActor: triggeringActor, + AutoMerge: autoMerge, + } + bumpversion.Yaml(params) + }, + } + + cmd.Flags().StringVarP( + &targetRepo, + "target-repo", + "t", + utils.GetEnv("TARGET_REPO", ""), + "Target Git repository slug(e.g. org-name/repo-name), defaults to TARGET_REPO env var.", + ) + + cmd.Flags().StringVarP( + &targetFile, + "target-file", + "f", + utils.GetEnv("TARGET_FILE", ""), + "Target file path(from repo root), defaults to TARGET_FILE env var.", + ) + + cmd.Flags().StringVar( + &address, + "address", + "", + "Yaml value address described as a yq selector, e.g. '.db.[] | select(.name == \"postgres\").image.tag'.", + ) + + cmd.Flags().StringVarP( + &replacement, + "replacement-string", + "n", + "", + "Replacement string that includes the version value of new artifact, e.g. 'v2.7.1'.", + ) + + cmd.Flags().StringVarP( + &githubHost, + "github-host", + "g", + "", + "GitHub instance HOSTNAME, defaults to \"github.com\". This is used for GitHub Enterprise Server instances.", + ) + + cmd.Flags().StringVarP( + &triggeringRepo, + "triggering-repo", + "p", + utils.GetEnv("GITHUB_REPOSITORY", ""), + "Github repo triggering the version bump(e.g. `octocat/Hello-World`) defaults to GITHUB_REPOSITORY env var.", + ) + + cmd.Flags().StringVarP( + &triggeringRepoSHA, + "triggering-repo-sha", + "s", + utils.GetEnv("GITHUB_SHA", ""), + "Git SHA of triggering repo, defaults to GITHUB_SHA env var.", + ) + + cmd.Flags().StringVarP( + &triggeringActor, + "triggering-actor", + "a", + utils.GetEnv("GITHUB_ACTOR", ""), + "GitHub user of the person/bot who triggered the bump, defaults to GITHUB_ACTOR env var.", + ) + + cmd.Flags().BoolVar( + &autoMerge, + "auto-merge", false, + "Automatically merges the created PR, defaults to false.", + ) + + rootCmd.AddCommand(cmd) +} diff --git a/cmd/telefonistka/event.go b/cmd/telefonistka/event.go index 3ff94caf..bf822bb0 100644 --- a/cmd/telefonistka/event.go +++ b/cmd/telefonistka/event.go @@ -1,40 +1,43 @@ -package telefonistka +package main import ( - "os" - - lru "github.com/hashicorp/golang-lru/v2" "github.com/spf13/cobra" - "github.com/wayfair-incubator/telefonistka/internal/pkg/githubapi" + "github.com/wayfair-incubator/telefonistka/internal/github" + "github.com/wayfair-incubator/telefonistka/pkg/utils" ) // This is still(https://github.com/spf13/cobra/issues/1862) the documented way to use cobra func init() { //nolint:gochecknoinits - var eventType string - var eventFilePath string - eventCmd := &cobra.Command{ + var ( + kind string + filePath string + ) + + var cmd = &cobra.Command{ Use: "event", Short: "Handles a GitHub event based on event JSON file", Long: "Handles a GitHub event based on event JSON file.\nThis operation mode was was built with GitHub Actions in mind", Args: cobra.ExactArgs(0), Run: func(cmd *cobra.Command, args []string) { - event(eventType, eventFilePath) + github.Event(kind, filePath) }, } - eventCmd.Flags().StringVarP(&eventType, "type", "t", getEnv("GITHUB_EVENT_NAME", ""), "Event type, defaults to GITHUB_EVENT_NAME env var") - eventCmd.Flags().StringVarP(&eventFilePath, "file", "f", getEnv("GITHUB_EVENT_PATH", ""), "File path for event JSON, defaults to GITHUB_EVENT_PATH env var") - rootCmd.AddCommand(eventCmd) -} -func event(eventType string, eventFilePath string) { - mainGhClientCache, _ := lru.New[string, githubapi.GhClientPair](128) - prApproverGhClientCache, _ := lru.New[string, githubapi.GhClientPair](128) - githubapi.ReciveEventFile(eventFilePath, eventType, mainGhClientCache, prApproverGhClientCache) -} + cmd.Flags().StringVarP( + &kind, + "type", + "t", + utils.GetEnv("GITHUB_EVENT_NAME", ""), + "Event type, defaults to GITHUB_EVENT_NAME env var", + ) -func getEnv(key, fallback string) string { - if value, ok := os.LookupEnv(key); ok { - return value - } - return fallback + cmd.Flags().StringVarP( + &filePath, + "file", + "f", + utils.GetEnv("GITHUB_EVENT_PATH", ""), + "File path for event JSON, defaults to GITHUB_EVENT_PATH env var", + ) + + rootCmd.AddCommand(cmd) } diff --git a/cmd/telefonistka/root.go b/cmd/telefonistka/root.go deleted file mode 100644 index b94fd1c3..00000000 --- a/cmd/telefonistka/root.go +++ /dev/null @@ -1,48 +0,0 @@ -package telefonistka - -import ( - "fmt" - "os" - - log "github.com/sirupsen/logrus" - "github.com/spf13/cobra" -) - -var rootCmd = &cobra.Command{ - Use: "telefonistka", - Version: "0.0.0", - Short: "telefonistka - Safe and Controlled GitOps Promotion Across Environments/Failure-Domains", - Long: `Telefonistka is a Github webhook server/CLI tool that facilitates change promotion across environments/failure domains in Infrastructure as Code GitOps repos - -see https://github.com/wayfair-incubator/telefonistka`, - Run: func(cmd *cobra.Command, args []string) { - }, -} - -func Execute() { - switch getEnv("LOG_LEVEL", "info") { - case "debug": - log.SetLevel(log.DebugLevel) - log.SetReportCaller(true) - case "info": - log.SetLevel(log.InfoLevel) - case "warn": - log.SetLevel(log.WarnLevel) - case "error": - log.SetLevel(log.ErrorLevel) - case "fatal": - log.SetLevel(log.FatalLevel) - case "panic": - log.SetLevel(log.PanicLevel) - } - - log.SetFormatter(&log.TextFormatter{ - DisableColors: false, - // ForceColors: true, - FullTimestamp: true, - }) // TimestampFormat - if err := rootCmd.Execute(); err != nil { - fmt.Fprintf(os.Stderr, "Whoops. There was an error while executing your CLI '%s'", err) - os.Exit(1) - } -} diff --git a/cmd/telefonistka/server.go b/cmd/telefonistka/server.go index 076b28f8..ae0018c1 100644 --- a/cmd/telefonistka/server.go +++ b/cmd/telefonistka/server.go @@ -1,75 +1,20 @@ -package telefonistka +package main import ( - "net/http" - "os" - "time" - - "github.com/alexliesenfeld/health" - lru "github.com/hashicorp/golang-lru/v2" - "github.com/prometheus/client_golang/prometheus/promhttp" - log "github.com/sirupsen/logrus" "github.com/spf13/cobra" - "github.com/wayfair-incubator/telefonistka/internal/pkg/githubapi" + "github.com/wayfair-incubator/telefonistka/internal/server" ) -func getCrucialEnv(key string) string { - if value, ok := os.LookupEnv(key); ok { - return value - } - log.Fatalf("%s environment variable is required", key) - os.Exit(3) - return "" -} - -var serveCmd = &cobra.Command{ - Use: "server", - Short: "Runs the web server that listens to GitHub webhooks", - Args: cobra.ExactArgs(0), - Run: func(cmd *cobra.Command, args []string) { - serve() - }, -} - // This is still(https://github.com/spf13/cobra/issues/1862) the documented way to use cobra func init() { //nolint:gochecknoinits - rootCmd.AddCommand(serveCmd) -} - -func handleWebhook(githubWebhookSecret []byte, mainGhClientCache *lru.Cache[string, githubapi.GhClientPair], prApproverGhClientCache *lru.Cache[string, githubapi.GhClientPair]) func(http.ResponseWriter, *http.Request) { - return func(w http.ResponseWriter, r *http.Request) { - err := githubapi.ReciveWebhook(r, mainGhClientCache, prApproverGhClientCache, githubWebhookSecret) - if err != nil { - log.Errorf("error handling webhook: %v", err) - http.Error(w, "Internal server error", http.StatusInternalServerError) - return - } - w.WriteHeader(http.StatusOK) - } -} - -func serve() { - githubWebhookSecret := []byte(getCrucialEnv("GITHUB_WEBHOOK_SECRET")) - livenessChecker := health.NewChecker() // No checks for the moment, other then the http server availability - readinessChecker := health.NewChecker() - - // mainGhClientCache := map[string]githubapi.GhClientPair{} //GH apps use a per-account/org client - mainGhClientCache, _ := lru.New[string, githubapi.GhClientPair](128) - prApproverGhClientCache, _ := lru.New[string, githubapi.GhClientPair](128) - - mux := http.NewServeMux() - mux.HandleFunc("/webhook", handleWebhook(githubWebhookSecret, mainGhClientCache, prApproverGhClientCache)) - mux.Handle("/metrics", promhttp.Handler()) - mux.Handle("/live", health.NewHandler(livenessChecker)) - mux.Handle("/ready", health.NewHandler(readinessChecker)) - - srv := &http.Server{ - Handler: mux, - Addr: ":8080", - ReadTimeout: 10 * time.Second, - WriteTimeout: 10 * time.Second, + var cmd = &cobra.Command{ + Use: "server", + Short: "Runs the web server that listens to GitHub webhooks", + Args: cobra.ExactArgs(0), + Run: func(cmd *cobra.Command, args []string) { + server.Serve() + }, } - log.Infoln("server started") - log.Fatal(srv.ListenAndServe()) + rootCmd.AddCommand(cmd) } diff --git a/internal/bumpversion/bumpversion.go b/internal/bumpversion/bumpversion.go new file mode 100644 index 00000000..4be90d7d --- /dev/null +++ b/internal/bumpversion/bumpversion.go @@ -0,0 +1,187 @@ +package bumpversion + +import ( + "context" + "os" + "regexp" + "strings" + + "github.com/hexops/gotextdiff" + "github.com/hexops/gotextdiff/myers" + "github.com/hexops/gotextdiff/span" + log "github.com/sirupsen/logrus" + + "github.com/wayfair-incubator/telefonistka/internal/github" + "github.com/wayfair-incubator/telefonistka/pkg/githubapi" + "github.com/wayfair-incubator/telefonistka/pkg/utils" +) + +type OverwriteParams struct { + TargetRepo string + TargetFile string + File string + GithubHost string + TriggeringRepo string + TriggeringRepoSHA string + TriggeringActor string + AutoMerge bool +} + +func Overwrite(params OverwriteParams) { + b, err := os.ReadFile(params.File) + if err != nil { + log.Fatalf("Failed to read file %s, %v", params.File, err) + } + newFileContent := string(b) + + if params.GithubHost != "" { + githubRestAltURL := "https://" + params.GithubHost + "/api/v3" + log.Infof("Github REST API endpoint is configured to %s", githubRestAltURL) + } + + ctx := context.Background() + ghPrClientDetails := githubapi.GhPrClientDetails{ + GhClientPair: github.NewGhClientPair(ctx, params.TargetRepo), + Ctx: ctx, + Owner: strings.Split(params.TargetRepo, "/")[0], + Repo: strings.Split(params.TargetRepo, "/")[1], + PrLogger: log.WithFields(log.Fields{}), // TODO what fields should be here? + } + + defaultBranch, _ := ghPrClientDetails.GetDefaultBranch() + + initialFileContent, statusCode, err := githubapi.GetFileContent(ghPrClientDetails, defaultBranch, params.TargetFile) + if statusCode == 404 { + ghPrClientDetails.PrLogger.Infof("File %s was not found\n", params.TargetFile) + } else if err != nil { + ghPrClientDetails.PrLogger.Errorf("Fail to fetch file content:%s\n", err) + os.Exit(1) + } + + edits := myers.ComputeEdits(span.URIFromPath(""), initialFileContent, newFileContent) + ghPrClientDetails.PrLogger.Infof("Diff:\n%s", gotextdiff.ToUnified("Before", "After", initialFileContent, edits)) + + if err = githubapi.BumpVersion( + ghPrClientDetails, + "main", + params.TargetFile, + newFileContent, + params.TriggeringRepo, + params.TriggeringRepoSHA, + params.TriggeringActor, + params.AutoMerge, + ); err != nil { + log.Fatalf("Failed to bump version: %v", err) + } +} + +type RegexParams struct { + TargetRepo string + TargetFile string + Regex string + Replacement string + GithubHost string + TriggeringRepo string + TriggeringRepoSHA string + TriggeringActor string + AutoMerge bool +} + +func Regex(params RegexParams) { + if params.GithubHost != "" { + githubAltUrl := "https://" + params.GithubHost + "/api/v3" + log.Infof("Github REST API endpoint is configured to %s", githubAltUrl) + } + + ctx := context.Background() + ghPrClientDetails := githubapi.GhPrClientDetails{ + GhClientPair: github.NewGhClientPair(ctx, params.TargetRepo), + Ctx: ctx, + Owner: strings.Split(params.TargetRepo, "/")[0], + Repo: strings.Split(params.TargetRepo, "/")[1], + PrLogger: log.WithFields(log.Fields{}), // TODO what fields should be here? + } + + defaultBranch, _ := ghPrClientDetails.GetDefaultBranch() + + initialFileContent, _, err := githubapi.GetFileContent(ghPrClientDetails, defaultBranch, params.TargetFile) + if err != nil { + ghPrClientDetails.PrLogger.Errorf("Fail to fetch file content:%s\n", err) + os.Exit(1) + } + + r := regexp.MustCompile(params.Regex) + newFileContent := r.ReplaceAllString(initialFileContent, params.Replacement) + edits := myers.ComputeEdits(span.URIFromPath(""), initialFileContent, newFileContent) + + ghPrClientDetails.PrLogger.Infof("Diff:\n%s", gotextdiff.ToUnified("Before", "After", initialFileContent, edits)) + + if err = githubapi.BumpVersion( + ghPrClientDetails, + "main", + params.TargetFile, + newFileContent, + params.TriggeringRepo, + params.TriggeringRepoSHA, + params.TriggeringActor, + params.AutoMerge, + ); err != nil { + log.Fatalf("Failed to bump version: %v", err) + } +} + +type YamlParams struct { + TargetRepo string + TargetFile string + Address string + Value string + GithubHost string + TriggeringRepo string + TriggeringRepoSHA string + TriggeringActor string + AutoMerge bool +} + +func Yaml(params YamlParams) { + if params.GithubHost != "" { + githubAltUrl := "https://" + params.GithubHost + "/api/v3" + log.Infof("Github REST API endpoint is configured to %s", githubAltUrl) + } + + ctx := context.Background() + ghPrClientDetails := githubapi.GhPrClientDetails{ + GhClientPair: github.NewGhClientPair(ctx, params.TargetRepo), + Ctx: ctx, + Owner: strings.Split(params.TargetRepo, "/")[0], + Repo: strings.Split(params.TargetRepo, "/")[1], + PrLogger: log.WithFields(log.Fields{}), // TODO what fields should be here? + } + + defaultBranch, _ := ghPrClientDetails.GetDefaultBranch() + initialFileContent, _, err := githubapi.GetFileContent(ghPrClientDetails, defaultBranch, params.TargetFile) + if err != nil { + ghPrClientDetails.PrLogger.Errorf("Fail to fetch file content:%s\n", err) + os.Exit(1) + } + newFileContent, err := utils.UpdateYaml(initialFileContent, params.Address, params.Value) + if err != nil { + ghPrClientDetails.PrLogger.Errorf("Fail to update yaml:%s\n", err) + os.Exit(1) + } + edits := myers.ComputeEdits(span.URIFromPath(""), initialFileContent, newFileContent) + + ghPrClientDetails.PrLogger.Infof("Diff:\n%s", gotextdiff.ToUnified("Before", "After", initialFileContent, edits)) + + if err := githubapi.BumpVersion( + ghPrClientDetails, + "main", + params.TargetFile, + newFileContent, + params.TriggeringRepo, + params.TriggeringRepoSHA, + params.TriggeringActor, + params.AutoMerge, + ); err != nil { + log.Fatalf("Failed to bump version: %v", err) + } +} diff --git a/internal/github/client.go b/internal/github/client.go new file mode 100644 index 00000000..5e71a8a8 --- /dev/null +++ b/internal/github/client.go @@ -0,0 +1,24 @@ +package github + +import ( + "context" + "strings" + + lru "github.com/hashicorp/golang-lru/v2" + + "github.com/wayfair-incubator/telefonistka/pkg/githubapi" +) + +func NewGhClientPair(ctx context.Context, repository string) *githubapi.GhClientPair { + var clientPair githubapi.GhClientPair + clientCache, _ := lru.New[string, githubapi.GhClientPair](128) + clientPair.GetAndCache( + clientCache, + "GITHUB_APP_ID", + "GITHUB_APP_PRIVATE_KEY_PATH", + "GITHUB_OAUTH_TOKEN", + strings.Split(repository, "/")[0], + ctx, + ) + return &clientPair +} diff --git a/internal/github/event.go b/internal/github/event.go new file mode 100644 index 00000000..ae091bf7 --- /dev/null +++ b/internal/github/event.go @@ -0,0 +1,13 @@ +package github + +import ( + lru "github.com/hashicorp/golang-lru/v2" + + "github.com/wayfair-incubator/telefonistka/pkg/githubapi" +) + +func Event(eventType string, eventFilePath string) { + mainGhClientCache, _ := lru.New[string, githubapi.GhClientPair](128) + prApproverGhClientCache, _ := lru.New[string, githubapi.GhClientPair](128) + githubapi.ReciveEventFile(eventFilePath, eventType, mainGhClientCache, prApproverGhClientCache) +} diff --git a/internal/logging/logging.go b/internal/logging/logging.go new file mode 100644 index 00000000..f9ccabf6 --- /dev/null +++ b/internal/logging/logging.go @@ -0,0 +1,26 @@ +package logging + +import ( + log "github.com/sirupsen/logrus" + + "github.com/wayfair-incubator/telefonistka/pkg/utils" +) + +var logLevels = map[string]log.Level{ + "debug": log.DebugLevel, + "info": log.InfoLevel, + "warn": log.WarnLevel, + "error": log.ErrorLevel, + "fatal": log.FatalLevel, + "panic": log.PanicLevel, +} + +func ConfigureLogging() { + if logLevel, ok := logLevels[utils.GetEnv("LOG_LEVEL", "info")]; ok { + if logLevel == log.DebugLevel { + log.SetReportCaller(true) + } + log.SetLevel(log.DebugLevel) + } + log.SetFormatter(&log.TextFormatter{DisableColors: false, FullTimestamp: true}) +} diff --git a/internal/server/server.go b/internal/server/server.go new file mode 100644 index 00000000..7faed343 --- /dev/null +++ b/internal/server/server.go @@ -0,0 +1,52 @@ +package server + +import ( + "net/http" + "time" + + "github.com/alexliesenfeld/health" + lru "github.com/hashicorp/golang-lru/v2" + "github.com/prometheus/client_golang/prometheus/promhttp" + log "github.com/sirupsen/logrus" + + "github.com/wayfair-incubator/telefonistka/pkg/githubapi" + "github.com/wayfair-incubator/telefonistka/pkg/utils" +) + +func handleWebhook(githubWebhookSecret []byte, mainGhClientCache *lru.Cache[string, githubapi.GhClientPair], prApproverGhClientCache *lru.Cache[string, githubapi.GhClientPair]) func(http.ResponseWriter, *http.Request) { + return func(w http.ResponseWriter, r *http.Request) { + err := githubapi.ReciveWebhook(r, mainGhClientCache, prApproverGhClientCache, githubWebhookSecret) + if err != nil { + log.Errorf("error handling webhook: %v", err) + http.Error(w, "Internal server error", http.StatusInternalServerError) + return + } + w.WriteHeader(http.StatusOK) + } +} + +func Serve() { + githubWebhookSecret := []byte(utils.MustGetEnv("GITHUB_WEBHOOK_SECRET")) + livenessChecker := health.NewChecker() // No checks for the moment, other then the http server availability + readinessChecker := health.NewChecker() + + // mainGhClientCache := map[string]githubapi.GhClientPair{} //GH apps use a per-account/org client + mainGhClientCache, _ := lru.New[string, githubapi.GhClientPair](128) + prApproverGhClientCache, _ := lru.New[string, githubapi.GhClientPair](128) + + mux := http.NewServeMux() + mux.HandleFunc("/webhook", handleWebhook(githubWebhookSecret, mainGhClientCache, prApproverGhClientCache)) + mux.Handle("/metrics", promhttp.Handler()) + mux.Handle("/live", health.NewHandler(livenessChecker)) + mux.Handle("/ready", health.NewHandler(readinessChecker)) + + srv := &http.Server{ + Handler: mux, + Addr: ":8080", + ReadTimeout: 10 * time.Second, + WriteTimeout: 10 * time.Second, + } + + log.Infoln("server started") + log.Fatal(srv.ListenAndServe()) +} diff --git a/main.go b/main.go deleted file mode 100644 index 3a7a955e..00000000 --- a/main.go +++ /dev/null @@ -1,9 +0,0 @@ -package main - -import ( - "github.com/wayfair-incubator/telefonistka/cmd/telefonistka" -) - -func main() { - telefonistka.Execute() -} diff --git a/internal/pkg/argocd/argocd.go b/pkg/argocd/argocd.go similarity index 99% rename from internal/pkg/argocd/argocd.go rename to pkg/argocd/argocd.go index c4ef8039..5c5cb9c2 100644 --- a/internal/pkg/argocd/argocd.go +++ b/pkg/argocd/argocd.go @@ -25,7 +25,7 @@ import ( "github.com/argoproj/argo-cd/v2/util/argo/normalizers" "github.com/argoproj/gitops-engine/pkg/sync/hook" log "github.com/sirupsen/logrus" - "github.com/wayfair-incubator/telefonistka/internal/pkg/argocd/diff" + "github.com/wayfair-incubator/telefonistka/pkg/argocd/diff" yaml2 "gopkg.in/yaml.v2" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" ) diff --git a/internal/pkg/argocd/argocd_copied_from_upstream.go b/pkg/argocd/argocd_copied_from_upstream.go similarity index 100% rename from internal/pkg/argocd/argocd_copied_from_upstream.go rename to pkg/argocd/argocd_copied_from_upstream.go diff --git a/internal/pkg/argocd/argocd_test.go b/pkg/argocd/argocd_test.go similarity index 99% rename from internal/pkg/argocd/argocd_test.go rename to pkg/argocd/argocd_test.go index dc78cecc..b2e85b9e 100644 --- a/internal/pkg/argocd/argocd_test.go +++ b/pkg/argocd/argocd_test.go @@ -10,7 +10,7 @@ import ( argoappv1 "github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1" "github.com/golang/mock/gomock" - "github.com/wayfair-incubator/telefonistka/internal/pkg/mocks" + "github.com/wayfair-incubator/telefonistka/pkg/mocks" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" ) diff --git a/internal/pkg/argocd/diff/README.md b/pkg/argocd/diff/README.md similarity index 100% rename from internal/pkg/argocd/diff/README.md rename to pkg/argocd/diff/README.md diff --git a/internal/pkg/argocd/diff/diff.go b/pkg/argocd/diff/diff.go similarity index 100% rename from internal/pkg/argocd/diff/diff.go rename to pkg/argocd/diff/diff.go diff --git a/internal/pkg/argocd/diff/diff_test.go b/pkg/argocd/diff/diff_test.go similarity index 100% rename from internal/pkg/argocd/diff/diff_test.go rename to pkg/argocd/diff/diff_test.go diff --git a/internal/pkg/argocd/diff/testdata/allnew.txt b/pkg/argocd/diff/testdata/allnew.txt similarity index 100% rename from internal/pkg/argocd/diff/testdata/allnew.txt rename to pkg/argocd/diff/testdata/allnew.txt diff --git a/internal/pkg/argocd/diff/testdata/allold.txt b/pkg/argocd/diff/testdata/allold.txt similarity index 100% rename from internal/pkg/argocd/diff/testdata/allold.txt rename to pkg/argocd/diff/testdata/allold.txt diff --git a/internal/pkg/argocd/diff/testdata/basic.txt b/pkg/argocd/diff/testdata/basic.txt similarity index 100% rename from internal/pkg/argocd/diff/testdata/basic.txt rename to pkg/argocd/diff/testdata/basic.txt diff --git a/internal/pkg/argocd/diff/testdata/dups.txt b/pkg/argocd/diff/testdata/dups.txt similarity index 100% rename from internal/pkg/argocd/diff/testdata/dups.txt rename to pkg/argocd/diff/testdata/dups.txt diff --git a/internal/pkg/argocd/diff/testdata/end.txt b/pkg/argocd/diff/testdata/end.txt similarity index 100% rename from internal/pkg/argocd/diff/testdata/end.txt rename to pkg/argocd/diff/testdata/end.txt diff --git a/internal/pkg/argocd/diff/testdata/eof.txt b/pkg/argocd/diff/testdata/eof.txt similarity index 100% rename from internal/pkg/argocd/diff/testdata/eof.txt rename to pkg/argocd/diff/testdata/eof.txt diff --git a/internal/pkg/argocd/diff/testdata/eof1.txt b/pkg/argocd/diff/testdata/eof1.txt similarity index 100% rename from internal/pkg/argocd/diff/testdata/eof1.txt rename to pkg/argocd/diff/testdata/eof1.txt diff --git a/internal/pkg/argocd/diff/testdata/eof2.txt b/pkg/argocd/diff/testdata/eof2.txt similarity index 100% rename from internal/pkg/argocd/diff/testdata/eof2.txt rename to pkg/argocd/diff/testdata/eof2.txt diff --git a/internal/pkg/argocd/diff/testdata/long.txt b/pkg/argocd/diff/testdata/long.txt similarity index 100% rename from internal/pkg/argocd/diff/testdata/long.txt rename to pkg/argocd/diff/testdata/long.txt diff --git a/internal/pkg/argocd/diff/testdata/same.txt b/pkg/argocd/diff/testdata/same.txt similarity index 100% rename from internal/pkg/argocd/diff/testdata/same.txt rename to pkg/argocd/diff/testdata/same.txt diff --git a/internal/pkg/argocd/diff/testdata/start.txt b/pkg/argocd/diff/testdata/start.txt similarity index 100% rename from internal/pkg/argocd/diff/testdata/start.txt rename to pkg/argocd/diff/testdata/start.txt diff --git a/internal/pkg/argocd/diff/testdata/triv.txt b/pkg/argocd/diff/testdata/triv.txt similarity index 100% rename from internal/pkg/argocd/diff/testdata/triv.txt rename to pkg/argocd/diff/testdata/triv.txt diff --git a/internal/pkg/argocd/testdata/TestDiffLiveVsTargetObject/1.live b/pkg/argocd/testdata/TestDiffLiveVsTargetObject/1.live similarity index 100% rename from internal/pkg/argocd/testdata/TestDiffLiveVsTargetObject/1.live rename to pkg/argocd/testdata/TestDiffLiveVsTargetObject/1.live diff --git a/internal/pkg/argocd/testdata/TestDiffLiveVsTargetObject/1.target b/pkg/argocd/testdata/TestDiffLiveVsTargetObject/1.target similarity index 100% rename from internal/pkg/argocd/testdata/TestDiffLiveVsTargetObject/1.target rename to pkg/argocd/testdata/TestDiffLiveVsTargetObject/1.target diff --git a/internal/pkg/argocd/testdata/TestDiffLiveVsTargetObject/1.want b/pkg/argocd/testdata/TestDiffLiveVsTargetObject/1.want similarity index 100% rename from internal/pkg/argocd/testdata/TestDiffLiveVsTargetObject/1.want rename to pkg/argocd/testdata/TestDiffLiveVsTargetObject/1.want diff --git a/internal/pkg/argocd/testdata/TestRenderDiff.live b/pkg/argocd/testdata/TestRenderDiff.live similarity index 100% rename from internal/pkg/argocd/testdata/TestRenderDiff.live rename to pkg/argocd/testdata/TestRenderDiff.live diff --git a/internal/pkg/argocd/testdata/TestRenderDiff.md b/pkg/argocd/testdata/TestRenderDiff.md similarity index 100% rename from internal/pkg/argocd/testdata/TestRenderDiff.md rename to pkg/argocd/testdata/TestRenderDiff.md diff --git a/internal/pkg/argocd/testdata/TestRenderDiff.target b/pkg/argocd/testdata/TestRenderDiff.target similarity index 100% rename from internal/pkg/argocd/testdata/TestRenderDiff.target rename to pkg/argocd/testdata/TestRenderDiff.target diff --git a/internal/pkg/configuration/config.go b/pkg/configuration/config.go similarity index 100% rename from internal/pkg/configuration/config.go rename to pkg/configuration/config.go diff --git a/internal/pkg/configuration/config_test.go b/pkg/configuration/config_test.go similarity index 100% rename from internal/pkg/configuration/config_test.go rename to pkg/configuration/config_test.go diff --git a/internal/pkg/configuration/tests/testConfigurationParsing.yaml b/pkg/configuration/tests/testConfigurationParsing.yaml similarity index 100% rename from internal/pkg/configuration/tests/testConfigurationParsing.yaml rename to pkg/configuration/tests/testConfigurationParsing.yaml diff --git a/internal/pkg/githubapi/.tmpMJcSWN b/pkg/githubapi/.tmpMJcSWN similarity index 100% rename from internal/pkg/githubapi/.tmpMJcSWN rename to pkg/githubapi/.tmpMJcSWN diff --git a/internal/pkg/githubapi/clients.go b/pkg/githubapi/clients.go similarity index 100% rename from internal/pkg/githubapi/clients.go rename to pkg/githubapi/clients.go diff --git a/internal/pkg/githubapi/drift_detection.go b/pkg/githubapi/drift_detection.go similarity index 98% rename from internal/pkg/githubapi/drift_detection.go rename to pkg/githubapi/drift_detection.go index 8546f575..e7d31080 100644 --- a/internal/pkg/githubapi/drift_detection.go +++ b/pkg/githubapi/drift_detection.go @@ -9,7 +9,7 @@ import ( "github.com/hexops/gotextdiff" "github.com/hexops/gotextdiff/myers" "github.com/hexops/gotextdiff/span" - prom "github.com/wayfair-incubator/telefonistka/internal/pkg/prometheus" + prom "github.com/wayfair-incubator/telefonistka/pkg/prometheus" ) func generateDiffOutput(ghPrClientDetails GhPrClientDetails, defaultBranch string, sourceFilesSHAs map[string]string, targetFilesSHAs map[string]string, sourcePath string, targetPath string) (bool, string, error) { diff --git a/internal/pkg/githubapi/drift_detection_test.go b/pkg/githubapi/drift_detection_test.go similarity index 100% rename from internal/pkg/githubapi/drift_detection_test.go rename to pkg/githubapi/drift_detection_test.go diff --git a/internal/pkg/githubapi/github.go b/pkg/githubapi/github.go similarity index 99% rename from internal/pkg/githubapi/github.go rename to pkg/githubapi/github.go index adc1b9b0..6c882a0f 100644 --- a/internal/pkg/githubapi/github.go +++ b/pkg/githubapi/github.go @@ -22,9 +22,9 @@ import ( "github.com/google/go-github/v62/github" lru "github.com/hashicorp/golang-lru/v2" log "github.com/sirupsen/logrus" - "github.com/wayfair-incubator/telefonistka/internal/pkg/argocd" - cfg "github.com/wayfair-incubator/telefonistka/internal/pkg/configuration" - prom "github.com/wayfair-incubator/telefonistka/internal/pkg/prometheus" + "github.com/wayfair-incubator/telefonistka/pkg/argocd" + cfg "github.com/wayfair-incubator/telefonistka/pkg/configuration" + prom "github.com/wayfair-incubator/telefonistka/pkg/prometheus" "golang.org/x/exp/maps" ) diff --git a/internal/pkg/githubapi/github_graphql.go b/pkg/githubapi/github_graphql.go similarity index 100% rename from internal/pkg/githubapi/github_graphql.go rename to pkg/githubapi/github_graphql.go diff --git a/internal/pkg/githubapi/github_test.go b/pkg/githubapi/github_test.go similarity index 100% rename from internal/pkg/githubapi/github_test.go rename to pkg/githubapi/github_test.go diff --git a/internal/pkg/githubapi/promotion.go b/pkg/githubapi/promotion.go similarity index 98% rename from internal/pkg/githubapi/promotion.go rename to pkg/githubapi/promotion.go index 298d73b0..c23fcbfd 100644 --- a/internal/pkg/githubapi/promotion.go +++ b/pkg/githubapi/promotion.go @@ -8,8 +8,8 @@ import ( "github.com/google/go-github/v62/github" log "github.com/sirupsen/logrus" - cfg "github.com/wayfair-incubator/telefonistka/internal/pkg/configuration" - prom "github.com/wayfair-incubator/telefonistka/internal/pkg/prometheus" + cfg "github.com/wayfair-incubator/telefonistka/pkg/configuration" + prom "github.com/wayfair-incubator/telefonistka/pkg/prometheus" yaml "gopkg.in/yaml.v2" ) diff --git a/internal/pkg/githubapi/promotion_test.go b/pkg/githubapi/promotion_test.go similarity index 99% rename from internal/pkg/githubapi/promotion_test.go rename to pkg/githubapi/promotion_test.go index d9f6afbd..601f360a 100644 --- a/internal/pkg/githubapi/promotion_test.go +++ b/pkg/githubapi/promotion_test.go @@ -10,7 +10,7 @@ import ( "github.com/migueleliasweb/go-github-mock/src/mock" log "github.com/sirupsen/logrus" "github.com/stretchr/testify/assert" - cfg "github.com/wayfair-incubator/telefonistka/internal/pkg/configuration" + cfg "github.com/wayfair-incubator/telefonistka/pkg/configuration" ) func generatePromotionPlanMetadataTestHelper(t *testing.T, config *cfg.Config, expectedPromotion map[string]PromotionInstance, mockedHTTPClient *http.Client) { diff --git a/internal/pkg/githubapi/testdata/diff_comment_data_test.json b/pkg/githubapi/testdata/diff_comment_data_test.json similarity index 100% rename from internal/pkg/githubapi/testdata/diff_comment_data_test.json rename to pkg/githubapi/testdata/diff_comment_data_test.json diff --git a/internal/pkg/githubapi/testdata/pr_body.golden.md b/pkg/githubapi/testdata/pr_body.golden.md similarity index 100% rename from internal/pkg/githubapi/testdata/pr_body.golden.md rename to pkg/githubapi/testdata/pr_body.golden.md diff --git a/internal/pkg/githubapi/webhook_proxy.go b/pkg/githubapi/webhook_proxy.go similarity index 96% rename from internal/pkg/githubapi/webhook_proxy.go rename to pkg/githubapi/webhook_proxy.go index c3eadb30..33b8c4e1 100644 --- a/internal/pkg/githubapi/webhook_proxy.go +++ b/pkg/githubapi/webhook_proxy.go @@ -12,8 +12,8 @@ import ( "github.com/google/go-github/v62/github" log "github.com/sirupsen/logrus" - "github.com/wayfair-incubator/telefonistka/internal/pkg/configuration" - prom "github.com/wayfair-incubator/telefonistka/internal/pkg/prometheus" + "github.com/wayfair-incubator/telefonistka/pkg/configuration" + prom "github.com/wayfair-incubator/telefonistka/pkg/prometheus" "golang.org/x/exp/maps" ) diff --git a/internal/pkg/githubapi/webhook_proxy_test.go b/pkg/githubapi/webhook_proxy_test.go similarity index 96% rename from internal/pkg/githubapi/webhook_proxy_test.go rename to pkg/githubapi/webhook_proxy_test.go index b4523e78..6602f61d 100644 --- a/internal/pkg/githubapi/webhook_proxy_test.go +++ b/pkg/githubapi/webhook_proxy_test.go @@ -10,7 +10,7 @@ import ( "github.com/go-test/deep" "github.com/google/go-github/v62/github" - cfg "github.com/wayfair-incubator/telefonistka/internal/pkg/configuration" + cfg "github.com/wayfair-incubator/telefonistka/pkg/configuration" ) func TestGenerateListOfEndpoints(t *testing.T) { diff --git a/internal/pkg/mocks/.gitignore b/pkg/mocks/.gitignore similarity index 100% rename from internal/pkg/mocks/.gitignore rename to pkg/mocks/.gitignore diff --git a/internal/pkg/mocks/mocks.go b/pkg/mocks/mocks.go similarity index 100% rename from internal/pkg/mocks/mocks.go rename to pkg/mocks/mocks.go diff --git a/internal/pkg/prometheus/prometheus.go b/pkg/prometheus/prometheus.go similarity index 100% rename from internal/pkg/prometheus/prometheus.go rename to pkg/prometheus/prometheus.go diff --git a/internal/pkg/prometheus/prometheus_test.go b/pkg/prometheus/prometheus_test.go similarity index 100% rename from internal/pkg/prometheus/prometheus_test.go rename to pkg/prometheus/prometheus_test.go diff --git a/pkg/utils/utils.go b/pkg/utils/utils.go new file mode 100644 index 00000000..08af5d7a --- /dev/null +++ b/pkg/utils/utils.go @@ -0,0 +1,35 @@ +package utils + +import ( + "fmt" + "log" + "os" + + "github.com/mikefarah/yq/v4/pkg/yqlib" +) + +func GetEnv(key, fallback string) string { + if value, ok := os.LookupEnv(key); ok { + return value + } + return fallback +} + +func MustGetEnv(key string) string { + if value, ok := os.LookupEnv(key); ok { + return value + } + log.Fatalf("%s environment variable is required", key) + os.Exit(3) + return "" +} + +func UpdateYaml(yamlContent, key, value string) (string, error) { + yqExpression := fmt.Sprintf("(%s)=\"%s\"", key, value) + preferences := yqlib.NewDefaultYamlPreferences() + evaluate, err := yqlib.NewStringEvaluator().Evaluate(yqExpression, yamlContent, yqlib.NewYamlEncoder(preferences), yqlib.NewYamlDecoder(preferences)) + if err != nil { + return "", err + } + return evaluate, nil +} diff --git a/cmd/telefonistka/bump-version-yaml_test.go b/pkg/utils/utils_test.go similarity index 92% rename from cmd/telefonistka/bump-version-yaml_test.go rename to pkg/utils/utils_test.go index f44c10b4..665594c6 100644 --- a/cmd/telefonistka/bump-version-yaml_test.go +++ b/pkg/utils/utils_test.go @@ -1,8 +1,6 @@ -package telefonistka +package utils -import ( - "testing" -) +import "testing" func TestUpdateYaml(t *testing.T) { t.Parallel() @@ -79,7 +77,7 @@ image: tt := tt t.Run(tt.name, func(t *testing.T) { t.Parallel() - got, err := updateYaml(tt.yamlContent, tt.address, tt.value) + got, err := UpdateYaml(tt.yamlContent, tt.address, tt.value) if err != nil { t.Errorf("updateYaml() error = %v", err) return From 65fbae3fe13e3b734e5819382a0cfae8d293b05f Mon Sep 17 00:00:00 2001 From: Jared Patrick Date: Tue, 15 Oct 2024 09:54:07 -0400 Subject: [PATCH 2/3] fix lint errors. add telefonistka command main --- cmd/telefonistka/bump_version_overwrite.go | 2 +- cmd/telefonistka/bump_version_regex.go | 2 +- cmd/telefonistka/bump_version_yaml.go | 2 +- cmd/telefonistka/event.go | 2 +- cmd/telefonistka/main.go | 28 ++++++++++++++++++++++ cmd/telefonistka/server.go | 2 +- internal/bumpversion/bumpversion.go | 1 - internal/github/client.go | 1 - internal/github/event.go | 1 - internal/logging/logging.go | 1 - internal/server/server.go | 1 - 11 files changed, 33 insertions(+), 10 deletions(-) create mode 100644 cmd/telefonistka/main.go diff --git a/cmd/telefonistka/bump_version_overwrite.go b/cmd/telefonistka/bump_version_overwrite.go index 33340fd3..c0e0142c 100644 --- a/cmd/telefonistka/bump_version_overwrite.go +++ b/cmd/telefonistka/bump_version_overwrite.go @@ -19,7 +19,7 @@ func init() { //nolint:gochecknoinits autoMerge bool ) - var cmd = &cobra.Command{ + cmd := &cobra.Command{ Use: "bump-overwrite", Short: "Bump artifact version based on provided file content.", Long: "Bump artifact version based on provided file content.\nThis open a pull request in the target repo.", diff --git a/cmd/telefonistka/bump_version_regex.go b/cmd/telefonistka/bump_version_regex.go index a4d6b2fb..2923da8b 100644 --- a/cmd/telefonistka/bump_version_regex.go +++ b/cmd/telefonistka/bump_version_regex.go @@ -20,7 +20,7 @@ func init() { //nolint:gochecknoinits autoMerge bool ) - var cmd = &cobra.Command{ + cmd := &cobra.Command{ Use: "bump-regex", Short: "Bump artifact version in a file using regex", Long: "Bump artifact version in a file using regex.\nThis open a pull request in the target repo.\n", diff --git a/cmd/telefonistka/bump_version_yaml.go b/cmd/telefonistka/bump_version_yaml.go index 94580f38..fde312de 100644 --- a/cmd/telefonistka/bump_version_yaml.go +++ b/cmd/telefonistka/bump_version_yaml.go @@ -20,7 +20,7 @@ func init() { //nolint:gochecknoinits autoMerge bool ) - var cmd = &cobra.Command{ + cmd := &cobra.Command{ Use: "bump-yaml", Short: "Bump artifact version in a file using yaml selector", Long: `Bump artifact version in a file using yaml selector. diff --git a/cmd/telefonistka/event.go b/cmd/telefonistka/event.go index bf822bb0..15ff4c1e 100644 --- a/cmd/telefonistka/event.go +++ b/cmd/telefonistka/event.go @@ -13,7 +13,7 @@ func init() { //nolint:gochecknoinits filePath string ) - var cmd = &cobra.Command{ + cmd := &cobra.Command{ Use: "event", Short: "Handles a GitHub event based on event JSON file", Long: "Handles a GitHub event based on event JSON file.\nThis operation mode was was built with GitHub Actions in mind", diff --git a/cmd/telefonistka/main.go b/cmd/telefonistka/main.go new file mode 100644 index 00000000..f49c7af7 --- /dev/null +++ b/cmd/telefonistka/main.go @@ -0,0 +1,28 @@ +package main + +import ( + "fmt" + "os" + + "github.com/spf13/cobra" + "github.com/wayfair-incubator/telefonistka/internal/logging" +) + +var version string + +var rootCmd = &cobra.Command{ + Use: "telefonistka", + Version: version, + Short: "telefonistka - Safe and Controlled GitOps Promotion Across Environments/Failure-Domains", + Long: `Telefonistka is a Github webhook server/CLI tool that facilitates change promotion across environments/failure domains in Infrastructure as Code GitOps repos + +see https://github.com/wayfair-incubator/telefonistka`, +} + +func main() { + logging.ConfigureLogging() + if err := rootCmd.Execute(); err != nil { + fmt.Fprintf(os.Stderr, "Whoops. There was an error while executing your CLI '%s'", err) + os.Exit(1) + } +} diff --git a/cmd/telefonistka/server.go b/cmd/telefonistka/server.go index ae0018c1..d6e4a1ab 100644 --- a/cmd/telefonistka/server.go +++ b/cmd/telefonistka/server.go @@ -7,7 +7,7 @@ import ( // This is still(https://github.com/spf13/cobra/issues/1862) the documented way to use cobra func init() { //nolint:gochecknoinits - var cmd = &cobra.Command{ + cmd := &cobra.Command{ Use: "server", Short: "Runs the web server that listens to GitHub webhooks", Args: cobra.ExactArgs(0), diff --git a/internal/bumpversion/bumpversion.go b/internal/bumpversion/bumpversion.go index 4be90d7d..193b197a 100644 --- a/internal/bumpversion/bumpversion.go +++ b/internal/bumpversion/bumpversion.go @@ -10,7 +10,6 @@ import ( "github.com/hexops/gotextdiff/myers" "github.com/hexops/gotextdiff/span" log "github.com/sirupsen/logrus" - "github.com/wayfair-incubator/telefonistka/internal/github" "github.com/wayfair-incubator/telefonistka/pkg/githubapi" "github.com/wayfair-incubator/telefonistka/pkg/utils" diff --git a/internal/github/client.go b/internal/github/client.go index 5e71a8a8..74c0bf1d 100644 --- a/internal/github/client.go +++ b/internal/github/client.go @@ -5,7 +5,6 @@ import ( "strings" lru "github.com/hashicorp/golang-lru/v2" - "github.com/wayfair-incubator/telefonistka/pkg/githubapi" ) diff --git a/internal/github/event.go b/internal/github/event.go index ae091bf7..578b96a2 100644 --- a/internal/github/event.go +++ b/internal/github/event.go @@ -2,7 +2,6 @@ package github import ( lru "github.com/hashicorp/golang-lru/v2" - "github.com/wayfair-incubator/telefonistka/pkg/githubapi" ) diff --git a/internal/logging/logging.go b/internal/logging/logging.go index f9ccabf6..413f7233 100644 --- a/internal/logging/logging.go +++ b/internal/logging/logging.go @@ -2,7 +2,6 @@ package logging import ( log "github.com/sirupsen/logrus" - "github.com/wayfair-incubator/telefonistka/pkg/utils" ) diff --git a/internal/server/server.go b/internal/server/server.go index 7faed343..043ea339 100644 --- a/internal/server/server.go +++ b/internal/server/server.go @@ -8,7 +8,6 @@ import ( lru "github.com/hashicorp/golang-lru/v2" "github.com/prometheus/client_golang/prometheus/promhttp" log "github.com/sirupsen/logrus" - "github.com/wayfair-incubator/telefonistka/pkg/githubapi" "github.com/wayfair-incubator/telefonistka/pkg/utils" ) From 894bb6e061618b538a67fea15a261e8ba5ca8cf0 Mon Sep 17 00:00:00 2001 From: Jared Patrick Date: Tue, 15 Oct 2024 10:32:50 -0400 Subject: [PATCH 3/3] update docker publish on comment workflow --- .github/workflows/docker-publish-on-comment.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/docker-publish-on-comment.yml b/.github/workflows/docker-publish-on-comment.yml index c0f86e36..a5b2f141 100644 --- a/.github/workflows/docker-publish-on-comment.yml +++ b/.github/workflows/docker-publish-on-comment.yml @@ -18,7 +18,7 @@ env: jobs: build: runs-on: ubuntu-latest - if: github.event.issue.pull_request && contains(github.event.comment.body, '/publish') && github.event.comment.user.login == 'Oded-B' + if: github.event.issue.pull_request && contains(github.event.comment.body, '/publish') && contains(fromJson('["Oded-B", "jared-logan-patrick-ct"]'), github.event.comment.user.login) permissions: contents: read packages: write