Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Tooling: Introduce pre-commit CHANGELOG verification #13594

Closed
wants to merge 2 commits into from

Conversation

aduth
Copy link
Member

@aduth aduth commented Jan 30, 2019

This pull request seeks to explore adding a pre-commit script which verifies that the contents of the pending commit include a CHANGELOG.md revision if applicable (i.e. within a packages directory, and not considered as an "ignored" change by Lerna).

Testing instructions:

With the branch checked out, verify a few combinations of commit attempts:

  • A change outside of a package (e.g. root README.md)
    • Should succeed
  • A change to a package-ignored file (e.g. packages/i18n/benchmark/index.js), without CHANGELOG
    • Should succeed
  • A change to a package not-ignored file (e.g. packages/i18n/src/index.js), without CHANGELOG
    • Should error
  • A change to a package not-ignored file (e.g. packages/i18n/src/index.js), with CHANGELOG
    • Should succeed

Future tasks:

It would be difficult to integrate this into a build step in its current form, as the script expects to receive the changed file paths as arguments. It should be enhanced to also retrieve a list of changed files from the current branch history.

The current incarnation can serve as a good, less-disruptive initial workflow to allow for some flexibility in the risk of false positives.

@aduth aduth added the [Type] Build Tooling Issues or PRs related to build tooling label Jan 30, 2019
@nerrad
Copy link
Contributor

nerrad commented Jan 30, 2019

So does this mean that every change in a commit must be accompanied by a change in the CHANGELOG.md? What happens when committing a bug fix or something in a watched file as a part of the overall work on the branch where a changelog modification was already made in an earlier commit on the pull?

Assuming most merges of pulls happen via the github ui/ux I wonder if we should instead use the github checks api via a custom github app and it checks there is a changelog entry for the changed code. We probably could base a custom app off of something like this. We could then enforce blocking merges of pulls unless there is a changelog entry.

If there are scenarios where a merge to master happens outside of the github ui then maybe we should investigate also doing a check similar to what you did in here but only on the merge commit to master?

@aduth
Copy link
Member Author

aduth commented Jan 30, 2019

So does this mean that every change in a commit must be accompanied by a change in the CHANGELOG.md? What happens when committing a bug fix or something in a watched file as a part of the overall work on the branch where a changelog modification was already made elsewhere?

The problem is that Lerna is dumb, and can't differentiate this point. It sees a touched file, it's going to prompt for publishing a new version. It also can't be on the person doing the publish to follow back the un-logged change to its source.

Presumably, if the file needed to be touched in a package, the change ought to be able to be described as standing on its own legs, as the modules themselves are meant to be standalone, not purely in service of some other thing.

Assuming most merges of pulls happen via the github ui/ux I wonder if we should instead use the github checks api via a custom github app and it checks there is a changelog entry for the changed code. We probably could base a custom app off of something like this.

I started down this path as well, even looking forward to things like actions to make these sorts of workflow automations easier / more integrated to GitHub.

The problem I faced is: I really don't want to go through the trouble of begging for an app to be approved for use in the WordPress organization. Or at least, it seemed there were viable alternatives by starting this as either just a pre-commit check, or as a step in the existing Travis build.

@gziolo gziolo self-requested a review January 30, 2019 14:34
Copy link
Member

@gziolo gziolo left a comment

Choose a reason for hiding this comment

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

I will take a closer look tomorrow but I think this is exactly what we would need for start.

*
* @type {Set}
*/
const verified = new Set;
Copy link
Member

Choose a reason for hiding this comment

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

Is it okey to omit parentheses?

Copy link
Member Author

Choose a reason for hiding this comment

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

Is it okey to omit parentheses?

Yes:

new Foo is equivalent to new Foo(), i.e. if no argument list is specified, Foo is called without arguments.

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/new#Description

Though some people might argue it's better to just be consistent:

https://eslint.org/docs/rules/new-parens

Copy link
Member

Choose a reason for hiding this comment

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

Interesting. I'm fine to leave it as is if JS is happy :)

* Example (Error):
*
* ```
* node bin/check-changelog.js /Gutenberg/packages/i18n/src/index.js
Copy link
Member

Choose a reason for hiding this comment

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

Is this comment correct? I would expect something containing Missing CHANGELOG.md entry for...

Copy link
Member Author

Choose a reason for hiding this comment

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

Is this comment correct? I would expect something containing Missing CHANGELOG.md entry for...

It's an example of a failing call, so yes, it would log the message.

@@ -197,6 +199,9 @@
"*.js": [
"wp-scripts lint-js"
],
"packages/*/**": [
Copy link
Member

Choose a reason for hiding this comment

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

I need to verify my assumption, but it might not work as intended for PR that has multiple commits. Use case I'm about to test is as follows:

  • add CHANGELOG.md changes upfront and commit
  • add code changes with another commit

Copy link
Member

Choose a reason for hiding this comment

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

Yes, this is what actually happened:

⚠️ Missing CHANGELOG.md entry for compose package edits.
   More information: https://github.com/WordPress/gutenberg/blob/master/packages/README.md#maintaining-changelogs

It works as expected based on the implementation but we need to find a way to improve it :)

Copy link
Member

@gziolo gziolo left a comment

Choose a reason for hiding this comment

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

See my comment: https://github.com/WordPress/gutenberg/pull/13594/files#r252659482

It works fine for a single commit but fails when CHANGELOG.md was already updated in one of the previous commits and isn't included in the commit with code changes.

@aduth
Copy link
Member Author

aduth commented Jan 31, 2019

Yes, I can see that being an issue. I'd justified it in my head as the sort of thing where the developer ought to always include the CHANGELOG with the change itself. It ties a bit into the noted "future goal" of allowing the file arguments to be optional and have the tool refer to the branch history instead if omitted.

@nerrad
Copy link
Contributor

nerrad commented Jan 31, 2019

Yes, I can see that being an issue. I'd justified it in my head as the sort of thing where the developer ought to always include the CHANGELOG with the change itself. It ties a bit into the noted "future goal" of allowing the file arguments to be optional and have the tool refer to the branch history instead if omitted.

This was kind of what I was getting at in my earlier comment though. I think practically, while the initial change a developer commits could include the CHANGELOG entry, pulls often have fixes needed as a result of a review and this creates extra friction for those subsequent commits.

@gziolo gziolo added the [Type] Project Management Meta-issues related to project management of Gutenberg label Jan 31, 2019
@aduth
Copy link
Member Author

aduth commented Jan 31, 2019

This doesn't stop someone from bundling many changes in the same branch, or in the same commit, it just requires that the CHANGELOG for each touched package would be updated as part of the commit, which is the point of the change we're trying to make.

@gziolo's example of preemptively updating a CHANGELOG in a separate, earlier commit is a very niche example; it's not something I'd expect anyone to be doing.

@gziolo
Copy link
Member

gziolo commented Jan 31, 2019

@gziolo's example of preemptively updating a CHANGELOG in a separate, earlier commit is a very niche example; it's not something I'd expect anyone to be doing.

It's extreme but very close to how I patch PRs when I spot mistakes after self-review on GitHub for newly pushed PR.

@aduth
Copy link
Member Author

aduth commented Jan 31, 2019

It's extreme but very close to how I patch PRs when I spot mistakes after self-review on GitHub for newly pushed PR.

Maybe I'm misreading, but is that not a commit which takes place after the original change, i.e. the exact thing this pull request would prevent from being allowed to happen?

The problem workflow I see is if someone (a) edited a changelog, (b) committed it, and (c) made the change corresponding the changelog note in a subsequent separate commit.

@gziolo
Copy link
Member

gziolo commented Feb 4, 2019

The problem workflow I see is if someone (a) edited a changelog, (b) committed it, and (c) made the change corresponding the changelog note in a subsequent separate commit.

I think it's every workflow for the existing PR where you add a new commit which contains only code changes but no update to the changelog file.

@aduth
Copy link
Member Author

aduth commented Feb 4, 2019

The problem workflow I see is if someone (a) edited a changelog, (b) committed it, and (c) made the change corresponding the changelog note in a subsequent separate commit.

I think it's every workflow for the existing PR where you add a new commit which contains only code changes but no update to the changelog file.

That is what this validation will catch and prevent from happening. The developer can then just add the CHANGELOG entry.

What I meant by "problem" in my previous commit is one which leaves the developer in an awkward unresolvable (at least not without a few extra steps) scenario.

@aduth
Copy link
Member Author

aduth commented Feb 7, 2019

Per previous comments and as discussed in this week's #core-js meeting, I've made improvements in a9514c7 to consider whether a previous commit would satisfy the requirement of a CHANGELOG revision having been made for an affected file.

The changes here are also quite nice in letting the script be run directly, without arguments, as a verification of the current branch. In other words, this could be used without any additional changes as part of a Travis task for node bin/check-changelog, but I've opted to not add that quite yet, since I think the precommit alone could prove sufficient at least for the time being. I'm open to reconsidering.

Copy link
Contributor

@nerrad nerrad left a comment

Choose a reason for hiding this comment

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

I like these changes 👍

`\u00A0\u00A0\u00A0More information: https://github.com/WordPress/gutenberg/blob/master/packages/README.md#maintaining-changelogs\n`
);

process.exit( 1 );
Copy link
Member

Choose a reason for hiding this comment

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

It will exit as soon as it will find the first violation, there might be more than one if several packages are updated. I don't consider it as a blocker but sharing here so we could discuss whether we should make iterate further.

Copy link
Member Author

Choose a reason for hiding this comment

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

It will exit as soon as it will find the first violation, there might be more than one if several packages are updated. I don't consider it as a blocker but sharing here so we could discuss whether we should make iterate further.

I can probably improve this without too much trouble 👍

*
* @type {string}
*/
const base = exec( 'git merge-base master HEAD' );
Copy link
Member

Choose a reason for hiding this comment

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

This part is tricky and might cause a lot of confusion because we reference the local copy of master branch. I run into this issue locally where my master branch is out of date if you compare with the upstream. Therefore when I run this script I see missing CHANGELOG.md files in folders that weren't updated in the branch where I tried to add a new commit. In fact, I wanted to add a new commit directly to this branch to verify how it would work with some flows. In my case git merge-base origin/master HEAD solves the issue, but that might differ for forks and can be also changed to something else.

I'm also wondering if this isn't a temporary issue caused by the fact that we don't update changelog files in a way this should happen. My assumption is that it wouldn't be an issue when this change lands and folks update their master to the latest version.

As a way to avoid so much confusion maybe we should include the note prompting to update master to the latest version and try again?

Copy link
Member

Choose a reason for hiding this comment

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

On the up to date master branch it works like a charm ✨

Copy link
Member Author

Choose a reason for hiding this comment

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

This part is tricky and might cause a lot of confusion because we reference the local copy of master branch. I run into this issue locally where my master branch is out of date if you compare with the upstream.

Argh, I'd hoped to have found some reliable way here. The other trouble too with dealing with branches is that Travis does some funny things with branches, which makes using the git command not as reliable (reference).

There's seemingly many ways to check for differences; I want to dig to see if there could be another option here, before resorting to the forced update prompt.

Copy link
Member

Choose a reason for hiding this comment

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

Jest supports something similar with the following flags:

  • --changedSince - "Runs tests related to the changes since the provided branch. If the current branch has diverged from the given branch, then only changes made locally will be tested."
  • --onlyChanged - "Attempts to identify which tests to run based on which files have changed in the current repository."

It might be a nice way to compare the approach they took.

@youknowriad
Copy link
Contributor

It seems like we very rarely update the package changelogs and it's understandable since it's not enforced. I'd think that we should make a decision. Try to land this PR or abandon these package changelogs entirely. Maybe something for the next #core-js chat

@gziolo
Copy link
Member

gziolo commented Mar 18, 2020

gutenberg/bin/commander.js

Lines 960 to 967 in 548e600

/**
* Update CHANGELOG files with the new version number for those packages that
* contain new entries.
*
* @param {string} minimumVersionBump Minimum version bump for the packages.
* @param {string} abortMessage Abort Message.
*/
async function updatePackageChangelogs( minimumVersionBump, abortMessage ) {

We use those CHANGELOG entries to automate version bumps for npm packages. It's very important for the tooling that might have breaking changes more often. I admit it's less of an issue for packages that contain components, but it still might be useful in some cases.

@aduth
Copy link
Member Author

aduth commented Mar 18, 2020

@youknowriad I'm keen to revisit this. Especially as the project has matured, the need to effectively communicate changes in individual packages has become increasingly a concern of mine.

But one thing which would be prudent is to try to consider just how we expect these to be used. I think there's a lot of important information that can be included in these CHANGELOGs, and it's for this reason we've thought it crucial they be updated. (Aside: Looking back at my original comment, I feel I could have been more clear with these reasons)

On the consuming end, we might want to think more about: (a) if and how they get incorporated into the Gutenberg release notes, (b) how someone like a plugin author can use these notes to know about upcoming or past changes associated with a WordPress release. A CHANGELOG workflow may be familiar for someone consuming packages from NPM, and this is certainly a use-case we want to support via these updates. I think it's also fair to say that at the current moment, it's not necessarily the primary one motivating these changes (save for a few packages like scripts, eslint-plugin, etc).

Or, at least, in addressing the other concern about how this may be viewed as a burden for contributors who aren't currently used to this being part of the workflow, it would be easier to do so if we could can clearly demonstrate the value that they bring.

I have a few more specific tactical remarks I have in mind here. I'll consider those in a separate comment.

Base automatically changed from master to trunk March 1, 2021 15:42
@aduth
Copy link
Member Author

aduth commented May 27, 2022

Clearly not a lot of urgency with this one, so will go ahead and close as stale.

Future work could pick this back up, mindful of the fact that some of the git operations may need to be updated (e.g. references to "master" branch).

@aduth aduth closed this May 27, 2022
@aduth aduth deleted the try/check-changelog branch May 27, 2022 22:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
[Type] Build Tooling Issues or PRs related to build tooling [Type] Project Management Meta-issues related to project management of Gutenberg
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants