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

Build: Move date module to packages maintained by Lerna #6658

Merged
merged 10 commits into from
May 11, 2018

Conversation

gziolo
Copy link
Member

@gziolo gziolo commented May 9, 2018

Description

Related issues: #3955, #6594.

This PR tries to provide Lerna setup similar to what we have in WordPress/packages. This would allow publishing source code of individual modules to npm to make them available for all plugin developers.

I started small with the date module to start the discussion.

The version number would be maintained in Lerna config instead of package.json. So the idea I had is that every time we publish a new version of the plugin to .org, we publish also the same version of npm packages. We will have to revisit after 5.0 mission is accomplished.

In the first iteration, we would release date with 2.8-alpha version as a development release. Once it is confirmed it works as expected, and we have build and build-module distributions we could switch to regular releases.

Issues discovered

We are using package-lock.json for Gutenberg. I disabled it for date package because it isn't required there at all. However when using --hoist flag with Lerna (to avoid duplicated node_modules) I noticed that package-lock.json doesn't get dependencies from packages included in the lock flag. To mitigate it I had to duplicate the same dependencies in both package and root package.json file. Question is if we should maintain it in both places or is fine to have it outside of lock file control?

How has this been tested?

Manually:

  • Removed node_modules folder.
  • npm install
  • npm test
  • npm run dev
  • npm run build
  • npm run package-plugin

New commands introduced:

  • npm run publish:check
  • npm run publish:dev
  • npm run publish:prod

It mirros what we have in WordPress/packages.

Types of changes

Refactoring.

Checklist:

  • My code is tested.
  • My code follows the WordPress code style.
  • My code follows the accessibility standards.
  • My code has proper inline documentation.

@gziolo gziolo added [Type] Technical Prototype Offers a technical exploration into an idea as an example of what's possible [Type] Build Tooling Issues or PRs related to build tooling labels May 9, 2018
@gziolo gziolo self-assigned this May 9, 2018
@gziolo gziolo requested review from tofumatt, youknowriad, ntwb, aduth and a team May 9, 2018 12:35
/**
* WordPress dependencies
*/
import { moment } from '@wordpress/date';
Copy link
Contributor

Choose a reason for hiding this comment

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

The usage of the regular moment was intentional here. The idea is that we don't need any locale set, we just use moment as an utility function without global locale. (this avoids a dependency between components and date which I think would be nice to keep independent.)

Copy link
Member Author

Choose a reason for hiding this comment

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

Reverting those changes 👍
I wasn't aware of this. It still would be useful to wrap those moment calls with some higher level API to make it possible to replace moment with something else as soon as there is good alternative for it :)

Copy link
Member

@tofumatt tofumatt left a comment

Choose a reason for hiding this comment

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

The exporting of moment from our package strikes me as strange and I'm finding it hard to separate out the package change from it conceptually 😅

The issue with losing package locking is just for our internal dependencies, which are in the repo already, right? If that's the case it's probably fine. 🤷‍♂️

/**
* WordPress dependencies
*/
import { moment } from '@wordpress/date';
Copy link
Member

Choose a reason for hiding this comment

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

I'm confused about the utility of importing this package from @wordpress/date when it's already available as a regular dependency. It seems like more stuff we have to manage to export the same API (and if we aren't exposing moment's exact API we should maybe call it something different). Why do this?

Copy link
Contributor

Choose a reason for hiding this comment

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

I agree with this, the idea is that it absorbs the WP locale and timezone settings. But the downside is that this forces us somehow to stay compatible with the current moment version. We should definitely try to remove moment from the date module entirely, but let's leave it for a separate PR.

@@ -123,7 +127,12 @@ const config = {
memo[ name ] = `./${ path }`;
return memo;
}, {} ),
packageNames.reduce( ( memo, packageName ) => {
gutenbergPackages.reduce( ( memo, path ) => {
Copy link
Member

Choose a reason for hiding this comment

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

Any reason to rename packageName to path? It's still just using the packageName and I like the explicitness of the variable name. Plus it will hopefully discourage someone from including more nested paths.

Copy link
Member Author

Choose a reason for hiding this comment

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

I guess it's copy and paste thing. Will fix :)

packageNames.reduce( ( memo, packageName ) => {
gutenbergPackages.reduce( ( memo, path ) => {
const name = camelCaseDash( path );
memo[ name ] = `./packages/${ path }`;
Copy link
Contributor

Choose a reason for hiding this comment

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

should we add an src folder here (and move the files) ./packages/${ path }/src to match the packages repository setup?

Copy link
Member Author

Choose a reason for hiding this comment

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

I have it locally, need to push. I thought the same when I saw diff on GitHub :)

"publishConfig": {
"access": "public"
}
}
Copy link
Contributor

Choose a reason for hiding this comment

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

I believe this is lacking the main/module configs to make the modules ready for npm. This would probably have an impact on the webpack config (separate dist folder) than the one currently used for the remaining modules

Copy link
Contributor

Choose a reason for hiding this comment

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

Which brings us back to having a dedicated build folder per package maybe 🤷‍♂️

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 seems like we need to have independent build folders for npm, because we use very specific Webpack config which does some additional work like exposing wp. globals. We also need to expose two version:

  • es5 friendly
  • import/export friendly

Copy link
Member

Choose a reason for hiding this comment

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

I've always found a dedicated build folder much easier to grok when I first explore a package

@gziolo
Copy link
Member Author

gziolo commented May 9, 2018

The issue with losing package locking is just for our internal dependencies, which are in the repo already, right? If that's the case it's probably fine.

it's for moment and moment-timezone, but it will become a wider issue when we move more packages. We need to provide the list of dependencies for every package we publish. To give some examples, for element it will be react and react-dom, for data it will be redux. For components the list will be long, and so on :)

@ntwb
Copy link
Member

ntwb commented May 9, 2018

I noticed that package-lock.json doesn't get dependencies from packages included in the lock flag. To mitigate it I had to duplicate the same dependencies in both package and root package.json file. Question is if we should maintain it in both places or is fine to have it outside of lock file control?

Maintaining both, manually, if that is what is required would be my suggestion, the latest npm releases heavily depend on lock files when installing, so either no lock file, or an up to date lock file is pretty much required.

@gziolo
Copy link
Member Author

gziolo commented May 9, 2018

Let's try to keep lock file as it is and maintain duplicates. If this is too much hassle we can always use package linter we are about to roll out for packages repository :)
I think Lerna also detects if versions of the same library don't match.

"lerna": "2.11.0",
"commands": {
"publish": {
"message": "chore(release): publish %s"
Copy link
Member

Choose a reason for hiding this comment

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

If the packages are going to be independently released as they are currently with the packages repo the %s here will be ignored and should be dropped here, see https://github.com/lerna/lerna#--message--m-msg

Copy link
Member Author

Choose a reason for hiding this comment

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

I thought we keep one version aligned with Gutenberg release version. I need to collect all my thoughts and move to description :)
So the idea I had is that every time we publish a new version of the plugin to .org, we publish also the same version of npm packages. We will have to revisit after 5.0 mission is accomplished.

Copy link
Member

Choose a reason for hiding this comment

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

Yes, makes sense 👍

On the %s issue, did you run lerna init with the --independent flag? If so %s will be ignored, I'll take a closer look tomorrow, its a pretty minor thing that we will see if it is or is not when lerna publish is run for th first time 😏

Copy link
Member Author

Choose a reason for hiding this comment

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

lerna init only :)

@gziolo gziolo requested a review from hypest May 9, 2018 13:54
@ntwb
Copy link
Member

ntwb commented May 9, 2018

Now's a good time to add a CHANGELOG.md file for the date package, see WordPress/packages#118

return settings;
}

function setupWPTimezone() {
Copy link
Contributor

Choose a reason for hiding this comment

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

I'd love to get rid of moment config entirely and just export simple functions but let's do this separately. The date module is still usable in a generic way using get/setSettings at the moment

Copy link
Member Author

Choose a reason for hiding this comment

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

We can now remove all those date related logic from the default Jest config. I will take care of it separately.

"pot-to-php": "./bin/pot-to-php.js",
"publish:check": "lerna updated",
"publish:dev": "lerna publish --npm-tag next",
"publish:prod": "lerna publish",
Copy link
Contributor

Choose a reason for hiding this comment

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

Adding docs to the RELEASE.md would be good (or contributing) to explain how to use these things :), could be done later once the config is more battle-tested.

Copy link
Member Author

Choose a reason for hiding this comment

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

Copy link
Contributor

@youknowriad youknowriad left a comment

Choose a reason for hiding this comment

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

I do think we should address the npm builds instead of just publishing the sources. I can tackle that separately though.

Also let's give this some visibility as it's important @aduth @mtias @mcsf

@aduth
Copy link
Member

aduth commented May 9, 2018

This PR tries to provide Lerna setup similar to what we have in WordPress/packages. This would allow publishing source code of individual modules to npm to make them available for all plugin developers.

What process do you propose we adopt for cutting releases?

@gziolo
Copy link
Member Author

gziolo commented May 10, 2018

What process do you propose we adopt for cutting releases?

@aduth, I briefly described it as follows:

So the idea I had is that every time we publish a new version of the plugin to .org, we publish also the same version of npm packages. We will have to revisit after 5.0 mission is accomplished.

In the first iteration, we would release date with 2.8-alpha version as a development release. Once it is confirmed it works as expected, and we have build (es5) and build-module (esnext with import/export) distributions we could switch to regular releases.

To expand on it, once this PR is merged, we publish 2.8-alpha for @wordpress/date. Then we repeat the same steps for all modules that don't depend on globals. I will take care of it. At the same time, @youknowriad will check how to expose build and build-module versions in a similar fashion to what we do in WordPress/packages - (ideally we share the same script).
When we release v2.9 of Gutenberg, we also publish 2.9 version of npm modules (alpha or stable depending on the progress). We repeat the steps every time a new version of Gutenberg is released. We continue until Gutenberg is merged to core and 5.0 is out, then we decide what's next.

@gziolo gziolo force-pushed the update/move-date-to-packages branch from 19de1fa to 37a7223 Compare May 10, 2018 11:00
@gziolo gziolo requested a review from pento May 10, 2018 11:00
@gziolo
Copy link
Member Author

gziolo commented May 10, 2018

Now's a good time to add a CHANGELOG.md file for the date package, see WordPress/packages#118

See: lerna/lerna#850 (comment)

  • --conventional-commits is currently only enabled when you use the "independent" versioning mode, not the default "fixed" versioning (the version field of lerna.json).
  • Only per-package CHANGELOG.md files are currently updated, not the root.
  • Enabling --conventional-commits from lerna.json should look something like this:

Let's test it in WordPress/packages first and see how it goes. I don't feel like independent makes a lot of sense when individual packages from Gutenberg depend on each other. It might be very confusing to use them otherwise.

@aduth
Copy link
Member

aduth commented May 10, 2018

So the idea I had is that every time we publish a new version of the plugin to .org, we publish also the same version of npm packages. We will have to revisit after 5.0 mission is accomplished.

So not SemVer ?

@tofumatt
Copy link
Member

Not using SemVer is a 👎 from me; it makes it difficult to consume the packages and make sense of changes, which is the point of doing releases 😄

@ntwb
Copy link
Member

ntwb commented May 11, 2018

I don't feel like independent makes a lot of sense when individual packages from Gutenberg depend on each other.

This is what the cause of breaking SemVer would be due to, by setting this configuration option in Lerna every package in this repo would use the same version, but this doesn't have to mean semantic versioning is not used.

Rather, it would add SemVer to the Gutenberg releases, so if there is a breaking API change made later today, then the next release of Gutenberg would be 3.0.0 and 2.9.0 would be skipped.

The alternative with Lerna is to use the independent option which would allow Gutenberg 2.9.0 to be published including version 3.0.0 of @wordpress/date. Which is SemVer for the packages, but not Gutenberg itself.

@tofumatt
Copy link
Member

Which is SemVer for the packages, but not Gutenberg itself.

That makes the most sense to me; Gutenberg's versioning is not SemVer, but we shouldn't condemn our packages to the same fate 😉

@gziolo
Copy link
Member Author

gziolo commented May 11, 2018

The alternative with Lerna is to use the independent option which would allow Gutenberg 2.9.0 to be published including version 3.0.0 of @wordpress/date. Which is SemVer for the packages, but not Gutenberg itself.

Let's fly with independent and leave Gutenberg and WordPress following their own versioning schema. I thought it would be easier to follow Gutenberg versioning for some time, but apparently it would make things more confusing than I anticipated :)

@gziolo gziolo force-pushed the update/move-date-to-packages branch from 37a7223 to 8f022b8 Compare May 11, 2018 10:52
"packages": [
"packages/*"
],
"version": "independent"
Copy link
Member

Choose a reason for hiding this comment

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

👍

@gziolo
Copy link
Member Author

gziolo commented May 11, 2018

I'm merging this PR in the current shape with the intention to the follow-up work:

  1. Nothing gets published to npm immediately.
  2. I'm going to work on moving more modules to the same setup.
  3. @youknowriad volunteered to help with integrating transpiled version for the distribution purpose (both es5 and esnext).
  4. Let's discuss publishing strategy on Tuesday during CoreJS chat and all others steps.

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] Technical Prototype Offers a technical exploration into an idea as an example of what's possible
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants