Configuration
pinup reads Renovate's configuration language. A repository with a renovate.json keeps it. Switching from Renovate changes no byte in a repository.
- Three layers: the run's configuration, the repository's file, the presets
- Merge semantics: Renovate's, measured against it
- Keys:
pinup migrateclassifies every one
Three layers
The run's configuration
--config: a file or a local> preset from the platform (local>group/runner, local>group/runner:release-fast). This is the estate's file: rules, custom managers, presets.
The repository's file
PINUP_RUNNER_PROJECT names the runner project when --config is a file
Exactly one of .pinup.yaml, .pinup.yml, .pinup.json, .pinup.jsonc, renovate.json, renovate.json5, .renovaterc and .renovaterc.json. Two of them is an error, not a silent choice: the one that lost would be edited for weeks with no effect. Which is also why that list is not a precedence. Its extends may name the run's file as local><runner-project>; pinup answers that name from the file it was started with, without a fetch, and also the project's old name after the file has moved. That is how an estate changes its runner without touching the repositories.
Presets
Renovate's built-in names (config:recommended, :disableDependencyDashboard …) come from pinup's own preset library, written from observed behaviour, not from Renovate's source. local> presets of other projects are fetched from the platform.
Merge semantics
The rules are Renovate's, measured against it:
- Objects deep-merge, arrays replace,
nullclears a key. packageRulesconcatenate across all layers and apply in array order. Every matching rule applies to a dependency, later ones win per key.- Rules run twice, as in Renovate: once per dependency before the lookup (a rule can disable, change versioning and registries), once per update, when
matchUpdateTypesandmatchEffectiveare known. - A matcher on an unknown field does not match. A
matchUpdateTypesrule is silent before the lookup, amatchEffectiverule before an analyzer has run.
Every resolved value keeps its whole origin chain. pinup print-config --config … --explain packageRules[25].automerge shows every source that set a path, winner last. A held update in the plan names the rule the same way.
The keys
pinup migrate --config … classifies every key. Supported means: the key does what it does in Renovate, measured. Partial names the difference. Unsupported means: nothing reads it, and the run says so.
Supported
$schema, addLabels, additionalBranchPrefix, allowedCommands, allowedVersions, automerge, branchPrefix, branchTopic, commitMessageAction, commitMessageExtra, commitMessageLowerCase, commitMessagePrefix, commitMessageSuffix, commitMessageTopic, customDatasources, customManagers, dependencyDashboard, dependencyDashboardApproval, dependencyDashboardTitle, description, enabled, enabledManagers, extends, extractVersion, fetchChangeLogs, groupName, groupSlug, ignoreDeps, ignorePaths, ignoreUnstable, internalChecksFilter, labels, lockFileMaintenance, matchCurrentValue, matchDatasources, matchDepNames, matchDepTypes, matchFileNames, matchManagers, matchPackageNames, matchUpdateTypes, minimumReleaseAge, minimumReleaseAgeBehaviour, osvVulnerabilityAlerts, packageRules, pinDigests, platformAutomerge, postUpgradeTasks, prBodyDefinitions, prBodyNotes, prConcurrentLimit, prHourlyLimit, rangeStrategy, registryUrls, schedule, semanticCommitScope, semanticCommitType, semanticCommits, separateMajorMinor, timezone, versioning, vulnerabilityAlerts – and pinup's own analyze, matchEffective, trustEffective.
Partial
matchCurrentVersion– matched as a version, not as a rangematchSourceUrls– the URL as the datasource reports itmatchJsonata– onlyisLockfileUpdateandsourceUrlcommitBody– read, not templatedprCreation– onlyimmediate; the not-pending deadlock is gone by designrebaseWhen– a branch with foreign commits is left alone, otherwise rebase on conflictseparateMinorPatch,separateMultipleMajor,separateMultipleMinor– read into the template variables;separateMajorMinordecidespostUpdateOptions–gomodTidyis what the gomod lock refresh does anyway, the rest is not readexecutionTimeout– the runner decides (PINUP_EXECUTION_TIMEOUT), never a repository
Unsupported
matchCategories– no category model; the rule never fires, andmigratesays so
A key not listed here is not read; migrate lists it as unsupported.
pinup's own keys
| Key | Where | Meaning |
|---|---|---|
analyze | rule | asks an analyzer what actually changed in this dependency's updates; off by default, because it fetches both versions |
matchEffective | rule | matches the analyzer's label: patch, minor, major, breaking-values; never fires while the label is unknown |
trustEffective | rule | lets an automerge stand that a matchEffective rule switched on although the declared label is stricter; without it the stricter label wins |
Custom managers
customManagers with customType: regex work as in Renovate: RE2 expressions with named groups (depName, currentValue, currentDigest, datasource, versioning, registryUrl, packageName, extractVersion), the *Template keys with a Handlebars subset ({{{x}}}, {{#if}}/{{else}}, {{#if (equals a "b")}}), matchStringsStrategyany and recursive. A captured group beats its template. # renovate: and # pinup: are both read.
Environment
| Variable | Meaning |
|---|---|
PINUP_PLATFORM | gitlab (the default) or github; a GitHub token with no GitLab instance in the environment means github |
PINUP_GITLAB_URL / CI_SERVER_URL | the GitLab instance |
PINUP_GITLAB_TOKEN / GITLAB_TOKEN | a personal access token (api, write_repository); CI_JOB_TOKEN when none is set (read-only) |
PINUP_GITHUB_URL / GITHUB_SERVER_URL | the GitHub host; github.com when empty |
PINUP_GITHUB_TOKEN / GITHUB_TOKEN | a token with repo, or a fine-grained one with contents, pull requests and issues read/write |
PINUP_REGISTRY_HOST / CI_REGISTRY | the estate's container registry; the token is exchanged for a pull token there and nowhere else |
GITHUB_COM_TOKEN | for github-* lookups and release notes, bound to api.github.com |
PINUP_GIT_NAME, PINUP_GIT_EMAIL | who commits |
PINUP_SIGNING_FORMAT, PINUP_SIGNING_KEY | openpgp or ssh and the key; unsigned only with the explicit word none |
PINUP_CACHE | the lookup cache (bbolt) |
PINUP_ALLOWED_COMMANDS | JSON array of anchored patterns a postUpgradeTasks command must match; the runner's decision, never a repository's |
PINUP_PLUGIN_ENV | variables a task may see besides PATH, LANG, TZ |
PINUP_TASK_NETRC | a .netrc written into each task's own HOME; never as a variable |
PINUP_EXECUTION_TIMEOUT | minutes per task |
PINUP_RUNNER_PROJECT | the project whose configuration the repositories include |
PINUP_APK_VIEWS | apk indexes served natively besides the public Wolfi repository |
Checking a configuration: pinup advise
pinup advise resolves a configuration the way a run does and says what should change. Every finding carries its pointer, the layer that wrote the value – file, preset or default – and, where the file owns the value, a fix.
pinup advise --config renovate.json --runner 'local>group/pinup-runner'
pinup advise --config renovate.json --plan plan.json # plus what the runs found
pinup advise --config renovate.json --fix --out fixed.json| Category | What it finds |
|---|---|
compat | keys pinup does not read; rules that never fire; a regex with a lookaround; a schedule that does not parse |
hygiene | a value a preset already sets; a preset extended twice; a rule a later one fully shadows |
performance | an ignorePaths that replaces the inherited list instead of adding to it; a lock refresh with no window |
security | an automerge that covers major updates; a registry over HTTP; advisories switched off |
With --plan the runs join in: rules no dependency reached, managers that found nothing, a repository whose every update one setting holds.
--fix applies the fixes byte for byte to JSON, JSONC and JSON5. Comments, order and formatting stay. Nothing is written until a gate has passed: the file is resolved before and after, and every line that differs must lie under a pointer a fix declared. A fix that declares nothing must leave the resolution unchanged. Without --out or --write it is a dry run. --skip holds back checks that need a decision. A YAML file is reported, not rewritten.
Every check with its ID, severity and fix is listed in docs/commands.md in the repository.
Next
Managers, datasources, versionings
Which files are read, which registries are asked, how versions are ordered.