From fa3ebfc900895485a4d5d4d8f81a283c2ffa0242 Mon Sep 17 00:00:00 2001 From: Sarvar Muminov <43311+msarvar@users.noreply.github.com> Date: Fri, 4 Feb 2022 13:45:04 -0800 Subject: [PATCH] Orca 4414 create default platform mode workflows (#169) * remove unused constants * remove unused functions in global_cfg.go * Adding default workflows for platform mode * refactor global_cfg.go * Adding tests * Merging server config to project * moving config from events/yaml to core/config * move PR and deployment workflows into their own maps * use correct method --- server/core/config/valid/global_cfg.go | 250 +++++++++--------- server/core/config/valid/global_cfg_test.go | 215 ++++++++++++++- server/core/config/valid/global_repo_cfg.go | 50 ++++ server/events/models/fixtures/fixtures.go | 1 + .../project_command_builder_internal_test.go | 4 +- 5 files changed, 380 insertions(+), 140 deletions(-) create mode 100644 server/core/config/valid/global_repo_cfg.go diff --git a/server/core/config/valid/global_cfg.go b/server/core/config/valid/global_cfg.go index 6252d05778..cbc83cf64c 100644 --- a/server/core/config/valid/global_cfg.go +++ b/server/core/config/valid/global_cfg.go @@ -15,11 +15,12 @@ const UnDivergedApplyReq = "undiverged" const SQUnlockedApplyReq = "unlocked" const PoliciesPassedApplyReq = "policies_passed" const ApplyRequirementsKey = "apply_requirements" -const PreWorkflowHooksKey = "pre_workflow_hooks" const WorkflowKey = "workflow" -const AllowedWorkflowsKey = "allowed_workflows" +const PullRequestWorkflowKey = "pull_request_workflow" +const DeploymentWorkflowKey = "deployment_workflow" const AllowedOverridesKey = "allowed_overrides" const AllowCustomWorkflowsKey = "allow_custom_workflows" + const DefaultWorkflowName = "default" const DeleteSourceBranchOnMergeKey = "delete_source_branch_on_merge" @@ -32,10 +33,12 @@ var NonOverrideableApplyReqs []string = []string{PoliciesPassedApplyReq} // GlobalCfg is the final parsed version of server-side repo config. type GlobalCfg struct { - Repos []Repo - Workflows map[string]Workflow - PolicySets PolicySets - Metrics Metrics + Repos []Repo + Workflows map[string]Workflow + PullRequestWorkflows map[string]Workflow + DeploymentWorkflows map[string]Workflow + PolicySets PolicySets + Metrics Metrics } type Metrics struct { @@ -47,28 +50,11 @@ type Statsd struct { Host string } -// Repo is the final parsed version of server-side repo config. -type Repo struct { - // ID is the exact match id of this config. - // If IDRegex is set then this will be empty. - ID string - // IDRegex is the regex match for this config. - // If ID is set then this will be nil. - IDRegex *regexp.Regexp - BranchRegex *regexp.Regexp - ApplyRequirements []string - PreWorkflowHooks []*PreWorkflowHook - Workflow *Workflow - AllowedWorkflows []string - AllowedOverrides []string - AllowCustomWorkflows *bool - DeleteSourceBranchOnMerge *bool - TemplateOverrides map[string]string -} - type MergedProjectCfg struct { ApplyRequirements []string Workflow Workflow + PullRequestWorkflow Workflow + DeploymentWorkflow Workflow AllowedWorkflows []string RepoRelDir string Workspace string @@ -121,41 +107,30 @@ var DefaultPlanStage = Stage{ }, } -// Deprecated: use NewGlobalCfgFromArgs -func NewGlobalCfgWithHooks(allowRepoCfg bool, mergeableReq bool, approvedReq bool, unDivergedReq bool, sqUnLockedReq bool, preWorkflowHooks []*PreWorkflowHook) GlobalCfg { - return NewGlobalCfgFromArgs(GlobalCfgArgs{ - AllowRepoCfg: allowRepoCfg, - MergeableReq: mergeableReq, - ApprovedReq: approvedReq, - UnDivergedReq: unDivergedReq, - SQUnLockedReq: sqUnLockedReq, - PreWorkflowHooks: preWorkflowHooks, - }) -} - -// NewGlobalCfg returns a global config that respects the parameters. -// allowRepoCfg is true if users want to allow repos full config functionality. -// mergeableReq is true if users want to set the mergeable apply requirement -// for all repos. -// approvedReq is true if users want to set the approved apply requirement -// for all repos. -// Deprecated: use NewGlobalCfgFromArgs -func NewGlobalCfg(allowRepoCfg bool, mergeableReq bool, approvedReq bool) GlobalCfg { - return NewGlobalCfgFromArgs(GlobalCfgArgs{ - AllowRepoCfg: allowRepoCfg, - MergeableReq: mergeableReq, - ApprovedReq: approvedReq, - }) +// DefaultLocklessPlanStage is the Atlantis default plan stage for PR workflows in +// platform mode. +var DefaultLocklessPlanStage = Stage{ + Steps: []Step{ + { + StepName: "init", + ExtraArgs: []string{"-lock=false"}, + }, + { + StepName: "plan", + ExtraArgs: []string{"-lock=false"}, + }, + }, } type GlobalCfgArgs struct { - AllowRepoCfg bool - MergeableReq bool - ApprovedReq bool - UnDivergedReq bool - SQUnLockedReq bool - PolicyCheckEnabled bool - PreWorkflowHooks []*PreWorkflowHook + AllowRepoCfg bool + MergeableReq bool + ApprovedReq bool + UnDivergedReq bool + SQUnLockedReq bool + PolicyCheckEnabled bool + PlatformModeEnabled bool + PreWorkflowHooks []*PreWorkflowHook } func NewGlobalCfgFromArgs(args GlobalCfgArgs) GlobalCfg { @@ -165,11 +140,10 @@ func NewGlobalCfgFromArgs(args GlobalCfgArgs) GlobalCfg { Plan: DefaultPlanStage, PolicyCheck: DefaultPolicyCheckStage, } + // Must construct slices here instead of using a `var` declaration because // we treat nil slices differently. applyReqs := []string{} - allowedOverrides := []string{} - allowedWorkflows := []string{} if args.MergeableReq { applyReqs = append(applyReqs, MergeableApplyReq) } @@ -186,62 +160,71 @@ func NewGlobalCfgFromArgs(args GlobalCfgArgs) GlobalCfg { applyReqs = append(applyReqs, PoliciesPassedApplyReq) } - allowCustomWorkflows := false - deleteSourceBranchOnMerge := false + var deleteSourceBranchOnMerge, allowCustomWorkflows bool + allowedOverrides := []string{} if args.AllowRepoCfg { allowedOverrides = []string{ApplyRequirementsKey, WorkflowKey, DeleteSourceBranchOnMergeKey} allowCustomWorkflows = true } - return GlobalCfg{ - Repos: []Repo{ - { - IDRegex: regexp.MustCompile(".*"), - BranchRegex: regexp.MustCompile(".*"), - ApplyRequirements: applyReqs, - PreWorkflowHooks: args.PreWorkflowHooks, - Workflow: &defaultWorkflow, - AllowedWorkflows: allowedWorkflows, - AllowedOverrides: allowedOverrides, - AllowCustomWorkflows: &allowCustomWorkflows, - DeleteSourceBranchOnMerge: &deleteSourceBranchOnMerge, - }, - }, + repo := Repo{ + IDRegex: regexp.MustCompile(".*"), + BranchRegex: regexp.MustCompile(".*"), + ApplyRequirements: applyReqs, + PreWorkflowHooks: args.PreWorkflowHooks, + Workflow: &defaultWorkflow, + AllowedWorkflows: []string{}, + AllowCustomWorkflows: &allowCustomWorkflows, + AllowedOverrides: allowedOverrides, + DeleteSourceBranchOnMerge: &deleteSourceBranchOnMerge, + } + + globalCfg := GlobalCfg{ Workflows: map[string]Workflow{ DefaultWorkflowName: defaultWorkflow, }, } -} -// IDMatches returns true if the repo ID otherID matches this config. -func (r Repo) IDMatches(otherID string) bool { - if r.ID != "" { - return r.ID == otherID - } - return r.IDRegex.MatchString(otherID) -} + if args.PlatformModeEnabled { + // defaultPullRequstWorkflow is only used in platform mode. By default it does not + // support apply stage, and plan stage run with -lock=false flag + pullRequestWorkflow := Workflow{ + Name: DefaultWorkflowName, + Plan: DefaultLocklessPlanStage, + PolicyCheck: DefaultPolicyCheckStage, + } -// BranchMatches returns true if the branch other matches a branch regex (if preset). -func (r Repo) BranchMatches(other string) bool { - if r.BranchRegex == nil { - return true - } - return r.BranchRegex.MatchString(other) -} + deploymentWorkflow := Workflow{ + Name: DefaultWorkflowName, + Apply: DefaultApplyStage, + Plan: DefaultPlanStage, + } + + if args.AllowRepoCfg { + repo.AllowedOverrides = append(repo.AllowedOverrides, PullRequestWorkflowKey, DeploymentWorkflowKey) + } -// IDString returns a string representation of this config. -func (r Repo) IDString() string { - if r.ID != "" { - return r.ID + globalCfg.PullRequestWorkflows = map[string]Workflow{ + DefaultWorkflowName: pullRequestWorkflow, + } + globalCfg.DeploymentWorkflows = map[string]Workflow{ + DefaultWorkflowName: deploymentWorkflow, + } + + repo.DeploymentWorkflow = &deploymentWorkflow + repo.PullRequestWorkflow = &pullRequestWorkflow } - return "/" + r.IDRegex.String() + "/" + + globalCfg.Repos = []Repo{repo} + + return globalCfg } // MergeProjectCfg merges proj and rCfg with the global config to return a // final config. It assumes that all configs have been validated. func (g GlobalCfg) MergeProjectCfg(log logging.SimpleLogging, repoID string, proj Project, rCfg RepoCfg) MergedProjectCfg { log.Debug("MergeProjectCfg started") - applyReqs, workflow, allowedOverrides, allowCustomWorkflows, deleteSourceBranchOnMerge := g.getMatchingCfg(log, repoID) + applyReqs, workflow, pullRequestWorkflow, deploymentWorkflow, allowedOverrides, allowCustomWorkflows, deleteSourceBranchOnMerge := g.getMatchingCfg(log, repoID) // If repos are allowed to override certain keys then override them. for _, key := range allowedOverrides { @@ -297,6 +280,8 @@ func (g GlobalCfg) MergeProjectCfg(log logging.SimpleLogging, repoID string, pro return MergedProjectCfg{ ApplyRequirements: applyReqs, Workflow: workflow, + PullRequestWorkflow: pullRequestWorkflow, + DeploymentWorkflow: deploymentWorkflow, RepoRelDir: proj.Dir, Workspace: proj.Workspace, Name: proj.GetName(), @@ -313,10 +298,12 @@ func (g GlobalCfg) MergeProjectCfg(log logging.SimpleLogging, repoID string, pro // repo with id repoID. It is used when there is no repo config. func (g GlobalCfg) DefaultProjCfg(log logging.SimpleLogging, repoID string, repoRelDir string, workspace string) MergedProjectCfg { log.Debug("building config based on server-side config") - applyReqs, workflow, _, _, deleteSourceBranchOnMerge := g.getMatchingCfg(log, repoID) + applyReqs, workflow, pullRequestWorkflow, deploymentWorkflow, _, _, deleteSourceBranchOnMerge := g.getMatchingCfg(log, repoID) return MergedProjectCfg{ ApplyRequirements: applyReqs, Workflow: workflow, + PullRequestWorkflow: pullRequestWorkflow, + DeploymentWorkflow: deploymentWorkflow, RepoRelDir: repoRelDir, Workspace: workspace, Name: "", @@ -425,7 +412,15 @@ func (g GlobalCfg) ValidateRepoCfg(rCfg RepoCfg, repoID string) error { } // getMatchingCfg returns the key settings for repoID. -func (g GlobalCfg) getMatchingCfg(log logging.SimpleLogging, repoID string) (applyReqs []string, workflow Workflow, allowedOverrides []string, allowCustomWorkflows bool, deleteSourceBranchOnMerge bool) { +func (g GlobalCfg) getMatchingCfg(log logging.SimpleLogging, repoID string) ( + applyReqs []string, + workflow Workflow, + pullRequestWorkflow Workflow, + deploymentWorkflow Workflow, + allowedOverrides []string, + allowCustomWorkflows bool, + deleteSourceBranchOnMerge bool, +) { toLog := make(map[string]string) traceF := func(repoIdx int, repoID string, key string, val interface{}) string { from := "default server config" @@ -447,36 +442,35 @@ func (g GlobalCfg) getMatchingCfg(log logging.SimpleLogging, repoID string) (app return fmt.Sprintf("setting %s: %s from %s", key, valStr, from) } - for _, key := range []string{ApplyRequirementsKey, WorkflowKey, AllowedOverridesKey, AllowCustomWorkflowsKey, DeleteSourceBranchOnMergeKey} { - for i, repo := range g.Repos { - if repo.IDMatches(repoID) { - switch key { - case ApplyRequirementsKey: - if repo.ApplyRequirements != nil { - toLog[ApplyRequirementsKey] = traceF(i, repo.IDString(), ApplyRequirementsKey, repo.ApplyRequirements) - applyReqs = repo.ApplyRequirements - } - case WorkflowKey: - if repo.Workflow != nil { - toLog[WorkflowKey] = traceF(i, repo.IDString(), WorkflowKey, repo.Workflow.Name) - workflow = *repo.Workflow - } - case AllowedOverridesKey: - if repo.AllowedOverrides != nil { - toLog[AllowedOverridesKey] = traceF(i, repo.IDString(), AllowedOverridesKey, repo.AllowedOverrides) - allowedOverrides = repo.AllowedOverrides - } - case AllowCustomWorkflowsKey: - if repo.AllowCustomWorkflows != nil { - toLog[AllowCustomWorkflowsKey] = traceF(i, repo.IDString(), AllowCustomWorkflowsKey, *repo.AllowCustomWorkflows) - allowCustomWorkflows = *repo.AllowCustomWorkflows - } - case DeleteSourceBranchOnMergeKey: - if repo.DeleteSourceBranchOnMerge != nil { - toLog[DeleteSourceBranchOnMergeKey] = traceF(i, repo.IDString(), DeleteSourceBranchOnMergeKey, *repo.DeleteSourceBranchOnMerge) - deleteSourceBranchOnMerge = *repo.DeleteSourceBranchOnMerge - } - } + for i, repo := range g.Repos { + if repo.IDMatches(repoID) { + if repo.ApplyRequirements != nil { + toLog[ApplyRequirementsKey] = traceF(i, repo.IDString(), ApplyRequirementsKey, repo.ApplyRequirements) + applyReqs = repo.ApplyRequirements + } + if repo.Workflow != nil { + toLog[WorkflowKey] = traceF(i, repo.IDString(), WorkflowKey, repo.Workflow.Name) + workflow = *repo.Workflow + } + if repo.PullRequestWorkflow != nil { + toLog[PullRequestWorkflowKey] = traceF(i, repo.IDString(), PullRequestWorkflowKey, repo.PullRequestWorkflow.Name) + pullRequestWorkflow = *repo.PullRequestWorkflow + } + if repo.DeploymentWorkflow != nil { + toLog[DeploymentWorkflowKey] = traceF(i, repo.IDString(), DeploymentWorkflowKey, repo.DeploymentWorkflow.Name) + deploymentWorkflow = *repo.DeploymentWorkflow + } + if repo.AllowedOverrides != nil { + toLog[AllowedOverridesKey] = traceF(i, repo.IDString(), AllowedOverridesKey, repo.AllowedOverrides) + allowedOverrides = repo.AllowedOverrides + } + if repo.AllowCustomWorkflows != nil { + toLog[AllowCustomWorkflowsKey] = traceF(i, repo.IDString(), AllowCustomWorkflowsKey, *repo.AllowCustomWorkflows) + allowCustomWorkflows = *repo.AllowCustomWorkflows + } + if repo.DeleteSourceBranchOnMerge != nil { + toLog[DeleteSourceBranchOnMergeKey] = traceF(i, repo.IDString(), DeleteSourceBranchOnMergeKey, *repo.DeleteSourceBranchOnMerge) + deleteSourceBranchOnMerge = *repo.DeleteSourceBranchOnMerge } } } diff --git a/server/core/config/valid/global_cfg_test.go b/server/core/config/valid/global_cfg_test.go index 240f678081..bba27ad238 100644 --- a/server/core/config/valid/global_cfg_test.go +++ b/server/core/config/valid/global_cfg_test.go @@ -46,6 +46,7 @@ func TestNewGlobalCfg(t *testing.T) { }, }, } + baseCfg := valid.GlobalCfg{ Repos: []valid.Repo{ { @@ -155,9 +156,9 @@ func TestNewGlobalCfg(t *testing.T) { UnDivergedReq: c.unDivergedReq, } act := valid.NewGlobalCfgFromArgs(globalCfgArgs) - // For each test, we change our expected cfg based on the parameters. - exp := deepcopy.Copy(baseCfg).(valid.GlobalCfg) + var exp valid.GlobalCfg + exp = deepcopy.Copy(baseCfg).(valid.GlobalCfg) exp.Repos[0].IDRegex = regexp.MustCompile(".*") // deepcopy doesn't copy the regex. exp.Repos[0].BranchRegex = regexp.MustCompile(".*") @@ -193,6 +194,159 @@ func TestNewGlobalCfg(t *testing.T) { } } +func TestPlatformModeNewGlobalCfg(t *testing.T) { + expDefaultWorkflow := valid.Workflow{ + Name: "default", + Apply: valid.Stage{ + Steps: []valid.Step{ + { + StepName: "apply", + }, + }, + }, + PolicyCheck: valid.Stage{ + Steps: []valid.Step{ + { + StepName: "show", + }, + { + StepName: "policy_check", + }, + }, + }, + Plan: valid.Stage{ + Steps: []valid.Step{ + { + StepName: "init", + }, + { + StepName: "plan", + }, + }, + }, + } + + expDefaultPRWorkflow := valid.Workflow{ + Name: "default", + PolicyCheck: valid.Stage{ + Steps: []valid.Step{ + { + StepName: "show", + }, + { + StepName: "policy_check", + }, + }, + }, + Plan: valid.Stage{ + Steps: []valid.Step{ + { + StepName: "init", + ExtraArgs: []string{"-lock=false"}, + }, + { + StepName: "plan", + ExtraArgs: []string{"-lock=false"}, + }, + }, + }, + } + expDefaultDeploymentWorkflow := valid.Workflow{ + Name: "default", + Apply: valid.Stage{ + Steps: []valid.Step{ + { + + StepName: "apply", + }, + }, + }, + Plan: valid.Stage{ + Steps: []valid.Step{ + { + StepName: "init", + }, + { + StepName: "plan", + }, + }, + }, + } + baseCfg := valid.GlobalCfg{ + Repos: []valid.Repo{ + { + IDRegex: regexp.MustCompile(".*"), + BranchRegex: regexp.MustCompile(".*"), + ApplyRequirements: []string{}, + Workflow: &expDefaultWorkflow, + PullRequestWorkflow: &expDefaultPRWorkflow, + DeploymentWorkflow: &expDefaultDeploymentWorkflow, + AllowedWorkflows: []string{}, + AllowedOverrides: []string{}, + AllowCustomWorkflows: Bool(false), + DeleteSourceBranchOnMerge: Bool(false), + }, + }, + Workflows: map[string]valid.Workflow{ + "default": expDefaultWorkflow, + }, + PullRequestWorkflows: map[string]valid.Workflow{ + "default": expDefaultPRWorkflow, + }, + DeploymentWorkflows: map[string]valid.Workflow{ + "default": expDefaultDeploymentWorkflow, + }, + } + + cases := []struct { + allowRepoCfg bool + }{ + { + allowRepoCfg: false, + }, + { + allowRepoCfg: true, + }, + } + + for _, c := range cases { + caseName := fmt.Sprintf("allow_repo: %t", + c.allowRepoCfg) + t.Run(caseName, func(t *testing.T) { + globalCfgArgs := valid.GlobalCfgArgs{ + AllowRepoCfg: c.allowRepoCfg, + PlatformModeEnabled: true, + } + act := valid.NewGlobalCfgFromArgs(globalCfgArgs) + + // For each test, we change our expected cfg based on the parameters. + exp := deepcopy.Copy(baseCfg).(valid.GlobalCfg) + exp.Repos[0].IDRegex = regexp.MustCompile(".*") // deepcopy doesn't copy the regex. + exp.Repos[0].BranchRegex = regexp.MustCompile(".*") + + if c.allowRepoCfg { + exp.Repos[0].AllowCustomWorkflows = Bool(true) + exp.Repos[0].AllowedOverrides = []string{"apply_requirements", "workflow", "delete_source_branch_on_merge", "pull_request_workflow", "deployment_workflow"} + } + + Equals(t, exp, act) + + // Have to hand-compare regexes because Equals doesn't do it. + for i, actRepo := range act.Repos { + expRepo := exp.Repos[i] + if expRepo.IDRegex != nil { + Assert(t, expRepo.IDRegex.String() == actRepo.IDRegex.String(), + "%q != %q for repos[%d]", expRepo.IDRegex.String(), actRepo.IDRegex.String(), i) + } + if expRepo.BranchRegex != nil { + Assert(t, expRepo.BranchRegex.String() == actRepo.BranchRegex.String(), + "%q != %q for repos[%d]", expRepo.BranchRegex.String(), actRepo.BranchRegex.String(), i) + } + } + }) + } +} + func TestGlobalCfg_ValidateRepoCfg(t *testing.T) { cases := map[string]struct { gCfg valid.GlobalCfg @@ -694,6 +848,7 @@ func TestGlobalCfg_MergeProjectCfg(t *testing.T) { cases := map[string]struct { gCfg string repoID string + platformMode bool proj valid.Project repoWorkflows map[string]valid.Workflow exp valid.MergedProjectCfg @@ -824,6 +979,44 @@ repos: PolicySets: emptyPolicySets, }, }, + "merge platform mode default config": { + platformMode: true, + gCfg: "", + repoID: "github.com/owner/repo", + proj: valid.Project{ + Dir: "mydir", + Workspace: "myworkspace", + Name: String("myname"), + Autoplan: valid.Autoplan{ + WhenModified: []string{".tf"}, + Enabled: true, + }, + }, + exp: valid.MergedProjectCfg{ + ApplyRequirements: []string{}, + Workflow: valid.Workflow{ + Name: "default", + Apply: valid.DefaultApplyStage, + PolicyCheck: valid.DefaultPolicyCheckStage, + Plan: valid.DefaultPlanStage, + }, + PullRequestWorkflow: valid.Workflow{ + Name: "default", + PolicyCheck: valid.DefaultPolicyCheckStage, + Plan: valid.DefaultLocklessPlanStage, + }, + DeploymentWorkflow: valid.Workflow{ + Name: "default", + Apply: valid.DefaultApplyStage, + Plan: valid.DefaultPlanStage, + }, + RepoRelDir: "mydir", + Workspace: "myworkspace", + Name: "myname", + AutoplanEnabled: true, + PolicySets: emptyPolicySets, + }, + }, } for name, c := range cases { t.Run(name, func(t *testing.T) { @@ -835,20 +1028,22 @@ repos: Ok(t, ioutil.WriteFile(path, []byte(c.gCfg), 0600)) var err error globalCfgArgs := valid.GlobalCfgArgs{ - AllowRepoCfg: false, - MergeableReq: false, - ApprovedReq: false, - UnDivergedReq: false, + AllowRepoCfg: false, + MergeableReq: false, + ApprovedReq: false, + UnDivergedReq: false, + PlatformModeEnabled: c.platformMode, } global, err = (&config.ParserValidator{}).ParseGlobalCfg(path, valid.NewGlobalCfgFromArgs(globalCfgArgs)) Ok(t, err) } else { globalCfgArgs := valid.GlobalCfgArgs{ - AllowRepoCfg: false, - MergeableReq: false, - ApprovedReq: false, - UnDivergedReq: false, + AllowRepoCfg: false, + MergeableReq: false, + ApprovedReq: false, + UnDivergedReq: false, + PlatformModeEnabled: c.platformMode, } global = valid.NewGlobalCfgFromArgs(globalCfgArgs) } diff --git a/server/core/config/valid/global_repo_cfg.go b/server/core/config/valid/global_repo_cfg.go new file mode 100644 index 0000000000..612896c472 --- /dev/null +++ b/server/core/config/valid/global_repo_cfg.go @@ -0,0 +1,50 @@ +package valid + +import "regexp" + +// Repo is the final parsed version of server-side repo config. +type Repo struct { + // ID is the exact match id of this config. + // If IDRegex is set then this will be empty. + ID string + // IDRegex is the regex match for this config. + // If ID is set then this will be nil. + IDRegex *regexp.Regexp + BranchRegex *regexp.Regexp + ApplyRequirements []string + PreWorkflowHooks []*PreWorkflowHook + Workflow *Workflow + PullRequestWorkflow *Workflow + DeploymentWorkflow *Workflow + AllowedWorkflows []string + AllowedPullRequestWorkflows []string + AllowedDeploymentWorkflows []string + AllowedOverrides []string + AllowCustomWorkflows *bool + DeleteSourceBranchOnMerge *bool + TemplateOverrides map[string]string +} + +// IDMatches returns true if the repo ID otherID matches this config. +func (r Repo) IDMatches(otherID string) bool { + if r.ID != "" { + return r.ID == otherID + } + return r.IDRegex.MatchString(otherID) +} + +// BranchMatches returns true if the branch other matches a branch regex (if preset). +func (r Repo) BranchMatches(other string) bool { + if r.BranchRegex == nil { + return true + } + return r.BranchRegex.MatchString(other) +} + +// IDString returns a string representation of this config. +func (r Repo) IDString() string { + if r.ID != "" { + return r.ID + } + return "/" + r.IDRegex.String() + "/" +} diff --git a/server/events/models/fixtures/fixtures.go b/server/events/models/fixtures/fixtures.go index 432b827350..487f0e4c21 100644 --- a/server/events/models/fixtures/fixtures.go +++ b/server/events/models/fixtures/fixtures.go @@ -15,6 +15,7 @@ package fixtures import ( "fmt" + "github.com/runatlantis/atlantis/server/core/config/valid" "github.com/runatlantis/atlantis/server/events/models" ) diff --git a/server/events/project_command_builder_internal_test.go b/server/events/project_command_builder_internal_test.go index 0a1022c467..0ebc2dd8c6 100644 --- a/server/events/project_command_builder_internal_test.go +++ b/server/events/project_command_builder_internal_test.go @@ -789,9 +789,9 @@ projects: // Write and parse the global config file. globalCfgPath := filepath.Join(tmp, "global.yaml") - Ok(t, os.WriteFile(globalCfgPath, []byte(c.globalCfg), 0600)) + Ok(t, ioutil.WriteFile(globalCfgPath, []byte(c.globalCfg), 0600)) parser := &config.ParserValidator{} - globalCfg, err := parser.ParseGlobalCfg(globalCfgPath, valid.NewGlobalCfg(false, false, false)) + globalCfg, err := parser.ParseGlobalCfg(globalCfgPath, valid.NewGlobalCfgFromArgs(valid.GlobalCfgArgs{})) Ok(t, err) if c.repoCfg != "" {