Skip to content

Commit

Permalink
More general purpose action names (#28)
Browse files Browse the repository at this point in the history
  • Loading branch information
Gerrit91 authored Nov 9, 2020
1 parent 7a15c25 commit 52e47ca
Show file tree
Hide file tree
Showing 8 changed files with 281 additions and 265 deletions.
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ A bot helping to automate some tasks on Github and Gitlab.
## Task Descriptions

- Automatically add releases of certain repositories to the [releases](https://github.com/metal-stack/releases) repository (`develop` branch)
- Automatically add commit and PR for swagger client repositories to update their clients (`auto-generate/<version>` branch, Github action needs to generate the client and push it back to this branch)
- Automatically add a commit and PR for swagger client repositories to update their clients (`auto-generate/<version>` branch, Github action needs to generate the client and push it back to this branch)
- Automatically add a commit and PR for docs repository after a metal-stack release
- Adds a comment on [docs](https://github.com/metal-stack/docs) PRs to a rendered preview
- Create team for repository maintainers on repository creation (can be used for CODEOWNERS)

Expand Down
9 changes: 5 additions & 4 deletions metal-robot.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ webhooks:
# file: "deploy/kubernetes.yaml"
# yaml-path: "metadata.name"

- type: release-vector
- type: aggregate-releases
client: metal-stack-github
args:
repository: releases
Expand Down Expand Up @@ -210,7 +210,7 @@ webhooks:
file: "release.yaml"
yaml-path: "projects.metal-stack.mini-lab.version"

- type: release-vector
- type: aggregate-releases
client: fi-ts-github
args:
repository: releases
Expand All @@ -230,11 +230,12 @@ webhooks:
file: "release.yaml"
yaml-path: "docker-images.metal-stack.generic.backup-restore-sidecar.tag"

- type: swagger-clients
- type: distribute-releases
client: metal-stack-github
args:
repository: metal-api
repository-url: https://github.com/metal-stack/metal-api
repos:
metal-api:
- repository: metal-python
repository-url: "https://github.com/metal-stack/metal-python"
modifiers:
Expand Down
33 changes: 18 additions & 15 deletions pkg/config/actions.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,23 +16,26 @@ type DocsPreviewCommentConfig struct {
RepositoryName string `mapstructure:"repository" description:"the name of the docs repo"`
}

type ReleaseVectorConfig struct {
RepositoryName string `mapstructure:"repository" description:"the name of the release repo"`
RepositoryURL string `mapstructure:"repository-url" description:"the url of the release repo"`
Branch *string `mapstructure:"branch" description:"the branch to push in the release vector repo"`
CommitMsgTemplate *string `mapstructure:"commit-tpl" description:"template of the commit message"`
PullRequestTitle *string `mapstructure:"pull-request-title" description:"title of the pull request"`
Repos map[string][]Modifier `mapstructure:"repos" description:"the repositories that will be pushed to the release vector"`
type AggregateReleasesConfig struct {
TargetRepositoryName string `mapstructure:"repository" description:"the name of the taget repo"`
TargetRepositoryURL string `mapstructure:"repository-url" description:"the url of the target repo"`
Branch *string `mapstructure:"branch" description:"the branch to push in the target repo"`
CommitMsgTemplate *string `mapstructure:"commit-tpl" description:"template of the commit message"`
PullRequestTitle *string `mapstructure:"pull-request-title" description:"title of the pull request"`
SourceRepos map[string][]Modifier `mapstructure:"repos" description:"the source repositories to trigger this action"`
}

type SwaggerClientsConfig struct {
BranchTemplate *string `mapstructure:"branch-template" description:"the branch to push in the swagger client repo"`
CommitMsgTemplate *string `mapstructure:"commit-tpl" description:"template of the commit message in the swagger client repo"`
Repos map[string][]SwaggerClientRepo `mapstructure:"repos" description:"the swagger client repositories that will be updated"`
type DistributeReleasesConfig struct {
SourceRepositoryName string `mapstructure:"repository" description:"the name of the source repo"`
SourceRepositoryURL string `mapstructure:"repository-url" description:"the url of the source repo"`
BranchTemplate *string `mapstructure:"branch-template" description:"the branch to push in the target repos"`
CommitMsgTemplate *string `mapstructure:"commit-tpl" description:"template of the commit message in the target repos"`
PullRequestTitle *string `mapstructure:"pull-request-title" description:"title of the pull request"`
TargetRepos []TargetRepo `mapstructure:"repos" description:"the repositories that will be updated"`
}

type SwaggerClientRepo struct {
RepositoryName string `mapstructure:"repository" description:"the name of the swagger client repo"`
RepositoryURL string `mapstructure:"repository-url" description:"the name of the swagger client repo"`
Patches []Modifier `mapstructure:"modifiers" description:"the name of the swagger client repo"`
type TargetRepo struct {
RepositoryName string `mapstructure:"repository" description:"the name of the target repo"`
RepositoryURL string `mapstructure:"repository-url" description:"the name of the target repo"`
Patches []Modifier `mapstructure:"modifiers" description:"the name of the target repo"`
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import (
"go.uber.org/zap"
)

type ReleaseVector struct {
type AggregateReleases struct {
logger *zap.SugaredLogger
client *clients.Github
branch string
Expand All @@ -30,29 +30,29 @@ type ReleaseVector struct {
pullRequestTitle string
}

type ReleaseVectorParams struct {
type AggregateReleaseParams struct {
RepositoryName string
TagName string
}

func NewReleaseVector(logger *zap.SugaredLogger, client *clients.Github, rawConfig map[string]interface{}) (*ReleaseVector, error) {
func NewAggregateReleases(logger *zap.SugaredLogger, client *clients.Github, rawConfig map[string]interface{}) (*AggregateReleases, error) {
var (
branch = "develop"
commitMessageTemplate = "Bump %s to version %s"
pullRequestTitle = "Next release"
)

var typedConfig config.ReleaseVectorConfig
var typedConfig config.AggregateReleasesConfig
err := mapstructure.Decode(rawConfig, &typedConfig)
if err != nil {
return nil, err
}

if typedConfig.RepositoryName == "" {
return nil, fmt.Errorf("repository must be specified")
if typedConfig.TargetRepositoryName == "" {
return nil, fmt.Errorf("target repository name must be specified")
}
if typedConfig.RepositoryURL == "" {
return nil, fmt.Errorf("repository-url must be specified")
if typedConfig.TargetRepositoryURL == "" {
return nil, fmt.Errorf("target repository-url must be specified")
}
if typedConfig.Branch != nil {
branch = *typedConfig.Branch
Expand All @@ -65,7 +65,7 @@ func NewReleaseVector(logger *zap.SugaredLogger, client *clients.Github, rawConf
}

patchMap := make(map[string][]filepatchers.Patcher)
for n, modifiers := range typedConfig.Repos {
for n, modifiers := range typedConfig.SourceRepos {
for _, m := range modifiers {
patcher, err := filepatchers.InitPatcher(m)
if err != nil {
Expand All @@ -81,31 +81,31 @@ func NewReleaseVector(logger *zap.SugaredLogger, client *clients.Github, rawConf
}
}

return &ReleaseVector{
return &AggregateReleases{
logger: logger,
client: client,
branch: branch,
commitMessageTemplate: commitMessageTemplate,
patchMap: patchMap,
repoURL: typedConfig.RepositoryURL,
repoName: typedConfig.RepositoryName,
repoURL: typedConfig.TargetRepositoryURL,
repoName: typedConfig.TargetRepositoryName,
pullRequestTitle: pullRequestTitle,
}, nil
}

// AddToRelaseVector adds a release to the release vector in a release repository
func (r *ReleaseVector) AddToRelaseVector(ctx context.Context, p *ReleaseVectorParams) error {
// AggregateRelease applies the given actions after push and release trigger of a given list of source repositories to a target repository
func (r *AggregateReleases) AggregateRelease(ctx context.Context, p *AggregateReleaseParams) error {
patches, ok := r.patchMap[p.RepositoryName]
if !ok {
r.logger.Debugw("skip adding new version to release vector because not a release vector repo", "repo", p.RepositoryName, "release", p.TagName)
r.logger.Debugw("skip applying release actions to aggregation repo, not in list of source repositories", "target-repo", r.repoName, "source-repo", p.RepositoryName, "tag", p.TagName)
return nil
}

tag := p.TagName
trimmed := strings.TrimPrefix(tag, "v")
_, err := semver.Make(trimmed)
if err != nil {
r.logger.Infow("skip adding new version to release vector because not a valid semver release tag", "repo", p.RepositoryName, "release", tag, "parse-error", err)
r.logger.Infow("skip applying release actions to aggregation repo because not a valid semver release tag", "target-repo", r.repoName, "source-repo", p.RepositoryName, "tag", p.TagName)
return nil
}

Expand Down Expand Up @@ -150,13 +150,13 @@ func (r *ReleaseVector) AddToRelaseVector(ctx context.Context, p *ReleaseVectorP
hash, err := git.CommitAndPush(repository, commitMessage)
if err != nil {
if err == git.NoChangesError {
r.logger.Debugw("skip adding new version to release vector because nothing changed", "repo", p.RepositoryName, "release", tag)
r.logger.Debugw("skip push to target repository because nothing changed", "target-repo", p.RepositoryName, "source-repo", p.RepositoryName, "release", tag)
return nil
}
return errors.Wrap(err, "error pushing release file")
return errors.Wrap(err, "error pushing to target repository")
}

r.logger.Infow("pushed to release repo", "repo", r.repoName, "release", tag, "branch", r.branch, "hash", hash)
r.logger.Infow("pushed to aggregate target repo", "target-repo", p.RepositoryName, "source-repo", p.RepositoryName, "release", tag, "branch", r.branch, "hash", hash)

once.Do(func() { lock.Unlock() })

Expand All @@ -172,7 +172,7 @@ func (r *ReleaseVector) AddToRelaseVector(ctx context.Context, p *ReleaseVectorP
return err
}
} else {
r.logger.Infow("created pull request", "url", pr.GetURL())
r.logger.Infow("created pull request", "target-repo", p.RepositoryName, "url", pr.GetURL())
}

return nil
Expand Down
62 changes: 30 additions & 32 deletions pkg/webhooks/github/actions/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,18 +15,18 @@ import (
)

const (
ActionAddToReleaseVector string = "release-vector"
ActionAggregateReleases string = "aggregate-releases"
ActionDocsPreviewComment string = "docs-preview-comment"
ActionCreateRepositoryMaintainers string = "create-repository-maintainers"
ActionUpdateSwaggerClients string = "swagger-clients"
ActionDistributeReleases string = "distribute-releases"
)

type WebhookActions struct {
logger *zap.SugaredLogger
rm []*repositoryMaintainers
dp []*docsPreviewComment
rv []*ReleaseVector
sc []*swaggerClient
ar []*AggregateReleases
dr []*distributeReleases
}

func InitActions(logger *zap.SugaredLogger, cs clients.ClientMap, config config.WebhookActions) (*WebhookActions, error) {
Expand All @@ -53,31 +53,29 @@ func InitActions(logger *zap.SugaredLogger, cs clients.ClientMap, config config.
return nil, err
}
actions.rm = append(actions.rm, h)
logger.Debugw("initialized github webhook action", "name", ActionCreateRepositoryMaintainers)
case ActionDocsPreviewComment:
h, err := newDocsPreviewComment(logger, c.(*clients.Github), spec.Args)
if err != nil {
return nil, err
}
actions.dp = append(actions.dp, h)
logger.Debugw("initialized github webhook action", "name", ActionDocsPreviewComment)
case ActionAddToReleaseVector:
h, err := NewReleaseVector(logger, c.(*clients.Github), spec.Args)
case ActionAggregateReleases:
h, err := NewAggregateReleases(logger, c.(*clients.Github), spec.Args)
if err != nil {
return nil, err
}
actions.rv = append(actions.rv, h)
logger.Debugw("initialized github webhook action", "name", ActionAddToReleaseVector)
case ActionUpdateSwaggerClients:
h, err := newSwaggerClient(logger, c.(*clients.Github), spec.Args)
actions.ar = append(actions.ar, h)
case ActionDistributeReleases:
h, err := newDistributeReleases(logger, c.(*clients.Github), spec.Args)
if err != nil {
return nil, err
}
actions.sc = append(actions.sc, h)
logger.Debugw("initialized github webhook action", "name", ActionUpdateSwaggerClients)
actions.dr = append(actions.dr, h)
default:
return nil, fmt.Errorf("handler type not supported: %s", t)
}

logger.Debugw("initialized github webhook action", "name", spec.Type)
}

return &actions, nil
Expand All @@ -88,19 +86,19 @@ func (w *WebhookActions) ProcessReleaseEvent(payload *ghwebhooks.ReleasePayload)
defer cancel()
g, ctx := errgroup.WithContext(ctx)

for _, a := range w.rv {
for _, a := range w.ar {
a := a
g.Go(func() error {
if payload.Action != "released" {
return nil
}
p := &ReleaseVectorParams{
params := &AggregateReleaseParams{
RepositoryName: payload.Repository.Name,
TagName: payload.Release.TagName,
}
err := a.AddToRelaseVector(ctx, p)
err := a.AggregateRelease(ctx, params)
if err != nil {
w.logger.Errorw("error adding release to release vector", "release-repo", a.repoURL, "repo", p.RepositoryName, "tag", p.TagName, "error", err)
w.logger.Errorw("error in aggregate release action", "source-repo", params.RepositoryName, "target-repo", a.repoName, "tag", params.TagName, "error", err)
return err
}

Expand All @@ -124,12 +122,12 @@ func (w *WebhookActions) ProcessPullRequestEvent(payload *ghwebhooks.PullRequest
if payload.Action != "opened" || payload.Repository.Name != "docs" {
return nil
}
p := &docsPreviewCommentParams{
params := &docsPreviewCommentParams{
PullRequestNumber: int(payload.PullRequest.Number),
}
err := a.AddDocsPreviewComment(ctx, p)
err := a.AddDocsPreviewComment(ctx, params)
if err != nil {
w.logger.Errorw("error adding docs preview comment to docs", "repo", payload.Repository.Name, "pull_request", p.PullRequestNumber, "error", err)
w.logger.Errorw("error adding docs preview comment to docs", "repo", payload.Repository.Name, "pull_request", params.PullRequestNumber, "error", err)
return err
}

Expand All @@ -147,42 +145,42 @@ func (w *WebhookActions) ProcessPushEvent(payload *ghwebhooks.PushPayload) {
defer cancel()
g, ctx := errgroup.WithContext(ctx)

for _, a := range w.rv {
for _, a := range w.ar {
a := a
g.Go(func() error {
if !payload.Created || !strings.HasPrefix(payload.Ref, "refs/tags/v") {
return nil
}
releaseParams := &ReleaseVectorParams{
params := &AggregateReleaseParams{
RepositoryName: payload.Repository.Name,
TagName: extractTag(payload),
}

err := a.AddToRelaseVector(ctx, releaseParams)
err := a.AggregateRelease(ctx, params)
if err != nil {
w.logger.Errorw("error adding new tag to release vector", "release-repo", a.repoURL, "repo", releaseParams.RepositoryName, "tag", releaseParams.TagName, "error", err)
w.logger.Errorw("error in aggregate release action", "source-repo", params.RepositoryName, "target-repo", a.repoName, "tag", params.TagName, "error", err)
return err
}

return nil
})
}

for _, a := range w.sc {
for _, a := range w.dr {
a := a
g.Go(func() error {
if !payload.Created || !strings.HasPrefix(payload.Ref, "refs/tags/v") {
return nil
}

swaggerParams := &swaggerParams{
params := &distributeReleaseParams{
RepositoryName: payload.Repository.Name,
TagName: extractTag(payload),
}

err := a.GenerateSwaggerClients(ctx, swaggerParams)
err := a.DistributeRelease(ctx, params)
if err != nil {
w.logger.Errorw("error creating branches for swagger client repositories", "repo", swaggerParams.RepositoryName, "tag", swaggerParams.TagName, "error", err)
w.logger.Errorw("error in distribute release action", "source-repo", params.RepositoryName, "tag", params.TagName, "error", err)
return err
}

Expand All @@ -207,13 +205,13 @@ func (w *WebhookActions) ProcessRepositoryEvent(payload *ghwebhooks.RepositoryPa
return nil
}

p := &repositoryMaintainersParams{
params := &repositoryMaintainersParams{
RepositoryName: payload.Repository.Name,
Creator: payload.Sender.Login,
}
err := a.CreateRepositoryMaintainers(ctx, p)
err := a.CreateRepositoryMaintainers(ctx, params)
if err != nil {
w.logger.Errorw("error creating repository maintainers team", "repo", p.RepositoryName, "error", err)
w.logger.Errorw("error creating repository maintainers team", "repo", params.RepositoryName, "error", err)
return err
}

Expand Down
Loading

0 comments on commit 52e47ca

Please sign in to comment.