Kai Ole Hartwig
pinup · documentation

The plan

Every run produces a machine-readable plan before it writes anything: whatif stops there, run continues. The plan is the backbone, not a debug flag. The compare job, the dashboard, the merge request text and the estate report read it.

  • A plan explains why nothing happens. Every held update carries its reason, when the hold lifts and which rule imposed it.
  • Nothing downstream of the plan invents a change. Branches carry byte-range edits and tasks; apply consumes those, never a dependency.
  • Format: JSON, --report <path>, %s for the project path, schemaVersion 1

The fields

Top level

FieldMeaning
pinupVersion, generatedAtwhich pinup planned, and when
repo.paththe project
limitsprHourlyLimit, prConcurrentLimit as resolved; the runner enforces them
dashboardwhether the dashboard issue is kept, and its title
deps, updates, branches, warnings, statssee below

deps

One entry per dependency per file: manager, file, depName, packageName, currentValue, currentDigest, lockedVersion, datasource, versioning, registryUrls, the values from the pre-lookup rule pass (rangeStrategy, minimumReleaseAge, pinDigests), the locus (byte offsets of value and digest) and, for custom managers, the index and the captures. A dependency that was not looked up says why in skipReason; one disabled by a rule names the rule in disabled.

updates

One entry per movement: dep, newValue (the bytes written), newVersion, newDigest, updateType (major, minor, patch, digest, pin, pinDigest, rollback, lockFileMaintenance, majorAvailable), declared and effective, analyzer and evidence, releaseTime with timeSource, securityFix – and:

branches

One entry per branch: name (Renovate-compatible), title, groupName, updateKeys, edits (file, byte range, old and new bytes, manager), tasks (lock refreshes and post-upgrade commands with their scope), automerge, labels, schedule, existing (the open merge request) and suppressedBy with heldWith where the branch is held as a whole.

warnings

stage (config, extract, lookup, analyze, apply, publish, cache), file, msg. An unreachable datasource, a preset that resolves to nothing, a task whose output left its scope, a cache that is too young: warnings, never a failed run for the rest of the repository.

Reading a plan

# every held update with its reason
jq -r '.updates[] | select(.blocks) | "\(.dep.depName) \(.dep.currentValue) -> \(.newValue): \(.blocks[0].reason) (\(.blocks[0].origin.source))"' plan.json

# the branches that would be written now
jq -r '.branches[] | select(.suppressedBy == null) | .name' plan.json

Next

Back to pinup

The overview: the problem, the fit check, the quickstart, every chapter.

pinup →
Back to pinup

Effective label

The second label on every update: the Helm chart analyzer, the safety rule, matchEffective and trustEffective.

Read →
Effective label