Skip to content

Patchula.pkl ​

This is the complete repository schema, bundled with every build. Print it with patchula config schema. The configuration guide explains how the pieces fit together.

Top-level fields ​

FieldTypeDefault
managersListing<Manager>every manager
defaultsPolicysee below
rulesListing<Rule>none
filesListing<FileSet>each manager's own patterns
extractorsListing<Extractor>none
ignoreListing<String>none
excludeListing<String>**/node_modules/**, **/vendor/**, **/.git/**
prsPullRequestssee below
lockfilesLockfilessee below
useVersionsHostBooleantrue
submodulesBooleanfalse
ignoreAuthorsListing<String>none

Policy ​

The defaults every rule starts from.

FieldTypeDefault
activeBooleantrue
versions"exact"|"preserve"|"widen""exact"
channel"stable"|"lts""stable"
actionDigestsBooleantrue
imageDigestsBooleantrue
mergeBooleanfalse
groupString?null
labelsListing<String>"dependencies"
commitPrefixString"chore(deps):"
releaseNotesBooleantrue
bodyNotesListing<String>none
permittedString?null
waitHoursInt24
windowsListing<Window>none (any time)

A rule's apply has the same fields as nullable overrides, plus digest, and leaves out the two digest switches. null leaves the earlier value alone.

Pull requests ​

FieldTypeDefault
concurrentInt?null (unlimited)
perHourInt?null (unlimited)
dashboardBooleanfalse
branchString"patchula/"
rebase"conflicts"|"behind""conflicts"
batchMergeBooleanfalse

Lockfiles ​

FieldTypeDefault
refreshBooleanfalse
waitHoursInt0
groupString"lockfile refresh"
tidyGoBooleanfalse
npmEngine"aube"|"npm""aube"
php"static"|"compiled""static"

The schema ​

pkl
/// Patchula's explicit defaults. Vendor with `patchula config schema` and amend
/// this module, or amend an organisation module that itself amends this one.
module Patchula

typealias Manager = "npm"|"bun"|"github-actions"|"mise"|"cargo"|"dockerfile"|"compose"|"go"|"terraform"|"kubernetes"|"kustomize"|"flux"|"helm-values"|"requirements"|"pyproject"|"pre-commit"|"helm"|"devcontainer"|"maven"|"gradle"|"nuget"|"bundler"|"composer"|"regex"
typealias Source = "npm"|"github-releases"|"github-tags"|"github-runners"|"docker"|"crates"|"go"|"terraform"|"pypi"|"helm"|"oci"|"mise"|"forge-tags"|"maven"|"nuget"|"rubygems"|"packagist"
typealias Update = "major"|"minor"|"patch"|"digest"|"pin"
typealias VersionPolicy = "exact"|"preserve"|"widen"
typealias ReleaseChannel = "stable"|"lts"
typealias Scheme = "semver"|"docker"|"pep440"|"poetry"|"maven"|"nuget"|"rubygems"|"composer"|"go"|"hashicorp"|"loose"
/// Dependency roles emitted by first-release managers. npm/bun use the first
/// four roles; Cargo also uses build. Ordinary Go/Python/regex packages use
/// production. Actions distinguish steps from reusable workflows; containers,
/// mise tools, Go language directives, Terraform providers/modules and Helm
/// charts have explicit roles. These are exact values, not match patterns.
typealias DependencyKind = "production"|"development"|"peer"|"optional"|"build"|"action"|"reusable-workflow"|"runner"|"container-image"|"tool"|"go-directive"|"toolchain"|"provider"|"module"|"chart"

/// Match lists are OR; populated selector fields are AND. Empty means any.
/// Patterns are path-aware globs, or `regex:...`; prefix `!` excludes a match.
/// Version filters are `semver:...`, `regex:...`, or their `!` negations.
class Selector {
  packages: Listing<String> = new {}
  dependencies: Listing<String> = new {}
  managers: Listing<Manager> = new {}
  files: Listing<String> = new {}
  updates: Listing<Update> = new {}
  sources: Listing<Source> = new {}
  kinds: Listing<DependencyKind> = new {}
  current: String? = null
}

class Window {
  /// Five-field cron expressions, interpreted in the named IANA timezone.
  cron: Listing<String> = new {}
  zone: String = "UTC"
}

/// Policy applied before rules. No implicit grouping or automatic merging.
class Policy {
  active: Boolean = true
  versions: VersionPolicy = "exact"
  /// Node LTS is opt-in; other sources retain stable selection by default.
  channel: ReleaseChannel = "stable"
  actionDigests: Boolean = true
  imageDigests: Boolean = true
  merge: Boolean = false
  /// Nonempty groups share a PR; an empty string forces individual PRs.
  group: String? = null
  labels: Listing<String> = new { "dependencies" }
  commitPrefix: String = "chore(deps):"
  releaseNotes: Boolean = true
  bodyNotes: Listing<String> = new {}
  permitted: String? = null
  /// Minimum release age when the source reports a date. Current pins are retained.
  waitHours: Int = 24
  /// An empty window list means updates may be proposed at any time.
  windows: Listing<Window> = new {}
}

/// Null leaves an earlier policy unchanged. Rules apply in declaration order;
/// scalars and lists replace earlier values. `digest` overrides source defaults.
class Overrides {
  active: Boolean? = null
  versions: VersionPolicy? = null
  channel: ReleaseChannel? = null
  digest: Boolean? = null
  merge: Boolean? = null
  group: String? = null
  labels: Listing<String>? = null
  commitPrefix: String? = null
  releaseNotes: Boolean? = null
  bodyNotes: Listing<String>? = null
  permitted: String? = null
  waitHours: Int? = null
  windows: Listing<Window>? = null
}

class Rule {
  note: String = ""
  select: Selector = new {}
  apply: Overrides = new {}
}

class FileSet {
  manager: Manager
  /// Replaces that manager's built-in file selection; empty is invalid.
  paths: Listing<String>
}

/// Regex captures use Rust regex syntax: (?<current>...), (?<dependency>...).
/// Templates substitute {capture} only; no expressions or executable helpers.
class Extractor {
  note: String = ""
  paths: Listing<String>
  patterns: Listing<String>
  source: String = "{source}"
  dependency: String = "{dependency}"
  package: String = "{dependency}"
  /// A Scheme name or a template such as "{scheme}".
  scheme: String = "semver"
  /// Optional tag regex with a required named `version` capture.
  extract: String? = null
}

class PullRequests {
  /// Null means unlimited; positive integers set a limit. Zero is invalid.
  concurrent: Int? = null
  perHour: Int? = null
  dashboard: Boolean = false
  branch: String = "patchula/"
  rebase: "conflicts"|"behind" = "conflicts"
  /// The batch PR collects updates whose "Add to batch" box was ticked. It
  /// only auto-merges when this is true, behind the usual check gates.
  batchMerge: Boolean = false
}

class Lockfiles {
  refresh: Boolean = false
  waitHours: Int = 0
  group: String = "lockfile refresh"
  tidyGo: Boolean = false
  /// Engine that regenerates npm lockfiles: aube by default, or native npm.
  /// pnpm and Yarn lockfiles always use aube and Yarn respectively.
  npmEngine: "aube"|"npm" = "aube"
  /// PHP for composer.lock: a prebuilt static binary, or PHP compiled from
  /// source by mise, which needs a C toolchain and development libraries.
  php: "static"|"compiled" = "static"
}

/// All first-release managers are selected unless a repository replaces this list.
managers: Listing<Manager> = new {
  "npm"; "bun"; "github-actions"; "mise"; "cargo"; "dockerfile"; "compose"
  "go"; "terraform"; "kubernetes"; "kustomize"; "flux"; "helm-values"
  "requirements"; "pyproject"; "pre-commit"; "helm"; "devcontainer"; "maven"; "gradle"; "nuget"; "bundler"; "composer"; "regex"
}
defaults: Policy = new {}
rules: Listing<Rule> = new {}
files: Listing<FileSet> = new {}
extractors: Listing<Extractor> = new {}
/// Dependency identifiers to leave untouched, using the same pattern syntax.
ignore: Listing<String> = new {}
/// Generated and vendored directories are excluded; repos can replace the list.
exclude: Listing<String> = new { "**/node_modules/**"; "**/vendor/**"; "**/.git/**" }
prs: PullRequests = new {}
lockfiles: Lockfiles = new {}
/// Prefer mise-versions for public catalogs; false uses the upstream sources.
useVersionsHost: Boolean = true
submodules: Boolean = false
/// Commits by these authors do not trigger a new extraction.
ignoreAuthors: Listing<String> = new {}

MIT licensed. Clean-room: no Renovate source was read in the making of this bat.