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.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.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.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.json