Tasks und Plugins
Der Kern von pinup entscheidet. Ein Task wendet an. Ein Task ist ein Kommando auf dem Checkout des Branches, nach den Edits und vor dem Commit: ein Lock-Refresh, den der Manager kennt, oder ein Kommando, das eine Regel angefordert hat (postUpgradeTasks). Was er ändert, wird mit den Edits in einem Commit eingecheckt. Ein Manifest landet nie ohne sein Lock.
- Kein Plattform-Token, kein Signierschlüssel im Task, nur
PATH,LANG,TZund wasPINUP_PLUGIN_ENVnennt - Allowlist auf dem kompilierten Kommando, Scope auf dem Ergebnis
Lock-Refreshes
| Manager | Kommando | Scope |
|---|---|---|
| composer | composer update <namen> --with-all-dependencies --no-plugins --no-install --no-scripts --no-audit --ignore-platform-reqs (ohne Namen bei Wartung) | composer.lock |
| npm | npm install --package-lock-only --no-audit --ignore-scripts | package-lock.json, npm-shrinkwrap.json |
| npm (yarn classic) | yarn install --ignore-scripts --ignore-engines --ignore-platform --non-interactive | yarn.lock |
| gomod | go mod tidy | go.mod, go.sum |
Eine Maschine ohne die Toolchain hält den Branch mit pluginRequired und nennt das Werkzeug. Eine Wartung für ein Lock, das kein Plugin aktualisiert (ein Terraform-Lock), wird genauso gehalten. Ein Refresh, der nichts ändert, ist nothingToRefresh und öffnet nichts.
Post-Upgrade-Kommandos
"packageRules": [{
"matchDatasources": ["git-refs"],
"postUpgradeTasks": {
"commands": ["node tools/update-expected-commit.mjs {{{packageFile}}}"],
"fileFilters": ["*.yaml"],
"executionMode": "update"
}
}]
Templates im Kommando rendern mit den Variablen des Updates (depName, currentValue, newValue, packageFile …). executionModeupdate läuft einmal pro Update, branch einmal pro Branch mit jedem Update der Regel.
Das Kommando muss einem Muster der allowedCommands des Runners entsprechen (PINUP_ALLOWED_COMMANDS, verankerte Muster, nie die Einstellung eines Repositories). Geprüft wird das kompilierte Kommando, nach dem Templating. Eines, das die Allowlist nicht zulässt, hält den Branch mit taskRefused und nennt das Kommando. Renovate hat das Kommando übersprungen und den Branch trotzdem gepusht. So hat ein Estate wochenlang jeden First-Party-Lock-Refresh verloren, ohne einen roten Job.
Der Scope
Ein Task läuft in einem eigenen HOME, mit PATH, LANG, TZ und dem, was PINUP_PLUGIN_ENV nennt. Sonst nichts: kein Plattform-Token, kein Signierschlüssel. Eine Toolchain, die ein privates Modul holen muss, liest eine .netrc in diesem HOME, aus PINUP_TASK_NETRC, ein read-only-Zugang, der nie als Variable weitergereicht wird.
Was der Task geändert hat, wird gegen seine fileFilters geprüft (das Lock bei einem Refresh, die Liste der Regel bei einem Kommando). Eine Änderung außerhalb des Scopes lässt den Branch beim Namen scheitern und verwirft alles, was der Task getan hat. Ein Task ist kein Weg, beliebige Dateien in ein Repository zu schreiben. Ein Repository, das node_modules/ committet, scheitert an seinem npm-Refresh genau so, zu Recht: der Refresh schreibt node_modules/.package-lock.json.
PINUP_EXECUTION_TIMEOUT (Minuten) begrenzt jeden Task.
Woher die Werkzeuge kommen
Tasks nutzen die Toolchain auf dem PATH des Job-Images: das Toolchain-Image des Runners trägt composer, npm und go, die Kommandos laufen im Prozess, ohne Shell (a || b gibt composer ein Paket namens ||). Eine Container-Variante desselben Vertrags, ein digest-gepinntes Image pro Task, beschreibt die Spezifikation; produktiv bewiesen ist die exec-Variante.
Weiter
Plattformen
GitLab und GitHub hinter einer Schnittstelle: Zugangsdaten, was jede kann und nicht kann.