Skip to content

Commit

Permalink
Merge branch 'wayfair-incubator:main' into main
Browse files Browse the repository at this point in the history
  • Loading branch information
Oded-B authored Apr 3, 2024
2 parents 72354b7 + 1508139 commit e159e49
Show file tree
Hide file tree
Showing 17 changed files with 225 additions and 151 deletions.
13 changes: 4 additions & 9 deletions .github/workflows/docker-publish-on-comment.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,6 @@ on:
issue_comment:
types: [created]

env:
# Use docker.io for Docker Hub if empty
REGISTRY: ghcr.io
# github.repository as <account>/<repo>
IMAGE_NAME: ${{ github.repository }}


jobs:
Expand Down Expand Up @@ -51,14 +46,15 @@ jobs:

# Login against a Docker registry except on PR
# https://github.com/docker/login-action
- name: Log into GH registry ${{ env.REGISTRY }}
- name: Log into GH registry (ghcr.io)
uses: docker/login-action@3d58c274f17dffee475a5520cbe67f0a882c4dbb
with:
registry: ${{ env.REGISTRY }}
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

- name: Log into Docker Hub registry ${{ env.REGISTRY }}
- name: Log into Docker Hub registry
if: secrets.DOCKERHUB_TOKEN != ''
uses: docker/login-action@3d58c274f17dffee475a5520cbe67f0a882c4dbb
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
Expand All @@ -75,7 +71,6 @@ jobs:
context: git
images: |
${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
wayfaiross/telefonistka
tags: |
type=ref,event=branch
type=ref,event=pr
Expand Down
17 changes: 5 additions & 12 deletions .github/workflows/docker-publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,6 @@ on:
pull_request:
branches: [ "main" ]

env:
# Use docker.io for Docker Hub if empty
REGISTRY: ghcr.io
# github.repository as <account>/<repo>
IMAGE_NAME: ${{ github.repository }}


jobs:
build:
Expand Down Expand Up @@ -53,16 +47,16 @@ jobs:

# Login against a Docker registry except on PR
# https://github.com/docker/login-action
- name: Log into GH registry ${{ env.REGISTRY }}
if: github.event_name != 'pull_request'
- name: Log into GH registry (ghcr.io)
if: github.event_name != 'pull_request'
uses: docker/login-action@3d58c274f17dffee475a5520cbe67f0a882c4dbb
with:
registry: ${{ env.REGISTRY }}
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

- name: Log into Docker Hub registry ${{ env.REGISTRY }}
if: github.event_name != 'pull_request'
- name: Log into Docker Hub registry
if: github.event_name != 'pull_request' && secrets.DOCKERHUB_TOKEN != ''
uses: docker/login-action@3d58c274f17dffee475a5520cbe67f0a882c4dbb
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
Expand All @@ -78,7 +72,6 @@ jobs:
with:
images: |
${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
wayfaiross/telefonistka
# Build and push Docker image with Buildx (don't push on PR)
Expand Down
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,10 @@ Allows separating promotions into a separate PRs per environment/failure domain

e.g. "Sync all dev clusters in one PR but open a dedicated PR for every production cluster"

Also allows automatic merging of PRs based on the promotion policy.

e.g. "Automatically merge PRs that promote to multiple `lab` environments"

### Optional per-component allow/block override list

Allows overriding the general(per-repo) promotion policy on a per component level.
Expand Down
15 changes: 11 additions & 4 deletions cmd/telefonistka/bump-version-overwrite.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"os"
"strings"

lru "github.com/hashicorp/golang-lru/v2"
"github.com/hexops/gotextdiff"
"github.com/hexops/gotextdiff/myers"
"github.com/hexops/gotextdiff/span"
Expand All @@ -22,13 +23,14 @@ func init() { //nolint:gochecknoinits
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)
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.")
Expand All @@ -38,10 +40,11 @@ func init() { //nolint:gochecknoinits
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) {
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)
Expand All @@ -56,10 +59,14 @@ func bumpVersionOverwrite(targetRepo string, targetFile string, file string, git
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.Ghclient = githubapi.CreateGithubRestClient(getCrucialEnv("GITHUB_OAUTH_TOKEN"), githubRestAltURL, ctx)
ghPrClientDetails.GhClientPair = &mainGithubClientPair
ghPrClientDetails.Ctx = ctx
ghPrClientDetails.Owner = strings.Split(targetRepo, "/")[0]
ghPrClientDetails.Repo = strings.Split(targetRepo, "/")[1]
Expand All @@ -77,7 +84,7 @@ func bumpVersionOverwrite(targetRepo string, targetFile string, file string, git
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)
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)
Expand Down
17 changes: 12 additions & 5 deletions cmd/telefonistka/bump-version-regex.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"regexp"
"strings"

lru "github.com/hashicorp/golang-lru/v2"
"github.com/hexops/gotextdiff"
"github.com/hexops/gotextdiff/myers"
"github.com/hexops/gotextdiff/span"
Expand All @@ -24,13 +25,14 @@ func init() { //nolint:gochecknoinits
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.",
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)
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.")
Expand All @@ -41,21 +43,26 @@ func init() { //nolint:gochecknoinits
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) {
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.Ghclient = githubapi.CreateGithubRestClient(getCrucialEnv("GITHUB_OAUTH_TOKEN"), githubRestAltURL, ctx)
ghPrClientDetails.GhClientPair = &mainGithubClientPair
ghPrClientDetails.Ctx = ctx
ghPrClientDetails.Owner = strings.Split(targetRepo, "/")[0]
ghPrClientDetails.Repo = strings.Split(targetRepo, "/")[1]
Expand All @@ -74,7 +81,7 @@ func bumpVersionRegex(targetRepo string, targetFile string, regex string, replac
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)
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)
Expand Down
5 changes: 4 additions & 1 deletion docs/installation.md
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,8 @@ Configuration keys:
|`promotionPaths`| Array of maps, each map describes a promotion flow|
|`promotionPaths[0].sourcePath`| directory that holds components(subdirectories) to be synced, can include a regex.|
|`promotionPaths[0].conditions` | conditions for triggering a specific promotion flows. Flows are evaluated in order, first one to match is triggered.|
|`promotionPaths[0].conditions.prHasLabels` | Array of PR labels, if the triggering PR has any of these labels the condition is considered fulfilled. Currently it's the only supported condition type|
|`promotionPaths[0].conditions.prHasLabels` | Array of PR labels, if the triggering PR has any of these labels the condition is considered fulfilled.|
|`promotionPaths[0].conditions.autoMerge`| Boolean value. If set to true, PR will be automatically merged after it is created.|
|`promotionPaths[0].promotionPrs`| Array of structures, each element represent a PR that will be opened when files are changed under `sourcePath`. Multiple elements means multiple PR will be opened|
|`promotionPaths[0].promotionPrs[0].targetPaths`| Array of strings, each element represent a directory to by synced from the changed component under `sourcePath`. Multiple elements means multiple directories will be synced in a PR|
|`dryRunMode`| if true, the bot will just comment the planned promotion on the merged PR|
Expand All @@ -102,6 +103,8 @@ Example:
```yaml
promotionPaths:
- sourcePath: "workspace/"
conditions:
autoMerge: true
promotionPrs:
- targetPaths:
- "clusters/dev/us-east4/c2"
Expand Down
6 changes: 4 additions & 2 deletions docs/version_bumping.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
If your IaC repo deploys software you maintain internally you probably want to automate artifact version bumping.
Telefonistka can automate opening the IaC repo PR for the version change from the Code repo pipeline.

Currently two modes of operation are supported:
Currently, two modes of operation are supported:

## Whole file overwrite

Expand All @@ -15,6 +15,7 @@ Usage:
telefonistka bump-overwrite [flags]

Flags:
--auto-merge Automatically merges the created PR, defaults to false.
-c, --file string File that holds the content the target file will be overwritten with, like "version.yaml" or '<(echo -e "image:\n tag: ${VERSION}")'.
-g, --github-host string GitHub instance HOSTNAME, defaults to "github.com". This is used for GitHub Enterprise Server instances.
-h, --help help for bump-overwrite.
Expand All @@ -40,6 +41,7 @@ Usage:
telefonistka bump-regex [flags]

Flags:
--auto-merge Automatically merges the created PR, defaults to false.
-g, --github-host string GitHub instance HOSTNAME, defaults to "github.com". This is used for GitHub Enterprise Server instances.
-h, --help help for bump-regex.
-r, --regex-string string Regex used to replace artifact version, e.g. 'tag:\s*(\S*)',
Expand All @@ -49,7 +51,7 @@ Flags:
-a, --triggering-actor string GitHub user of the person/bot who triggered the bump, defaults to GITHUB_ACTOR env var.
-p, --triggering-repo octocat/Hello-World Github repo triggering the version bump(e.g. octocat/Hello-World) defaults to GITHUB_REPOSITORY env var.
-s, --triggering-repo-sha string Git SHA of triggering repo, defaults to GITHUB_SHA env var.
```
```

notes:

Expand Down
1 change: 1 addition & 0 deletions internal/pkg/configuration/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ type ComponentConfig struct {

type Condition struct {
PrHasLabels []string `yaml:"prHasLabels"`
AutoMerge bool `yaml:"autoMerge"`
}

type PromotionPr struct {
Expand Down
7 changes: 7 additions & 0 deletions internal/pkg/configuration/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ func TestConfigurationParse(t *testing.T) {
PrHasLabels: []string{
"some-label",
},
AutoMerge: true,
},
PromotionPrs: []PromotionPr{
{
Expand All @@ -45,6 +46,9 @@ func TestConfigurationParse(t *testing.T) {
},
{
SourcePath: "env/staging/us-east4/c1/",
Conditions: Condition{
AutoMerge: false,
},
PromotionPrs: []PromotionPr{
{
TargetPaths: []string{
Expand All @@ -55,6 +59,9 @@ func TestConfigurationParse(t *testing.T) {
},
{
SourcePath: "env/prod/us-central1/c2/",
Conditions: Condition{
AutoMerge: false,
},
PromotionPrs: []PromotionPr{
{
TargetPaths: []string{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,20 @@ promotionPaths:
conditions:
prHasLabels:
- "some-label"
autoMerge: true
promotionPrs:
- targetPaths:
- "env/staging/us-east4/c1/"
- targetPaths:
- "env/staging/europe-west4/c1/"
- sourcePath: "env/staging/us-east4/c1/"
conditions:
autoMerge: false
promotionPrs:
- targetPaths:
- "env/prod/us-central1/c2/"
- sourcePath: "env/prod/us-central1/c2/"
conditions:
promotionPrs:
- targetPaths:
- "env/prod/us-west1/c2/"
Expand Down
8 changes: 4 additions & 4 deletions internal/pkg/githubapi/clients.go
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ func createGithubAppRestClient(githubAppPrivateKeyPath string, githubAppId int64
return client
}

func CreateGithubRestClient(githubOauthToken string, githubRestAltURL string, ctx context.Context) *github.Client {
func createGithubRestClient(githubOauthToken string, githubRestAltURL string, ctx context.Context) *github.Client {
ts := oauth2.StaticTokenSource(
&oauth2.Token{AccessToken: githubOauthToken},
)
Expand Down Expand Up @@ -182,15 +182,15 @@ func createGhTokenClientPair(ctx context.Context, ghOauthToken string) GhClientP
log.Debugf("Using public Github API endpoint")
}

// ghClientPair.v3Client := CreateGithubRestClient(ghOauthToken, githubRestAltURL, ctx)
// ghClientPair.v3Client := createGithubRestClient(ghOauthToken, githubRestAltURL, ctx)
// ghClientPair.v4Client := createGithubGraphQlClient(ghOauthToken, githubGraphqlAltURL)
return GhClientPair{
v3Client: CreateGithubRestClient(ghOauthToken, githubRestAltURL, ctx),
v3Client: createGithubRestClient(ghOauthToken, githubRestAltURL, ctx),
v4Client: createGithubGraphQlClient(ghOauthToken, githubGraphqlAltURL),
}
}

func (gcp *GhClientPair) getAndCache(ghClientCache *lru.Cache[string, GhClientPair], ghAppIdEnvVarName string, ghAppPKeyPathEnvVarName string, ghOauthTokenEnvVarName string, repoOwner string, ctx context.Context) {
func (gcp *GhClientPair) GetAndCache(ghClientCache *lru.Cache[string, GhClientPair], ghAppIdEnvVarName string, ghAppPKeyPathEnvVarName string, ghOauthTokenEnvVarName string, repoOwner string, ctx context.Context) {
githubAppId := getEnv(ghAppIdEnvVarName, "")
var keyExist bool
if githubAppId != "" {
Expand Down
4 changes: 2 additions & 2 deletions internal/pkg/githubapi/drift_detection.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ func generateDiffOutput(ghPrClientDetails GhPrClientDetails, defaultBranch strin

if len(filesWithDiff) != 0 {
diffOutput.WriteString("\n### Blame Links:\n")
githubURL := ghPrClientDetails.Ghclient.BaseURL.String()
githubURL := ghPrClientDetails.GhClientPair.v3Client.BaseURL.String()
blameUrlPrefix := githubURL + ghPrClientDetails.Owner + "/" + ghPrClientDetails.Repo + "/blame"

for _, f := range filesWithDiff {
Expand Down Expand Up @@ -100,7 +100,7 @@ func generateFlatMapfromFileTree(ghPrClientDetails *GhPrClientDetails, workingPa
getContentOpts := &github.RepositoryContentGetOptions{
Ref: *branch,
}
_, directoryContent, resp, _ := ghPrClientDetails.Ghclient.Repositories.GetContents(ghPrClientDetails.Ctx, ghPrClientDetails.Owner, ghPrClientDetails.Repo, *workingPath, getContentOpts)
_, directoryContent, resp, _ := ghPrClientDetails.GhClientPair.v3Client.Repositories.GetContents(ghPrClientDetails.Ctx, ghPrClientDetails.Owner, ghPrClientDetails.Repo, *workingPath, getContentOpts)
prom.InstrumentGhCall(resp)
for _, elementInDir := range directoryContent {
if *elementInDir.Type == "file" {
Expand Down
Loading

0 comments on commit e159e49

Please sign in to comment.