Skip to content

fix(release): ignore embedded metadata in changedset, list breaking changes first - #323

Merged
re-gius merged 9 commits into
masterfrom
fix/release-metadata-release-notes-breaking-changes
Sep 30, 2026
Merged

re-gius merged 9 commits into
masterfrom
fix/release-metadata-release-notes-breaking-changes

Conversation

@GHkrishna

@GHkrishna GHkrishna commented Sep 29, 2026 •

Copy link
Copy Markdown
Contributor

Description

This PR fixes two things in the release tooling (scripts/js/release-metadata.mjs).

1. changedset no longer flags StoreFactory after comment-only edits

StoreFactory deploys other contracts with new, so its bytecode carries a copy of their creation code. Each copy ends with that contract's own metadata hash, and that hash changes whenever a comment or NatSpec line changes. changedset only stripped StoreFactory's own metadata at the end of its bytecode, so a comment edit in LabelStore made StoreFactory look changed and asked for an upgrade nobody needed.

Now the hash inside each embedded copy is set to zeros before hashing. Real code changes still show up. codehashes.json gets a new hashScheme field so that files hashed the old way and the new way are never compared by mistake. changedset reads that field and hashes the current build the same way the previous file was hashed.

2. Shorter ABI section in the release notes

The release body now has a "Breaking ABI changes" list with only the changes that break an existing caller or indexer, one line each: changed function signatures, removed functions, contracts no longer published, then changed or removed events. Everything else (additions, new contracts, custom errors) goes in a collapsed block with a count. abi-diff.json is unchanged and still has the full diff.

A contract and the interfaces it implements usually carry the same change, so each change is listed once, under the interface that declares it. A new bases command reads which published ABIs each contract inherits from, straight from the build, so pairs whose names don't match (like DotnsFlatPricing and IDotnsPricing) are matched too. The extract step in both publish workflows runs it and passes the result to abidiff --bases.

Type

  • Bug fix
  • Feature
  • Breaking change
  • Documentation
  • Chore
  • Refactor
  • Security

Scope

  • Registration
  • Resolver
  • Store
  • Proof of Personhood
  • Deployment scripts
  • Tests

Release tooling only. No contract code changes.

Related Issues

Found in #321, whose NatSpec-only edits to LabelStore put StoreFactory in its changedset.

Fixes

Fixes #322

Checklist

Code

  • Follows project style
  • forge build passes
  • forge test passes
  • No new compiler warnings

Testing

  • New tests added for changed behavior
  • Fuzz tests added where applicable
  • Invariant tests verified

Security

  • No new selfdestruct or delegatecall
  • Access control reviewed
  • No storage layout conflicts (for upgradeable contracts)

Documentation

  • NatSpec updated on changed interfaces
  • README updated if needed

Breaking Changes

  • No breaking changes
  • Breaking changes documented below

Breaking changes:

How to test

changedset fix

forge build
node scripts/js/release-metadata.mjs build --tag base --out /tmp/base --addresses false
# change only a comment in contracts/store/LabelStore.sol
forge build
node scripts/js/release-metadata.mjs changedset --previous /tmp/base/codehashes.json
# nothing is listed

# now make a real code change in LabelStore.sol
forge build
node scripts/js/release-metadata.mjs changedset --previous /tmp/base/codehashes.json
# LabelStore and StoreFactory are listed

Release notes

forge build
node scripts/js/release-metadata.mjs bases --out /tmp/bases.json
node scripts/js/release-metadata.mjs abidiff --current <abis-dir> \
  --previous <previous-abis-dir> --previous-tag <previous-tag> --bases /tmp/bases.json

Against the v0.7.0 and v0.8.0 release ABIs, the breaking list is the single IUserStore.initialize line, and the other 26 changes are in the collapsed block.

Notes

  • The next release still compares against the previous release's codehashes.json, which was hashed the old way. So StoreFactory will show up once more in that release's changedset if any contract it deploys changed, even if only a comment changed. After that it is clean.
  • If we want that next release to be clean too, we can regenerate the previous release's metadata with this fix and compare against that instead. Check out the previous release tag, apply this change, run forge build and release-metadata.mjs build, then pass the new codehashes.json to changedset. If StoreFactory is not listed, its code did not change and it does not need an upgrade.
  • bases reads the base contracts from the build info of the same compiler run, because AST ids only mean something inside one run. If no build info matches, it fails and asks for forge clean && forge build.
  • A contract that was removed isn't in the current build, so its bases aren't known and it keeps its own line.

Signed-off-by: GHkrishna <krishna@parity.io>
Signed-off-by: GHkrishna <krishna@parity.io>
Signed-off-by: GHkrishna <krishna@parity.io>
@GHkrishna GHkrishna self-assigned this Sep 29, 2026
@GHkrishna
GHkrishna requested a review from a team as a code owner September 29, 2026 10:13
@github-actions

github-actions Bot commented Sep 29, 2026 •

Copy link
Copy Markdown
Contributor

CI Summary

Check Result
File Validation Passed - All tracked files valid
Deploy Contracts Reproduces the expected address set; resume verified
PR Title PR Title Valid
Labels Unknown
Secret Scan Passed - No secrets detected

Deploy Contracts

Deployed addresses vs the expected set

Expected is the committed expected-address set; actual is this CI deployment of the same pipeline.

Contract Expected Actual Match
Create3Factory 0x8533c79E058c5a6489CAFeCA86dc600E029D75f5 0x8533c79E058c5a6489CAFeCA86dc600E029D75f5 match
DotnsContentResolver 0x7F74D7CD50f5a834270E2ad395a01b01891AB37d 0x7F74D7CD50f5a834270E2ad395a01b01891AB37d match
DotnsCostModelRegistry 0x8bfd1f0957e73716732e725802f13830B5682da4 0x8bfd1f0957e73716732e725802f13830B5682da4 match
DotnsFlatPricing 0xD839B281dF72Df44fF275305E72cAEEc0fDAA648 0xD839B281dF72Df44fF275305E72cAEEc0fDAA648 match
DotnsNameEscrow 0x4881Afb78e7C908cAe818168B926229D93376520 0x4881Afb78e7C908cAe818168B926229D93376520 match
DotnsNameWhitelist 0x420166cD67Ca0233094E492a4BbA67045eD7C38C 0x420166cD67Ca0233094E492a4BbA67045eD7C38C match
DotnsPopController 0xCC932348606cc1f3318cADeC5A5Cd2CA447f8a4b 0xCC932348606cc1f3318cADeC5A5Cd2CA447f8a4b match
DotnsPopLens 0xfe5A45f7fD58D1A6FE09455DB799405b1dcE9411 0xfe5A45f7fD58D1A6FE09455DB799405b1dcE9411 match
DotnsPopResolver 0xDaC984884EcA8Fc44011f1D6C49B27828390A72B 0xDaC984884EcA8Fc44011f1D6C49B27828390A72B match
DotnsProtocolRegistry 0xD19e3D0C97CF501125a04A97405e3e6592fa846E 0xD19e3D0C97CF501125a04A97405e3e6592fa846E match
DotnsRegistrar 0x4f06E818Ba3d987704fd91cf3d868E4b019106Ab 0x4f06E818Ba3d987704fd91cf3d868E4b019106Ab match
DotnsRegistrarController 0xBdaA01bD1bA67d709F2b1fF286Da0d854977EA30 0xBdaA01bD1bA67d709F2b1fF286Da0d854977EA30 match
DotnsRegistry 0xf34054fd76BbF85f216cf9908226D5f0A72E50CA 0xf34054fd76BbF85f216cf9908226D5f0A72E50CA match
DotnsResolver 0xbd1165E549DF96F083c0A16f61590927bC187009 0xbd1165E549DF96F083c0A16f61590927bC187009 match
DotnsReverseResolver 0xee3883d7eB60Ee9BCD7F3bcD8f2f05302A9Cc035 0xee3883d7eB60Ee9BCD7F3bcD8f2f05302A9Cc035 match
LabelStoreBeacon 0x2227d9807F5A71332Aaa0640643030f2A3bf84cD 0x2227d9807F5A71332Aaa0640643030f2A3bf84cD match
Multicall3 0xB4468000abD87D3c56cbFBd153161223D7b109e5 0xB4468000abD87D3c56cbFBd153161223D7b109e5 match
PopRules 0x747B456bE03aec0b42bd85C51513730FBD45DA31 0x747B456bE03aec0b42bd85C51513730FBD45DA31 match
StoreFactory 0x99605a926FcB40aB520F659c6505E5ff862771f6 0x99605a926FcB40aB520F659c6505E5ff862771f6 match
UserStoreBeacon 0x3d1Ca165f7A5e387C2df02DB2FadD3149c1C72ad 0x3d1Ca165f7A5e387C2df02DB2FadD3149c1C72ad match

View full logs

Labels

other, type: docs

@re-gius re-gius left a comment •

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please shorten the breaking-change section so it is only the broken ABIs, and list each break once. We should avoid putting too much information in there, otherwise people will end up skipping it.

The ordering is right: changed function signatures, removed functions, contracts no longer published, then changed or removed events. The text around that list is what people will skip. Drop the per-group explanations ("Existing callers get a bare revert…", "Calls to these now revert…", and so on). Drop the copied pull-request bodies.

The body should look like this:

Breaking ABI changes since v0.7.0

  • IUserStore.initialize: initialize(address) → initialize(address,address)

Also notice v0.8.0 listed that same change twice, on UserStore and on IUserStore. UserStore is IUserStore, and both ABIs are published, so the signature is identical. It would have been better to print it once, under the interface, which is what callers bind to, same for events. If the implementation has a breaking signature the interface does not, keep that line. Pair them the way .github/abi-contracts.txt does: Foo with IFoo.

You can put additions, new contracts, and custom errors behind a collapsed

Details ...

block with a count in the summary, or leave them to abi-diff.json. They are not breaking, and in v0.8.0 they were most of the section.

Signed-off-by: GHkrishna <krishna@parity.io>
Signed-off-by: GHkrishna <krishna@parity.io>
@GHkrishna
GHkrishna requested a review from re-gius September 29, 2026 13:56

@re-gius re-gius left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, almost done!

However, the Foo / IFoo check still lists DotnsFlatPricing and IDotnsPricing twice, because their names do not match.

Read the bases from the Forge artifacts the release job already built. Use a base only when it is also a published ABI. Record those names in the extract step and pass them to abidiff, so to cover all interface implementations.

Signed-off-by: GHkrishna <krishna@parity.io>
…eaking changes

Signed-off-by: GHkrishna <krishna@parity.io>
…n breaking changes

Signed-off-by: GHkrishna <krishna@parity.io>
@GHkrishna

Copy link
Copy Markdown
Contributor Author

Good catch, thanks. The extract step now records each contract's published bases from the build, and abidiff lists a change once, under the interface declaring it. Base ids are resolved through the same run's build info, since incremental builds mix ids. Removed contracts still get their own line.

@GHkrishna
GHkrishna requested a review from re-gius September 30, 2026 06:19

@re-gius re-gius left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM!

nit: fix PR description.

@re-gius
re-gius merged commit 7516913 into master Sep 30, 2026
10 checks passed
@re-gius
re-gius deleted the fix/release-metadata-release-notes-breaking-changes branch September 30, 2026 09:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: changedset reports StoreFactory as changed after comment-only edits to its dependencies

2 participants