Working with Changelogs
Each product has a changelog that tells customers what changed. Your pull requests and deploy script keep it complete; your team decides what customers see and when.
How it fits together
| Changelog | One per product, like cl_…, linked to the product’s repositories. |
| Change | One thing that changed: new, improved or fixed, for public (customers read it) or internal. |
| Release | Collects changes. There’s always one open release; a deploy ships it; a lead publishes it for customers. |
What your deploy script does
- With each pull request, check whether it has a change. Ask by pull request; an empty list means record one.
curl -G "https://api.olamma.sh/v1/w/your-workspace/changes" \ -H "Authorization: Bearer $OLAMMA_KEY" \ --data-urlencode 'product=APP' \ --data-urlencode 'pullRequest={"repo":"acme/app","number":415}'const response = await fetch(`https://api.olamma.sh/v1/w/your-workspace/changes?${new URLSearchParams({"product":"APP","pullRequest":"{\"repo\":\"acme/app\",\"number\":415}"})}`, { headers: { Authorization: `Bearer ${process.env.OLAMMA_KEY}`, }, }); const data = await response.json(); if (!response.ok) throw new Error(`${data.error.code}: ${data.error.message}`);import os import requests response = requests.get( "https://api.olamma.sh/v1/w/your-workspace/changes", headers={"Authorization": f"Bearer {os.environ['OLAMMA_KEY']}"}, params={"product":"APP","pullRequest":"{\"repo\":\"acme/app\",\"number\":415}"}, timeout=30, ) data = response.json() response.raise_for_status() - Record the change in customers’ words. It joins the open release. Linking tasks adds their reporters, so they can be told when it ships.
curl -X POST "https://api.olamma.sh/v1/w/your-workspace/changes" \ -H "Authorization: Bearer $OLAMMA_KEY" \ -H "Idempotency-Key: pr-acme-app-415" \ -H "Content-Type: application/json" \ -d '{ "product": "APP", "type": "fixed", "audience": "public", "title": "Card payments work after a top-up", "pullRequests": [ { "repo": "acme/app", "number": 415 } ], "tasks": [ "APP-12" ] }'const response = await fetch(`https://api.olamma.sh/v1/w/your-workspace/changes`, { method: "POST", headers: { Authorization: `Bearer ${process.env.OLAMMA_KEY}`, "Idempotency-Key": "pr-acme-app-415", "Content-Type": "application/json", }, body: JSON.stringify({ "product": "APP", "type": "fixed", "audience": "public", "title": "Card payments work after a top-up", "pullRequests": [ { "repo": "acme/app", "number": 415 } ], "tasks": [ "APP-12" ] }), }); const data = await response.json(); if (!response.ok) throw new Error(`${data.error.code}: ${data.error.message}`);import os import requests response = requests.post( "https://api.olamma.sh/v1/w/your-workspace/changes", headers={"Authorization": f"Bearer {os.environ['OLAMMA_KEY']}", "Idempotency-Key": "pr-acme-app-415"}, json={ "product": "APP", "type": "fixed", "audience": "public", "title": "Card payments work after a top-up", "pullRequests": [ { "repo": "acme/app", "number": 415 } ], "tasks": [ "APP-12" ] }, timeout=30, ) data = response.json() response.raise_for_status() - After a production deploy, ship the release with the deployed pull requests. Their changes ship; the rest wait in a new open release.
curl -X POST "https://api.olamma.sh/v1/w/your-workspace/releases/ship" \ -H "Authorization: Bearer $OLAMMA_KEY" \ -H "Idempotency-Key: deploy-a1b2c3d" \ -H "Content-Type: application/json" \ -d '{ "product": "APP", "commit": "a1b2c3d", "previousCommit": "9f8e7d6", "pullRequests": [ { "repo": "acme/app", "number": 415 } ] }'const response = await fetch(`https://api.olamma.sh/v1/w/your-workspace/releases/ship`, { method: "POST", headers: { Authorization: `Bearer ${process.env.OLAMMA_KEY}`, "Idempotency-Key": "deploy-a1b2c3d", "Content-Type": "application/json", }, body: JSON.stringify({ "product": "APP", "commit": "a1b2c3d", "previousCommit": "9f8e7d6", "pullRequests": [ { "repo": "acme/app", "number": 415 } ] }), }); const data = await response.json(); if (!response.ok) throw new Error(`${data.error.code}: ${data.error.message}`);import os import requests response = requests.post( "https://api.olamma.sh/v1/w/your-workspace/releases/ship", headers={"Authorization": f"Bearer {os.environ['OLAMMA_KEY']}", "Idempotency-Key": "deploy-a1b2c3d"}, json={ "product": "APP", "commit": "a1b2c3d", "previousCommit": "9f8e7d6", "pullRequests": [ { "repo": "acme/app", "number": 415 } ] }, timeout=30, ) data = response.json() response.raise_for_status() - Check it’s ready. Fix each problem listed, in order: record or skip pull requests without a change, and make sure customers have something to read.
curl -G "https://api.olamma.sh/v1/w/your-workspace/releases/check" \ -H "Authorization: Bearer $OLAMMA_KEY" \ --data-urlencode 'product=APP'const response = await fetch(`https://api.olamma.sh/v1/w/your-workspace/releases/check?${new URLSearchParams({"product":"APP"})}`, { headers: { Authorization: `Bearer ${process.env.OLAMMA_KEY}`, }, }); const data = await response.json(); if (!response.ok) throw new Error(`${data.error.code}: ${data.error.message}`);import os import requests response = requests.get( "https://api.olamma.sh/v1/w/your-workspace/releases/check", headers={"Authorization": f"Bearer {os.environ['OLAMMA_KEY']}"}, params={"product":"APP"}, timeout=30, ) data = response.json() response.raise_for_status()
Shipping on deploy is for changelogs set to release on deploy. Others release on a schedule or by hand in Olamma; List changelogs shows which.
Pull requests nobody would notice
Dependency bumps, tests and tooling don’t need a change. Skip them with a reason, so they stop counting as missing:
curl -X POST "https://api.olamma.sh/v1/w/your-workspace/releases/cr_…/skip" \
-H "Authorization: Bearer $OLAMMA_KEY" \
-H "Idempotency-Key: skip-acme-app-411" \
-H "Content-Type: application/json" \
-d '{
"repo": "acme/app",
"number": 411,
"reason": "Dependency bump; nobody would notice."
}'const response = await fetch(`https://api.olamma.sh/v1/w/your-workspace/releases/cr_…/skip`, {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.OLAMMA_KEY}`,
"Idempotency-Key": "skip-acme-app-411",
"Content-Type": "application/json",
},
body: JSON.stringify({
"repo": "acme/app",
"number": 411,
"reason": "Dependency bump; nobody would notice."
}),
});
const data = await response.json();
if (!response.ok) throw new Error(`${data.error.code}: ${data.error.message}`);import os
import requests
response = requests.post(
"https://api.olamma.sh/v1/w/your-workspace/releases/cr_…/skip",
headers={"Authorization": f"Bearer {os.environ['OLAMMA_KEY']}", "Idempotency-Key": "skip-acme-app-411"},
json={
"repo": "acme/app",
"number": 411,
"reason": "Dependency bump; nobody would notice."
},
timeout=30,
)
data = response.json()
response.raise_for_status()What stays with people
- Publishing a release to customers is proposed through the API and approved by a lead in Olamma. A release with no headline, or nothing public, is refused until it has both.
- Telling reporters emails the people who reported its changes. Email can’t be unsent, so a lead always approves it first.
- Once a release is published, only its leads can change what customers read.
Write public titles in customers’ words: “Receipts load faster”, not “Cache receipt PDFs”. Refactors, alerts and infrastructure are internal.