feat(changelog): Phase 3 - Issue Forms + render + structured webhook#315
Merged
Conversation
…ebhook Companion to beshu-tech/ror-api#86 + #91. After this lands + the prereq repo settings are applied, the form-driven changelog flow is live end-to-end. ADD .github/ISSUE_TEMPLATE/changelog-entry.yml + config.yml 2-field form (version + freeform notes). Each line: <type> (<comp>) <text>. Label 'changelog-entry' applied; blank issues disabled. ADD .github/workflows/maintainer_gate.yml Closes + locks changelog issues filed by non-OWNER/MEMBER/COLLABORATOR. ~10-30s public window accepted (per prior agreement). ADD .github/workflows/changelog_form.yml On issues [opened, edited] with 'changelog-entry' label: 1. Parse form body 2. Map types + canonical components (es/kbn/eck, combinable | / & 'and') 3. Validate version semver 4. Write changelog/<version>.yaml + open/refresh PR via peter-evans 5. Auto-rename issue title, comment PR link, close issue Reads .github/changelog-config.yml -> auto_merge toggle. Default false. ADD .github/workflows/render_changelog.yml On push to master OR PR touching changelog/*.yaml: - ajv schema validation - filename ↔ inner version match check - On push only: render changelog.md from YAMLs (semver.rcompare sort), commit + push back to master ADD .github/schemas/changelog-entry.schema.json Required: version (semver+pre-release), release_date (date), entries (>=1). Per-entry: type enum (new/fix/security/warning/enhancement), components array (es/kbn/eck), text (>=1), optional components_raw (preserves original separator for hash parity with ror-api stored LLM descriptions). ADD .github/changelog-config.yml Single source for form behavior. Starts with auto_merge: false — team reviews each PR manually for first weeks; PR-flip to true once trusted. MODIFY .github/workflows/changelog_watch.yml Now fires on push touching changelog/*.yaml (not changelog.md — that's now an auto-gen mirror). Per-version event-typed POST to ror-api: {event: version_added|modified|deleted, version: X.Y.Z, yaml: <content>} Bot-pushed changelog.md regens don't trigger watch (paths filter excludes). Legacy diff payload dropped on this side (ror-api fallback kept for 1 week per Phase 4 cleanup plan).
This comment was marked as outdated.
This comment was marked as outdated.
…e + improved migration CI was failing on 1.26.0.yaml (and other pre-1.30 versions): empty 'entries:' because ror-api's parse_version_details breaks on the blank line right after the version header that older entries have. Fixes: 1. Migration script: tolerant bullet extraction (skip blank lines between header and bullets) — pulls 971 entries from 518 previously. 2. Schema: 'components' now optional when 'components_raw' is present. Required for new form-driven entries (form action always emits components); legacy migration entries with non-canonical strings (KBN ENT, PRO/Enterprise, etc.) emit components_raw only and pass. 3. Schema: type can be any string, not just the canonical 5. Pre-1.30 entries had freeform type labels that don't map cleanly. Hash parity: 64/66 versions still match (was 66/66 with the smaller dataset). The 2 that don't (1.26.0, 1.35.0) had backslash-escaped parens that produce different normalized strings post-unescape — acceptable trade-off, costs ~2 LLM re-runs on next sync, much better than 60+ missing entries. Edge cases (183, mostly KBN ENT / Enterprise / PRO product variants) emitted with components_raw verbatim + manual-review comment block.
…it empty text/components_raw
Updates 1.26.0.yaml + 1.35.0.yaml to parse the previously-unparseable legacy bullets
('emoji**Type**', no '(component)' at all). Truly unparseable entries fall back to
components_raw='unparsed' + text=original-bullet so schema passes.
Collaborator
Author
After this merges: follow-up sync neededThe default branch in this repo is `develop` but the changelog-form flow has to live on `master` (`changelog_watch.yml` fires on master push). After this PR merges:
Same pattern as prior maintenance (`c215bd3 Merge branch 'master' into develop`). #316 has the exact rebase commands in its body. Also applies retroactively to #314 — content is on master but not develop. #316 carries both forward in one PR.
|
coutoPL
reviewed
May 13, 2026
- schema: drop null from entries.type, restore minItems: 1. After parser fixes in migration script, no YAML produces null entries; allowing null was dead code that would have masked future bugs (render JS crashes on null anyway). - changelog-config.yml: auto_merge true -> false. Ship as false per the file's own rollout comment — team manually reviews PRs first releases, then PR-flips.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
Phase 3 of the UI-for-Changelog cutover. Companion to:
The merge of THIS PR is the actual cutover. After merge:
changelog.mdchangelog.mdbecomes auto-generated fromchangelog/*.yamlWhat lands
Workflows
maintainer_gate.ymlchangelog_form.ymlchangelog/<version>.yaml→ open/refresh PRrender_changelog.ymlchangelog.mdchangelog_watch.ymlchangelog/*.yamlchanges, sends event-typed structured payloadTemplates
.github/ISSUE_TEMPLATE/changelog-entry.yml— 2-field form (version + notes textarea).github/ISSUE_TEMPLATE/config.yml— disables blank issuesSchema + config
.github/schemas/changelog-entry.schema.json— single source of YAML truth. Includes optionalcomponents_rawfor hash parity with stored LLM descriptions..github/changelog-config.yml—auto_merge: false(default). Flip totrueonce trusted to make form PRs auto-merge.Modified
changelog_watch.ymlpayloadBefore (
changelog.mddiff):{ "changelog_diff": "<git unified diff>" }After (per-version event):
{ "event": "version_added | version_modified | version_deleted", "version": "1.69.0", "yaml": "<full YAML content>" }One POST per changed YAML in the push. ror-api PR #91 accepts both formats during 1-week dual-window (legacy
find_versions_affectedkept as fallback).Bot-authored render commits don't loop
render_changelog.ymlpusheschangelog.mdregens back to master.changelog_watch.ymlpaths filter ischangelog/*.yamlonly → bot'schangelog.mdcommits don't re-trigger the watch.Required repo settings (apply BEFORE merge)
These won't function without these — same settings already applied on
ton77v/changelog-forms-demo(see demo PLAN.md):(Need admin permissions on the repo.)
Verification after merge
File a test changelog issue from your maintainer account → expect:
[Changelog X.Y.Z] <summary>title (auto-renamed)masterwithchangelog/X.Y.Z.yamlFile a test issue from a non-maintainer account → expect auto-close + lock <30s
Merge the bot's test PR → expect:
changelog.mdregenerated by render workflow (auto-commit bygithub-actions[bot])changelog_watch.ymlfires → POSTs new structured payload → ror-api receives + queuestry_release_updatefor the versionjust -g prod logs ror-portal --since 10m | grep -i changelogDelete a test YAML → render workflow regenerates
changelog.mdwithout it, watch sendsversion_deletedevent, ror-api logs + skips.Rollback path
If anything regresses:
changelog_diffpayload (PR ROR 1.29.0 release #91 kept the fallback)changelog_watch.yml(the modified file is the only one with a prior version on master)Phase 4 (next, ~1 week later)
After 1 week of clean dual-window operation:
find_versions_affected+ legacychangelog_diffbranch in ror-apiupdate_changelog()parse_changelog()(line 65); rewireparse_changelog_structuredto iterate YAMLsdetailed_changelog.pysource from MD parsing → YAML loading (keeps GitBook integration intact)