Custom OpenRewrite recipes by Anacoders.
Creates YAML files in multiple directories matching a wildcard pattern. Files are only created if they don't already exist.
Create a config.yaml file in every subdirectory under projects/:
---
type: specs.openrewrite.org/v1beta/recipe
name: com.yourorg.CreateProjectConfigs
displayName: Create config files in all projects
recipeList:
- com.anacoders.cookbook.yaml.CreateYamlFilesByPattern:
filePattern: projects/*/config.yaml
fileContents: |
apiVersion: v1
kind: Config
metadata:
name: example| Pattern | Description | Creates Files In |
|---|---|---|
projects/*/config.yaml |
Single wildcard * |
Each direct subdirectory of projects/ |
apps/*/deployment.yaml |
Works at any depth | Each subdirectory under apps/ |
src/main/*/application.yaml |
Nested paths | Each subdirectory under src/main/ |
apps/*/config/*/settings.yaml |
Multiple wildcards | Matching nested paths |
src/**/config.yaml |
Recursive ** |
Any depth under src/ |
- ✅ Creates files only in directories that match the pattern
- ✅ Skips creation if the file already exists (never overwrites)
- ✅ Works with any directory depth and nesting
- ✅ Supports multiple
*wildcards in a single pattern
Change a YAML property, optionally only when specified conditions are met. Expects dot notation for nested YAML mappings. Based on org.openrewrite.yaml.ChangePropertyValue with added support for conditional execution.
Update spec.replicas only in Deployments in the production environment:
---
type: specs.openrewrite.org/v1beta/recipe
name: com.yourorg.ScaleProductionDeployments
displayName: Scale production deployments
recipeList:
- com.anacoders.cookbook.yaml.ChangeYamlPropertyConditionally:
propertyKey: spec.replicas
newValue: "5"
conditions:
- key: kind
value: Deployment
- key: metadata.labels.environment
value: productionUpdate the version in a path while preserving prefix and suffix using capture groups, only for Deployments:
---
type: specs.openrewrite.org/v1beta/recipe
name: com.yourorg.UpdateVersion
displayName: Update version in path
recipeList:
- com.anacoders.cookbook.yaml.ChangeYamlPropertyConditionally:
propertyKey: spec.path
oldValue: "(.*/)v[0-9]+\\.[0-9]+\\.[0-9]+(/.*)"
newValue: "$1v2.0.0$2"
regex: true
conditions:
- key: kind
value: DeploymentThis transforms /apps/myapp/v1.2.3/config/settings.yaml into /apps/myapp/v2.0.0/config/settings.yaml.
| Option | Description | Example |
|---|---|---|
propertyKey |
The key to look for (dot notation). Supports glob patterns. | spec.replicas |
newValue |
The new value to set | 3 |
oldValue |
Only change if current value matches (exact match, or regex if regex: true) |
1 |
regex |
If true, interpret oldValue as a regex pattern (default: false) |
true |
relaxedBinding |
Use relaxed binding rules for matching (default: true) |
false |
conditions |
List of conditions that must ALL match (AND logic) for change to occur | See examples |
conditions[].key |
Property key to check (dot notation) | kind |
conditions[].value |
Value that the property must have | Deployment |
filePattern |
Optional glob to filter files | **/k8s/**/*.yaml |
- ✅ Uses dot notation for nested properties (e.g.,
spec.replicas) - ✅ Supports glob patterns in property key (e.g.,
spec.*.replicas) - ✅ Regex-based replacement with capture groups (
$1,$2, etc.) whenregex: true - ✅ Multiple conditions with AND logic (all must match)
- ✅ Conditions evaluated per YAML document (supports multi-document files)
- ✅ No change if target value already matches
- ✅ No change if
oldValuedoesn't match current value - ✅ Optional file pattern filtering
- ✅ Supports relaxed binding (kebab-case, camelCase matching)
Change an HCL attribute value based on comment-based conditions. Useful for updating Terraform configurations conditionally.
Update version only in modules marked with a # release-channel: stable comment:
---
type: specs.openrewrite.org/v1beta/recipe
name: com.yourorg.UpdateStableModules
displayName: Update stable module versions
recipeList:
- com.anacoders.cookbook.hcl.ChangeHclAttributeConditionally:
attributeName: version
newValue: "2.0.0"
commentConditions:
- pattern: "# release-channel:"
value: stableThis transforms:
module "app" {
# release-channel: stable
source = "registry.example.com/modules/app"
version = "1.0.0"
}Into:
module "app" {
# release-channel: stable
source = "registry.example.com/modules/app"
version = "2.0.0"
}Update the minor version while preserving the patch version:
---
type: specs.openrewrite.org/v1beta/recipe
name: com.yourorg.BumpMinorVersion
displayName: Bump minor version
recipeList:
- com.anacoders.cookbook.hcl.ChangeHclAttributeConditionally:
attributeName: version
oldValue: "1\\.0\\.(\\d+)"
newValue: "2.0.$1"
regex: true
commentConditions:
- pattern: "# release-channel:"
value: stable| Option | Description | Example |
|---|---|---|
attributeName |
The HCL attribute name to update | version |
newValue |
The new value to set | 2.0.0 |
oldValue |
Only change if current value matches (exact match, or regex if regex: true) |
1.0.0 |
regex |
If true, interpret oldValue as a regex pattern (default: false) |
true |
commentConditions |
List of comment conditions that must ALL match (AND logic) | See examples |
commentConditions[].pattern |
Comment text pattern to match (include # prefix) |
# release-channel: |
commentConditions[].value |
Value that must appear after the pattern | stable |
filePattern |
Optional glob to filter files | **/*.tf |
- ✅ Updates HCL attribute values in Terraform files
- ✅ Comment-based conditions check comments within the containing block
- ✅ Multiple conditions with AND logic (all must match)
- ✅ Regex-based replacement with capture groups (
$1,$2, etc.) whenregex: true - ✅ No change if target value already matches
- ✅ No change if
oldValuedoesn't match current value - ✅ Optional file pattern filtering
- ✅ Preserves quoting style (quoted strings stay quoted)
Add to your build.gradle.kts or build.gradle:
plugins {
id("org.openrewrite.rewrite") version("latest.release")
}
repositories {
mavenCentral()
maven { url = uri("https://jitpack.io") }
}
dependencies {
// Use a specific release version (recommended)
rewrite("com.github.rhart:openrewrite-cookbook:v0.5.0")
// Or use the latest commit from main branch (snapshot)
// rewrite("com.github.rhart:openrewrite-cookbook:main-SNAPSHOT")
// Or use a specific commit hash
// rewrite("com.github.rhart:openrewrite-cookbook:5811e78")
}Then run:
./gradlew rewriteRunYou can also use the recipes directly in code:
import com.anacoders.cookbook.yaml.CreateYamlFilesByPattern;
import com.anacoders.cookbook.yaml.ChangeYamlPropertyConditionally;
import com.anacoders.cookbook.hcl.ChangeHclAttributeConditionally;
import java.util.List;
var createRecipe = new CreateYamlFilesByPattern(
"projects/*/config.yaml",
"apiVersion: v1\nkind: Config"
);
// Simple replacement
var changeRecipe = new ChangeYamlPropertyConditionally(
"spec.replicas", // propertyKey
"3", // newValue
null, // oldValue
null, // regex
null, // relaxedBinding
null, // conditions
null // filePattern
);
// Conditional replacement
var conditionalRecipe = new ChangeYamlPropertyConditionally(
"spec.replicas",
"5",
null,
null,
null,
List.of(
new ChangeYamlPropertyConditionally.Condition("kind", "Deployment"),
new ChangeYamlPropertyConditionally.Condition("metadata.labels.environment", "production")
),
null
);
// Regex replacement with capture groups
var regexRecipe = new ChangeYamlPropertyConditionally(
"spec.path", // propertyKey
"$1v2.0.0$2", // newValue
"(.*/)v[0-9]+\\.[0-9]+\\.[0-9]+(/.*)", // oldValue (regex)
true, // regex
null, // relaxedBinding
null, // conditions
"**/k8s/**/*.yaml" // filePattern
);
// HCL attribute change with comment conditions
var hclRecipe = new ChangeHclAttributeConditionally(
"version", // attributeName
"2.0.0", // newValue
null, // oldValue
null, // regex
List.of(
new ChangeHclAttributeConditionally.CommentCondition(
"# release-channel:",
"stable"
)
),
"**/*.tf" // filePattern
);Build and test:
./gradlew build testTest locally in another project:
./gradlew publishToMavenLocalThen in your test project, use mavenLocal() in repositories and reference:
rewrite("com.anacoders:openrewrite-cookbook:latest.integration")Apache License 2.0
This project uses JitPack for distribution - no manual publishing needed!
-
Tag a version:
git tag v0.1.0 git push origin v0.1.0
-
Create a GitHub Release (optional but recommended):
- Go to your GitHub repository
- Click "Releases" → "Create a new release"
- Select your tag (e.g.,
v0.1.0) - Add release notes describing changes
- Publish the release
-
JitPack builds automatically!
- Visit https://jitpack.io/#rhart/openrewrite-cookbook
- Your release will be available within a few minutes
- Users can then add it as a dependency
For testing unreleased features, users can depend on a specific commit:
- Get the commit hash from GitHub (short form, first 7-10 characters)
- Use it as the version:
rewrite("com.github.rhart:openrewrite-cookbook:abc1234")
Note: JitPack will build the commit on first request, which may take a few minutes. Check the build status at https://jitpack.io/#rhart/openrewrite-cookbook