Prep OpenMetadata Product Update
Overview
The user maintains open-metadata-site (this repo). Each OpenMetadata release needs a matching markdown file under content/product-updates/ and a metadata entry in content/product-updates/versions.json. This skill takes a release identifier (a GitHub release URL or the product-updates page URL) and produces both files in the exact style the site already uses.
Inputs Accepted
https://github.com/open-metadata/OpenMetadata/releases/tag/X.Y.Z-release
https://open-metadata.org/product-updates#vX.Y.Z-changelog
- Bare version + link — anything containing
X.Y.Z is enough to derive the tag.
Workflow
Follow these steps in order. Do not skip.
1. Parse the version
Extract X.Y.Z from the link. The GitHub tag is X.Y.Z-release. The site version string is vX.Y.Z. The file is content/product-updates/vX.Y.Z.md.
2. Confirm the previous release
Read content/product-updates/versions.json to find the most recent published version. Use its tag (e.g. 1.13.3-release) as the base for the GitHub compare. Note its id — the new file's id is max(id) + 1.
3. Pull the release notes and commit list
Try the release body first:
rtk gh api repos/open-metadata/OpenMetadata/releases/tags/X.Y.Z-release | jq -r '.body'
If body is null or empty (common when the release is still being cut), fall back to the compare API and paginate manually — 100 per page — because releases regularly exceed 100 commits and --paginate gets swallowed by rtk's jq filter:
gh api "repos/open-metadata/OpenMetadata/compare/PREV-release...X.Y.Z-release?per_page=100&page=1" > /tmp/p1.json
gh api "repos/open-metadata/OpenMetadata/compare/PREV-release...X.Y.Z-release?per_page=100&page=2" > /tmp/p2.json
jq -r '.commits[] | "\(.sha[0:8]) \(.commit.message | split("\n")[0])"' /tmp/p*.json > /tmp/commits.txt
Check .total_commits first to know how many pages to fetch.
4. Read the previous version file as a style reference
content/product-updates/vPREV.md shows the exact tone, grouping, and formatting for a maintenance release. Match it:
- One-sentence release summary at the top of
## Changelog, calling out the themes (e.g. "connector reliability, search and lineage correctness, governance workflow stability").
- Group by area using the emoji headings from
content/product-updates/README.md:
- 🔌 Connectors & Ingestion
- 📊 Data Quality
- 🔍 Search & Discovery
- 🛡️ Data Governance & Quality
- 🔗 Lineage
- 🤖 MCP Server / Automations
- 🔐 Authentication
- ⚙️ Platform
- 🎛️ UI
- 🔒 Security
- 📣 Notifications
- ⚠️ Backward Incompatible Changes (only if present)
- Each bullet is one line:
**Short problem statement** [#PR](url): what the fix does + why it matters. Focus on user-facing symptoms, not internal refactors.
5. Filter commits
Drop from the changelog:
- CI / workflow tweaks (
ci:, test(playwright):, test(e2e):, fix(e2e):, chore:, build fix, nit, "Revert" followed by a re-apply)
- Merge commits and branch rebases
- Version bump commit itself (
chore(release): bump version to X.Y.Z)
- Test flake fixes that don't affect end users
- Anything that got reverted with no re-apply
Keep:
- Connector fixes with a named connector (Snowflake, Databricks, Oracle, BigQuery, MLflow, Tableau, Trino, Unity Catalog, Fivetran, KafkaConnect, ADLS, BurstIQ, etc.)
- Security bumps that clear a specific CVE or upgrade a runtime (Debian, Python, netty, thrift, BouncyCastle, httpclient5, c3p0, sqlparse, libthrift, etc.) — group these together under 🔒 Security
- Search, lineage, governance, workflow, and MCP fixes
- Backend fixes with visible impact (async delete, pagination, API endpoints, permissions)
- Real UI regressions and new UI affordances
- Migrations — always call these out (search for "migration" in the commit body if unsure)
- Anything explicitly marked "Fixes #NNNN"
If a fix was reverted, then re-applied later in the same release, cite the final PR only.
6. Look up PR titles when unclear
The commit subject is usually enough. If a subject is opaque, fetch the PR body:
gh pr view NNNN --repo open-metadata/OpenMetadata --json title,body
Do this sparingly — batch grouping decisions from the subjects first.
7. Write the file
Path: content/product-updates/vX.Y.Z.md. Frontmatter:
---
id: NEXT_ID
version: vX.Y.Z
date: Released on Nth <Month> YYYY.
---
date — parse the release's published_at from the GitHub API. Format is the site's convention: Released on 21st August 2026. with ordinal suffix (1st, 2nd, 3rd, 4th…).
- Body starts with
## Changelog on line 8 (one blank line above), matching the previous file.
8. Update versions.json
Prepend the new version to the array in content/product-updates/versions.json:
{
"version": "vX.Y.Z",
"date": "Released on Nth <Month> YYYY.",
"hasFeatures": false
},
Set hasFeatures to true only if the release has a ## Features section with actual product features (not maintenance fixes). For every X.Y.Z patch release, hasFeatures is false.
9. Verify
Before reporting done:
rtk proxy grep "^id:" content/product-updates/*.md | sort -t: -k2 -n | tail — confirm no duplicate IDs.
- Open
versions.json and check the new entry is first and the JSON is still valid.
- Skim the generated markdown once — every bullet should read as a sentence a user cares about, every link should point at a real PR.
Style Rules (do not violate)
- One line per fix. No sub-bullets, no paragraphs.
- Bold the problem, not the fix. Users scan for symptoms.
- Cite the merged PR, not the linked issue. Link format:
[#NNNNN](https://github.com/open-metadata/OpenMetadata/pull/NNNNN).
- Never fabricate PR numbers. If you can't find the PR, leave the commit SHA link:
[\abcdef12`](https://github.com/open-metadata/OpenMetadata/commit/abcdef12345…)`.
- No emojis in bullet text, only in section headings.
- No "we", "our", "the team". Third-person, present tense.
- Group carry-forwards from the previous release only when they were actively reinforced (a follow-up fix in this release). Otherwise skip — don't rehash last version's changelog.
Quick Reference
| Task |
Command |
| Release body |
gh api repos/open-metadata/OpenMetadata/releases/tags/X.Y.Z-release | jq -r '.body' |
| Compare commits |
gh api "repos/open-metadata/OpenMetadata/compare/PREV-release...X.Y.Z-release?per_page=100&page=N" |
| PR detail |
gh pr view NNNN --repo open-metadata/OpenMetadata --json title,body |
| Next id |
grep "^id:" content/product-updates/*.md | awk -F: '{print $NF+0}' | sort -n | tail -1 |
| Published date |
gh api repos/open-metadata/OpenMetadata/releases/tags/X.Y.Z-release | jq -r '.published_at' |
Common Mistakes
- Skipping pagination.
--paginate + jq -s looks fine but silently truncates when the compare exceeds a page. Always check .total_commits and fetch page-by-page.
- Copying the raw commit list. The changelog is curated, not a mirror of
git log. If a bullet doesn't have a user-facing effect, drop it.
- Wrong id. New files continue the counter from the highest existing
id:, not from the previous version's id + 1 (patches can be out of order — always take the max).
hasFeatures: true on a patch. A patch never has a Features section. Only major/minor releases do.
- Guessed dates. Read
published_at from the GitHub API; don't guess from the tag name.
Verification Checklist
Before ending the turn:
1---2name: prep-product-update3description: Use when the user shares an OpenMetadata GitHub release link (github.com/open-metadata/OpenMetadata/releases/tag/X.Y.Z-release) or the product-updates page URL for a version, and wants the site's product update page prepared. Also use when asked to "prep the product update", "draft the changelog", "add release notes", or "generate the release page" for a new version of open-metadata-site.4---56# Prep OpenMetadata Product Update78## Overview910The user maintains open-metadata-site (this repo). Each OpenMetadata release needs a matching markdown file under `content/product-updates/` and a metadata entry in `content/product-updates/versions.json`. This skill takes a release identifier (a GitHub release URL or the product-updates page URL) and produces both files in the exact style the site already uses.1112## Inputs Accepted1314- `https://github.com/open-metadata/OpenMetadata/releases/tag/X.Y.Z-release`15- `https://open-metadata.org/product-updates#vX.Y.Z-changelog`16- Bare version + link — anything containing `X.Y.Z` is enough to derive the tag.1718## Workflow1920Follow these steps in order. Do not skip.2122### 1. Parse the version2324Extract `X.Y.Z` from the link. The GitHub tag is `X.Y.Z-release`. The site version string is `vX.Y.Z`. The file is `content/product-updates/vX.Y.Z.md`.2526### 2. Confirm the previous release2728Read `content/product-updates/versions.json` to find the most recent published version. Use its tag (e.g. `1.13.3-release`) as the base for the GitHub compare. Note its `id` — the new file's `id` is `max(id) + 1`.2930### 3. Pull the release notes and commit list3132Try the release body first:3334```bash35rtk gh api repos/open-metadata/OpenMetadata/releases/tags/X.Y.Z-release | jq -r '.body'36```3738If `body` is `null` or empty (common when the release is still being cut), fall back to the compare API and paginate manually — 100 per page — because releases regularly exceed 100 commits and `--paginate` gets swallowed by rtk's jq filter:3940```bash41gh api "repos/open-metadata/OpenMetadata/compare/PREV-release...X.Y.Z-release?per_page=100&page=1" > /tmp/p1.json42gh api "repos/open-metadata/OpenMetadata/compare/PREV-release...X.Y.Z-release?per_page=100&page=2" > /tmp/p2.json43jq -r '.commits[] | "\(.sha[0:8]) \(.commit.message | split("\n")[0])"' /tmp/p*.json > /tmp/commits.txt44```4546Check `.total_commits` first to know how many pages to fetch.4748### 4. Read the previous version file as a style reference4950`content/product-updates/vPREV.md` shows the exact tone, grouping, and formatting for a maintenance release. Match it:5152- **One-sentence release summary** at the top of `## Changelog`, calling out the themes (e.g. "connector reliability, search and lineage correctness, governance workflow stability").53- **Group by area** using the emoji headings from `content/product-updates/README.md`:54 - 🔌 Connectors & Ingestion55 - 📊 Data Quality56 - 🔍 Search & Discovery57 - 🛡️ Data Governance & Quality58 - 🔗 Lineage59 - 🤖 MCP Server / Automations60 - 🔐 Authentication61 - ⚙️ Platform62 - 🎛️ UI63 - 🔒 Security64 - 📣 Notifications65 - ⚠️ Backward Incompatible Changes (only if present)66- **Each bullet is one line**: `**Short problem statement** [#PR](url): what the fix does + why it matters.` Focus on user-facing symptoms, not internal refactors.6768### 5. Filter commits6970Drop from the changelog:7172- CI / workflow tweaks (`ci:`, `test(playwright):`, `test(e2e):`, `fix(e2e):`, `chore:`, `build fix`, `nit`, "Revert" followed by a re-apply)73- Merge commits and branch rebases74- Version bump commit itself (`chore(release): bump version to X.Y.Z`)75- Test flake fixes that don't affect end users76- Anything that got reverted with no re-apply7778Keep:7980- Connector fixes with a named connector (Snowflake, Databricks, Oracle, BigQuery, MLflow, Tableau, Trino, Unity Catalog, Fivetran, KafkaConnect, ADLS, BurstIQ, etc.)81- Security bumps that clear a specific CVE or upgrade a runtime (Debian, Python, netty, thrift, BouncyCastle, httpclient5, c3p0, sqlparse, libthrift, etc.) — group these together under 🔒 Security82- Search, lineage, governance, workflow, and MCP fixes83- Backend fixes with visible impact (async delete, pagination, API endpoints, permissions)84- Real UI regressions and new UI affordances85- **Migrations** — always call these out (search for "migration" in the commit body if unsure)86- Anything explicitly marked "Fixes #NNNN"8788If a fix was reverted, then re-applied later in the same release, cite the final PR only.8990### 6. Look up PR titles when unclear9192The commit subject is usually enough. If a subject is opaque, fetch the PR body:9394```bash95gh pr view NNNN --repo open-metadata/OpenMetadata --json title,body96```9798Do this sparingly — batch grouping decisions from the subjects first.99100### 7. Write the file101102Path: `content/product-updates/vX.Y.Z.md`. Frontmatter:103104```markdown105---106id: NEXT_ID107version: vX.Y.Z108date: Released on Nth <Month> YYYY.109---110```111112- `date` — parse the release's `published_at` from the GitHub API. Format is the site's convention: `Released on 21st August 2026.` with ordinal suffix (`1st`, `2nd`, `3rd`, `4th`…).113- Body starts with `## Changelog` on line 8 (one blank line above), matching the previous file.114115### 8. Update versions.json116117Prepend the new version to the array in `content/product-updates/versions.json`:118119```json120{121 "version": "vX.Y.Z",122 "date": "Released on Nth <Month> YYYY.",123 "hasFeatures": false124},125```126127Set `hasFeatures` to `true` only if the release has a `## Features` section with actual product features (not maintenance fixes). For every `X.Y.Z` patch release, `hasFeatures` is `false`.128129### 9. Verify130131Before reporting done:132133- `rtk proxy grep "^id:" content/product-updates/*.md | sort -t: -k2 -n | tail` — confirm no duplicate IDs.134- Open `versions.json` and check the new entry is first and the JSON is still valid.135- Skim the generated markdown once — every bullet should read as a sentence a user cares about, every link should point at a real PR.136137## Style Rules (do not violate)138139- **One line per fix.** No sub-bullets, no paragraphs.140- **Bold the problem, not the fix.** Users scan for symptoms.141- **Cite the merged PR**, not the linked issue. Link format: `[#NNNNN](https://github.com/open-metadata/OpenMetadata/pull/NNNNN)`.142- **Never fabricate PR numbers.** If you can't find the PR, leave the commit SHA link: `[\`abcdef12\`](https://github.com/open-metadata/OpenMetadata/commit/abcdef12345…)`.143- **No emojis in bullet text**, only in section headings.144- **No "we", "our", "the team".** Third-person, present tense.145- **Group carry-forwards from the previous release only when they were actively reinforced** (a follow-up fix in this release). Otherwise skip — don't rehash last version's changelog.146147## Quick Reference148149| Task | Command |150|---|---|151| Release body | `gh api repos/open-metadata/OpenMetadata/releases/tags/X.Y.Z-release \| jq -r '.body'` |152| Compare commits | `gh api "repos/open-metadata/OpenMetadata/compare/PREV-release...X.Y.Z-release?per_page=100&page=N"` |153| PR detail | `gh pr view NNNN --repo open-metadata/OpenMetadata --json title,body` |154| Next id | `grep "^id:" content/product-updates/*.md \| awk -F: '{print $NF+0}' \| sort -n \| tail -1` |155| Published date | `gh api repos/open-metadata/OpenMetadata/releases/tags/X.Y.Z-release \| jq -r '.published_at'` |156157## Common Mistakes158159- **Skipping pagination.** `--paginate` + `jq -s` looks fine but silently truncates when the compare exceeds a page. Always check `.total_commits` and fetch page-by-page.160- **Copying the raw commit list.** The changelog is curated, not a mirror of `git log`. If a bullet doesn't have a user-facing effect, drop it.161- **Wrong id.** New files continue the counter from the highest existing `id:`, not from the previous version's id + 1 (patches can be out of order — always take the max).162- **`hasFeatures: true` on a patch.** A patch never has a Features section. Only major/minor releases do.163- **Guessed dates.** Read `published_at` from the GitHub API; don't guess from the tag name.164165## Verification Checklist166167Before ending the turn:168169- [ ] `content/product-updates/vX.Y.Z.md` exists with the correct frontmatter.170- [ ] `content/product-updates/versions.json` has the new entry as its first element.171- [ ] Every PR link is a real PR on `open-metadata/OpenMetadata`.172- [ ] Every reverted-and-not-reapplied change is absent.173- [ ] The one-sentence intro names the themes, not just "maintenance release".174- [ ] Migrations are called out explicitly.175- [ ] Security section groups CVE bumps together with the CVE ID where known.