feat(changelog): add changelog-release-pr composite action#66
Open
yonib05 wants to merge 31 commits into
Open
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.
Add a push-to-fork input so an account without write access to target-repo (an outside collaborator) can open changelog PRs: the branch lands on its fork and the cross-repo PR is opened against target-repo. A classic PAT with the public_repo scope is sufficient for this flow. Derive the backfill branch name from a content hash of the written release set rather than a constant, so an open-but-unmerged sync PR isn't clobbered by a later run that contains a different set of releases.
…le list The authoring-template example nested a ```python block inside a ```markdown block at the same fence depth, so GitHub closed the outer block early and the rest of the section rendered as broken loose text. Use a 4-backtick outer fence so the 3-backtick inner fence nests legally. Also correct the curated-file list: it claimed six files but seven carry hand-written bodies (evals/v0.1.0 was missing). Drop the hard-coded count so it doesn't drift as more curated notes are added.
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 the
changelog-release-pr/composite action — the automation half of the Strands changelog feature. It turns GitHub Releases into structured changelog markdown for the harness-sdk docs site (#2717) and opens a PR there.Deterministic, no LLM. Pipeline:
area-*labels → areas,breaking changelabel, merge-commit SHA, author, and — for monorepo releases — a changed-file language gate (python vs typescript).site/src/content/changelog/<sdk>/<file>.mdmatching the harness-sdk Zod schema, preserving human-writtenhighlights/body on re-sync.peter-evans/create-pull-request.Built to devtools house style: dependency-free
.cjsmodules invoked throughactions/github-script; pure logic with injected fetchers/fs; tests via Node's built-in runner (node --test).Notable behaviors
dependabot[bot]), never leaked into entries, language-gated like entries.python/v*,typescript/v*, and barev*tags (incl. the archivedsdk-typescript) to the right stream for the one-time backfill.push-to-fork): an account without write access to the target repo opens the PR from its own fork; a classic PAT withpublic_repois sufficient. PRs authored this way (a real user) trigger the required CI Gate, which GITHUB_TOKEN-authored PRs do not.skip-existing): only generates missing files, never regresses existing enrichment.Tests
cd changelog-release-pr/scripts && node --test— 87 tests, all green.Merge order
First in the stack: #66 (this) → #2717 → #2761 → #2765. The sync workflow (#2765) pins this action at
@main, so this must land first.