Skip to content

Commit

Permalink
chore: refactoring
Browse files Browse the repository at this point in the history
  • Loading branch information
marcportabellaclotet-mt committed Aug 13, 2023
1 parent 77a454d commit 1ad114e
Show file tree
Hide file tree
Showing 7 changed files with 202 additions and 227 deletions.
2 changes: 1 addition & 1 deletion cmd/cmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ func genAtlantisYaml(ccmd *cobra.Command, args []string) error {
ProjectsPatternDetector: atlantisProjectsPatternDetector,
}

err = atlantis.GenAtlantisYaml(ghParams, atlantisParams)
err = atlantis.GenerateAtlantisYAML(ghParams, atlantisParams)
return err
}

Expand Down
1 change: 1 addition & 0 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,6 @@ import (
)

func main() {

cmd.Init()
}
245 changes: 125 additions & 120 deletions pkg/atlantis/atlantis.go
Original file line number Diff line number Diff line change
@@ -1,12 +1,6 @@
package atlantis

// TODO
// improve error handling
// Add comments
// Add tests

import (
"errors"
"fmt"
"os"
"path/filepath"
Expand All @@ -28,25 +22,6 @@ var DefaultWhenModified = []string{
"**/*.xml",
}

var (
//changedFiles []string
resources []Resource
atlantisProjects []Project
)

type Parameters struct {
Automerge string
ParallelApply string
ParallelPlan string
TfRootDir string
OutputFile string
Workflow string
WhenModified []string
ExcludedProjects string
IncludedProjects string
ProjectsPatternDetector string
}

type Config struct {
Version int `yaml:"version"`
Automerge bool `yaml:"automerge"`
Expand All @@ -66,50 +41,147 @@ type Project struct {
} `yaml:"autoplan"`
}

type Resource struct {
type Parameters struct {
Automerge string
ParallelApply string
ParallelPlan string
TfRootDir string
OutputFile string
Workflow string
WhenModified []string
ExcludedProjects string
IncludedProjects string
ProjectsPatternDetector string
}

type ProjectFolder struct {
Path string
Project string
WorkspaceList []string
}

func GenAtlantisYaml(gh github.GithubRequest, at Parameters) error {
err := errors.New("")
func GenerateAtlantisYAML(gh github.GithubRequest, at Parameters) error {
projectFoldersList, err := scanProjectFolders(at.TfRootDir, at.Workflow, gh)
if err != nil {
return err
}
projectFoldersListWithWorkspaces, err := detectProjectWorkspaces(projectFoldersList, at.Workflow, gh)
if err != nil {
return err
}
atlantisProjects, err := generateAtlantisProjects(at.Workflow, projectFoldersListWithWorkspaces)
if err != nil {
return err
}
filteredAtlantisProjects, err := filterAtlantisProjects(at.ExcludedProjects, at.IncludedProjects, atlantisProjects)
if err != nil {
return err
}
atlantisConfig, err := generateAtlantisConfig(at, filteredAtlantisProjects)
if err != nil {
return err
}
err = generateOutputYAML(&atlantisConfig, at.OutputFile)
if err != nil {
return err
}
return nil
}

//workflow = at.Workflow
//whenModified = at.WhenModified
//projectPatternDetector = at.ProjectsPatternDetector
func filterAtlantisProjects(excludedProjects, includedProjects string, atlantisProjects []Project) (filteredAtlantisProjects []Project, err error) {
projectFilter := helpers.ProjectRegexFilter{
Includes: includedProjects,
Excludes: excludedProjects,
}
for _, project := range atlantisProjects {
projectFilterResult, err := helpers.ProjectFilter(project.Name, projectFilter)
if err != nil {
return nil, err
}

if projectFilterResult {
filteredAtlantisProjects = append(filteredAtlantisProjects, project)
}
}
return filteredAtlantisProjects, nil
}

//projectFilter = helpers.ProjectRegexFilter{
// Includes: at.IncludedProjects,
// Excludes: at.ExcludedProjects,
//}
func detectProjectWorkspaces(foldersList []ProjectFolder, workflow string, gh github.GithubRequest) ([]ProjectFolder, error) {
switch workflow {
case "single-workspace":
foldersList, _ = singleWorkspaceDetectProjectWorkspaces(foldersList)
case "multi-workspace":
foldersList, _ = multiWorkspaceDetectProjectWorkspaces(gh, foldersList)
}
return foldersList, nil
}

// Get the changed files from the PR
func scanProjectFolders(basePath, workflow string, gh github.GithubRequest) (projectFolders []ProjectFolder, err error) {
changedFiles, err := github.GetChangedFiles(gh)
if err != nil {
return err
return nil, err
}

// Check the workflow type
switch at.Workflow {
case "multi-workspace":
err = multiWorkspace(at, changedFiles)
if err != nil {
err = filepath.Walk(basePath, func(path string, info os.FileInfo, err error) error {
if err != nil || info == nil {
return err
}

relPath, _ := filepath.Rel(basePath, filepath.Dir(path))
workflowFilterResult := workflowFilter(info, path, workflow)
prFilterResult := prFilter(relPath, changedFiles)
if workflowFilterResult && prFilterResult {
projectFolders = append(projectFolders, ProjectFolder{
Path: relPath,
})
}

return nil
})
return projectFolders, err
}

func workflowFilter(info os.FileInfo, path, workflow string) bool {
switch workflow {
case "single-workspace":
err = singleWorkspace(at, changedFiles)
if err != nil {
return err
return singleWorkspaceWorkflowFilter(info, path)
case "multi-workspace":
return multiWorkspaceWorkflowFilter(info, path)
}
return true
}

func prFilter(relPath string, changedFiles []string) bool {
for _, file := range changedFiles {
if strings.HasPrefix(file, fmt.Sprintf("%s/", relPath)) {
return true
}
default:
err = fmt.Errorf("workflow %s not supported", at.Workflow)
return err
}
return err
return false
}

func generateAtlantisProjects(workflow string, projectFolderList []ProjectFolder) (projects []Project, err error) {
for _, folder := range projectFolderList {
for _, workspace := range folder.WorkspaceList {
name := genProjectName(folder.Path, workspace)
projects = append(projects, Project{
Name: name,
Dir: folder.Path,
Workspace: workspace,
Workflow: workflow,
})
}
}
return projects, nil
}

func genProjectName(path, workspace string) string {
if workspace != "default" {
return fmt.Sprintf("%s-%s", strings.Replace(path, "/", "-", 1), workspace)
}
return strings.Replace(path, "/", "-", 1)
}

func generateConfig(at Parameters) (Config, error) {
func generateAtlantisConfig(at Parameters, projects []Project) (Config, error) {
// Parse atlantis parameters
automerge, err := strconv.ParseBool(at.Automerge)
if err != nil {
Expand All @@ -132,7 +204,7 @@ func generateConfig(at Parameters) (Config, error) {
ParallelPlan: parallelPlan,
}
// Append generated projects to the atlantis config
for _, info := range atlantisProjects {
for _, info := range projects {
project := Project{
Name: info.Name,
Workspace: info.Workspace,
Expand All @@ -152,74 +224,7 @@ func generateConfig(at Parameters) (Config, error) {
return config, err
}

func scanFolders(at Parameters, changedFiles []string) error {
err := filepath.Walk(at.TfRootDir, func(path string, info os.FileInfo, err error) error {
if err != nil {
return err
}

if workflowFilter(info, path, at.Workflow) {
project, err := helpers.GetRelativePath(path, at.TfRootDir)
if err != nil {
return err
}
if prChangesFilter(project, changedFiles) {
addResource(filepath.Dir(path), project, at.TfRootDir, at.Workflow, changedFiles)
}
}
return nil
})
return err
}

func workflowFilter(info os.FileInfo, path string, workflow string) bool {
switch workflow {
case "multi-workspace":
return multiWorkspaceFilter(info, path)

case "single-workspace":
return singleWorkspaceFilter(info, path)
}
return false
}

func prChangesFilter(project string, changedFiles []string) bool {
for _, file := range changedFiles {
if strings.HasPrefix(file, fmt.Sprintf("%s/", project)) {
return true
}
}
return false
}

func addResource(path, project, tfRootDir string, workflow string, changedFiles []string) error {
switch workflow {
case "multi-workspace":
return multiWorkspaceAddResource(path, project, tfRootDir, changedFiles)
case "single-workspace":
return singleWorkspaceAddResource(path, project, tfRootDir, changedFiles)
}
return nil
}

func genAtlantisProjects(workflow string, projectFilter helpers.ProjectRegexFilter) error {
for _, folder := range resources {
for _, workspace := range folder.WorkspaceList {
name := fmt.Sprintf("%s-%s", strings.Replace(folder.Project, "/", "-", 1), workspace)
if helpers.ProjectFilter(name, projectFilter) {
atlantisProjects = append(atlantisProjects, Project{
Name: name,
Dir: folder.Path,
Workspace: workspace,
Workflow: workflow,
})
}
}
}
return nil
}

func genOutput(config *Config, outputFile string) error {
func generateOutputYAML(config *Config, outputFile string) error {
yamlBytes, err := yaml.Marshal(&config)
if err != nil {
return err
Expand Down
32 changes: 32 additions & 0 deletions pkg/atlantis/atlantis_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package atlantis

import (
"testing"

"github.com/stretchr/testify/assert"
)

func TestFilterAtlantisProjects(t *testing.T) {
excludedProjects := "excluded\\d"
includedProjects := "included\\d"

atlantisProjects := []Project{
{Name: "project1"},
{Name: "excluded1"},
{Name: "project2"},
{Name: "excluded2"},
{Name: "included1"},
}

filteredProjects, err := filterAtlantisProjects(excludedProjects, includedProjects, atlantisProjects)

assert.NoError(t, err, "FilterAtlantisProjects should not return an error")
assert.Len(t, filteredProjects, 2, "Number of filtered projects should match")

expectedFilteredProjects := []Project{
{Name: "project1"},
{Name: "project2"},
}

assert.Equal(t, expectedFilteredProjects, filteredProjects)
}
Loading

0 comments on commit 1ad114e

Please sign in to comment.