feat(mixins): recurse into nested modules and only update existing copies#50
feat(mixins): recurse into nested modules and only update existing copies#50oycyc wants to merge 6 commits into
Conversation
fe1ae22 to
2bbc903
Compare
…copies Closes #47. The `mixins:update-all` task previously assumed a flat `./components/*` layout, so nested deployable instances like `aws-iam/delegated-tf-role` were never updated. It also unconditionally copied the mixin into every top-level component directory, which is wrong: a given mixin is not universally applicable (e.g. the `secrets.sops.tf` mixin only belongs in components that actually consume SOPS secrets). Copying it everywhere creates unused files that have to be deleted by hand. Changes: - Locate destinations by recursively finding existing copies of the named mixin under `./components/` (`find ... -type f -name <file>`). A component opts in to a mixin by having a copy of it on disk; this task only keeps those existing copies in sync. To adopt a mixin in a new component, copy it in manually once — that becomes the explicit opt-in and future `update-all` runs will track the template. - Recursion picks up nested instance layouts (e.g. `components/aws-iam/delegated-tf-role/<file>`) automatically. - Prune `.terraform/` and `.terragrunt-cache/` so vendored child-module copies that Terraform/Terragrunt drop on disk during init are not overwritten. - Set `dir: "{{.USER_WORKING_DIR}}"` so `./mixins/` and `./components/` resolve from where the user invoked `task`, not from the included taskfile's own directory. - Drop the `generates:` glob — it cannot express nested outputs and was causing Task to falsely treat the task as up-to-date. - Rewrite the loop to avoid `read -d ''` (not supported by Task's mvdan/sh interpreter).
The remaining precondition for `mixins:update-all` is checking the source template exists. The `./components/` directory check is unnecessary — if it's missing, `find` simply produces no matches and the task no-ops cleanly, which is the correct behavior. Removing the check also lets the task succeed in repos that haven't created a `./components/` directory yet.
📝 WalkthroughWalkthroughThis PR updates the Estimated code review effort🎯 2 (Simple) | ⏱️ ~10 minutes 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
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. Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@lib/mixins/Taskfile.yml`:
- Around line 28-29: Quote the template variable {{.CLI_ARGS}} to prevent
word-splitting for filenames with spaces: update the find invocation to use
-name "{{.CLI_ARGS}}" and quote the source path in the cp command (e.g. cp -v
"./mixins/{{.CLI_ARGS}}" "$dest"); this fixes both usages in the shown find |
while ... block that reference {{.CLI_ARGS}}.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 682cbab8-2127-415d-ac88-9d156077d0c8
📒 Files selected for processing (1)
lib/mixins/Taskfile.yml
2bbc903 to
2fead6b
Compare
| update-all: | ||
| desc: "Update a mixin across the components. Example: `task mixins:update-all -- context.tf`." | ||
| # Updates (by overwriting) every existing copy of the named mixin under | ||
| # ./components/ with the current ./mixins/<file> template. |
There was a problem hiding this comment.
Sorry to add this on, but since we don't really use ./components anymore -- Want to update this to be configurable so this is usable in mp-infra and new client repos?
There was a problem hiding this comment.
@Gowiem I'm even thinking do it recursively based on the current user directory, rather than having user specify.
If a repo has internal custom child modules AND root modules that both use mixins (e.g. context null label), I would want both to be updated.
- but then for huge monorepos, that's inefficient and they can't do it from root, they'd have to
cdthose directories. but then for monorepos, they have their dedicated directories for each "repo" so they be working from those directories I suppose e.g.repo/infra
There was a problem hiding this comment.
Shape it how you want, let's just make sure that ./components is not the way. Maybe we force providing a directory so we can always ensure we're doing it in the right location? This isn't run all that often so some level of explicitness is fine.
Replaces the hard-coded `./components/` scope with a recursive search from the current working directory. Existing copies of the mixin are discovered wherever they live in the consuming repo, so a single `update-all` run keeps the mixin in sync across every consumer — root modules, in-repo child modules, and anything else that has opted in by having the file on disk. Motivation: not every consumer repo follows a `./components/` layout, and even repos that do may also have in-repo child modules that consume the same mixin (e.g. `context.tf` from CloudPosse null-label). Hard-coding `./components/` left those out. The source `./mixins/` directory is added to the prune list so we never descend into it and accidentally copy the source onto itself. `.terraform/` and `.terragrunt-cache/` continue to be pruned to avoid vendored child-module copies.
The recursive search remains user-cwd-relative — invoking the task from a subdirectory still scopes the update to that subtree — but the source mixin path no longer depends on cwd. It's resolved from `<repo-root>/mixins/<file>` via `git rev-parse --show-toplevel`, so the task works from any directory inside the repo without the precondition or `cp` source path breaking. Also cleans up the long single-line `find` into a multi-line pipeline with explicit prune/match clauses, factors repeated paths into `vars.MIXIN_SRC`, and tightens the desc.
Closes #47.
Summary
Make
mixins:update-allrecurse from the user's working directory and only update existing copies of the mixin. Drops the hard-coded./components/scope so the task works in any consuming repo regardless of layout, and a single run keeps the mixin in sync across every consumer (root modules, in-repo child modules, etc.).Approach
secrets.sops.tfonly belongs in certain modules that consume SOPS. Copying it everywhere creates unused files that have to be deleted by hand. Existing presence on disk is the opt-in signal..(the user's working directory) rather than./components/, so the task works in repos that don't follow a./components/layout, and so a single run also keeps in-repo child modules in sync — not just top-level components..terraform/,.terragrunt-cache/, and the source./mixins/directory so vendored child-module copies aren't overwritten and we don't try to copy the source mixin onto itself.Test plan
Validated end-to-end against the internal
mp-infra-spacelift-automationTerraform infra repo (masterpoint-internal/mp-infra-spacelift-automation), which has both a flat-and-nested root-module layout AND in-repo child modules that consume the samecontext.tfmixin from CloudPosse null-label. The same logic was first applied to that repo's localtaskfiles/mixins/Taskfile.ymloverride and exercised before being ported here.Commands run in
mp-infra-spacelift-automation:Verified:
aws-iam/delegated-tf-role,aws-iam/primary-tf-role,demo/rds) appeared in thecp -voutput.child-modules/demo-kms-key/context.tfandchild-modules/demo-rds/context.tfwere updated, which the previous./components/-scoped version would have missed. This is the headline benefit of the recursive search.context.tfwas overwritten in exactly the 26 directories that already had one on disk. Root modules without acontext.tf(e.g.aws-organization,github-organization-secrets,github-repositories,tfstate-backend) were left untouched.git statusshowed no new files added../mixins/pruned.mixins/context.tf.tplwas confirmed unchanged after the run, so we didn't walk into the template source directory or attempt a self-copy..terraform/pruned. A raw recursive scan would otherwise hit ~165 vendoredmain.tfentries; no mixin files were written into.terraform/or.terragrunt-cache/.File does not exist: ./mixins/<file>and produces no copies.