Versioning & Contracts
Pikku tracks the "contract" of each function β its name and input/output schemas β and detects when contracts change between releases. This prevents accidental breaking changes when multiple clients depend on your API.
How It Worksβ
- Each function's contract is hashed (function key + input schema + output schema β 16-char hex hash)
- Hashes are stored in a version manifest (
versions.pikku.json) - On each build, the CLI compares current contracts against the manifest
- If a contract changed without a version bump, the build fails
Quick Startβ
Initialize the manifestβ
npx pikku versions init
This creates versions.pikku.json with the current contract hashes for all your functions.
Check for breaking changesβ
npx pikku versions check
Compares current function contracts against the manifest. Fails if:
- A published contract was modified (input/output schema changed)
- A version bump is required but not applied
Update the manifestβ
npx pikku versions update
Records the current contracts into the manifest. Run this after bumping function versions.
Version Manifestβ
The manifest file (versions.pikku.json) tracks contract history:
{
"manifestVersion": 1,
"contracts": {
"createTodo": {
"latest": 1,
"versions": {
"1": "a1b2c3d4e5f6g7h8"
}
},
"getTodos": {
"latest": 2,
"versions": {
"1": "i9j0k1l2m3n4o5p6",
"2": "q7r8s9t0u1v2w3x4"
}
}
}
}
Each function entry contains:
latestβ The current version numberversionsβ A map of version numbers to contract hashes
Versioning Rulesβ
The contract system enforces strict rules:
| Rule | Description |
|---|---|
| Immutability | Published version hashes cannot change |
| Sequential versioning | New versions must be latest + 1 |
| No gaps | Cannot skip version numbers (e.g., 1 β 3) |
| Change detection | Modified contracts require a version bump |
| Manifest consistency | The latest field must match the highest version key |
Contract Hashesβ
A contract hash is computed from:
- The function key (name)
- The input JSON schema
- The output JSON schema
If any of these change, the hash changes, indicating a potentially breaking modification.
Error Codesβ
| Code | Name | Description |
|---|---|---|
| PKU860 | MANIFEST_MISSING | Version manifest not found β run versions init |
| PKU861 | FUNCTION_VERSION_MODIFIED | Contract hash changed for an existing version (immutable) |
| PKU862 | CONTRACT_CHANGED_REQUIRES_BUMP | Latest contract changed without a version bump |
| PKU863 | VERSION_REGRESSION_OR_CONFLICT | New version is β€ latest but not in the manifest |
| PKU864 | VERSION_GAP_NOT_ALLOWED | Version skips a number (e.g., 1 β 3) |
| PKU865 | MANIFEST_INTEGRITY_ERROR | latest field doesn't match the highest version key |
CI Integrationβ
Add contract checking to your CI pipeline to catch breaking changes before they're deployed:
# GitHub Actions example
- name: Check API contracts
run: npx pikku versions check
If a function's input or output schema changed, the check fails and the developer must explicitly bump the version number β making breaking changes intentional rather than accidental.
Workflowβ
- Develop β Change function inputs/outputs as needed
- Check β
npx pikku versions checkdetects the contract change - Bump β Increment the function's version number
- Update β
npx pikku versions updaterecords the new contract - Commit β Check in the updated
versions.pikku.json