From e03aee818ad18edcc23bc6e0fb02074987e967fb Mon Sep 17 00:00:00 2001 From: Marc Portabella Date: Mon, 18 Dec 2023 19:40:42 +0100 Subject: [PATCH] chore: generator improvements - decouple workflow with discovery mode (bad logic used in 0.0.2) - create a new flag for discovery-mode which replaces the workflow mode - read github credentials from $HOME/.git-credentials - update tests - update readme - bump version to v0.0.3 --- README.md | 41 ++++++++------- .../generate-with-include-filter.sh | 2 +- .../multiple-projects/generate.sh | 2 +- .../single-project/generate.sh | 2 +- .../generate.sh | 2 +- .../multiple-projects/generate.sh | 2 +- .../single-project/generate.sh | 2 +- go.mod | 14 +++-- go.sum | 52 ++++++++++++------- main.go | 4 -- pkg/atlantis/atlantis.go | 32 ++++++------ pkg/atlantis/atlantis_test.go | 49 ++++++++--------- ...low.go => multiple-workspace-discovery.go} | 2 +- ...o => multiple-workspace-discovery_test.go} | 0 ...kflow.go => single-workspace-discovery.go} | 2 +- ....go => single-workspace-discovery_test.go} | 0 pkg/config/config.go | 19 ++++--- pkg/github/github.go | 26 +++++++--- pkg/version/version.go | 2 +- pkg/version/version_test.go | 2 +- 20 files changed, 142 insertions(+), 115 deletions(-) rename pkg/atlantis/{multiple-workspace-workflow.go => multiple-workspace-discovery.go} (95%) rename pkg/atlantis/{multiple-workspace-workflow_test.go => multiple-workspace-discovery_test.go} (100%) rename pkg/atlantis/{single-workspace-workflow.go => single-workspace-discovery.go} (80%) rename pkg/atlantis/{single-workspace-workflow_test.go => single-workspace-discovery_test.go} (100%) diff --git a/README.md b/README.md index 0c674f3..91e7bc0 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ It automates the process of detecting projects within your Terraform codebase, c ------------ - Generate `atlantis.yaml` files with ease. -- Automatically detect projects and workspaces based on your specified workflow. +- Automatically detect projects and workspaces based on discovery mode rules. - Customize configurations such as automerge, parallel plan/apply, and more. - Flexible project inclusion and exclusion using regular expressions. - Create an Atlantis project by taking into account the files modified in the PR. This approach @@ -31,6 +31,7 @@ Run the tool using the following command: | `-r, --base-repo-name` | Github Repo Name. | `BASE_REPO_NAME` | | | `-o, --base-repo-owner`| Github Repo Owner Name. | `BASE_REPO_OWNER` | | | `-x, --excluded-projects`| Atlantis regex filter to exclude projects. | `EXCLUDED_PROJECTS` | | +| `-d, --discovery-mode`| mode used to discover projects | `DISCOVERY_MODE` | `single-workspace`| | `-t, --gh-token` | Github Token Value. | `GH_TOKEN` | | | `-h, --help` | Help for atlantis-yaml-generator. | | | | `-z, --included-projects`| Atlantis regex filter to only include projects. | `INCLUDED_PROJECTS` | | @@ -38,8 +39,8 @@ Run the tool using the following command: | `-e, --output-type` | Atlantis YAML output type [file stdout] | `OUTPUT_TYPE` | `file` | | `--parallel-apply` | Atlantis parallel apply config value. | `PARALLEL_APPLY` | `true` | | `--parallel-plan` | Atlantis parallel plan config value. | `PARALLEL_PLAN` | `true` | -| `-q, --pattern-detector`| Discover projects based on files or directories names. | `PATTERN_DETECTOR` | | -| `-y, --pr-filter` | Filter projects based on the PR changes (Only for github SCM).| `PR_FILTER` | `false` | +| `-q, --pattern-detector`| Discover projects based on files or directories names. | `PATTERN_DETECTOR` | `main.tf` | +| `-u, --pr-filter` | Filter projects based on the PR changes (Only for github SCM).| `PR_FILTER` | `false` | | `-p, --pull-num` | Github Pull Request Number to check diffs. | `PULL_NUM` | | | `--terraform-base-dir` | Basedir for terraform resources. | `TERRAFORM_BASE_DIR`| `./` | | `-v, --version` | Version for atlantis-yaml-generator. | | | @@ -57,7 +58,7 @@ Run the tool using the following command:
Multi workspace workflow ``` -# atlantis-yaml-generator -w multi-workspace --pattern-detector workspace_vars -e stdout +# atlantis-yaml-generator -d multi-workspace -w myWorkflow --pattern-detector workspace_vars -e stdout version: 3 automerge: true @@ -66,7 +67,7 @@ parallel_plan: true projects: - name: project_one-dev workspace: dev - workflow: multi-workspace + workflow: myWorkflow dir: project_one autoplan: enabled: true @@ -79,7 +80,7 @@ projects: - '**/*.xml' - name: project_one-production workspace: production - workflow: multi-workspace + workflow: myWorkflow dir: project_one autoplan: enabled: true @@ -92,7 +93,7 @@ projects: - '**/*.xml' - name: project_one-staging workspace: staging - workflow: multi-workspace + workflow: myWorkflow dir: project_one autoplan: enabled: true @@ -105,7 +106,7 @@ projects: - '**/*.xml' - name: project_two-production workspace: production - workflow: multi-workspace + workflow: myWorkflow dir: project_two autoplan: enabled: true @@ -118,7 +119,7 @@ projects: - '**/*.xml' - name: project_two-staging workspace: staging - workflow: multi-workspace + workflow: myWorkflow dir: project_two autoplan: enabled: true @@ -132,10 +133,10 @@ projects: ```
-
Single workspace workflow +
Single workspace discovery mode ``` -# atlantis-yaml-generator -w single-workspace -e stdout --pattern-detector main.tf +# atlantis-yaml-generator -d single-workspace -w myWorkflow -e stdout --pattern-detector main.tf version: 3 automerge: true @@ -144,7 +145,7 @@ parallel_plan: true projects: - name: project_one workspace: default - workflow: single-workspace + workflow: myWorkflow dir: project_one autoplan: enabled: true @@ -247,17 +248,17 @@ projects: ------- -**Workflows** +**Discovery Modes** ------------- -Currenlty `atlantis-yaml-generator` support 2 workflow types: +Currenlty `atlantis-yaml-generator` support 2 discovery modes: - `single-workspace`: Intended for Terraform configurations that do not utilize multiple workspaces. In this context, the pattern detector parameters establish the criteria for identifying project folders. For instance, if the pattern-detector is set to main.tf (file), and this file is located at database/dev/main.tf, the resulting project would be labeled as database-env. Consequently, Terraform commands would be executed within the database/dev folder. - `multiple-workspace`: Intended for Terraform configurations that utilize multiple workspaces. In this context, the pattern detector parameters establish the criteria for identifying project folders. For instance, if the pattern-detector is set to workspace_vars (folder), and there are several files located in this folder, i.e. (database/workspace_vars/dev.tf |database/workspace_vars/staging.tf ), the resulting projects would be labeled as (database-dev|database-staging). Consequently, Terraform commands would be executed within the database folder. Please be aware that in this scenario, the Atlantis workflow requires the use of the -var-file parameter, specifically in the form of -var-file=(workspace_vars/dev.tf|workspace_vars/staging.tf). -If there is the need for additional workflows, they can be easily added at code level. Current code is ready to easily add new workflows, while sharing common actions. +If there is the need for additional discovery modes, they can be easily added at code level. Current code is ready to easily add new discovery modes, while sharing common actions. ``` -func detectProjectWorkspaces(foldersList []ProjectFolder, workflow string, patternDetector string, changedFiles []string) (updatedFoldersList []ProjectFolder, err error) { - // Detect project workspaces based on the workflow +func detectProjectWorkspaces(foldersList []ProjectFolder, discoveryMode string, patternDetector string, changedFiles []string) (updatedFoldersList []ProjectFolder, err error) { + // Detect project workspaces based on the discovery mode switch workflow { case "single-workspace": updatedFoldersList, err = singleWorkspaceDetectProjectWorkspaces(foldersList) @@ -281,7 +282,7 @@ Incorporating this generator into Atlantis requires setting up a [`pre-workflow- ```yaml pre_workflow_hooks: - run: > - atlantis-yaml-generator -w single-workspace --pattern-detector main.tf + atlantis-yaml-generator -d single-workspace -w myWorkflow --pattern-detector main.tf ``` Sample output: @@ -304,7 +305,7 @@ parallel_plan: true projects: - name: project-one workspace: default - workflow: single-workspace + workflow: myWorkflow dir: project/one autoplan: enabled: true @@ -317,7 +318,7 @@ projects: - '**/*.xml' - name: project-two workspace: default - workflow: single-workspace + workflow: myWorkflow dir: project/two autoplan: enabled: true diff --git a/examples/multi-workspace/multiple-projects/generate-with-include-filter.sh b/examples/multi-workspace/multiple-projects/generate-with-include-filter.sh index 9d69f6f..df2e705 100755 --- a/examples/multi-workspace/multiple-projects/generate-with-include-filter.sh +++ b/examples/multi-workspace/multiple-projects/generate-with-include-filter.sh @@ -1 +1 @@ -atlantis-yaml-generator -e stdout -w multi-workspace --pattern-detector workspace_vars --included-projects "staging$" +atlantis-yaml-generator -e stdout -d multi-workspace -w workflow1 --pattern-detector workspace_vars --included-projects "staging$" diff --git a/examples/multi-workspace/multiple-projects/generate.sh b/examples/multi-workspace/multiple-projects/generate.sh index 7f606c3..c18d8e9 100755 --- a/examples/multi-workspace/multiple-projects/generate.sh +++ b/examples/multi-workspace/multiple-projects/generate.sh @@ -1 +1 @@ -atlantis-yaml-generator -e stdout -w multi-workspace --pattern-detector workspace_vars +atlantis-yaml-generator -e stdout -d multi-workspace -w workflow1 --pattern-detector workspace_vars diff --git a/examples/multi-workspace/single-project/generate.sh b/examples/multi-workspace/single-project/generate.sh index 7f606c3..b28f55e 100755 --- a/examples/multi-workspace/single-project/generate.sh +++ b/examples/multi-workspace/single-project/generate.sh @@ -1 +1 @@ -atlantis-yaml-generator -e stdout -w multi-workspace --pattern-detector workspace_vars +atlantis-yaml-generator -e stdout -d multi-workspace -w workflow2 --pattern-detector workspace_vars diff --git a/examples/single-workspace/multiple-projects-environments/generate.sh b/examples/single-workspace/multiple-projects-environments/generate.sh index 8322bb6..d7c2eab 100755 --- a/examples/single-workspace/multiple-projects-environments/generate.sh +++ b/examples/single-workspace/multiple-projects-environments/generate.sh @@ -1 +1 @@ -atlantis-yaml-generator -e stdout -w single-workspace --pattern-detector main.tf +atlantis-yaml-generator -e stdout -d single-workspace -w workflow1 --pattern-detector main.tf diff --git a/examples/single-workspace/multiple-projects/generate.sh b/examples/single-workspace/multiple-projects/generate.sh index 8322bb6..d7c2eab 100755 --- a/examples/single-workspace/multiple-projects/generate.sh +++ b/examples/single-workspace/multiple-projects/generate.sh @@ -1 +1 @@ -atlantis-yaml-generator -e stdout -w single-workspace --pattern-detector main.tf +atlantis-yaml-generator -e stdout -d single-workspace -w workflow1 --pattern-detector main.tf diff --git a/examples/single-workspace/single-project/generate.sh b/examples/single-workspace/single-project/generate.sh index 8322bb6..d7c2eab 100755 --- a/examples/single-workspace/single-project/generate.sh +++ b/examples/single-workspace/single-project/generate.sh @@ -1 +1 @@ -atlantis-yaml-generator -e stdout -w single-workspace --pattern-detector main.tf +atlantis-yaml-generator -e stdout -d single-workspace -w workflow1 --pattern-detector main.tf diff --git a/go.mod b/go.mod index 3e53bac..4a2f644 100644 --- a/go.mod +++ b/go.mod @@ -1,29 +1,27 @@ module github.com/totmicro/atlantis-yaml-generator -go 1.20 +go 1.21 require github.com/google/go-github v17.0.0+incompatible require ( github.com/davecgh/go-spew v1.1.1 // indirect github.com/golang/protobuf v1.5.3 // indirect + github.com/google/go-cmp v0.6.0 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/kr/pretty v0.3.1 // indirect - github.com/onsi/gomega v1.27.10 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect - github.com/rogpeppe/go-internal v1.10.0 // indirect + github.com/rogpeppe/go-internal v1.12.0 // indirect github.com/spf13/pflag v1.0.5 // indirect - golang.org/x/net v0.14.0 // indirect - google.golang.org/appengine v1.6.7 // indirect + google.golang.org/appengine v1.6.8 // indirect google.golang.org/protobuf v1.31.0 // indirect gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect ) require ( github.com/google/go-querystring v1.1.0 // indirect - github.com/spf13/cobra v1.7.0 + github.com/spf13/cobra v1.8.0 github.com/stretchr/testify v1.8.4 - github.com/tcnksm/go-gitconfig v0.1.2 - golang.org/x/oauth2 v0.11.0 + golang.org/x/oauth2 v0.15.0 gopkg.in/yaml.v3 v3.0.1 ) diff --git a/go.sum b/go.sum index 8ab36b6..0aa3169 100644 --- a/go.sum +++ b/go.sum @@ -1,14 +1,15 @@ -github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= +github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= +github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-github v17.0.0+incompatible h1:N0LgJ1j65A7kfXrZnUDaYCs/Sf4rEjNlfyDHW9dolSY= github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ= github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8= @@ -22,37 +23,48 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= -github.com/onsi/gomega v1.27.10 h1:naR28SdDFlqrG6kScpT8VWpu1xWY5nJRCF3XaYyBjhI= -github.com/onsi/gomega v1.27.10/go.mod h1:RsS8tutOdbdgzbPtzzATp12yT7kM5I5aElG3evPbQ0M= github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= -github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= -github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= +github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= +github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= -github.com/spf13/cobra v1.7.0 h1:hyqWnYt1ZQShIddO5kBpj3vu05/++x6tJ6dg8EC572I= -github.com/spf13/cobra v1.7.0/go.mod h1:uLxZILRyS/50WlhOIKD7W6V5bgeIt+4sICxh6uRMrb0= +github.com/spf13/cobra v1.8.0 h1:7aJaZx1B85qltLMc546zn58BxxfZdR/W22ej9CFoEf0= +github.com/spf13/cobra v1.8.0/go.mod h1:WXLWApfZ71AjXPya3WOlMsY9yMs7YeiHhFVlvLyhcho= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= -github.com/tcnksm/go-gitconfig v0.1.2 h1:iiDhRitByXAEyjgBqsKi9QU4o2TNtv9kPP3RgPgXBPw= -github.com/tcnksm/go-gitconfig v0.1.2/go.mod h1:/8EhP4H7oJZdIPyT+/UIsG87kTzrzM4UsLGSItWYCpE= +github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= -golang.org/x/net v0.14.0 h1:BONx9s002vGdD9umnlX1Po8vOZmrgH34qlHcD1MfK14= -golang.org/x/net v0.14.0/go.mod h1:PpSgVXXLK0OxS0F31C1/tv6XNguvCrnXIDrFMspZIUI= -golang.org/x/oauth2 v0.11.0 h1:vPL4xzxBM4niKCW6g9whtaWVXTJf1U5e4aZxxFx/gbU= -golang.org/x/oauth2 v0.11.0/go.mod h1:LdF7O/8bLR/qWK9DrpXmbHLTouvRHK0SgJl0GmDBchk= +golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/oauth2 v0.15.0 h1:s8pnnxNVzjWyrvYdFUQq5llS1PX2zhPXmccZv99h7uQ= +golang.org/x/oauth2 v0.15.0/go.mod h1:q48ptWNTY5XWf+JNten23lcvHpLJ0ZSxF5ttTHKVCAM= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= -golang.org/x/text v0.12.0 h1:k+n5B8goJNdU7hSvEtMUz3d1Q6D/XW4COJSJR6fN0mc= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c= -google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/appengine v1.6.8 h1:IhEN5q69dyKagZPYMSdIjS2HqprW324FRQZJcGqPAsM= +google.golang.org/appengine v1.6.8/go.mod h1:1jJ3jBArFh5pcgW8gCtRJnepW8FzD1V44FJffLiz/Ds= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8= diff --git a/main.go b/main.go index af168be..0f1e1a4 100644 --- a/main.go +++ b/main.go @@ -5,9 +5,5 @@ import ( ) func main() { - cmd.Init() } - -// TODO -// - [ ] Add tests diff --git a/pkg/atlantis/atlantis.go b/pkg/atlantis/atlantis.go index d0bad02..1fa906f 100644 --- a/pkg/atlantis/atlantis.go +++ b/pkg/atlantis/atlantis.go @@ -28,7 +28,7 @@ type Config struct { type Project struct { Name string `yaml:"name"` Workspace string `yaml:"workspace"` - Workflow string `yaml:"workflow"` + Workflow string `yaml:"workflow,omitempty"` Dir string `yaml:"dir"` Autoplan struct { Enabled bool `yaml:"enabled"` @@ -60,7 +60,7 @@ func GenerateAtlantisYAML() error { // Scan folders to detect projects projectFoldersList, err := scanProjectFolders( config.GlobalConfig.Parameters["terraform-base-dir"], - config.GlobalConfig.Parameters["workflow"], + config.GlobalConfig.Parameters["discovery-mode"], config.GlobalConfig.Parameters["pattern-detector"], ) if err != nil { @@ -75,7 +75,7 @@ func GenerateAtlantisYAML() error { // Detect project workspaces projectFoldersListWithWorkspaces, err := detectProjectWorkspaces( projectFoldersList, - config.GlobalConfig.Parameters["workflow"], + config.GlobalConfig.Parameters["discovery-mode"], config.GlobalConfig.Parameters["pattern-detector"], prChangedFiles, enablePRFilter) if err != nil { @@ -120,12 +120,12 @@ func GenerateAtlantisYAML() error { return nil } -func scanProjectFolders(basePath, workflow, patternDetector string) (projectFolders []ProjectFolder, err error) { +func scanProjectFolders(basePath, discoveryMode, patternDetector string) (projectFolders []ProjectFolder, err error) { err = filepath.Walk(basePath, func(path string, info os.FileInfo, err error) error { if err != nil || info == nil { return err } - if workflowFilter(info, path, workflow, patternDetector) { + if discoveryFilter(info, path, discoveryMode, patternDetector) { relPath, _ := filepath.Rel(basePath, filepath.Dir(path)) projectFolders = append(projectFolders, ProjectFolder{Path: relPath}) } @@ -148,15 +148,15 @@ func applyPRFilter(projectFolders []ProjectFolder, changedFiles []string) (filte return filteredProjectFolders, nil } -func detectProjectWorkspaces(foldersList []ProjectFolder, workflow string, patternDetector string, changedFiles []string, enablePRfilter bool) (updatedFoldersList []ProjectFolder, err error) { - // Detect project workspaces based on the workflow - switch workflow { +func detectProjectWorkspaces(foldersList []ProjectFolder, discoveryMode string, patternDetector string, changedFiles []string, enablePRfilter bool) (updatedFoldersList []ProjectFolder, err error) { + // Detect project workspaces based on the discovert mode + switch discoveryMode { case "single-workspace": updatedFoldersList, err = singleWorkspaceDetectProjectWorkspaces(foldersList) case "multi-workspace": updatedFoldersList, err = multiWorkspaceDetectProjectWorkspaces(changedFiles, enablePRfilter, foldersList, patternDetector) } - // You can add more workflows rules here if required + // You can add more discoveryMode rules here if required return updatedFoldersList, err } @@ -251,16 +251,16 @@ func generateOutputYAML(config *Config, outputFile string, outputType string) er } } -func workflowFilter(info os.FileInfo, path, workflow, patternDetector string) bool { - // Detect projects folders based on the workflow - // Each workflow has different rules to detect projects - switch workflow { +func discoveryFilter(info os.FileInfo, path, discoveryMode, patternDetector string) bool { + // Detect projects folders based on the discovery modes + // Each discovery mode has different rules to detect projects + switch discoveryMode { case "single-workspace": - return singleWorkspaceWorkflowFilter(info, path, patternDetector) + return singleWorkspaceDiscoveryFilter(info, path, patternDetector) case "multi-workspace": - return multiWorkspaceWorkflowFilter(info, path, patternDetector) + return multiWorkspaceDiscoveryFilter(info, path, patternDetector) } - // You can add more workflows rules here if required + // You can add more discoveryMode rules here if required return true } diff --git a/pkg/atlantis/atlantis_test.go b/pkg/atlantis/atlantis_test.go index 55a3239..75f1a71 100644 --- a/pkg/atlantis/atlantis_test.go +++ b/pkg/atlantis/atlantis_test.go @@ -256,7 +256,7 @@ func TestGenerateAtlantisProjects(t *testing.T) { WorkspaceList: []string{"dev", "prod"}, }, } - + //TODO: improve test to better test workflow workflow := "myWorkflow" expectedProjects := []Project{ @@ -351,14 +351,14 @@ func TestApplyPRFilter(t *testing.T) { func TestScanProjectFolders(t *testing.T) { tests := []struct { basePath string - workflow string + discoveryMode string patternDetector string expectedProjectFolder []ProjectFolder expectedError bool }{ { basePath: "mockproject", - workflow: "multi-workspace", + discoveryMode: "multi-workspace", patternDetector: "workspace_vars", expectedProjectFolder: []ProjectFolder{ {Path: "multiworkspace"}, @@ -367,7 +367,7 @@ func TestScanProjectFolders(t *testing.T) { }, { basePath: "mockproject", - workflow: "single-workspace", + discoveryMode: "single-workspace", patternDetector: "main.tf", expectedProjectFolder: []ProjectFolder{ {Path: "singleworkspace"}, @@ -376,7 +376,7 @@ func TestScanProjectFolders(t *testing.T) { }, { basePath: "invalidpath", // Invalid path to check file walk error - workflow: "single-workspace", + discoveryMode: "single-workspace", patternDetector: "main.tf", expectedProjectFolder: []ProjectFolder{ {Path: "singleworkspace"}, @@ -386,8 +386,8 @@ func TestScanProjectFolders(t *testing.T) { } for _, test := range tests { - t.Run(test.workflow, func(t *testing.T) { - projectFolders, err := scanProjectFolders(test.basePath, test.workflow, test.patternDetector) + t.Run(test.discoveryMode, func(t *testing.T) { + projectFolders, err := scanProjectFolders(test.basePath, test.discoveryMode, test.patternDetector) if test.expectedError { assert.Error(t, err) } else { @@ -457,39 +457,39 @@ func TestProjectFilter(t *testing.T) { } } -func TestWorkflowFilter(t *testing.T) { +func TestDiscoveryFilter(t *testing.T) { tests := []struct { name string path string - workflow string + discoveryMode string patternDetector string expectedResult bool }{ { name: "single-workspace-true", path: "mockproject/singleworkspace/main.tf", - workflow: "single-workspace", + discoveryMode: "single-workspace", patternDetector: "main.tf", expectedResult: true, }, { name: "single-workspace-false", path: "mockproject/singleworkspace/dummy.tf", - workflow: "single-workspace", + discoveryMode: "single-workspace", patternDetector: "main.tf", expectedResult: false, }, { name: "multi-workspace", path: "mockproject/multiworkspace/workspace_vars", - workflow: "multi-workspace", + discoveryMode: "multi-workspace", patternDetector: "workspace_vars", expectedResult: true, }, { - name: "undefined-workflow", + name: "undefined-mode", path: "mockproject/multiworkspace/workspace_vars", - workflow: "", + discoveryMode: "", patternDetector: "", expectedResult: true, }, @@ -501,7 +501,7 @@ func TestWorkflowFilter(t *testing.T) { t.Run(test.name, func(t *testing.T) { info, err := os.Stat(test.path) if err == nil { - result := workflowFilter(info, test.path, test.workflow, test.patternDetector) + result := discoveryFilter(info, test.path, test.discoveryMode, test.patternDetector) assert.Equal(t, test.expectedResult, result) } else { assert.Error(t, err) @@ -514,7 +514,7 @@ func TestDetectProjectWorkspaces(t *testing.T) { tests := []struct { name string foldersList []ProjectFolder - workflow string + discoveryMode string patternDetector string changedFiles []string enablePRFilter bool @@ -524,7 +524,7 @@ func TestDetectProjectWorkspaces(t *testing.T) { { name: "single-workspace", foldersList: []ProjectFolder{{Path: "mockproject/singleworkspace"}}, - workflow: "single-workspace", + discoveryMode: "single-workspace", patternDetector: "main.tf", changedFiles: []string{"mockproject/singleworkspace/main.tf"}, enablePRFilter: true, @@ -536,7 +536,7 @@ func TestDetectProjectWorkspaces(t *testing.T) { { name: "single-workspace", foldersList: []ProjectFolder{{Path: "mockproject/singleworkspace"}, {Path: "mockproject/singleworkspace2"}}, - workflow: "single-workspace", + discoveryMode: "single-workspace", patternDetector: "main.tf", changedFiles: []string{"mockproject/singleworkspace/main.tf"}, enablePRFilter: false, @@ -549,7 +549,7 @@ func TestDetectProjectWorkspaces(t *testing.T) { { name: "multi-workspace-invalid-path", foldersList: []ProjectFolder{{Path: "invalidpath"}}, - workflow: "multi-workspace", + discoveryMode: "multi-workspace", patternDetector: "workspace_vard", changedFiles: []string{"invalid/workspace_vars/test1.tfvars"}, enablePRFilter: true, @@ -561,7 +561,7 @@ func TestDetectProjectWorkspaces(t *testing.T) { { name: "multi-workspace", foldersList: []ProjectFolder{{Path: "mockproject/multiworkspace"}}, - workflow: "multi-workspace", + discoveryMode: "multi-workspace", patternDetector: "workspace_vars", changedFiles: []string{"mockproject/multiworkspace/workspace_vars/test1.tfvars"}, enablePRFilter: true, @@ -576,7 +576,7 @@ func TestDetectProjectWorkspaces(t *testing.T) { { name: "multi-workspace", foldersList: []ProjectFolder{{Path: "mockproject/multiworkspace"}, {Path: "mockproject/multiworkspace2"}}, - workflow: "multi-workspace", + discoveryMode: "multi-workspace", patternDetector: "workspace_vars", changedFiles: []string{"mockproject/multiworkspace/workspace_vars/test1.tfvars", "mockproject/multiworkspace2/workspace_vars/test2.tfvars", @@ -597,7 +597,7 @@ func TestDetectProjectWorkspaces(t *testing.T) { { name: "multi-workspace", foldersList: []ProjectFolder{{Path: "mockproject/multiworkspace"}, {Path: "mockproject/multiworkspace2"}}, - workflow: "multi-workspace", + discoveryMode: "multi-workspace", patternDetector: "workspace_vars", changedFiles: []string{"mockproject/multiworkspace/workspace_vars/test1.tfvars", "mockproject/multiworkspace2/workspace_vars/test2.tfvars", @@ -620,7 +620,7 @@ func TestDetectProjectWorkspaces(t *testing.T) { for _, test := range tests { t.Run(test.name, func(t *testing.T) { - updatedFoldersList, err := detectProjectWorkspaces(test.foldersList, test.workflow, test.patternDetector, test.changedFiles, test.enablePRFilter) + updatedFoldersList, err := detectProjectWorkspaces(test.foldersList, test.discoveryMode, test.patternDetector, test.changedFiles, test.enablePRFilter) if test.expectedErr { assert.Error(t, err) } else { @@ -693,7 +693,8 @@ func TestGenerateAtlantisYAML(t *testing.T) { config.GlobalConfig.Parameters["base-repo-owner"] = "test-owner" config.GlobalConfig.Parameters["base-repo-name"] = "test-repo" config.GlobalConfig.Parameters["pull-num"] = "55" - config.GlobalConfig.Parameters["workflow"] = "single-workspace" + config.GlobalConfig.Parameters["workflow"] = "workflow1" + config.GlobalConfig.Parameters["discoveryMode"] = "single-workspace" config.GlobalConfig.Parameters["pattern-detector"] = "main.tf" config.GlobalConfig.Parameters["terraform-base-dir"] = "mockproject" config.GlobalConfig.Parameters["output-file"] = tempFile diff --git a/pkg/atlantis/multiple-workspace-workflow.go b/pkg/atlantis/multiple-workspace-discovery.go similarity index 95% rename from pkg/atlantis/multiple-workspace-workflow.go rename to pkg/atlantis/multiple-workspace-discovery.go index 01ca2f0..692c77b 100644 --- a/pkg/atlantis/multiple-workspace-workflow.go +++ b/pkg/atlantis/multiple-workspace-discovery.go @@ -56,7 +56,7 @@ func multiWorkspaceDetectProjectWorkspaces(changedFiles []string, enablePRFilter return foldersList, nil } -func multiWorkspaceWorkflowFilter(info os.FileInfo, path, patternDetector string) bool { +func multiWorkspaceDiscoveryFilter(info os.FileInfo, path, patternDetector string) bool { return info.IsDir() && info.Name() == patternDetector && !strings.Contains(path, ".terraform") diff --git a/pkg/atlantis/multiple-workspace-workflow_test.go b/pkg/atlantis/multiple-workspace-discovery_test.go similarity index 100% rename from pkg/atlantis/multiple-workspace-workflow_test.go rename to pkg/atlantis/multiple-workspace-discovery_test.go diff --git a/pkg/atlantis/single-workspace-workflow.go b/pkg/atlantis/single-workspace-discovery.go similarity index 80% rename from pkg/atlantis/single-workspace-workflow.go rename to pkg/atlantis/single-workspace-discovery.go index d86f3cb..2b2e402 100644 --- a/pkg/atlantis/single-workspace-workflow.go +++ b/pkg/atlantis/single-workspace-discovery.go @@ -5,7 +5,7 @@ import ( "strings" ) -func singleWorkspaceWorkflowFilter(info os.FileInfo, path, patternDetector string) bool { +func singleWorkspaceDiscoveryFilter(info os.FileInfo, path, patternDetector string) bool { return !info.IsDir() && info.Name() == patternDetector && !strings.Contains(path, ".terraform") diff --git a/pkg/atlantis/single-workspace-workflow_test.go b/pkg/atlantis/single-workspace-discovery_test.go similarity index 100% rename from pkg/atlantis/single-workspace-workflow_test.go rename to pkg/atlantis/single-workspace-discovery_test.go diff --git a/pkg/config/config.go b/pkg/config/config.go index c1a4ca9..3d4ce48 100644 --- a/pkg/config/config.go +++ b/pkg/config/config.go @@ -35,7 +35,7 @@ var ParameterList = []Parameter{ Name: "automerge", Description: "Atlantis automerge config value.", Required: false, - DefaultValue: "true", + DefaultValue: "false", Shorthand: "", }, { @@ -75,8 +75,8 @@ var ParameterList = []Parameter{ }, { Name: "workflow", - Description: "Atlantis Workflow to be used. [single-workspace|multi-workspace].", - Required: true, + Description: "Atlantis Workflow to be used.", + Required: false, DefaultValue: "", Shorthand: "w", }, @@ -104,10 +104,17 @@ var ParameterList = []Parameter{ { Name: "pattern-detector", Description: "discover projects based on files or directories names.", - Required: true, - DefaultValue: "", + Required: false, + DefaultValue: "main.tf", Shorthand: "q", }, + { + Name: "discovery-mode", + Description: "mode used to discover projects [single-workspace|multi-workspace]", + Required: false, + DefaultValue: "single-workspace", + Shorthand: "d", + }, { Name: "pull-num", Description: "Github Pull Request Number to check diffs.", @@ -142,7 +149,7 @@ var ParameterList = []Parameter{ Required: false, Dependencies: DependentParameters{ WhenParentParameterIs: "true", - ParameterList: []string{"pull-num", "base-repo-name", "base-repo-owner", "gh-token"}}, + ParameterList: []string{"pull-num", "base-repo-name", "base-repo-owner"}}, DefaultValue: "false", Shorthand: "u", }, diff --git a/pkg/github/github.go b/pkg/github/github.go index 643790c..e22cf97 100644 --- a/pkg/github/github.go +++ b/pkg/github/github.go @@ -4,12 +4,14 @@ import ( "context" "errors" "fmt" + "os/user" + "path/filepath" "strconv" "strings" "github.com/google/go-github/github" - "github.com/tcnksm/go-gitconfig" "github.com/totmicro/atlantis-yaml-generator/pkg/config" + "github.com/totmicro/atlantis-yaml-generator/pkg/helpers" "golang.org/x/oauth2" ) @@ -51,7 +53,7 @@ func runGHRequest(authToken, owner, repo, pullReqNum string) ([]string, error) { // GetChangedFiles gets the parameters to call a ghrequest that returns a list of changed files. func GetChangedFiles() (ChangedFiles []string, err error) { // Parse the token from the git config file - token, _ := getTokenFromGitConfig() + token, _ := getTokenFromGitCredentialsFile() if token == "" { token = config.GlobalConfig.Parameters["gh-token"] } @@ -71,12 +73,23 @@ func GetChangedFiles() (ChangedFiles []string, err error) { return prChangedFiles, err } -func getTokenFromGitConfig() (string, error) { - url, err := gitconfig.Local("remote.origin.url") +func getTokenFromGitCredentialsFile() (string, error) { + // Get the current user + usr, err := user.Current() if err != nil { - return "", fmt.Errorf("token not found in the [remote \"origin\"] block") + return "", err } - token, err := extractTokenFromURL(url) + + // Construct the path to the .git-credentials file + credentialsFilePath := filepath.Join(usr.HomeDir, ".git-credentials") + + // ReadFile credentials file + file, err := helpers.ReadFile(credentialsFilePath) + if err != nil { + return "", err + } + + token, err := extractTokenFromURL(file) return token, err } @@ -94,5 +107,4 @@ func extractTokenFromURL(urlLine string) (string, error) { } return "", fmt.Errorf("token not found in url line") - } diff --git a/pkg/version/version.go b/pkg/version/version.go index f7832e3..cb41907 100644 --- a/pkg/version/version.go +++ b/pkg/version/version.go @@ -1,6 +1,6 @@ package version -const VERSION = "0.0.2" +const VERSION = "0.0.3" func GetVersion() string { return VERSION diff --git a/pkg/version/version_test.go b/pkg/version/version_test.go index 8362b21..ed6e22d 100644 --- a/pkg/version/version_test.go +++ b/pkg/version/version_test.go @@ -3,7 +3,7 @@ package version import "testing" func TestGetVersion(t *testing.T) { - expectedVersion := "0.0.2" + expectedVersion := "0.0.3" actualVersion := GetVersion() if actualVersion != expectedVersion { t.Errorf("Expected version %s, but got %s", expectedVersion, actualVersion)