Repository navigation
Scaffold .changes/*.yml template automatically when a PR is opened - #41
Closed
fivetran-catfritz wants to merge 3 commits into
Closed
fivetran-catfritz wants to merge 3 commits into
fivetran-catfritz wants to merge 3 commits into
Conversation
Adds a new scaffold-changes-template job to check-docs-current.yml, gated on github.event.action == 'opened' so it fires exactly once per PR (not on every push). It checks out the PR's actual head branch (not the default merge ref), skips if a real .changes/*.yml or the template already exists, downloads templates/changes-template.yml, and commits it as .changes/TODO.yml.template - a deliberately inert extension that release_yaml_files()'s *.yml glob never matches, so it can't be mistaken for a real release entry until renamed. Reuses the existing check-docs-current.yml caller already deployed in every package repo (on: pull_request: types: [opened, synchronize, reopened]) - no new per-repo workflow file needed. Skipped entirely for fork PRs, since GITHUB_TOKEN/secrets.GH_TOKEN can't push there. Verified: the skip-if-exists check (ls-based, not compgen -G - that doesn't reliably signal "no match" via exit status) against all three cases (nothing exists, real entry exists, template exists), and that templates/changes-template.yml is fetchable from the POC branch URL this hardcodes for now. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…ges was current RELEVANT_CHANGES_YML checked the whole .changes/ path, so the scaffold job's own commit (adding .changes/TODO.yml.template) counted as "last touched .changes/" - making the three-way check think a real changelog entry existed when only the inert template did. Scoped the pathspec to .changes/*.yml specifically, which the template's .yml.template extension doesn't match. Reproduced against a live test PR (fivetran/dbt_amazon_ads#55): after the scaffold job added the template, the docs/generated status wrongly read "Missing: docs regeneration, CHANGELOG.md update" - note the absence of "a .changes/*.yml entry", which should have still been there. Verified locally that scoping the pathspec to .changes/*.yml fixes it. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
fivetran-joemarkiewicz
left a comment
Collaborator
There was a problem hiding this comment.
I like the idea with this PR; however, I believe this would fit better as a skill and not a step in the check-docs github action. See internal notes for more details.
fivetran-catfritz
added a commit
that referenced
this pull request
Oct 21, 2026
Last step before merging: the script URL was hardcoded to this POC branch so it could be curled before the script existed on main. Swapped to refs/heads/main now that this is about to land there. Confirmed via grep: no other references to changelog-poc/initial-test, the scaffold-changes-template approach (superseded, PR #41 closed), or any other stale branch names remain anywhere in the repo. All workflow YAML validates, update_changelog.py's syntax is clean. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
fivetran-catfritz
added a commit
that referenced
this pull request
Oct 21, 2026
* changelog-poc/initial-test
* Fetch update_changelog.py via curl instead of a full checkout
Reusable workflows called via `uses:` only pull in the workflow YAML
itself, not the calling repo's other files - so the script path never
existed on the runner when invoked from a downstream repo. Since this
repo is public, curl the raw script instead of checking out the whole
repo.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
* Hardcode the automations script URL to the POC test branch
github.workflow_ref reflects the top-level caller's own workflow ref
(e.g. a PR merge ref in dbt_amazon_ads), not this reusable workflow's
ref in dbt_package_automations, so it can't be used to derive the
script URL dynamically. Hardcoding for the POC; revisit once this
lands on main.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
* Fix insertion position and match real per-repo CHANGELOG formatting
The insertion logic assumed any leading '#' lines were a document
title to skip past, but dbt_amazon_ads has no separate title - its
newest entry itself is an H1 (e.g. "# dbt_amazon_ads v1.3.1"). That
caused new entries to land inside the existing top entry instead of
above it. Now only skip a leading '#' line if it doesn't look like a
version header (no "vX.Y.Z"), and stop immediately once one is found.
Also switched rendering to match the real downstream package
convention observed in dbt_amazon_ads: "# {package} v{version}" (no
injected date or breaking-change tag), a "[PR #N](url) includes the
following updates:" line, and H2 sections instead of H3. Dependency
bumps fold into Under the Hood since there's no separate category for
them in the standard section list.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
* Match real Contributors and Schema/Data Change conventions
Per ~/.claude/package_contents/the_changelog.md and existing Fivetran
package changelogs (dbt_apple_store, dbt_asana): contributors get
their own "## Contributors" section with linked GitHub handles, and
schema/data changes render as a table with a total/breaking-change
summary line, breaking changes sorted first.
schema_data_changes.entries is now a list of structured objects
(model, change_type, old, new, notes, breaking) instead of flat
strings, to populate the table columns.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
* Give dependency bumps their own Dependency Updates section
Real Fivetran package changelogs (ad_reporting, google_ads, hubspot,
klaviyo, shopify, zendesk, ...) consistently use a "## Dependency
Updates" section rather than folding bumps into Under the Hood.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
* Normalize list item shape and support sub-bullets
new_features used {title, description}, bug_fixes used {description}
only, and dependencies/under_the_hood were bare strings - inconsistent
shapes across otherwise-identical bullet sections. All four now go
through a shared render_bullets() helper: every item is either a
plain string or {description, title?, details?}, where details
renders as indented sub-bullets under the main bullet.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
* Bring in config.yaml, structured dependencies/contributors, models list
Per the design in GA-1035597:
- Add .changes/config.yaml (package, repo_url, per-section headings)
and have update_changelog.py read it instead of hardcoding those
values, falling back to GITHUB_REPOSITORY/defaults when absent.
- schema_data_changes entries take a `models` list (was singular
`model`), matching the "same change across multiple models -> one
row" rule, and use `is_breaking` instead of `breaking` for naming
consistency with the rest of the schema.
- dependencies accepts structured {package, old_version, new_version,
description} bump records, rendering as "Bumps `pkg` from X to Y",
in addition to plain strings.
- contributors accepts structured {name, github_handle, is_fivetran,
contribution} records alongside bare handles.
- hide_from_docs is accepted throughout (schema entries, features,
bug fixes, dependencies, under_the_hood, contributors, top-level)
but intentionally has no effect on CHANGELOG.md rendering - it's
metadata for the future JSON/docs consumer, not this pipeline.
- Updated .changes/1.6.1.yaml to exercise every field.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
* Authenticate checkout with GH_TOKEN so pushes attribute to the bot user
Without an explicit token, actions/checkout falls back to the default
GITHUB_TOKEN, which authenticates as the github-actions[bot] app
installation. Setting git config user.name/email only changes the
commit author/committer metadata - it doesn't change who GitHub
attributes the push (and the resulting PR "synchronize" event) to.
generate-docs.yml already does this correctly via secrets.GH_TOKEN;
this brings update-changelog.yml in line with it.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
* Flatten pr.number to pr_number, allow per-contributor pr_number override
Matches the format update made in dbt_amazon_ads's .changes/1.3.2.yaml:
pr: {number: N} is now a flat pr_number field, and a contributor's own
pr_number (when they contributed via a different PR than the one
driving this release) overrides the release-level pr_number for their
Contributors line.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
* Remove .changes/ from this repo - it belongs in downstream package repos
dbt_package_automations is tooling, not a dbt package released through
this pipeline, so it has no releases of its own to track here. The
example/test YAML and config.yaml moved to dbt_amazon_ads, which is
what actually exercises them.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
* Support .yml extension for release YAML and config files
dbt_amazon_ads renamed its .changes/ files from .yaml to .yml, which
the script's hardcoded "*.yaml" globs silently missed - it kept
reporting "nothing to add" since no file matched. release_yaml_files()
now globs both extensions (excluding config.yml/config.yaml by stem),
and load_config() checks config.yml before falling back to config.yaml.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
* Simplify to .yml only
.yaml support was unneeded complexity - the pipeline only needs to
recognize one extension, and .yml is the established convention.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
* Separate multiple models and the breaking tag with <br> in the schema table
Comma-joining models in the Data Model(s) cell reads poorly once
there's more than one; <br> puts each on its own line within the
cell. The (Breaking) tag now gets its own line too instead of being
appended inline.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
* Trigger on the existing docs:ready label instead of a new one
Reuses the label generate-docs.yml already listens for, rather than
introducing a separate changelog:ready label for downstream repos to
manage.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
* Revert "Trigger on the existing docs:ready label instead of a new one"
This reverts commit e889da5.
* Delete .github/scripts/caller-example-update-changelog.yml
* Flatten schema_data_changes.entries[].models to a plain string list
Was a list of {name: ...} objects - one key wrapping one string, for
no benefit, and it doubled up the dash-list nesting in an already
list-heavy structure. models is now just a flat list of model name
strings.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
* Remove config.yml mechanism, hardcode section headings
Section headings and package/repo_url derivation now live directly in
update_changelog.py (SECTION_HEADINGS, repo_info()) instead of being
overridable per-repo via .changes/config.yml. Keeps every package's
changelog using the same standard section names.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
* Fold changelog update into generate-docs.yml, retire update-changelog.yml
Both workflows were separately triggered by pull_request labeled and
independently checked out/committed/pushed to the same PR branch,
risking a push race (one job's push getting rejected as non-fast-
forward by the other's). Running the changelog update as steps inside
generate-docs.yml's existing job means one checkout, one CHANGELOG.md
update, one git add/commit/push - no more race, since it's now
strictly serial within a single job. Both docs and changelog updates
land in the same commit.
update_changelog.py itself is unchanged and still lives at
.github/scripts/update_changelog.py; only the standalone reusable
workflow that called it on its own is removed.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
* Fix docs generation breaking for repos without a .changes/ directory
git add on a nonexistent pathspec fails (exit 128), and Actions runs
steps under bash -e, so `git add docs/ .changes/ CHANGELOG.md` would
abort the whole commit step - and therefore fail docs generation
entirely - for any repo that hasn't adopted the .changes/ convention
yet (every repo except dbt_amazon_ads today). mkdir -p .changes first
guarantees the pathspec always resolves; an empty directory just adds
nothing.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
* Repurpose check-docs-current.yml to check docs, CHANGELOG.md, and .changes/*.yml
Was a single docs-staleness check. Now runs the same "relevant changes
since this path was last touched" logic against docs/, CHANGELOG.md,
and .changes/ independently, and reports specifically which of the
three are missing/stale in the docs/generated status description
(e.g. "Missing: CHANGELOG.md update, a .changes/*.yml entry") instead
of a generic pass/fail. Still removes the docs:ready label if anything
is missing, and keeps the same "docs/generated" status context so
existing branch protection rules aren't affected.
Verified against four scenarios locally: only-model-changed (all three
flagged), everything current (success), stale-again after a later
relevant change (all three flagged again), and irrelevant-only changes
(success).
Note: for any repo that hasn't adopted .changes/ yet, this will always
report the changelog-entry check as missing whenever a relevant change
is made, since no commit has ever touched that path. That's correct
enforcement once a repo opts in, but means this shouldn't go to @main
until repos are ready to adopt the .changes/ convention.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
* Add v1.1.0 CHANGELOG entry for the changelog generation CICD process
This repo doesn't do dbt-style releases, but tracking this change is
worth it given its scope: the new update_changelog.py pipeline, its
merge into generate-docs.yml, and the repurposed three-way
check-docs-current.yml check.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
* Address review feedback: retention window, version sort, is_fivetran, README
- Bump RETENTION_DAYS 30 -> 45: docs publish monthly, and 30 days risked
pruning a .changes/*.yml file before a busy month's docs run picked it up.
- Fix release_yaml_files() to sort by parsed version tuple instead of
lexically - sorted() alone put "1.10.1.yml" before "1.9.0.yml".
- Remove is_fivetran from the contributor schema - never read by
render_contributor_bullets, and there's no case for differentiating
internal/external credit.
- Add a .changes/*.yml field reference table to the README, documenting
every supported field and explicitly flagging which ones (hide_from_docs
everywhere, is_breaking on a dependency item) are accepted but inert for
CHANGELOG.md rendering - reserved for a future docs-side consumer.
Pre-release version handling (e.g. "1.2.0-beta.1") is intentionally left
open pending input on whether/how Fivetran packages ship those.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
* Support pre-release/beta version sort ordering (-a1, -b1, etc.)
Answers the open question from review: Fivetran packages use -a1, -a2
for pre-releases and -b1, -b2 for betas. _version_sort_key now parses
that suffix and ranks pre-releases before that version's final release
(1.3.0-a1 < 1.3.0-a2 < 1.3.0-b1 < 1.3.0-b2 < 1.3.0), instead of lumping
every non-plain-numeric filename at the end indiscriminately.
Verified end-to-end with a -b1 release file rendering correctly.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
* Add a full example .changes/*.yml to the README
The field reference table alone doesn't show how the pieces fit
together. Adds a complete worked example exercising every field,
verified by running it through update_changelog.py directly.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
* Add a changes-template.yml, link it from failure status, inline-comment the README example
- templates/changes-template.yml: a blank, copy-paste-ready .changes/*.yml
with inline comments for every field.
- check-docs-current.yml: when a .changes/*.yml entry is specifically what's
missing, the docs/generated failure status's target_url now points to
that template, so the link is directly actionable from the PR's status
checks instead of just saying what's missing. Switched status payload
construction to jq -n (matches the pattern already used in
auto-release.yml) instead of manual string interpolation.
- README: the example .changes/1.3.0.yml now carries inline field comments
in the same style used for `vars:` blocks in package READMEs, rather than
relying solely on the separate reference table. Links to the new template.
Verified: both the commented README example and the template parse and
render identically to the uncommented version through update_changelog.py.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
* Fix false-positive version match and clarify retention wording
discover_pending_yaml used a plain substring check (f"v{version}" not in
changelog_text), so once a pre-release like v1.3.0-a1 was published,
the final v1.3.0 release would be silently treated as already-released
and skipped - "v1.3.0" is a substring of "v1.3.0-a1". Replaced with
_version_already_released(), which requires the match not be followed
by another version-continuation character (digit, ".", or "-").
Verified: v1.3.0 is no longer falsely matched against v1.3.0-a1 or
v1.3.0-b10 vs v1.3.0-b1, a genuine v1.3.0 header still matches
correctly, and a full pipeline run now correctly renders a pending
v1.3.0 entry even with v1.3.0-a1 already in CHANGELOG.md.
Also reworded the retention note in the README: pruning happens as
part of the next invocation of this action (triggered by any release
in the repo), not on a separate schedule.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
* Repoint update_changelog.py curl to @main, ready for merge
Last step before merging: the script URL was hardcoded to this POC
branch so it could be curled before the script existed on main. Swapped
to refs/heads/main now that this is about to land there.
Confirmed via grep: no other references to changelog-poc/initial-test,
the scaffold-changes-template approach (superseded, PR #41 closed), or
any other stale branch names remain anywhere in the repo. All workflow
YAML validates, update_changelog.py's syntax is clean.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
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.
Summary
Follow-up to the discussion on #40: instead of requiring a label or expecting authors to remember the
.changes/*.ymlconvention,check-docs-current.ymlnow scaffolds a template automatically the moment a PR is opened.scaffold-changes-templatejob, gated ongithub.event.action == 'opened'so it fires exactly once per PR, not on every push..changes/*.ymlor the template already exists, so it never clobbers an author's work or re-adds itself after a deliberate deletion.templates/changes-template.ymland commits it as.changes/TODO.yml.template— the.yml.templateextension is deliberate:release_yaml_files()'s*.ymlglob never matches it, so it can't be mistaken for a real release entry until the author renames it to.changes/{version}.yml.GITHUB_TOKEN/secrets.GH_TOKENcan't push to a fork's branch.No new per-repo workflow file needed — this reuses the
check-docs-current.ymlcaller already deployed in every package repo (on: pull_request: types: [opened, synchronize, reopened]).Why this approach over the alternatives discussed
opened) would reintroduce the push-race risk we eliminated by mergingupdate-changelog.ymlintogenerate-docs.yml, and would spam commits before the author's ready.Test plan
bash(matching the Actions runner shell — an earliercompgen -G-based version passed locally under zsh but doesn't reliably signal "no match" via exit status).templates/changes-template.ymlis fetchable from the hardcoded POC-branch URL and matches the local copy.🤖 Generated with Claude Code