Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Add project depends on functionality #3292

Merged

Conversation

Luay-Sol
Copy link
Contributor

@Luay-Sol Luay-Sol commented Apr 4, 2023

what

  • The main purpose of this PR is to add Dependencies functionality to Atlantis. The change introduces a new key depends_on to the project config in the atlantis.yaml file.

why

Using the depends_on functionality will allow Atlantis to handle cases requiring one project to be applied prior to the other. In other words, allow promotions between projects/environments (dev -> staging -> production)

tests

  • I have tested my changes by adding new unit tests, running Atlantis locally, and testing the depends_on functionality.

references

@Luay-Sol Luay-Sol requested a review from a team as a code owner April 4, 2023 14:23
server/core/config/valid/global_cfg.go Show resolved Hide resolved
@@ -62,6 +69,8 @@ type ProjectContext struct {
PullReqStatus models.PullReqStatus
// CurrentProjectPlanStatus is the status of the current project prior to this command.
ProjectPlanStatus models.ProjectPlanStatus

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

could you add a comment here of what this is doing?

@jamengual
Copy link
Contributor

will these work by running atlantis plan and then atlantis apply in all projects and the apply will go though the dependencies in order?

@jamengual
Copy link
Contributor

Thanks for the contribution @Luay-Sol

@Luay-Sol
Copy link
Contributor Author

Luay-Sol commented Apr 14, 2023

will these work by running atlantis plan and then atlantis apply in all projects and the apply will go though the dependencies in order?

Actually, this feature is more for the case where the user tries to apply to a specific project/workspace. What you have described already exists in Atlantis and is called execution_order_group. So I see this feature will work in conjunction with the execution_order_group. For example, this is how my project block looks like:

projects:
  - name: development
    dir: .
    autoplan:
      when_modified: ["*.tf", "vars/development.tfvars"]
    execution_order_group: 1
    workspace: development
    workflow: infra
  - name:staging
    dir: .
    autoplan:
      when_modified: ["*.tf", "vars/staging.tfvars"]
    depends_on: ["development"]
    execution_order_group: 2
    workspace: staging
    workflow: infra
  - name: production
    dir: .
    autoplan:
      when_modified: ["*.tf", "vars/production.tfvars"]
    depends_on: ["staging"]
    execution_order_group: 3
    workspace: production
    workflow: infra

So with this, if the user just comments atlantis apply the execution_order_group will ensure that the changes will go development->staging->production. Else if the user makes the apply command sequentially atlantis apply -w development, then atlantis apply -w staging, then atlantis apply -w production, the depends_on feature will make sure that production is not applied before staging for example.

@jamengual
Copy link
Contributor

Amazing that is what I was expecting and I can see how useful this will be.

Copy link
Member

@GenPage GenPage left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great work. Thank you for your contribution. Please address nitpick comments. I envision we can deprecate execution_order_group after this. It's a bit ambiguous. I feel like overloading depends_on is a better place. If you need the projects executed in a particular order, that implies dependency.

I can see needing only "ordering" vs a "hard fail" like dependencies. How difficult would it be to add a key somewhat like:

version: 3
    projects:
    - dir: .
      name: project-2
      depends_on: 
           softFail: false
           projects: [project-1]

Thoughts?

@@ -31,6 +31,7 @@ type Project struct {
PlanRequirements []string `yaml:"plan_requirements,omitempty"`
ApplyRequirements []string `yaml:"apply_requirements,omitempty"`
ImportRequirements []string `yaml:"import_requirements,omitempty"`
Dependencies []string `yaml:"depends_on,omitempty"`
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nitpick: Can we follow the annotation style and rename the variable to DependsOn

@@ -72,12 +73,17 @@ func (p Project) Validate() error {
return errors.Wrapf(err, "parsing: %s", branch)
}

Dependencies := func(value interface{}) error {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nitpick: Can we follow the annotation style and rename the variable to DependsOn

return validation.ValidateStruct(&p,
validation.Field(&p.Dir, validation.Required, validation.By(hasDotDot)),
validation.Field(&p.PlanRequirements, validation.By(validPlanReq)),
validation.Field(&p.ApplyRequirements, validation.By(validApplyReq)),
validation.Field(&p.ImportRequirements, validation.By(validImportReq)),
validation.Field(&p.TerraformVersion, validation.By(VersionValidator)),
validation.Field(&p.Dependencies, validation.By(Dependencies)),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nitpick: Can we follow the annotation style and rename the variable to DependsOn

@@ -121,6 +127,8 @@ func (p Project) ToValid() valid.Project {

v.Name = p.Name

v.Dependencies = p.Dependencies
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nitpick: Can we follow the annotation style and rename the variable to DependsOn

@@ -88,6 +85,7 @@ type MergedProjectCfg struct {
ImportRequirements []string
Workflow Workflow
AllowedWorkflows []string
Dependencies []string
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rename to DependsOn

server/core/config/valid/global_cfg.go Show resolved Hide resolved
@@ -129,6 +129,7 @@ type Project struct {
PlanRequirements []string
ApplyRequirements []string
ImportRequirements []string
Dependencies []string
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rename to DependsOn

// Atlantis uses this information to valid the apply
// orders and to warn the user if they're applying a project that
// depends on other projects.
Dependencies []string
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rename to DependsOn

},
},
wantFailure: "Can't apply your project unless you apply its dependencies: [project2]",
wantErr: assert.NoError,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nitpick: Tests are good so far, can we include some more scenarios that include 3 projects to make sure Atlantis doesn't continue past the 2nd project?

Project 1: success
Project 2: fail
Project 3: skipped

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Luay-Sol - re: the bug you were struggling with, is there a test case in here that ensures no regressions against that bug? (in case I change the depends_on code)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oh, so the bug was related to missing

&& project.Status != models.PlannedNoChangesPlanStatus

to break the dependency chain, and I see above you already added a test case for this 🎉

@@ -65,6 +67,20 @@ func (a *DefaultCommandRequirementHandler) ValidateApplyProject(repoDir string,
return "", nil
}

func (a *DefaultCommandRequirementHandler) ValidateProjectDependencies(ctx command.ProjectContext) (failure string, err error) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Dependencies makes sense here for the function name. I know I mentioned renaming some of the variables to DependsOn. I'm not going to nit pick on every single one, just use good judgment on which ones make sense to change.

@nitrocode
Copy link
Member

@GenPage

I envision we can deprecate execution_order_group after this

From @Luay-Sol 's above comment, it seems like we can use both execution order group and depends_on together, no?

@Luay-Sol
Copy link
Contributor Author

Great work. Thank you for your contribution. Please address nitpick comments. I envision we can deprecate execution_order_group after this. It's a bit ambiguous. I feel like overloading depends_on is a better place. If you need the projects executed in a particular order, that implies dependency.

I can see needing only "ordering" vs a "hard fail" like dependencies. How difficult would it be to add a key somewhat like:

version: 3
    projects:
    - dir: .
      name: project-2
      depends_on: 
           softFail: false
           projects: [project-1]

Thoughts?

Thanks for your feedback @GenPage. For your first point about deprecating execution_order_group, I agree and I think in the next iteration we can beef up depends_on and have it handle both cases (explicit project/workspace apply & global apply).

For your second point, It is not complicated to add such a key. However, I would like to better understand the use case. I am trying to figure out when a softfail will be used. If it is just to prevent failure, maybe not define any dependencies to the project.

Thanks.

@Luay-Sol
Copy link
Contributor Author

@GenPage

I envision we can deprecate execution_order_group after this

From @Luay-Sol 's above comment, it seems like we can use both execution order group and depends_on together, no?

@nitrocode While it is true there's no issue with having both, I see merit points to merging the two. At the moment it is confusing to have 2 features that fundamentally try to do the same thing, i.e create an execution order, but each one handles a different use case, explicit project/workspace apply vs global apply.

The way I envision this is if we get the depend_on to do both, it will be much simpler for the user, to define it only once.

@nitrocode
Copy link
Member

ah ok, ty for the clarification.

@jamengual
Copy link
Contributor

For your second point, It is not complicated to add such a key. However, I would like to better understand the use case. I am trying to figure out when a softfail will be used. If it is just to prevent failure, maybe not define any dependencies to the project.

I think @GenPage is referring to this PR use case? #3323

@GenPage
Copy link
Member

GenPage commented Apr 20, 2023

Thanks for your feedback @GenPage. For your first point about deprecating execution_order_group, I agree and I think in the next iteration we can beef up depends_on and have it handle both cases (explicit project/workspace apply & global apply).

@Luay-Sol Sounds good.

For your second point, It is not complicated to add such a key. However, I would like to better understand the use case. I am trying to figure out when a softfail will be used. If it is just to prevent failure, maybe not define any dependencies to the project.

The idea is you would still get ordering, but the project doesn't stop the continuation of dependency execution. If we were to deprecate execution_order_group that functionality that provides an ordered run without stopping would be gone.

e.g. "Hey, I want to execute in this order but I don't care if this project fails to apply, I want to rest of the dependencies to run"

We can address that in a separate PR, where-as this PR just adds depends_on

@GenPage GenPage added this to the v0.24.0 milestone May 6, 2023
@GenPage
Copy link
Member

GenPage commented May 6, 2023

@Luay-Sol Any update on addressing some of the code comments?

@GenPage GenPage added the waiting-on-response Waiting for a response from the user label May 6, 2023
@Luay-Sol
Copy link
Contributor Author

Luay-Sol commented May 6, 2023

@Luay-Sol Any update on addressing some of the code comments?

@GenPage I will be getting back to this PR soon.

@GenPage GenPage added work-in-progress and removed waiting-on-response Waiting for a response from the user labels May 15, 2023
@GenPage GenPage modified the milestones: v0.24.0, v0.25.0 May 15, 2023
@Luay-Sol
Copy link
Contributor Author

@jamengual @GenPage @vincentgna can I get final review on this? Anything else needed from me or I can do to get it out? Thanks.

@jamengual jamengual added waiting-on-review Waiting for a review from a maintainer and removed waiting-on-response Waiting for a response from the user labels Nov 15, 2023
@jamengual jamengual modified the milestones: v0.25.0, v0.26.0 Nov 15, 2023
@GenPage GenPage modified the milestones: v0.26.0, v0.27.0 Dec 11, 2023
GenPage
GenPage previously approved these changes Dec 11, 2023
Copy link
Member

@GenPage GenPage left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Luay-Sol Excellent work, thank you for taking the time to contribute this.

@GenPage GenPage self-assigned this Dec 11, 2023
@GenPage
Copy link
Member

GenPage commented Dec 11, 2023

@Luay-Sol Are you able to resolve the merge conflicts locally? We cannot resolve them via the web UI. Can you rebase from the Atlantis main branch please?

@GenPage GenPage added waiting-on-response Waiting for a response from the user feature New functionality/enhancement and removed waiting-on-review Waiting for a review from a maintainer work-in-progress labels Dec 11, 2023
jamengual
jamengual previously approved these changes Dec 11, 2023
@Luay-Sol Luay-Sol dismissed stale reviews from jamengual and GenPage via 3ea3bc9 December 11, 2023 20:14
@jamengual jamengual merged commit f79ece8 into runatlantis:main Dec 11, 2023
24 checks passed
@glasser
Copy link
Contributor

glasser commented Dec 12, 2023

Hi, just to check my understanding — in earlier discussions on this PR, the idea that this replaces execution_order_group is discussed. In the actual version merged, depends_on only adds potential validation errors and does not affect ordering when you run plan or apply without a specific subdirectory, right? So likely folks will want to use them in conjunction with each other?

@Luay-Sol
Copy link
Contributor Author

Hi, just to check my understanding — in earlier discussions on this PR, the idea that this replaces execution_order_group is discussed. In the actual version merged, depends_on only adds potential validation errors and does not affect ordering when you run plan or apply without a specific subdirectory, right? So likely folks will want to use them in conjunction with each other?

@glasser yes, you understood it correctly. Here's an example of how I use it:

projects:
  - name: development
    dir: .
    autoplan:
      when_modified: ["*.tf", "vars/development.tfvars"]
    execution_order_group: 1
    workspace: development
    workflow: infra
  - name: rc
    dir: .
    autoplan:
      when_modified: ["*.tf", "vars/rc.tfvars"]
    depends_on: ["development"]
    execution_order_group: 2    
    workspace: stability-test
    workflow: infra
  - name: staging
    dir: .
    autoplan:
      when_modified: ["*.tf", "vars/staging.tfvars"]
    depends_on: ["rc"]
    execution_order_group: 3
    workspace: staging
    workflow: infra 
    ```

ijames-gc pushed a commit to gocardless/atlantis that referenced this pull request Feb 13, 2024
* feat: implemented the code for the depends on functionality

Co-authored-by: Vincent <106497818+vincentgna@users.noreply.github.com>
ijames-gc pushed a commit to gocardless/atlantis that referenced this pull request Feb 13, 2024
* feat: implemented the code for the depends on functionality

Co-authored-by: Vincent <106497818+vincentgna@users.noreply.github.com>
vincentgna added a commit to vincentgna/atlantis that referenced this pull request Feb 20, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
docs Documentation feature New functionality/enhancement go Pull requests that update Go code waiting-on-response Waiting for a response from the user
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

6 participants