Add changelog-release-pr composite action#66
Draft
yonib05 wants to merge 29 commits into
Draft
Conversation
…ndered frontmatter
…inst transient PR errors
…es in both streams
…po gating, PR memoization, fail-fast inputs, action_ref pinning, prerelease skip, docs
Drop PRs that only touch docs/website dirs (site/, docs/) from every stream, so the changelog stays focused on SDK+language work. Derive a docsOnly flag from changed-file paths in enrich, and gate entries and new contributors on it. Fix language gating for early python releases re-tagged python/v* whose PRs live in the old flat sdk-python repo (code under src/, no strands-py/ dir): only language-gate when the PR lives in the monorepo repo itself (prRepo === repo), since cross-repo PRs have no dir-based language signal and were being dropped wholesale, emptying those releases. Fetch PR files for all repos now, since the docs-only gate needs them on single-language repos too.
… gating Document the curated narrative-release-notes convention (highlights + markdown body, both preserved across re-syncs) with a template and the rules that keep them valid: don't restate the structured data, start body headings at h3. Add tests for the new-contributors language gate: a monorepo release whose first-contributor PR lives in the old flat repo is not dir-gated, and a docs-only contributor is dropped even on a monorepo stream. Fix the stale deps.enrich JSDoc to include languages and docsOnly.
…otation Newer harness release notes reference PRs as "by @author in #2740" (short form, no full URL) under emoji section headers, which the URL-only TAIL regex missed entirely (parsed 0 bullets). Accept the short form too — prRepo stays null so the caller defaults it to the release's own repo. Also strip the cross-SDK "_(shared with TS/Python)_" annotation from titles; language gating already decides stream membership from the PR's changed files.
…s-only Check out the scripts from github.action_repository (not a hard-coded strands-agents/devtools), so pinning the action to a fork/mirror sha actually runs that fork's scripts instead of upstream. Extend the docs-only filter to top-level documentation files — repo-root Markdown and well-known root docs (README, CONTRIBUTING, AGENTS.md, etc.) — so a PR confined to them is dropped from the changelog like site/ and docs/ PRs already are. A root doc PR that also touches code is still kept.
Only `branch` and `warnings` are consumed by the composite action; the written count is already logged via core.info, so the unused setOutput was misleading API surface.
… body Source structured entries from GitHub's compare API (every merged commit between the prior tag in the same stream and this release, each resolved to its PR via the commit->PR API) instead of parsing the auto-generated "What's Changed" bullet list. This makes the breakdown deterministic and immune to release-note format drift — we'd already hit three body formats (standard bullets, short "in #N", and hand-written prose) that broke or defeated parsing. The body is now curated narrative only (highlights + prose), preserved on re-sync; "New Contributors" is still read from it. New: derive-entries.cjs (deriveEntries + previousTagInStream), semver-compare.cjs (stream-ordering, ported from the site's compareVersionDesc). parse-release-body exposes classifyTitle (shared conventional-commit classifier); its bullet/TAIL entry path is now unused but kept. run-action adds listTags/compareCommits/ commitPulls; run wires prior-tag resolution (backfill from the release list, single via previousTagInStream). 85 tests pass.
…ignal Paginate the compare API's commits array (100/page) when deriving entries — a single page silently dropped every commit past the first 100, producing an incomplete changelog for any release range over 100 commits. Walk all pages and reserve the `truncated` warning for GitHub's genuine 250-commit cap. Also fix language gating: only drop a PR when it has a POSITIVE dir signal for the other language (touches strands-py/ or strands-ts/). PRs with empty languages — root/CI changes, or pre-monorepo flat-layout PRs whose code lived under src/ before the strands-py/ dir existed — are kept, not dropped. Gating on empty languages wrongly emptied pre-monorepo releases re-tagged as python/v*.
…e from compare API parseReleaseBody and countChangelogBullets (plus the TAIL/LOOSE_ENTRY regexes) had no production caller after entries moved to the compare API; only classifyTitle and parseNewContributors are still live. Rework the build-release-file test stub onto a local bullet-body helper and refocus the parse-release-body tests on the two remaining functions. Also document the full-resync reformat churn in the README and note that semver-compare.cjs must stay in sync with the site's compareVersionDesc.
The entries loop and the new-contributors loop applied the same docs-only + language gate independently. Extract dropFromStream(enr) and reuse it in both, so the keep/drop policy lives in one place.
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.
Description
Adds a
changelog-release-pr/composite action that turns GitHub Releases into structured changelog markdown for the harness-sdk docs site (#2717) and opens a PR there. The automation half of the Strands changelog feature.Deterministic, no LLM. Pipeline: fetch release(s) → derive structured entries from the GitHub compare API (every merged commit between the prior tag and this one, each resolved to its PR — independent of release-note format) → enrich each from its linked PR (
area-*labels → areas,breaking changelabel, merge-commit SHA, author, and — for monorepo releases — the changed-file language gate) → rendersite/src/content/changelog/<sdk>/<file>.mdmatching the harness-sdk Zod schema (preserving human-writtenhighlights/body on re-sync) → open a PR via peter-evans/create-pull-request.Built to match devtools house style: dependency-free
.cjsmodules invoked throughactions/github-script(likestrands-command/scripts/javascript/process-input.cjs); pure logic modules with injected fetchers/fs; tests via Node's built-in runner.Notable behaviors
dependabot[bot]), never leaked into entries, language-gated like entries.sdk-python/sdk-typescript; enrichment + links use each PR's own repo.github.action_refscripts checkout so callers pinning@<sha>pin the scripts too; create-pull-request pinned to a commit SHA.Type of Change
New feature
Testing
cd changelog-release-pr/scripts && node --test— 81 tests, all pass. Pure logic modules with injected fetchers/fs, so the whole suite runs offline; coverage spans tag→meta mapping, semver ordering, compare-API entry derivation (commit→PR resolution, dedup, direct-push skip, truncation warning), PR enrichment (areas/breaking/commit, language + docs-only gating, graceful degradation), title classification, new-contributor parsing, markdown rendering (YAML-quoting edge cases, highlights/body preservation on re-sync), and the full build orchestration (language/docs gating, skip-existing, memoization, drafts/prereleases). End-to-end validated against the harness-sdk changelog schema (astro sync+ full site build).Review follow-up (latest commit)
After moving entry derivation to the compare API, the body-parsing path (
parseReleaseBody,countChangelogBullets, and theirTAIL/LOOSE_ENTRYregexes) had no production caller — onlyclassifyTitleandparseNewContributorsremain live. Removed the dead code and reworked the affected tests onto a small local bullet-body helper (built onclassifyTitle), explicitly labeled as a test convenience rather than a production path. How verified: confirmed zero non-test references to the removed symbols via grep before deletion, then re-rannode --test(81 pass / 0 fail). Net −5 tests = dead-function tests dropped, live-function tests added.Consumers / merge order
Called by harness-sdk#2765 and evals#259. This merges first (the
uses:path doesn't exist on devtoolsmainuntil then); after merge, pin those workflows' refs from@mainto the merge SHA.By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice.