Skip to content

Conversation

oycyc
Copy link
Contributor

@oycyc oycyc commented Jul 24, 2025

what

  • Add support for nested directories.
image

why

When it comes to monorepos, if root modules are on the thinner side of things, it would easy to rack up a bunch of root module directories and can look messy. This is useful if a monorepo wants to be organized in directories, such as teams/service oriented

  • This is backward compatible. None of the existing tests has been modified and it passes. We all say it multiple times, but really appreciate the amount of coverage it has so I feel safe and validated it is not breaking.
  • There are new tests to cover this new case too.

Lots of new lines of code, but mostly just tests!

references

I've dogfooded this in our mp-infra internal Spacelift account. Existing stacks are not impacted, and new stacks are created based on the new structure.

image image

Summary by CodeRabbit

  • New Features

    • Added support for discovering stack configuration files and root modules in nested directory structures, improving flexibility for organizing stacks.
    • Introduced new test cases to validate nested directory handling, including multi-instance and single-instance scenarios, deep nesting, and filtering of .terraform directories.
  • Bug Fixes

    • Improved filtering to exclude files from .terraform directories, preventing unintended stack discovery.
  • Tests

    • Expanded test coverage to ensure correct stack discovery, project root extraction, and label assignment in nested and deeply nested directories.
    • Updated schema validation tests to account for the increased number of valid stack configurations.

@oycyc oycyc requested a review from a team as a code owner July 24, 2025 22:43
@oycyc oycyc requested a review from westonplatter July 24, 2025 22:43
@oycyc oycyc changed the title Feat/support nested directories feat: support nested directories Jul 24, 2025
@oycyc oycyc changed the title feat: support nested directories feat: support root module nested directories Jul 24, 2025
Copy link
Contributor

coderabbitai bot commented Jul 24, 2025

Walkthrough

This update enhances the handling of stack YAML files and root module discovery within the Terraform configuration, enabling support for nested directories. The logic for identifying stack files is expanded to recursively search for both MultiInstance and SingleInstance stacks, while filtering out files from .terraform directories. The extraction of root module names is adjusted to accurately reflect nested directory structures. New test fixtures and a comprehensive test suite are introduced to validate these changes, including scenarios for nested and deeply nested directories, and to ensure proper filtering and discovery. The schema validation test is updated to account for the increased number of valid stack configurations.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~18 minutes

Suggested reviewers

  • Gowiem

Note

⚡️ Unit Test Generation is now available in beta!

Learn more here, or try it out under "Finishing Touches" below.

✨ Finishing Touches
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/support-nested-directories

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai generate unit tests to generate unit tests for this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (8)
main.tf (3)

34-57: Comment block contains copy-paste duplication
Lines 49-56 repeat the earlier example block almost verbatim. Trimming this will keep the file shorter and easier to scan.


64-70: Prefer simple contains() over can(regex()) for path filtering
!can(regex("\\.terraform/", file)) works but is harder to read and invokes the regex engine for every file. A straight string check is both clearer and faster:

-_multi_instance_stack_files  = [for file in local._multi_instance_stack_files_raw : file if !can(regex("\\.terraform/", file))]
-_single_instance_stack_files = [for file in local._single_instance_stack_files_raw : file if !can(regex("\\.terraform/", file))]
+_multi_instance_stack_files  = [for file in local._multi_instance_stack_files_raw : file if !contains(file, "/.terraform/")]
+_single_instance_stack_files = [for file in local._single_instance_stack_files_raw : file if !contains(file, "/.terraform/")]

Less cognitive load, same behaviour.


74-80: Path derivation logic is correct but consider a helper for clarity
The paired dirname() / dirname(dirname()) expressions work yet obscure intent. Extracting this into a small helper local (e.g., _root_module_from_stack_path) would make the distinction between structures self-documenting and avoid double-calling dirname.

tests/schema-validation.tftest.hcl (1)

11-11: Hard-coded count may require frequent updates
As the fixture set grows, this equality assertion will need manual tweaks (now 5 → 8). Consider asserting > 0 or comparing against a computed expected count to reduce churn.

tests/fixtures/nested-multi-instance/parent/nested/stacks/prod.yaml (1)

4-5: Prefer hyphens over underscores in labels

Existing stack labels elsewhere in the repo use kebab-case (foo-bar) rather than snake_case (foo_bar). Staying consistent avoids surprises when filtering or querying by label.

-    - nested_prod_label
+    - nested-prod-label
tests/fixtures/nested-single-instance/parent/nested/stack.yaml (1)

4-5: Align label casing with project convention

See previous comment – use hyphens for consistency.

-    - nested_single_label
+    - nested-single-label
tests/nested-directories.tftest.hcl (2)

13-16: Path literals are duplicated – factor into a local

The path "./tests/fixtures/nested-multi-instance" is reused in multiple runs. Extracting it to a locals {} block at the top keeps future updates in one place and reduces the chance of divergence.
Example:

locals {
  nested_multi_fixture = "./tests/fixtures/nested-multi-instance"
}

# then
root_modules_path = local.nested_multi_fixture

119-135: Minor: pre-compile regex for clarity

The same "\.terraform" pattern is evaluated twice. Define once and reference:

locals {
  dot_terraform = "\\.terraform"
}

!can(regex(local.dot_terraform, stack_name))

Purely cosmetic, but it tightens the assertions and aids readability.

📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between cb241fe and 9a309ba.

📒 Files selected for processing (8)
  • main.tf (2 hunks)
  • tests/fixtures/nested-multi-instance/parent/nested/stacks/dev.yaml (1 hunks)
  • tests/fixtures/nested-multi-instance/parent/nested/stacks/prod.yaml (1 hunks)
  • tests/fixtures/nested-multi-instance/parent/nested/tfvars/dev.tfvars (1 hunks)
  • tests/fixtures/nested-multi-instance/parent/nested/tfvars/prod.tfvars (1 hunks)
  • tests/fixtures/nested-single-instance/parent/nested/stack.yaml (1 hunks)
  • tests/nested-directories.tftest.hcl (1 hunks)
  • tests/schema-validation.tftest.hcl (1 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
**/*.tf

⚙️ CodeRabbit Configuration File

**/*.tf: You're a Terraform expert who has thoroughly studied all the documentation from Hashicorp https://developer.hashicorp.com/terraform/docs and OpenTofu https://opentofu.org/docs/.
You have a strong grasp of Terraform syntax and prioritize providing accurate and insightful code suggestions.
As a fan of the Cloud Posse / SweetOps ecosystem, you incorporate many of their best practices https://docs.cloudposse.com/best-practices/terraform/ while balancing them with general Terraform guidelines.

Files:

  • main.tf
🧠 Learnings (7)
📓 Common learnings
Learnt from: gberenice
PR: masterpointio/terraform-spacelift-automation#3
File: modules/spacelift-automation/main.tf:224-230
Timestamp: 2024-10-29T17:52:31.823Z
Learning: In the `masterpointio/terraform-spacelift-automation` repository, the `context.tf` file is a mixin file that we don't own. Do not make suggestions or comments on `context.tf` in future reviews.
Learnt from: Gowiem
PR: masterpointio/terraform-spacelift-automation#3
File: main.tf:56-59
Timestamp: 2024-10-30T17:04:09.798Z
Learning: In this module, `path.root` is intentionally used instead of `path.module` when constructing file paths, as it refers to the root path of the calling module, which is necessary for correctly locating the stack YAML files.
Learnt from: oycyc
PR: masterpointio/terraform-aws-ssm-agent#28
File: tests/main.tftest.hcl:27-28
Timestamp: 2024-10-23T14:10:29.597Z
Learning: In Terraform test files (e.g., `tests/main.tftest.hcl`), module outputs can be accessed without assigning an explicit name to the module.
Learnt from: Gowiem
PR: masterpointio/terraform-spacelift-automation#3
File: main.tf:280-293
Timestamp: 2024-10-31T20:47:29.322Z
Learning: In Terraform configurations, when working with the `spacelift_stack_destructor` resource, the existing `depends_on` block is valid and should not be modified with `try()` expressions. Avoid suggesting updates to the `depends_on` block in this context.
Learnt from: gberenice
PR: masterpointio/terraform-users-groups-automation-googleworkspace#1
File: examples/import-existing-org/imports.tf:7-7
Timestamp: 2025-05-12T15:44:10.001Z
Learning: In Terraform, local variables defined in one .tf file are available throughout all other .tf files in the same module directory, which allows for referencing locals across different files.
Learnt from: gberenice
PR: masterpointio/terraform-users-groups-automation-googleworkspace#1
File: examples/import-existing-org/imports.tf:7-7
Timestamp: 2025-05-12T15:44:10.001Z
Learning: In Terraform, local variables defined in one .tf file are available throughout all other .tf files in the same module directory, which allows for referencing locals across different files.
Learnt from: gberenice
PR: masterpointio/terraform-spacelift-aws-integrations#2
File: main.tf:2-8
Timestamp: 2024-11-18T12:59:36.156Z
Learning: In this Terraform configuration, `module.this` is defined in `context.tf`.
Learnt from: oycyc
PR: masterpointio/masterpoint.io#68
File: layouts/partials/head.html:0-0
Timestamp: 2025-07-02T01:48:08.985Z
Learning: In the masterpointio/masterpoint.io Hugo project, the user oycyc prefers to maintain consistency with existing code patterns rather than making isolated optimizations, even when technically better approaches are available. They prioritize consistency over over-optimization.
tests/schema-validation.tftest.hcl (3)

Learnt from: oycyc
PR: masterpointio/terraform-aws-ssm-agent#28
File: tests/cpu-compatibility.tftest.hcl:1-11
Timestamp: 2024-10-23T14:10:26.952Z
Learning: In tests/cpu-compatibility.tftest.hcl, the variables block contains mock values intended for testing purposes.

Learnt from: Gowiem
PR: masterpointio/terraform-aws-ssm-agent#28
File: tests/main.tftest.hcl:14-46
Timestamp: 2024-11-07T21:31:09.849Z
Learning: In tftest.hcl files, export_outputs is not a valid attribute within a run block.

Learnt from: oycyc
PR: masterpointio/terraform-aws-ssm-agent#28
File: tests/unit.tftest.hcl:34-71
Timestamp: 2024-10-23T18:20:57.022Z
Learning: In the terraform-aws-ssm-agent module, the user prefers not to include additional assertions for network and security configurations (e.g., root volume encryption, network interface configurations, and security group associations) in the verify_launch_template unit test in tests/unit.tftest.hcl.

tests/fixtures/nested-multi-instance/parent/nested/tfvars/dev.tfvars (10)

Learnt from: gberenice
PR: masterpointio/terraform-users-groups-automation-googleworkspace#1
File: examples/import-existing-org/imports.tf:7-7
Timestamp: 2025-05-12T15:44:10.001Z
Learning: In Terraform, local variables defined in one .tf file are available throughout all other .tf files in the same module directory, which allows for referencing locals across different files.

Learnt from: gberenice
PR: masterpointio/terraform-users-groups-automation-googleworkspace#1
File: examples/import-existing-org/imports.tf:7-7
Timestamp: 2025-05-12T15:44:10.001Z
Learning: In Terraform, local variables defined in one .tf file are available throughout all other .tf files in the same module directory, which allows for referencing locals across different files.

Learnt from: gberenice
PR: #3
File: modules/spacelift-automation/main.tf:224-230
Timestamp: 2024-10-29T17:52:31.823Z
Learning: In the masterpointio/terraform-spacelift-automation repository, the context.tf file is a mixin file that we don't own. Do not make suggestions or comments on context.tf in future reviews.

Learnt from: gberenice
PR: #3
File: modules/spacelift-automation/variables.tf:0-0
Timestamp: 2024-10-30T17:11:38.812Z
Learning: In the Terraform module's variables.tf file, the variable autodeploy defaulting to true is acceptable since it matches the default provider value.

Learnt from: gberenice
PR: masterpointio/terraform-spacelift-aws-integrations#2
File: main.tf:2-8
Timestamp: 2024-11-18T12:59:36.156Z
Learning: In this Terraform configuration, module.this is defined in context.tf.

Learnt from: gberenice
PR: masterpointio/infra-monorepo-template#1
File: root-module/main.tf:25-31
Timestamp: 2024-12-11T17:35:43.671Z
Learning: In the client-tf-templates repository, the module masterpointio/random/pet used in root-module/main.tf is a dummy example and may not exist in the Terraform Registry. This is intentional and should not be flagged as an error in future reviews.

Learnt from: oycyc
PR: masterpointio/terraform-aws-ssm-agent#28
File: tests/main.tftest.hcl:27-28
Timestamp: 2024-10-23T14:10:29.597Z
Learning: In Terraform test files (e.g., tests/main.tftest.hcl), module outputs can be accessed without assigning an explicit name to the module.

Learnt from: gberenice
PR: #3
File: modules/spacelift-automation/variables.tf:0-0
Timestamp: 2024-10-30T16:46:36.813Z
Learning: For the variable terraform_smart_sanitization in variables.tf, prefer to keep the default value as false.

Learnt from: gberenice
PR: masterpointio/terraform-aws-tailscale#41
File: variables.tf:100-116
Timestamp: 2024-11-17T14:41:46.190Z
Learning: In Terraform, variable validation blocks can only reference the variable being validated and cannot reference other variables.

Learnt from: Gowiem
PR: #3
File: modules/spacelift-automation/main.tf:221-227
Timestamp: 2024-10-29T00:06:05.693Z
Learning: In the Terraform module modules/spacelift-automation/main.tf, when var.aws_integration_id is a required variable, avoid suggesting to make the spacelift_aws_integration_attachment resource conditional based on whether aws_integration_id is provided.

tests/fixtures/nested-single-instance/parent/nested/stack.yaml (2)

Learnt from: Gowiem
PR: #3
File: main.tf:231-257
Timestamp: 2024-10-30T17:01:23.897Z
Learning: In main.tf, grouping related attributes in the spacelift_stack resource using locals may overcomplicate things and remove important logic elsewhere; prefer to keep attributes as is.

Learnt from: Gowiem
PR: #3
File: main.tf:56-59
Timestamp: 2024-10-30T17:04:09.798Z
Learning: In this module, path.root is intentionally used instead of path.module when constructing file paths, as it refers to the root path of the calling module, which is necessary for correctly locating the stack YAML files.

tests/fixtures/nested-multi-instance/parent/nested/tfvars/prod.tfvars (10)

Learnt from: gberenice
PR: masterpointio/terraform-users-groups-automation-googleworkspace#1
File: examples/import-existing-org/imports.tf:7-7
Timestamp: 2025-05-12T15:44:10.001Z
Learning: In Terraform, local variables defined in one .tf file are available throughout all other .tf files in the same module directory, which allows for referencing locals across different files.

Learnt from: gberenice
PR: masterpointio/terraform-users-groups-automation-googleworkspace#1
File: examples/import-existing-org/imports.tf:7-7
Timestamp: 2025-05-12T15:44:10.001Z
Learning: In Terraform, local variables defined in one .tf file are available throughout all other .tf files in the same module directory, which allows for referencing locals across different files.

Learnt from: gberenice
PR: #3
File: modules/spacelift-automation/variables.tf:0-0
Timestamp: 2024-10-30T17:11:38.812Z
Learning: In the Terraform module's variables.tf file, the variable autodeploy defaulting to true is acceptable since it matches the default provider value.

Learnt from: gberenice
PR: #3
File: modules/spacelift-automation/main.tf:224-230
Timestamp: 2024-10-29T17:52:31.823Z
Learning: In the masterpointio/terraform-spacelift-automation repository, the context.tf file is a mixin file that we don't own. Do not make suggestions or comments on context.tf in future reviews.

Learnt from: gberenice
PR: masterpointio/terraform-spacelift-aws-integrations#2
File: main.tf:2-8
Timestamp: 2024-11-18T12:59:36.156Z
Learning: In this Terraform configuration, module.this is defined in context.tf.

Learnt from: gberenice
PR: masterpointio/infra-monorepo-template#1
File: root-module/main.tf:25-31
Timestamp: 2024-12-11T17:35:43.671Z
Learning: In the client-tf-templates repository, the module masterpointio/random/pet used in root-module/main.tf is a dummy example and may not exist in the Terraform Registry. This is intentional and should not be flagged as an error in future reviews.

Learnt from: oycyc
PR: masterpointio/terraform-aws-ssm-agent#28
File: tests/main.tftest.hcl:27-28
Timestamp: 2024-10-23T14:10:29.597Z
Learning: In Terraform test files (e.g., tests/main.tftest.hcl), module outputs can be accessed without assigning an explicit name to the module.

Learnt from: Gowiem
PR: #3
File: modules/spacelift-automation/main.tf:221-227
Timestamp: 2024-10-29T00:06:05.693Z
Learning: In the Terraform module modules/spacelift-automation/main.tf, when var.aws_integration_id is a required variable, avoid suggesting to make the spacelift_aws_integration_attachment resource conditional based on whether aws_integration_id is provided.

Learnt from: gberenice
PR: #3
File: modules/spacelift-automation/variables.tf:0-0
Timestamp: 2024-10-30T16:46:36.813Z
Learning: For the variable terraform_smart_sanitization in variables.tf, prefer to keep the default value as false.

Learnt from: gberenice
PR: masterpointio/terraform-aws-tailscale#41
File: variables.tf:100-116
Timestamp: 2024-11-17T14:41:46.190Z
Learning: In Terraform, variable validation blocks can only reference the variable being validated and cannot reference other variables.

main.tf (9)

Learnt from: Gowiem
PR: #3
File: main.tf:56-59
Timestamp: 2024-10-30T17:04:09.798Z
Learning: In this module, path.root is intentionally used instead of path.module when constructing file paths, as it refers to the root path of the calling module, which is necessary for correctly locating the stack YAML files.

Learnt from: Gowiem
PR: #3
File: main.tf:231-257
Timestamp: 2024-10-30T17:01:23.897Z
Learning: In main.tf, grouping related attributes in the spacelift_stack resource using locals may overcomplicate things and remove important logic elsewhere; prefer to keep attributes as is.

Learnt from: gberenice
PR: masterpointio/terraform-users-groups-automation-googleworkspace#1
File: examples/import-existing-org/imports.tf:7-7
Timestamp: 2025-05-12T15:44:10.001Z
Learning: In Terraform, local variables defined in one .tf file are available throughout all other .tf files in the same module directory, which allows for referencing locals across different files.

Learnt from: gberenice
PR: masterpointio/terraform-users-groups-automation-googleworkspace#1
File: examples/import-existing-org/imports.tf:7-7
Timestamp: 2025-05-12T15:44:10.001Z
Learning: In Terraform, local variables defined in one .tf file are available throughout all other .tf files in the same module directory, which allows for referencing locals across different files.

Learnt from: gberenice
PR: #3
File: modules/spacelift-automation/main.tf:224-230
Timestamp: 2024-10-29T17:52:31.823Z
Learning: In the masterpointio/terraform-spacelift-automation repository, the context.tf file is a mixin file that we don't own. Do not make suggestions or comments on context.tf in future reviews.

Learnt from: gberenice
PR: masterpointio/terraform-spacelift-aws-integrations#2
File: main.tf:2-8
Timestamp: 2024-11-18T12:59:36.156Z
Learning: In this Terraform configuration, module.this is defined in context.tf.

Learnt from: Gowiem
PR: #3
File: modules/spacelift-automation/main.tf:215-218
Timestamp: 2024-10-29T00:05:59.989Z
Learning: In the modules/spacelift-automation/main.tf file, it's valid to directly reference resource collections created with for_each in the depends_on attribute. For example, in the spacelift_stack_destructor resource, referencing spacelift_drift_detection.this and spacelift_aws_integration_attachment.this directly is acceptable and should not be flagged.

Learnt from: gberenice
PR: masterpointio/infra-monorepo-template#1
File: root-module/main.tf:25-31
Timestamp: 2024-12-11T17:35:43.671Z
Learning: In the client-tf-templates repository, the module masterpointio/random/pet used in root-module/main.tf is a dummy example and may not exist in the Terraform Registry. This is intentional and should not be flagged as an error in future reviews.

Learnt from: oycyc
PR: masterpointio/terraform-aws-ssm-agent#28
File: tests/main.tftest.hcl:27-28
Timestamp: 2024-10-23T14:10:29.597Z
Learning: In Terraform test files (e.g., tests/main.tftest.hcl), module outputs can be accessed without assigning an explicit name to the module.

tests/nested-directories.tftest.hcl (12)

Learnt from: oycyc
PR: masterpointio/terraform-aws-ssm-agent#28
File: tests/main.tftest.hcl:27-28
Timestamp: 2024-10-23T14:10:29.597Z
Learning: In Terraform test files (e.g., tests/main.tftest.hcl), module outputs can be accessed without assigning an explicit name to the module.

Learnt from: oycyc
PR: masterpointio/terraform-aws-ssm-agent#28
File: tests/unit.tftest.hcl:34-71
Timestamp: 2024-10-23T18:20:57.022Z
Learning: In the terraform-aws-ssm-agent module, the user prefers not to include additional assertions for network and security configurations (e.g., root volume encryption, network interface configurations, and security group associations) in the verify_launch_template unit test in tests/unit.tftest.hcl.

Learnt from: Gowiem
PR: #3
File: main.tf:231-257
Timestamp: 2024-10-30T17:01:23.897Z
Learning: In main.tf, grouping related attributes in the spacelift_stack resource using locals may overcomplicate things and remove important logic elsewhere; prefer to keep attributes as is.

Learnt from: gberenice
PR: #3
File: modules/spacelift-automation/main.tf:224-230
Timestamp: 2024-10-29T17:52:31.823Z
Learning: In the masterpointio/terraform-spacelift-automation repository, the context.tf file is a mixin file that we don't own. Do not make suggestions or comments on context.tf in future reviews.

Learnt from: Gowiem
PR: masterpointio/terraform-aws-ssm-agent#28
File: tests/main.tftest.hcl:14-46
Timestamp: 2024-11-07T21:31:09.849Z
Learning: In tftest.hcl files, export_outputs is not a valid attribute within a run block.

Learnt from: oycyc
PR: masterpointio/terraform-aws-ssm-agent#28
File: tests/cpu-compatibility.tftest.hcl:1-11
Timestamp: 2024-10-23T14:10:26.952Z
Learning: In tests/cpu-compatibility.tftest.hcl, the variables block contains mock values intended for testing purposes.

Learnt from: gberenice
PR: masterpointio/terraform-spacelift-aws-integrations#2
File: main.tf:2-8
Timestamp: 2024-11-18T12:59:36.156Z
Learning: In this Terraform configuration, module.this is defined in context.tf.

Learnt from: Gowiem
PR: #3
File: modules/spacelift-automation/main.tf:215-218
Timestamp: 2024-10-29T00:05:59.989Z
Learning: In the modules/spacelift-automation/main.tf file, it's valid to directly reference resource collections created with for_each in the depends_on attribute. For example, in the spacelift_stack_destructor resource, referencing spacelift_drift_detection.this and spacelift_aws_integration_attachment.this directly is acceptable and should not be flagged.

Learnt from: gberenice
PR: masterpointio/terraform-users-groups-automation-googleworkspace#1
File: examples/import-existing-org/imports.tf:7-7
Timestamp: 2025-05-12T15:44:10.001Z
Learning: In Terraform, local variables defined in one .tf file are available throughout all other .tf files in the same module directory, which allows for referencing locals across different files.

Learnt from: gberenice
PR: masterpointio/terraform-users-groups-automation-googleworkspace#1
File: examples/import-existing-org/imports.tf:7-7
Timestamp: 2025-05-12T15:44:10.001Z
Learning: In Terraform, local variables defined in one .tf file are available throughout all other .tf files in the same module directory, which allows for referencing locals across different files.

Learnt from: gberenice
PR: masterpointio/infra-monorepo-template#1
File: root-module/main.tf:25-31
Timestamp: 2024-12-11T17:35:43.671Z
Learning: In the client-tf-templates repository, the module masterpointio/random/pet used in root-module/main.tf is a dummy example and may not exist in the Terraform Registry. This is intentional and should not be flagged as an error in future reviews.

Learnt from: Gowiem
PR: #3
File: main.tf:280-293
Timestamp: 2024-10-31T20:47:29.322Z
Learning: In Terraform configurations, when working with the spacelift_stack_destructor resource, the existing depends_on block is valid and should not be modified with try() expressions. Avoid suggesting updates to the depends_on block in this context.

🔇 Additional comments (4)
tests/fixtures/nested-multi-instance/parent/nested/stacks/dev.yaml (1)

1-7: YAML looks solid – no issues spotted
Schema keys are correct, values sensible, and nothing sensitive is exposed.

tests/fixtures/nested-multi-instance/parent/nested/tfvars/dev.tfvars (1)

1-2: Variables file is concise and valid
Nothing to change here.

tests/fixtures/nested-multi-instance/parent/nested/tfvars/prod.tfvars (1)

1-2: Looks good – mirrors the dev tfvars appropriately
Values are environment-specific and syntactically correct.

tests/nested-directories.tftest.hcl (1)

165-169: all_root_modules_enabled overrides enabled_root_modules

Setting all_root_modules_enabled = true means every root module under root_modules_path is brought in, so the explicit enabled_root_modules list is ignored. If the intent is to test selective enablement, flip the boolean:

-    all_root_modules_enabled = true
+    all_root_modules_enabled = false

Otherwise, drop enabled_root_modules to avoid confusion.

Copy link
Member

@gberenice gberenice left a comment

Choose a reason for hiding this comment

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

One suggestion.
Love the tests 💯

@oycyc oycyc merged commit 78b675b into main Aug 1, 2025
5 checks passed
@oycyc oycyc deleted the feat/support-nested-directories branch August 1, 2025 14:07
oycyc pushed a commit that referenced this pull request Aug 5, 2025
🤖 I have created a release *beep* *boop*
---


##
[1.5.0](v1.4.0...v1.5.0)
(2025-08-01)


### Features

* support root module nested directories
([#80](#80))
([78b675b](78b675b))

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).

Co-authored-by: masterpointbot[bot] <177651640+masterpointbot[bot]@users.noreply.github.com>
br3ndonland added a commit to br3ndonland/masterpointio-terraform-spacelift-automation that referenced this pull request Aug 21, 2025
By default, this module assumes all stacks are in the same repo as the
stack with the module instance.

What if users want to use this module to manage stacks in _another
repo_? We had this use case and came up with a "remote stacks" approach.

It would be great to document this approach for other users.

This PR will document the remote stacks approach in the README. The
example looks like this:

```text
this-repo
├── remote-stacks
│   └── other-repo
│       └── other-repo-random-pet
│           └── stack.yaml
└── stacks
    └── spacelift-automation
        ├── main.tf
        ├── stack.yaml
        └── versions.tofu
```

```yaml
# this-repo/remote-stacks/other-repo/other-repo-random-pet/stack.yaml
stack_settings:
  project_root: stacks/random-pet
```

```text
other-repo
└── stacks
    └── random-pet
        ├── main.tf
        └── versions.tofu
```

Note that the README recommends that the remote stacks directory should
_not_ be nested inside of another stack. This is because of the changes
to globbing behavior introduced in masterpointio#80 and module v1.5.0. The new
behavior introduced some unexpected changes for our repo because we had
a remote stacks directory nested inside our stacks directory, like this
basically:

```hcl
# this-repo/app/stacks/spacelift-automation/main.tf
module "spacelift_automation_for_stacks_in_this_repo" {
  source = "git::https://github.com/masterpointio/terraform-spacelift-automation.git"

  all_root_modules_enabled = true
  repository               = "this-repo"
  root_module_structure    = "SingleInstance"
  root_modules_path        = "../../../app/stacks"
}

module "spacelift_automation_for_stacks_in_other_repo" {
  source = "git::https://github.com/masterpointio/terraform-spacelift-automation.git"

  all_root_modules_enabled = true
  repository               = "other-repo"
  root_module_structure    = "SingleInstance"
  root_modules_path        = "../../../app/stacks/spacelift-automation/remote-stacks/other-repo"
}
```

After updating to module v1.5.0, the `spacelift_automation_this_repo`
module instance started picking up the `stack.yaml` files in the nested
`remote-stacks` subdirectory.

The easiest solution is just to not nest the remote stacks dir. Another
solution is to set `all_root_modules_enabled = false` and then add the
stacks in the repo to `enabled_root_modules`. This of course means that
new stacks added to `app/stacks/new-stack-name/stack.yaml` have to be
added to `enabled_root_modules` to be detected.

```hcl
# this-repo/app/stacks/spacelift-automation/main.tf
module "spacelift_automation_for_stacks_in_this_repo" {
  source = "git::https://github.com/masterpointio/terraform-spacelift-automation.git"

  all_root_modules_enabled = false
  enabled_root_modules = [
    "development",
    "production",
    "spacelift-automation",
  ]
  repository            = "this-repo"
  root_module_structure = "SingleInstance"
  root_modules_path     = "../../../app/stacks"
}

module "spacelift_automation_for_stacks_in_other_repo" {
  source = "git::https://github.com/masterpointio/terraform-spacelift-automation.git"

  all_root_modules_enabled = true
  repository               = "other-repo"
  root_module_structure    = "SingleInstance"
  root_modules_path        = "../../../app/stacks/spacelift-automation/remote-stacks/other-repo"
}
```
gberenice added a commit that referenced this pull request Sep 3, 2025
## Description

By default, this module assumes all stacks are in the same repo as the
stack with the module instance.

What if the module needs to manage stacks in _another repo_? We had this
use case and developed a "remote stacks" approach. Here's @Gowiem to
explain:

<a href="https://www.loom.com/share/34d556aecb43409280bf36d0b107e968">
<img width="50%"
src="https://cdn.loom.com/sessions/thumbnails/34d556aecb43409280bf36d0b107e968-bf0eaf87465c0bfc-full-play.gif">
</a>

It would be great to document this approach for other users.

## Changes

This PR will document the remote stacks approach in the README. The
example looks like this:

```text
this-repo
├── remote-stacks
│   └── other-repo
│       └── other-repo-random-pet
│           └── stack.yaml
└── stacks
    └── spacelift-automation
        ├── main.tf
        ├── stack.yaml
        └── versions.tofu
```

```yaml
# this-repo/remote-stacks/other-repo/other-repo-random-pet/stack.yaml
stack_settings:
  project_root: stacks/random-pet
```

```text
other-repo
└── stacks
    └── random-pet
        ├── main.tf
        └── versions.tofu
```

Note that the README recommends that the remote stacks directory should
_not_ be nested inside of another stack. This is because of the changes
to globbing behavior introduced in
#80 and [module
v1.5.0](https://github.com/masterpointio/terraform-spacelift-automation/releases/tag/v1.5.0).
The new behavior introduced some unexpected changes for our repo because
we had a remote stacks directory nested inside our stacks directory,
like this basically:

```hcl
# this-repo/app/stacks/spacelift-automation/main.tf
module "spacelift_automation_for_stacks_in_this_repo" {
  source = "git::https://github.com/masterpointio/terraform-spacelift-automation.git"

  all_root_modules_enabled = true
  repository               = "this-repo"
  root_module_structure    = "SingleInstance"
  root_modules_path        = "../../../app/stacks"
}

module "spacelift_automation_for_stacks_in_other_repo" {
  source = "git::https://github.com/masterpointio/terraform-spacelift-automation.git"

  all_root_modules_enabled = true
  repository               = "other-repo"
  root_module_structure    = "SingleInstance"
  root_modules_path        = "../../../app/stacks/spacelift-automation/remote-stacks/other-repo"
}
```

After updating to module v1.5.0, the `spacelift_automation_this_repo`
module instance started picking up the `stack.yaml` files in the nested
`remote-stacks` subdirectory.

The easiest solution is just to not nest the remote stacks dir. Another
solution is to set `all_root_modules_enabled = false` and then add the
stacks in the repo to `enabled_root_modules`. This of course means that
new stacks added to `app/stacks/new-stack-name/stack.yaml` have to be
added to `enabled_root_modules` to be detected.

```hcl
# this-repo/app/stacks/spacelift-automation/main.tf
module "spacelift_automation_for_stacks_in_this_repo" {
  source = "git::https://github.com/masterpointio/terraform-spacelift-automation.git"

  all_root_modules_enabled = false
  enabled_root_modules = [
    "development",
    "production",
    "spacelift-automation",
  ]
  repository            = "this-repo"
  root_module_structure = "SingleInstance"
  root_modules_path     = "../../../app/stacks"
}

module "spacelift_automation_for_stacks_in_other_repo" {
  source = "git::https://github.com/masterpointio/terraform-spacelift-automation.git"

  all_root_modules_enabled = true
  repository               = "other-repo"
  root_module_structure    = "SingleInstance"
  root_modules_path        = "../../../app/stacks/spacelift-automation/remote-stacks/other-repo"
}
```

## Related

- #80


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

- Documentation
  - Added a section on managing stacks in a separate Git repository.
- Includes guidance on repo setup, access permissions, directory layout,
and detection caveats.
- Provides example file structures and configuration snippets for
linking local and remote stacks.
- Clarifies setting project root paths across repos and referencing
multiple root modules.
  - Notes relevant module version context.
  - No functional changes; documentation-only update.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: Matt Gowie <[email protected]>
Co-authored-by: Veronika Gnilitska <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants