From b1161be635f1dc16d265cef0dae332e5ec3f7612 Mon Sep 17 00:00:00 2001 From: EdifyContent Date: Fri, 10 Jan 2025 17:10:47 -0500 Subject: [PATCH 01/11] Update index.md --- docs/2.0/docs/patcher/concepts/index.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/2.0/docs/patcher/concepts/index.md b/docs/2.0/docs/patcher/concepts/index.md index b93714b3b..cf7ab8275 100644 --- a/docs/2.0/docs/patcher/concepts/index.md +++ b/docs/2.0/docs/patcher/concepts/index.md @@ -1,9 +1,9 @@ # What is Gruntwork Patcher? -Gruntwork Patcher helps you automatically keep your infrastructure code ([Terragrunt](https://terragrunt.gruntwork.io/) and [OpenTofu](https://opentofu.org/)) up to date, including patching your code to make it work with backward incompatible module releases. +Gruntwork Patcher automates the process of keeping your infrastructure code ([Terragrunt](https://terragrunt.gruntwork.io/) and [OpenTofu](https://opentofu.org/)) up to date, including applying patches to ensure compatibility with backward-incompatible module releases. -Without Patcher, the manual process of discovering updates and determining if they can be safely applied can take hours of an engineer's time for each module dependency. +Manually identifying updates and assessing whether they can be safely applied can consume significant engineering time for each module dependency. Patcher eliminates this inefficiency by streamlining the update process. -You can use Patcher to maintain your dependencies on the Gruntwork IaC Library which includes patches for recent breaking changes to Gruntwork modules. Patcher can also be used to update dependencies on your own modules and dependencies on open source modules using semantic versioning to decide which versions can be safely updated and which require manual intervention. +You can use Gruntwork Patcher to manage dependencies on the Gruntwork IaC Library, which includes patches for recent breaking changes to Gruntwork modules. Patcher also supports updating dependencies for your own modules or open-source projects, using semantic versioning to identify safe updates and highlight those that need manual review. -Gruntwork Patcher provides a straightforward README driven workflow for use when applying breaking changes that don't have patches. Patcher updates the dependency to the version with a breaking changes, generates a README file into the folder that contains the file that has been updated, and then stops. The README will contain the release note for the breaking change. The user reads the README file, takes any action that is required and then deletes the README file before running Patcher again. +Gruntwork Patcher provides a clear, README-driven workflow for breaking changes without available patches. When Patcher detects breaking changes, it updates the relevant dependency to the version containing those changes and generates a README file in the folder with the updated file. This README outlines the release notes and details the breaking changes. Users must review the README, address any necessary actions, and remove the file before rerunning Patcher. From bfd1ecca41e7a07e6f84165d3a39b6bb5bdc7ce5 Mon Sep 17 00:00:00 2001 From: EdifyContent Date: Fri, 10 Jan 2025 17:12:25 -0500 Subject: [PATCH 02/11] Update patches.md --- docs/2.0/docs/patcher/concepts/patches.md | 93 +++++++++++------------ 1 file changed, 45 insertions(+), 48 deletions(-) diff --git a/docs/2.0/docs/patcher/concepts/patches.md b/docs/2.0/docs/patcher/concepts/patches.md index 0911e8ea8..0714d02f0 100644 --- a/docs/2.0/docs/patcher/concepts/patches.md +++ b/docs/2.0/docs/patcher/concepts/patches.md @@ -1,8 +1,8 @@ # What is a Patcher Patch? -A Patch is a set of instructions executed by Patcher that do code transformations. -This strategy is especially useful as a way to automate adoption of a breaking change with infrastructure as code, such as Terragrunt, OpenTofu, or Terraform. -This instruction sheet is delivered by means of a `yaml` file in a specific format: +A patch in Patcher is a set of instructions designed to automate code transformations. It enables the seamless adoption of breaking changes in infrastructure-as-code projects, streamlining updates for tools like Terragrunt, OpenTofu, and Terraform. + +These instructions are delivered through a `yaml` file in the following format: ```yaml title=".patcher/patches/v1.0.0/my-patch/patch.yaml" name: "" @@ -14,7 +14,7 @@ dependencies: - name: terrapatch version: "0.1.0" -# Steps necessary to resolve breaking change +# Steps necessary to resolve breaking changes steps: - name: "" run: @@ -22,83 +22,80 @@ steps: run: # etc ``` - -[Check out an example of a patch in the CIS Service Catalog.](https://github.com/gruntwork-io/terraform-aws-service-catalog/blob/c3d5ede211fc3230a7d493ceea43622b337ee88a/.patcher/patches/v0.96.4/switch-to-cis-rds-module/patch.yaml) +[View an example patch in the CIS Service Catalog.](https://github.com/gruntwork-io/terraform-aws-service-catalog/blob/c3d5ede211fc3230a7d493ceea43622b337ee88a/.patcher/patches/v0.96.4/switch-to-cis-rds-module/patch.yaml) ## Module consumers and module authors -Patcher is built around the idea of two specific personas: +Patcher is designed for two key personas: + +- **Module authors**: Write or update OpenTofu/Terraform modules. +- **Module consumers**: Use OpenTofu/Terraform modules created by module authors, typically referenced in Terragrunt units (`terragrunt.hcl` files) or directly in Terraform/OpenTofu code. + +## For module authors -- **Module authors.** Module authors write OpenTofu/Terraform modules, or make updates to those modules. -- **Module consumers.** Module consumers make use of an OpenTofu/Terraform module that was created by a module author, typically in Terragrunt units (`terragrunt.hcl` files) or directly in OpenTofu/Terraform code that calls a module. +Module authors often need to introduce breaking changes in their modules, which can create a challenging experience for module consumers who must manually update their code. Patcher simplifies this process by allowing module authors to include a patch YAML file that automates these updates. -## For Module Authors +When a module consumer executes a patch, their code is updated automatically to reflect changes such as adding or renaming variables, updating provider references, or applying other transformations defined in the patch. -Module authors periodically need to introduce breaking changes in their modules, causing a downstream, potentially painful, experience for module consumers. -With patches, module authors include a patch YAML file that automatically updates consuming code to incorporate the breaking changes associated with the updated module code. For example, when module consumers "execute" a patch and their code will automatically be updated to add a variable, rename a variable, update a provider reference, or incorporate some other transformation specified by the module author. -This allows module consumers to automatically update consuming code to adopt breaking changes. +While module authors have the flexibility to write any command steps for patches—such as validating tool versions or using `sed` for find-and-replace operations—it is **strongly recommended** to use [`terrapatch`](https://github.com/gruntwork-io/terrapatch). Terrapatch is a Gruntwork tool that enables precise updates to Terraform/OpenTofu HCL files. -In a Patcher ecosystem, the module author spends a small amount of extra time to author a patch, but now all module consumers can automatically update their code to consume the latest breaking change. +By investing a small amount of additional time in authoring a patch, module authors enable all module consumers to seamlessly adopt breaking changes without manual intervention. -In theory, you may write whatever command execution steps you want to perform patch steps. -For example, there are many cases where validating tool versions are required, or using `sed` to find and replace certain values. -However, we _strongly_ recommend using [`terrapatch`](https://github.com/gruntwork-io/terrapatch), a Gruntwork tool that surgically updates Terraform/OpenTofu HCL files. +## For module consumers -## For Module Consumers +Module consumers typically reference specific versions of OpenTofu/Terraform modules to maintain consistency. Over time, as new versions of modules are released, consumer code can become outdated. In cases where updates introduce breaking changes, the code must be edited to ensure compatibility—this is where Patcher proves valuable. -When module consumers reference an OpenTofu/Terraform module, it is a best practice to reference a specific version of the OpenTofu/Terraform module. -Over time, module authors release new versions of the module, and the code that consumes those modules slowly gets out of date. -In some cases, the latest update of the underlying modules requires a breaking change to the consuming code, meaning the version can't just be bumped; the code needs to be edited. -This is when using a patch with Patcher comes in handy. +Patcher automates updates by applying patches that incorporate breaking changes, reducing the manual effort required to keep infrastructure code current. ### Two update strategies -Patches can be consumed with either a "push" strategy, where Patcher proactively opens a pull request with the latest update, or a "pull" strategy, where a repo is manually scanned to look at the current state of your infrastructure using the Patcher CLI tool. +Patcher offers two flexible strategies for applying updates: -Regardless of methodology, the concept remains the same. -Patcher will suggest changes to your codebase in order to keep your infrastructure up to date, however you see fit. +1. **Push strategy**: Patcher automatically opens pull requests containing updates, allowing consumers to review and merge changes as needed. +2. **Pull strategy**: Users manually run the Patcher CLI to scan their repository, identify updates, and apply them directly. -### Update Push Strategy +While the implementation details differ, the purpose remains the same: Patcher suggests changes to keep your infrastructure code up to date. -In the "push" strategy, Patcher opens pull requests against your codebase on a schedule you set. You can further customize how those pull requests are grouped by environment, module version, or other parameters. Here is an example of such a pull request: +### Update push strategy + +In the push strategy, Patcher automatically opens pull requests on a schedule you define. Pull requests can be grouped by parameters such as environment or module version. For example: ![Patcher PR Example](/img/patcher/pr-example.png) -You can implement the push strategy by using the [Patcher GitHub action workflow](https://github.com/gruntwork-io/patcher-action). +To enable the push strategy, implement the [Patcher GitHub Action workflow](https://github.com/gruntwork-io/patcher-action). This action provides full control over your upgrade cadence. For safer updates, you can promote changes sequentially through environments like `dev`, `stage`, and `prod`. -The intention with this GitHub action is to leave the repo owner in full control of your upgrade cadence. Check out our guide on [promotion workflows](/2.0/docs/patcher/guides/promotion-workflows), so that updates can proceed from `dev` to `stage` to `prod` (or any other environment sequence) to mitigate risks around upgrades. +Refer to our guide on [promotion workflows](/2.0/docs/patcher/guides/promotion-workflows) for more details. -### Update Pull Strategy +### Update pull strategy -In the "pull" strategy, you the user choose to launch the Patcher CLI to scan the current state of your repo. +In the pull strategy, users manually invoke the Patcher CLI to scan the repository and apply updates. +To begin, run the following command in the target repository: -The first step is to run `patcher update` within the repo in which updates are desired. -When `patcher update` is run, the default mode is to click through the updates **interactively**. -In this mode, available updates are found, and the details of those updates are presented to you: +```bash +$ patcher update ./ +``` -![Patcher Update Interactive Mode](/img/patcher/interactive-update.png) +By default, the CLI operates interactively, presenting details of available updates: -You can choose to run in `--non-interactive` mode, which will modify the codebase and present results about what the program did at the end. +![Patcher Update Interactive Mode](/img/patcher/interactive-update.png). -By default a pull request will _not_ be opened with the changes. -However, the changes should be visible within the version control system. At that point, you may make a pull request or apply the changes using your IaC system. +Alternatively, use `--non-interactive` mode to apply updates automatically: -### Examples Running `patcher update` +```bash +$ patcher update --non-interactive +``` +By default, Patcher does not open a pull request. However, changes are visible in version control, allowing you to create pull requests or integrate changes using your IaC workflow -Here's the easiest way to run this command: +### Examples running `patcher update` +Here is a basic example: ```bash $ cd -# Show what patches are available for everything in the current directory and all it's children +# Show patches available for all directories $ patcher update ./ ``` - -If more fine-grain controls are desired, the following example (which includes advanced usage topics like [update strategies](/2.0/docs/patcher/concepts/update-strategies.md)) has those: - +For advanced usage, including automated PR creation, run: ```bash -# run 'update' non-interactively, only up to the next safe version, and publish a PR with the changes $ patcher update --update-strategy next-safe --non-interactive --publish --pr-branch grunty/update-via-patcher --pr-title "[Patcher] Update All Dependencies to Next Safe" ``` - -More details on the available options included in `patcher update` can be found in the [reference section](/2.0/reference/patcher/index.md#update). - +For a complete list of options, refer to the [Patcher CLI Reference](/2.0/reference/patcher/index.md#update). From 9664bbfc38b2fcc396b966f1be95ecb65cb7ec6c Mon Sep 17 00:00:00 2001 From: EdifyContent Date: Fri, 10 Jan 2025 17:13:35 -0500 Subject: [PATCH 03/11] Update grouping.md --- docs/2.0/docs/patcher/concepts/grouping.md | 97 +++++++++++----------- 1 file changed, 50 insertions(+), 47 deletions(-) diff --git a/docs/2.0/docs/patcher/concepts/grouping.md b/docs/2.0/docs/patcher/concepts/grouping.md index 1e21c7ab1..d0e0cba0c 100644 --- a/docs/2.0/docs/patcher/concepts/grouping.md +++ b/docs/2.0/docs/patcher/concepts/grouping.md @@ -1,19 +1,18 @@ # Update Grouping & Pull Request Strategy ## Overview -When working with enterprise IaC repositories you'll often find that you tend to reuse modules many times across a single repository. This creates a scenario where when a dependent module releases a new version, you are prompted with updating your reference to that dependency many times. This is in contrast to the traditional dependency update scenario for application codebases in e.g. a Java or NodeJS codebase, where a single dependency update may result in a change in a single change in a gradle.build or package.json file. In those environments, a pull request to bump a version would likely be only a few lines of code, and the build with those updates would progress through CI to reach higher environments in sequence. In IaC, you often have those environments repeated within a codebase, and references to those dependencies in many places. Patcher thus has a choice - when a dependency releases a new version, how to divide the diff of applying those updates into pull requests. - -The naive option is to simply make one pull request per dependency update found within a repository. At scale, this quickly becomes unmanageable. Patcher does support this behavior, but it also includes the ability to create PRs to address all of those changes in a single PR, to create a single PR per environment (e.g. update everything in dev), to create a PR per dependency update (e.g. update every instance of dependency XYZ), or to make a PR per dependency update per environment (update dependency XYZ in dev). - -In summary, there are five ways to group pull requests generated by Patcher: -1. **Full-Consolidation**: One PR to update everything. -2. **No-Consolidation**: One PR for each update. -3. **Dependency-Only Consolidation**: One PR per dependency. This allows you to merge one dependency at a time to all environments where they are used. -4. **Environment-Only Consolidation**: One PR per environment. This allows you to promote all dependencies as a group through environments one at a time. -5. **(Environment x Dependency) Consolidation**: One per dependency per environment. This allows you to promote a single dependency at a time through environments - -## Grouping Examples -To clarify via example, let's imagine we have the following repository +Enterprise IaC repositories often reuse modules extensively across a single repository. As a result, updating a dependent module version can require changes in multiple references across the codebase. Unlike application codebases in environments like Java or Node.js—where a single version bump typically involves updating centralized files such as `gradle.build` or `package.json`—IaC repositories frequently repeat environments and dependencies across folders. This repetition raises a critical question: how should dependency updates be grouped into pull requests to maintain a balance between efficiency and manageability? + +The simplest approach is to create one pull request for each dependency update. While simple, this method can quickly become overwhelming at scale. Patcher supports this approach but also offers more flexible options for grouping updates. Pull requests can be consolidated based on the following strategies: + +- **Full-consolidation**: A single pull request updates all dependencies across the repository. +- **No-consolidation**: A separate pull request is created for each individual update. +- **Dependency-only consolidation**: A single pull request is created for each dependency, updating it across all environments. +- **Environment-only consolidation**: A single pull request is created for each environment, updating all dependencies within that environment. +- **(Environment x Dependency) consolidation**: A single pull request is created for each dependency within each environment. + +## Grouping examples +To demonstrate these strategies, consider the following example repository: ``` /dev/unit1/terragrunt.hcl -> dependency1@1.0.0 /dev/unit2/terragrunt.hcl -> dependency1@1.0.0 @@ -24,40 +23,44 @@ To clarify via example, let's imagine we have the following repository /prod/unit4/terragrunt.hcl -> dependency3@1.0.0 ``` -In this example, assuming all 3 dependencies have newer versions available, the 5 strategies would result in: -1. **Full-Consolidation**: One pull request with an update to all 7 units -2. **No-Consolidation**: Seven pull requests, one for each unit -3. **Dependency-Only Consolidation**: Three pull requests, one for each dependency, with the PRs for `dependency1` and `dependency2` updating both `dev` and `prod`. -4. **Environment-Only Consolidation**: Two pull requests, one for `dev` and one for `prod`. -5. **(Environment x Dependency) Consolidation**: Five pull requests, two for `dev` and three for `prod`. +Assuming newer versions are available for all three dependencies, the strategies would result in: +- **Full-consolidation**: One pull request updating all seven units. +- **No-consolidation**: Seven separate pull requests, one per unit. +- **Dependency-only consolidation**: Three pull requests—one for each dependency. For example, `dependency1` would be updated across both `dev` and 'prod'. +- **Environment-only consolidation**: Two pull requests—one for all updates in `dev` and one for all updates in `prod`. +- **(Environment x Dependency) consolidation**: Five pull requests—two for updates in `dev` and three for updates in `prod`. ## Terminology -* `unit` A unit refers to a folder containing a `terragrunt.hcl` file, and thus a single corresponding OpenTofu state file. A unit may specify one or multiple modules as `dependencies`. -* `dependency` (also referred to as `target`) A dependency is an OpenTofu module that is referenced by `ref` (usually a full source code path AND a version number) inside your `unit`. Patcher understands the semantics of semantic versioning on dependency `ref`s. -* `environment` is a logical grouping of infrastructure to represent your application environments, such as `dev` or `prod`. An environment usually contains multiple `units` and thus many `dependencies`. Generally IaC environments are similar to each other, and represented as a folder structure in your repository. -* `update` is the the act of changing a single instance of a dependency to reference a newer version and to accommodate any breaking changes. +* `unit`: A folder containing a `terragrunt.hcl` file, representing a single OpenTofu state file. A unit may reference one or more modules as dependencies. +* `dependency` (or `target`): An OpenTofu module referenced using a `ref` (typically a full source path and version) in a `unit`. Patcher interprets semantic versioning for dependency updates. +* `environment`: A logical grouping of infrastructure representing application stages, such as `dev` or `prod`. Environments are generally organized as folders in the repository and include multiple units and dependencies. +* `update`: The action of modifying a dependency reference to use a newer version and accommodating any associated breaking changes. + :::info - As of November 2024 Patcher's understanding of environments is limited to groupings of folders matched with glob patterns. E.g. `dev` is all folders matching `dev-*`, `prod` is all folders matching `prod-*`. Pipelines has a sophisticated HCL configuration syntax that allows for much more powerful definitions of environments. It is planned that Patcher will be able to leverage this method of defining environments in the future. Let us know if this expanded definitional capability is important to your use case. + + As of November 2024, Patcher recognizes environments using folder groupings matched with glob patterns. For example, `dev` may correspond to `dev-*` folders and 'prod' to `prod-*` folders. A more sophisticated environment definition using HCL syntax (similar to Pipelines) is planned for future releases. Let us know if this capability is important for your use case. + ::: -## Implementation Discussion - -When generating pull requests in CI, the workflow generally involves first invoking `patcher report` to identify what updates are available, then `patcher update` to create PRs applying those updates. Patcher does not have a built-in way to specify the grouping strategy by name, instead the grouping strategies are implemented with flags to the report and update commands. +## Implementation discussion -### Patcher Report +In CI workflows, pull requests are typically generated by first running a patcher report to identify updates, followed by `patcher update` to apply those updates. Patcher does not include a single option to specify grouping strategies by name. Instead, grouping is implemented through combinations of `report` and `update` command flags. -Patcher [report](/2.0/reference/patcher/#report) accepts a `--include-dirs` argument. When passed, this will cause `patcher report` to only output updates matching the glob pattern specified. This allows the developer to in essence limit the resulting PR to only a single environment. By invoking `patcher report` multiple times with different `--include-dirs` arguments, the developer can in effect create different PR workflows for each environment. +### Patcher report +The `patcher report` command accepts the `--include-dirs` flag, which filters updates based on matching glob patterns. This allows developers to limit updates to specific environments. By running `patcher report` multiple times with different `--include-dirs` values, you can create distinct workflows for each environment. Patcher `report` outputs in JSON which can be inspected or iterated over to achieve desired behaviors. -### Patcher Update +The patcher report output is JSON-formatted and can be inspected or iterated for further customization. -Patcher [update](/2.0/reference/patcher/#update) accepts a `--target` argument. This argument can be specified one or many times, and limits which dependencies patcher will include in the generated pull request. By invoking `patcher update` multiple times with different `--target` arguments, the developer can in effect create different PR workflows for each dependency. +### Patcher update -## Implementation Walkthrough +The `patcher update` command accepts a `--target` flag, which specifies one or more dependencies to update. By running `patcher update` with different `--target` values, you can control which dependencies are included in each pull request. -### Full-Consolidation -To implement a full-consolidation workflow, do not pass either `--include-dirs` or `--target` arguments to patcher `report` and `update`. The output of patcher `report` will include all updates that are available, and the effect of patcher `update` will be to create a single PR that includes all targets (dependencies) across all folders. +## Implementation walkthrough + +### Full-consolidation +For full consolidation, omit the `--include-dirs` and `--target` arguments. This approach generates a single pull request containing all updates. **Pseudocode:** ``` @@ -65,10 +68,9 @@ run patcher report run patcher update ``` +### No-consolidation -### No-Consolidation - -Patcher `report` has two types of outputs, a `plan` and a `spec`. Generally we use the `spec` file as its simpler and contains the information needed for most workflows. To achieve a no-consolidation workflow, however, we need the full `plan`. +To create one pull request per update, use the `plan` output of `patcher report` and iterate over each dependency and its instances. **Pseudocode:** ``` @@ -79,19 +81,19 @@ for each dependency in plan.json run patcher update --target $dependency.org/$dependency.repo/$dependency.module ``` -### Dependency-Only Consolidation -To implement a dependency-only consolidation workflow, run patcher `update` without any `--include-dirs` arguments. This will create a single report output JSON file for all updates. Iterate over the targets in that JSON file and run patcher `update` once per identified target. +### Dependency-only consolidation +To group by dependency, run `patcher update` for each target without filtering environments. **Pseudocode:** ``` run patcher report without an include-dirs argument -for each $target in the output of patcher report +for each $target in output run patcher update --target=$target ``` -### Environment-Only Consolidation -To implement a environment-only consolidation workflow you need to iterate over each of your environments, passing in the environment to `--include-dirs` to `report` and then pass the complete output from report to a single `update` command. +### Environment-only consolidation +To group updates by environment, use `--include-dirs` to filter by environment and run `patcher update` without specifying targets. **Pseudocode:** ``` @@ -100,16 +102,17 @@ for each $environment run patcher update without any target argument ``` -### (Environment x Dependency) Consolidation -To implement a environment x dependency consolidation workflow you will need to iterate over each of your environments, passing in the environment to `--include-dirs` to `report` and then iterating over each target in the report output and passing `--target` to `update`. +### (Environment x Dependency) consolidation +To create pull requests for each dependency within specific environments, combine `--include-dirs` with `--target`. + **Pseudocode:** ``` -for each $environment (identified as a glob pattern of folders) +for each $environment e.g., glob patterns like dev-* or prod-*) run patcher report --include-dirs=$environment - for each $target in the output of patcher report + for each $target output run patcher update --target=$target ``` -**Pseudocode:** \ No newline at end of file +**Pseudocode:** From 9200f038f6d2ba15923b37232df2df5a5befa422 Mon Sep 17 00:00:00 2001 From: EdifyContent Date: Fri, 10 Jan 2025 17:14:46 -0500 Subject: [PATCH 04/11] Update promotion-workflows.md --- docs/2.0/docs/patcher/concepts/promotion-workflows.md | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/docs/2.0/docs/patcher/concepts/promotion-workflows.md b/docs/2.0/docs/patcher/concepts/promotion-workflows.md index 1b5d5a254..1fa1bbabf 100644 --- a/docs/2.0/docs/patcher/concepts/promotion-workflows.md +++ b/docs/2.0/docs/patcher/concepts/promotion-workflows.md @@ -2,11 +2,13 @@ Before you promote an infrastructure change to production, it's natural to want to validate that change in a lower environment. We call this general process of moving changes between environments a promotion workflow. -Patcher was built with promotion workflows in mind, and this document aims to outline how to integrate that flow with GitHub Actions. Specifically, Patcher is able to detect an infrastructure change and then facilitate incorporating that change across environments (e.g. dev, stage, prod). The idea is to create a series of pull requests for your code that each include the relevant changes for a particular environment which can then be reviewed and tested. Once approved the act of merging a given pull request with "dispatch" a patcher workflow which will generate an analogous pull request on the next environment in the chain. This continues until the end of the chain at which point the final pull request is merged and no further dispatching occurs. +Patcher was built with promotion workflows in mind, and this document aims to outline how to integrate that flow with GitHub Actions. Specifically, Patcher is able to detect an infrastructure change and then facilitate incorporating that change across environments (e.g., dev, stage, prod). The idea is to create a series of pull requests, each containing the relevant changes for a specific environment. These pull requests can be reviewed and tested individually. -Patcher was built specifically for infrastructure as code and has a first-class understanding of versioning in Terraform/OpenTofu/Terragrunt. As a result, even if your infrastructure has differences between environments, Patcher is still able to identify out of date modules and apply updates in a sane way through a promotion workflow. +Once a pull request is approved, merging it using the `dispatch` action triggers the Patcher workflow, which generates a corresponding pull request for the next environment in the deployment chain. This process continues until the end of the chain, when the final pull request is merged, and no further dispatching occurs. -Below is a sequence diagram walking through a hypothetical promotion workflow from "dev" to "stage" to "prod" environments +Patcher was explicitly built for infrastructure as code and has a first-class understanding of versioning in Terraform/OpenTofu/Terragrunt. As a result, even if your infrastructure has differences between environments, Patcher can still identify outdated modules and apply updates in a sane way through a promotion workflow. + +Below is a sequence diagram walking through a hypothetical promotion workflow from `dev` to `stage` to `prod` environments ```mermaid sequenceDiagram From 7f98cc732d5b311e08d1e6eb6c2fd7b6b41cedc6 Mon Sep 17 00:00:00 2001 From: EdifyContent Date: Fri, 10 Jan 2025 17:15:57 -0500 Subject: [PATCH 05/11] Update update-strategies.md --- .../patcher/concepts/update-strategies.md | 64 +++++++++---------- 1 file changed, 31 insertions(+), 33 deletions(-) diff --git a/docs/2.0/docs/patcher/concepts/update-strategies.md b/docs/2.0/docs/patcher/concepts/update-strategies.md index 98eb3e541..0fe6d5a58 100644 --- a/docs/2.0/docs/patcher/concepts/update-strategies.md +++ b/docs/2.0/docs/patcher/concepts/update-strategies.md @@ -1,26 +1,29 @@ # Update Strategies -Patcher supports two update strategies: **next safe** and **next breaking**. These update strategies determine how Patcher will behave if it encounters a breaking change that it cannot patch. +Patcher supports two update strategies: **next safe** and **next breaking**. These strategies dictate how Patcher behaves when encountering a breaking change that cannot be automatically patched. For example, the Gruntwork `terraform-aws-security/custom-iam-entity` module has two recent breaking changes: `0.62.0` and `0.65.0`. -And in `infrastructure-live/dev` there are 2 dependencies on `terraform-aws-security/custom-iam-entity`: -- `_global/ops-admin-role/terragrunt.hcl` currently uses `0.65.6` -- `_global/website-ci-cd-access/terragrunt.hcl` currently use `0.61.0` +In the `infrastructure-live/dev` environment, there are two dependencies on the `terraform-aws-security/custom-iam-entity` module: +- `_global/ops-admin-role/terragrunt.hcl` currently uses version `0.65.6`. +- `_global/website-ci-cd-access/terragrunt.hcl` currently uses version `0.61.0`. -## "Next Safe" Update Strategy (Default) +## "Next safe" update strategy (default) -The **next safe** strategy will update a dependency to either the highest version **before the next closest breaking change** or the latest version of the dependency, whichever is encountered first. +The **next safe** strategy updates a dependency to either the highest version **before the next closest breaking change** or the latest version of the dependency, whichever occurs first. -So if Patcher encounters a breaking change that it cannot patch then it will update the dependencies to the highest version before that breaking change and stop. Otherwise, if no breaking changes are encountered it will update the dependencies the latest version of that module. +If Patcher encounters a breaking change that cannot be automatically patched, it stops at the highest version before that breaking change. If no breaking changes are detected, it updates the dependency to the latest available version. For example, for the dependencies on `terraform-aws-security/custom-iam-entity` in `infrastructure-live/dev`: -- `_global/ops-admin-role/terragrunt.hcl` will be updated from `0.65.6` to `0.68.2`, the latest version - - There are no breaking changes between `0.65.6` and `0.68.2` -- `_global/website-ci-cd-access/terragrunt.hcl` will be updated from `0.61.0` to `0.61.1`, the highest version before `0.62.0` - - `0.62.0` is the next highest version that contains a breaking change which requires manual intervention -This is an example of the YAML that Patcher writes to `stdout` describing these updates: +- `_global/ops-admin-role/terragrunt.hcl` is updated from `0.65.6` to `0.68.2`, the latest version. + - There are no breaking changes between `0.65.6` and `0.68.2`. + +- `_global/website-ci-cd-access/terragrunt.hcl` is updated from `0.61.0` to `0.61.1`, the highest version before `0.62.0`. + - Version `0.62.0` introduces a breaking change that requires manual intervention. + + +This is an example of the YAML that Patcher outputs to `stdout` to describe these updates: ```yaml successful_updates: @@ -41,22 +44,21 @@ This is an example of the YAML that Patcher writes to `stdout` describing these release_notes_url: https://github.com/gruntwork-io/terraform-aws-security/releases/tag/v0.62.0 ``` -## "Next Breaking" Update Strategy - -The **next breaking** strategy will update a dependency to either the next closest breaking change or the latest version of the dependency, whichever is encountered first. +## "Next breaking" update strategy -So if Patcher encounters a breaking change that it cannot patch then it will update the dependencies to the version with the breaking change and stop. Otherwise, if no breaking changes are encountered, it will update the dependencies to the latest version of that module. +The **next breaking** strategy updates a dependency to either the next closest breaking change or the latest version of the dependency, whichever occurs first. -This may result in an update that requires manual intervention. If so, Patcher will provide additional information to help you understand what needs to be done. +If Patcher encounters a breaking change that cannot be automatically patched, it updates the dependency to the version containing the breaking change and stops. If no breaking changes are found, it updates the dependency to the latest available version. -Patcher does this by writing a `README-TO-COMPLETE-UPDATE.md` into the folder containing the dependency. If more than one dependency in a folder has been updated to a breaking version, then the `README-TO-COMPLETE-UPDATE.md` file will contain a release note extract for each breaking change in that folder. +This strategy may result in updates that require manual intervention. In such cases, Patcher provides additional guidance by writing a `README-TO-COMPLETE-UPDATE.md` file into the folder containing the dependency. If multiple dependencies in a folder are updated to breaking versions, the `README-TO-COMPLETE-UPDATE.md` file will include release note extracts for each breaking change. For example, for the dependencies on `terraform-aws-security/custom-iam-entity` in `infrastructure-live/dev`: -- `_global/ops-admin-role/terragrunt.hcl` will be updated from `0.65.6` to `0.68.2`, the latest version - - There are no breaking changes between `0.65.6` and `0.68.2` -- `_global/website-ci-cd-access/terragrunt.hcl` will be updated from `0.61.0` to `0.62.0`, the next highest version with a breaking change that requires manual intervention. -If any of the dependencies were updated to a breaking version, then the YAML that Patcher writes to `stdout` describing these updates will include a `manual_steps_you_must_follow` section listing the generated `README-TO-COMPLETE-UPDATE.md` files, for example: +- `_global/ops-admin-role/terragrunt.hcl` is updated from `0.65.6` to `0.68.2`, the latest version. + - There are no breaking changes between `0.65.6` and `0.68.2`. +- `_global/website-ci-cd-access/terragrunt.hcl` is updated from `0.61.0` to `0.62.0`, the next version containing a breaking change that requires manual intervention. + +If any dependencies are updated to a breaking version, the YAML output that Patcher writes to `stdout` will include a `manual_steps_you_must_follow` section listing the generated `README-TO-COMPLETE-UPDATE.md` files. For example: ```yaml successful_updates: @@ -82,16 +84,12 @@ If any of the dependencies were updated to a breaking version, then the YAML tha This is the `README-TO-COMPLETE-UPDATE.md` written into `dev/_global/website-ci-cd-access`: ```markdown -# custom-iam-entity v0.61.0 -> v0.62.0 (2023.06.05 12:26:30) - -Updated dependency custom-iam-entity in ~/infrastructure-live/dev/_global/website-ci-cd-access/terragrunt.hcl to version v0.62.0, which contains breaking changes. You MUST follow the instructions in the release notes to complete this update safely: https://github.com/gruntwork-io/terraform-aws-security/releases/tag/v0.62.0 +# custom-iam-entity v0.61.0 -> v0.62.0 (2023.06.05 12:26:30)Updated dependency `custom-iam-entity` in `~/infrastructure-live/dev/_global/website-ci-cd-access/terragrunt.hcl` to version `v0.62.0`, which contains breaking changes. You **must** follow the instructions in the release notes to complete this update safely: https://github.com/gruntwork-io/terraform-aws-security/releases/tag/v0.62.0 -Here are the release notes for version v0.62.0: +Here are the release notes for version `v0.62.0`: - -## Description -**Terraform 1.1 upgrade**: We have verified that this repo is compatible with Terraform `1.1.x`! - - From this release onward, we will only be running tests with Terraform `1.1.x` against this repo, so we recommend updating to `1.1.x` soon! - - We have also updated the minimum required version of Terraform to `1.0.0`. While our repos might continue to be compatible with pre-1.0.0 version of Terraform, we are no longer making any guarantees of that. - - Once all Gruntwork repos have been upgraded to work with `1.1.x`, we will publish a migration guide with a version compatibility table and announce it all via the Gruntwork Newsletter. -``` +## Description +**Terraform 1.1 Upgrade**: We have verified that this repository is compatible with Terraform `1.1.x`! +- From this release onward, we will only run tests with Terraform `1.1.x` against this repository, so we recommend updating to `1.1.x` soon. +- The minimum required version of Terraform has been updated to `1.0.0`. While earlier versions of Terraform may still work, we no longer guarantee compatibility with pre-1.0.0 versions. +- Once all Gruntwork repositories have been upgraded to work with `1.1.x`, we will publish a migration guide with a version compatibility table and announce it via the Gruntwork Newsletter. From e87ac94addd8ed678ef70a551e1d5bd74e4b7829 Mon Sep 17 00:00:00 2001 From: EdifyContent Date: Fri, 10 Jan 2025 17:17:00 -0500 Subject: [PATCH 06/11] Update index.md --- docs/2.0/docs/patcher/architecture/index.md | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/docs/2.0/docs/patcher/architecture/index.md b/docs/2.0/docs/patcher/architecture/index.md index a40a177a2..75c443ddd 100644 --- a/docs/2.0/docs/patcher/architecture/index.md +++ b/docs/2.0/docs/patcher/architecture/index.md @@ -3,14 +3,15 @@ ### Environments -Patcher allows teams to define environments as a grouping of folders using glob patterns. Patcher commands (on the CLI and in GitHub Actions) accept commands to match those folders, such as the argument to `patcher-action` -- `include_dirs: "{*prod*}/**"` which would match all folders with "prod" in the name. A given environment can include 1 or many (without limit) folders. Patcher will scan the entire group of folders at once for potential updates and changes. +Patcher allows teams to define environments as groupings of folders using glob patterns. Patcher commands on the CLI and in GitHub Actions accept arguments to match these folders. For example, the `patcher-action` argument `include_dirs: "{*prod*}/**"` matches all folders containing "prod" in their name. A single environment can include one or multiple folders without any set limit. Patcher scans the entire group of folders simultaneously for potential updates and changes. -There is no limit on how many environments you can have, or other limit on the naming structure for those environments. +There are no restrictions on the number of environments or the naming structure you can use. -In the future it is planned to model environments using a configuration based system (to be shared with Gruntwork Pipelines) which will allow for even more flexibility in your folder structure. +In the future, you'll model environments using a configuration-based system integrated with Gruntwork Pipelines, offering greater flexibility in organizing folder structures. ### Dependencies -A `dependency` in Patcher workflows is a reference to code that is versioned and in use by your codebase, generally a Terraform or Tofu module that exists in a git repo using a specific git tag for versioning. For example, if you are using `gruntwork-io/terraform-aws-messaging.git//modules/sqs?ref=v0.8.0` as a terraform source module, then your dependency would be `gruntwork-io/terraform-aws-messaging/sqs`. +A `dependency` in Patcher workflows refers to versioned code that your codebase references, typically a Terraform or OpenTofu module stored in a Git repository and tagged with a specific version. For example, if your Terraform source module is `gruntwork-io/terraform-aws-messaging.git//modules/sqs?ref=v0.8.0`, the corresponding dependency is `gruntwork-io/terraform-aws-messaging/sqs`. -Patcher generally models promotion workflows around the idea of grouping changes together per-dependency. Patcher would then identify all usages of `gruntwork-io/terraform-aws-messaging/sqs` within a given environment and create a single pull request to update to the next appropriate version. + +Patcher organizes promotion workflows by grouping changes per dependency. It identifies all instances of `gruntwork-io/terraform-aws-messaging/sqs` within a specified environment and generates a single pull request to update the dependency to the next appropriate version. From 0410d23373e6353ed4e139a2a55ad20c27370f01 Mon Sep 17 00:00:00 2001 From: EdifyContent Date: Fri, 10 Jan 2025 17:18:21 -0500 Subject: [PATCH 07/11] Update index.md --- docs/2.0/docs/patcher/installation/index.md | 38 +++++++++++---------- 1 file changed, 20 insertions(+), 18 deletions(-) diff --git a/docs/2.0/docs/patcher/installation/index.md b/docs/2.0/docs/patcher/installation/index.md index 47f2e3322..c4d1cf158 100644 --- a/docs/2.0/docs/patcher/installation/index.md +++ b/docs/2.0/docs/patcher/installation/index.md @@ -2,27 +2,28 @@ ## Installation -To install Patcher, download the appropriate package for your system from the [releases](https://github.com/gruntwork-io/patcher-cli/releases) page. +To install Patcher, download the appropriate package for your system from the [releases](https://github.com/gruntwork-io/patcher-cli/releases) page. -### For MacOS and Linux users +### For MacOS and Linux users -Patcher runs as a single binary called `patcher`. Make sure it's available within your `PATH`. +Patcher runs as a single binary called `patcher`. Make sure it's available within your system's `PATH`. -1. After downloading Patcher, move it to your desired destination directory. If you're using MacOS, you will have to unzip the package. For other operating systems, the artifact you download is the executable itself. -2. If necessary, rename the binary to `patcher`. +1. After downloading Patcher, move it to your desired destination directory. +2. On macOS, unzip the downloaded package. For other operating systems, the downloaded artifact is the executable itself. +3. If needed, rename the binary to `patcher`. ```bash mv patcher_linux_amd64 patcher ``` -3. Move `patcher` to a location available in your `PATH`. In the example below, we move to `/usr-local/bin`. +4. Move `patcher` to a location available in your `PATH`. In the example below, we move to `/usr-local/bin`. ```bash $ echo $PATH /opt/homebrew/bin:/opt/homebrew/sbin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/go/bin:/Library/Apple/usr/bin:/Users/grunty/bin:/Users/grunty/go/bin $ mv patcher /usr/local/bin ``` -## Before Running Patcher +## Before running Patcher -### GitHub Personal Access Token +### GitHub personal access token To fetch information from GitHub, Patcher requires a [GitHub Personal Access Token](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/creating-a-personal-access-token), with the `repo` scope. Set the `GITHUB_OAUTH_TOKEN` environment variable to your GitHub Personal Access token: @@ -33,28 +34,29 @@ export GITHUB_OAUTH_TOKEN="" ### Docker -Starting in `0.4.1`, the Patcher update command applies patches using a Docker sandbox by default and will pull the latest version of the [`gruntwork/patcher_bash_env`](https://hub.docker.com/r/gruntwork/patcher_bash_env) image. +Starting in version `0.4.1`, the Patcher `update` command applies patches using a Docker sandbox by default and pulls the latest version of the [`gruntwork/patcher_bash_env`](https://hub.docker.com/r/gruntwork/patcher_bash_env) image. -To run the Patcher update command locally without Docker or in a CI pipeline you should add the `--skip-container-runtime` flag. +To run the Patcher `update` command locally without Docker or in a CI pipeline, use the `--skip-container-runtime` flag. ## Running Patcher -Patcher should be run in a local Terraform or Terragrunt Git repo. It will analyze _all_ modules that belong to the current folder including its children. Patcher supports `source` values only from GitHub. +Patcher must be run in a local Terraform or Terragrunt Git repository. It analyzes **all** modules in the current folder, including child folders. Patcher supports `source` values only from GitHub. -If you purchased and deployed our [Reference Architecture](https://gruntwork.io/reference-architecture/) and have your deployment organized in an `infrastructure-live` repository, we recommend running Patcher inside each environment folder, e.g. `infrastructure-live/dev`. +If you have purchased and deployed the [Reference Architecture](https://gruntwork.io/reference-architecture/) and your deployment is organized in an `infrastructure-live` repository, we recommend running Patcher within each environment folder, such as `infrastructure-live/dev`. -### Patcher Report -The patcher [report command](/2.0/docs/patcher/guides/report) is a read-only version of Patcher that shows the changelog per module and its usages. +### Patcher report -### Patcher Update +The `patcher report` command is a read-only operation that displays the changelog for each module and its usages. Learn more in the [report command guide](/2.0/docs/patcher/guides/report). -The patcher [update command](/2.0/docs/patcher/guides/update) allows you to update some or all of the module dependencies in the current folder and any child folders. +### Patcher update + +The `patcher update` command updates some or all module dependencies in the current folder and any child folders. Learn more in the [update command guide](/2.0/docs/patcher/guides/update). ## Debugging -All logs are stored in the folder `~/.patcher/logs`. To also send `debug` logs, run Patcher with the `--loglevel debug` flag. +Patcher logs are stored in the `~/.patcher/logs` directory. To include `debug` logs, run Patcher with the `--loglevel debug` flag. ``` patcher report --loglevel debug -``` \ No newline at end of file +``` From 2dca848f0a1bf5cc0596eefe2803ef57c650d9a0 Mon Sep 17 00:00:00 2001 From: EdifyContent Date: Wed, 15 Jan 2025 02:11:13 -0500 Subject: [PATCH 08/11] Update index.md --- docs/2.0/docs/patcher/installation/index.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/2.0/docs/patcher/installation/index.md b/docs/2.0/docs/patcher/installation/index.md index c4d1cf158..c95df3933 100644 --- a/docs/2.0/docs/patcher/installation/index.md +++ b/docs/2.0/docs/patcher/installation/index.md @@ -6,7 +6,7 @@ To install Patcher, download the appropriate package for your system from the [r ### For MacOS and Linux users -Patcher runs as a single binary called `patcher`. Make sure it's available within your system's `PATH`. +Patcher runs as a single binary called `patcher`. Verify that the patcher binary is in your system's `PATH` to allow command-line access from any directory. 1. After downloading Patcher, move it to your desired destination directory. 2. On macOS, unzip the downloaded package. For other operating systems, the downloaded artifact is the executable itself. @@ -14,7 +14,7 @@ Patcher runs as a single binary called `patcher`. Make sure it's available withi ```bash mv patcher_linux_amd64 patcher ``` -4. Move `patcher` to a location available in your `PATH`. In the example below, we move to `/usr-local/bin`. +4. Move `patcher` to a directory included in your `PATH`. In the example below, we move it to `/usr-local/bin`. ```bash $ echo $PATH /opt/homebrew/bin:/opt/homebrew/sbin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/go/bin:/Library/Apple/usr/bin:/Users/grunty/bin:/Users/grunty/go/bin @@ -40,7 +40,7 @@ To run the Patcher `update` command locally without Docker or in a CI pipeline, ## Running Patcher -Patcher must be run in a local Terraform or Terragrunt Git repository. It analyzes **all** modules in the current folder, including child folders. Patcher supports `source` values only from GitHub. +Run Patcher within a local Git repository that uses Terraform or Terragrunt t0 analyze **all** modules in the current folder, including child folders. Patcher supports `source` values only from GitHub. If you have purchased and deployed the [Reference Architecture](https://gruntwork.io/reference-architecture/) and your deployment is organized in an `infrastructure-live` repository, we recommend running Patcher within each environment folder, such as `infrastructure-live/dev`. From 3431ff878966d26c00dd6e46b3e2179c2a31c533 Mon Sep 17 00:00:00 2001 From: EdifyContent Date: Wed, 15 Jan 2025 02:14:24 -0500 Subject: [PATCH 09/11] Update update-strategies.md --- docs/2.0/docs/patcher/concepts/update-strategies.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/2.0/docs/patcher/concepts/update-strategies.md b/docs/2.0/docs/patcher/concepts/update-strategies.md index 0fe6d5a58..f1e44d2f1 100644 --- a/docs/2.0/docs/patcher/concepts/update-strategies.md +++ b/docs/2.0/docs/patcher/concepts/update-strategies.md @@ -10,7 +10,7 @@ In the `infrastructure-live/dev` environment, there are two dependencies on the ## "Next safe" update strategy (default) -The **next safe** strategy updates a dependency to either the highest version **before the next closest breaking change** or the latest version of the dependency, whichever occurs first. +The **next safe** strategy updates a dependency to the latest version available that avoids introducing breaking changes. If no breaking changes exist, it updates to the latest version. If Patcher encounters a breaking change that cannot be automatically patched, it stops at the highest version before that breaking change. If no breaking changes are detected, it updates the dependency to the latest available version. From 7f85e0d44e6b12f0ef73c560a7fcbd97df1ce3c6 Mon Sep 17 00:00:00 2001 From: EdifyContent Date: Wed, 15 Jan 2025 02:16:13 -0500 Subject: [PATCH 10/11] Update promotion-workflows.md --- docs/2.0/docs/patcher/concepts/promotion-workflows.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/2.0/docs/patcher/concepts/promotion-workflows.md b/docs/2.0/docs/patcher/concepts/promotion-workflows.md index 1fa1bbabf..80801c6be 100644 --- a/docs/2.0/docs/patcher/concepts/promotion-workflows.md +++ b/docs/2.0/docs/patcher/concepts/promotion-workflows.md @@ -6,7 +6,7 @@ Patcher was built with promotion workflows in mind, and this document aims to ou Once a pull request is approved, merging it using the `dispatch` action triggers the Patcher workflow, which generates a corresponding pull request for the next environment in the deployment chain. This process continues until the end of the chain, when the final pull request is merged, and no further dispatching occurs. -Patcher was explicitly built for infrastructure as code and has a first-class understanding of versioning in Terraform/OpenTofu/Terragrunt. As a result, even if your infrastructure has differences between environments, Patcher can still identify outdated modules and apply updates in a sane way through a promotion workflow. +Patcher is purpose-built for infrastructure as code, offering built-in support for versioning in Terraform, OpenTofu, and Terragrunt. As a result, even if your infrastructure has differences between environments, Patcher can still identify outdated modules and apply updates in a sane way through a promotion workflow. Below is a sequence diagram walking through a hypothetical promotion workflow from `dev` to `stage` to `prod` environments From 9d036b4a13177ba2505b66a5c2de5cb924f0e30d Mon Sep 17 00:00:00 2001 From: EdifyContent Date: Wed, 15 Jan 2025 02:17:53 -0500 Subject: [PATCH 11/11] Update grouping.md --- docs/2.0/docs/patcher/concepts/grouping.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/2.0/docs/patcher/concepts/grouping.md b/docs/2.0/docs/patcher/concepts/grouping.md index d0e0cba0c..342f77d36 100644 --- a/docs/2.0/docs/patcher/concepts/grouping.md +++ b/docs/2.0/docs/patcher/concepts/grouping.md @@ -1,7 +1,7 @@ # Update Grouping & Pull Request Strategy ## Overview -Enterprise IaC repositories often reuse modules extensively across a single repository. As a result, updating a dependent module version can require changes in multiple references across the codebase. Unlike application codebases in environments like Java or Node.js—where a single version bump typically involves updating centralized files such as `gradle.build` or `package.json`—IaC repositories frequently repeat environments and dependencies across folders. This repetition raises a critical question: how should dependency updates be grouped into pull requests to maintain a balance between efficiency and manageability? +Enterprise IaC repositories often reuse modules extensively across a single repository. As a result, updating a dependent module version can require changes in multiple references across the codebase. Unlike application codebases in environments like Java or Node.js—where a single version bump typically involves updating centralized files such as `gradle.build` or `package.json`—IaC repositories frequently repeat environments and dependencies across folders. This repetition creates a challenge: how to group dependency updates into pull requests for optimal efficiency and maintainability? The simplest approach is to create one pull request for each dependency update. While simple, this method can quickly become overwhelming at scale. Patcher supports this approach but also offers more flexible options for grouping updates. Pull requests can be consolidated based on the following strategies: