Skip to content

Latest commit

 

History

History
557 lines (328 loc) · 22.1 KB

CONTRIBUTING.md

File metadata and controls

557 lines (328 loc) · 22.1 KB

Contributing

The following documentation is only for the maintainers of this repository.

Monorepo setup

This repository is managed as a monorepo that is composed of many npm packages.

For more information on monorepo:

Lerna

Lerna is used to manage this monorepo. The packages of the monorepo can be found in the packages directory.

Since Yarn workspace feature offer native mono-repo capabilities and a seemless integration with Lerna this is our goto package manager for this project.

When Lerna is configured to use Yarn, the installation of the npm dependencies and the management of the packages inter-dependencies will be delegated to Yarn. It result in an increase of performance and a more reliable experience than using the same features from Lerna. The native integration between Lerna and Yarn make it worthwill to switch from npm to Yarn for this project.

So why do we use Lerna if Yarn workspace take care of everything?

Lerna workflow greatly facilitate the release of the packages of a monorepo.

For more information, read the following Lerna commands documentation:

This monorepo is configured to release the packages independently. The decision to release or not a package is based on whether or not the code of the package has changed.

Yarn workspace

This monorepo is using Yarn workspace feature to handle the installation of the npm dependencies and manage the packages inter-dependencies.

It's important to note that Yarn workspace will hoist the npm dependencies at the root of the workspace. This means that there might not be a node_modules directory nested in the packages directories. The npm dependencies are installed in a node_modules directory at the root of the workspace and a single yarn.lock file is generated at the root of the workspace.

Since Storybook is not handled by the monorepo tooling, the .storybook directory will contain a node_modules directory and a yarn.lock file.

Installation

This project use Yarn workspace. Therefore, you must install Yarn:

choco install yarn

For more options to install Yarn, view https://yarnpkg.com/lang/en/docs/install/#windows-stable.

To install the project, open a terminal at the root of the workspace and execute the following command:

yarn

The installation should take up to 5 minutes.

During the installation you will encoutered several missing peerDependencies warnings. Ignore those warnings, this is happening because the devDependencies of this monorepo are defined at the root of the workspace.

Develop a component

The following documentation is a brief overview of the tools and processes involved in the development of a component. For more information, please read the React components documentation.

Adding or modifying an icon

When adding a new icon in @orbit-ui/icons, you want to make sure that the @orbit-ui/components package is updated accordingly. You will need to generate a new react component for that icon using the yarn generate-icons-components command.

Storybook

Every components must be developed and documented in Storybook.

Storybook is a convenient sandbox that help the developpers write organized and isolated stories that match the specifications of the component. Storybook also facilitate functionnal testing and integrate very well with automated visual testing technologies.

The resulting Storybook playbook will represent a catalog of all the Sharegate design system components and will be available online for the design team.

For more informations about automated visual tests, read the Testings section.

Start developing

To start developing, open a terminal in VSCode and execute the following command at the root of the workspace:

yarn start

Any updates to the packages or Storybook's stories will automatically re-compile the packages and refresh the Storybook app accordingly.

Start Storybook in docs mode.

To start developing in docs mode, open a terminal in VSCode and execute the following command at the root of the workspace:

yarn start-sb-docs

Basically the only difference is that the process will be start with the --docs arguments.

Any updates to the packages or Storybook's stories will automatically re-compile the packages and refresh the Storybook app accordingly.

Release the packages

When you are ready to release the packages, you must follow the following steps:

  1. Run yarn new-version to bump the version of the packages that have been updated since the previous release. You will be prompted to select the type of release (major, minor or patch) for each package and to enter release notes. If you prefer writing the release notes in a text editor, enter a placeholder line in the command line, and the you can modify the file generated before committing it.
  2. Commit the newly generated file in your branch and submit a new Pull Request(PR). Changesets will automatically detect the changes and post a message in your pull request telling you that once the PR closes, the versions will be released.
  3. Merge the Pull request into master. A Github action will automatically trigger and update the version of the packages and publish them to npm.
  4. Create a new Github release associated to the tag created previously
  5. Optionally deploy Storybook and the document Website

Alpha release

Sometimes it's useful to publish an alpha version to test the packages installation or share a preview.

Before you release, make sure you are in the master branch or a branch with a name matching the feature/* pattern, have write access to every selected npm packages and that you are logged in to npm.

To release an alpha version, open a terminal at the root of the workspace and execute the following commands:

yarn release-alpha

When Lerna version prompt pop, you should pick a version number matching your future main version. E.g. if you plan on publishing your changes as version 19.0.0 once they are done, your alpha version should be 19.0.0-alpha.1.

If you need to publish a subsequent alpha package for the same version, do not select any Lerna suggestion. Instead, select "Custom Prelease" and then enter "alpha". By doing so, the new alpha package version will be 19.0.0-alpha.2.

Troubleshooting

Github

Make sure you're Git is clean (No pending changes).

npm

Make sure you have write access to the selected npm packages.

If you are using 2FA, make sure you specified a valid OTP.

Compilation

If the packages failed to compile, it's easier to debug without executing the full release flow everytime. To do so, instead, execute the following command:

yarn build

By default, packages compilation output will be in their respective dist directory. For more details, read the packages README file.

Release docs

Orbit documentation is host on Netlify. 2 sites are available, a currated site for the official documentation (https://orbit.sharegate.design) and a raw site containing every Storybook stories (https://sg-storybook.netlify.com).

Login to Netlify and make sure you have access to the sg-orbit and sg-storybook sites of the GSoft team.

Netlify is configured to automatically deploy (unpublished) both sites everytime a new commit is done in an opened PR or a PR is merged back into master.

To publish a site:

  • Login to Netlify
  • Find the latest deploy of your site
  • Click on the deploy link to access it's overview
  • Click on the "Publish deploy" button

Troubleshoot

If you encounter any errors when building or publishing a site, login to Netlify and go to the deploy settings of the site. Make sure the Build command and the Publish directory properties are valid.

The Build command property should match a script of the root package.json file and the Publish directory property should be a relative path matching a folder of the solution containing the static site to deploy after build.

Local CLI deploy

A Netlify deploy can be started locally with a CLI command. This is useful if you are working in a branch and want to share a preview of your work with someone else.

To deploy a draft to the sg-storybook site, open a terminal at the root of the workspace and execute the following commands:

yarn deploy-netlify-sb-preview

The draft link will be available in the terminal (ex. https://616dab5c22680800ccd47d6f--sg-storybook.netlify.app).

If you encountered any problem with the CLI command, make sure the site App ID of sg-storybook site match the --site parameter of the script deploy-netlify-sb-preview in the package.json file.

Commands

All commands are available in the package.json file. Here's a list of the commands you might need to use frequently. The following commands must be executed in a terminal opened at the root of the workspace.

start

Compile all the packages & start Storybook.

yarn start

start-sb-docs

Compile all the packages & start Storybook in docs mode.

yarn start-sb-docs

build

Build all the packages and Storybook for production.

yarn build

reset

Reset the monorepo installation. The following will be deleted:

  • All the node_modules directories
  • All the yarn.lock files
  • All the compiled & cache folders
yarn reset

If you encounter the following error:

C:\Dev\20_gsoft\sg-orbit\node_modules\rimraf\bin.js:47
      throw er
      ^

[Error: EPERM: operation not permitted, unlink 'XXX\sg-orbit\node_modules\@types'] {

Close & re-open VSCode and delete manually the node_modules folder at the root of the workspace.

lint

Execute all the linters & validate the TypeScript types.

yarn lint

typecheck

Validate the TypeScript types.

yarn typecheck

jest

Execute all the Jest tests.

yarn jest

deploy-sb-preview

Manually deploy Storybook to Netlify from any branch.

yarn deploy-sb-preview

release-alpha

Deploy an alpha version of the packages.

yarn release-alpha

Testing

For testing the components we currently rely only on visual testing & interaction testing.

Visual testing

Visual testing assert on what visually appears on the screen instead of asserting on specifics CSS selectors or DOM elements.

This is a more black box and robust testing approach since it shouldn't requires to modify the tests if the code refactor haven't change anything visually.

This approach is usually strictly use to assert that the visual of a component do not regress. Since it's easy and very efficient to write a robust test with this approach, we also use it to test the specifications of a component that are related to the behaviors and states.

Therefore, prefer this approach to interactions and api testing when possible.

Setting all the tools to perform automated visual tests involve a lot of time and knowledge. Therefore, we bought a license of Chromatic QA. This is the perfect tool for us since it perfectly integrate with Storybook.

For access to our Chromatic QA environment, ask to join the gsoft-inc organization on Github.

For more information about automated visual testing:

Interaction testing

UI is all about interacting with the user. We need to test if a component work properly when those interactions occurs.

This approach is used to cover the interaction behaviors of a component.

Examples:

  • Ensure that a given element X is visible when the user click on the element Y.
  • Ensure that an handler of the component interface is called when the user on the element Y.

To facilite those tests, we use a combination of Jest and React testing library.

For more information about interaction testing:

API testing

API testing is useful to tests the properties of a component that can hardly be tested with visual testing.

Visual testing can easily assert that the disabled property of a component visually work as expected. Asserting that the onChange handler has been only called once when the user type a value in a textbox is harder.

This is where API testing shine.

To facilite those tests, we use a combination of Jest and React testing library.

CI

Circle CI is the continuous integration platform for this repository. To have access to the CI environment, ask to join the gsoft-inc on Github.

2 builds are currently configured:

On commits

On every commits the CI will execute the linters.

Nightly

Once per night, the CI will execute the automated visual tests. Those tests can't be executed on every commits since visual test snapshots are pricy and limited.

For more information on the automated visual tests, read the Testing section.

Troubleshooting

SSH

To investigate general problems with Circle CI you can debug with SSH.

Chromatic & Storybook

If Chromatic can't reach the Storybook server, the Storybook potentially can't compile.

Sadly the Chromatic CLI doesn't properly relay Storybook compilation errors. To see the errors, build the Storybook app locally.

Add a new package to the monorepo

There is a few steps to add a new packages to the monorepo.

Before you add a new package, please read the GSoft Github guidelines.

Create the package

First, create a new folder matching the package name in the packages directory.

Open a terminal, navigate to the newly created directory and execute the following command:

yarn init

Answer the CLI questions.

Once the package.json is generated, please read again the GSoft Github guidelines and make sure the package name, author and license are valid.

Don't forget to add the npm scope "@orbit-ui" before the package name. For example if the project name is "foo", your package name should be "@orbit-ui/foo".

Make sure the package publish access is public by adding the following to the package.json file:

"publishConfig": {
    "access": "public"
}

Dependencies

npm dependencies and peerDependencies must be added to the package own package.json file.

However, the devDependencies must be added to the package.json file at the root of the workspace.

Why?

Because packages hoisting is dangerous! When multiple packages of the monorepo requires the same dependencies but with a different version there is no garantee on which version will be hoisted to the node_modules directory at the root of the workspace and which version will be installed locally. To prevent all kinds of problems, always install the devDependencies at the root of the workspace. This ensure that every packages use the same version of the dependencies.

If you are uncertain wether or not you should add a peerDependencies, please read the post dependencies-done-right on the Yarn website.

Scripts

Before adding a script, make sure you read the following gotcha.

React components

If you're package is a new component, please read the React components documentation

Add a new Yarn script

When adding a new script, there is a few rules to follow.

Think in terms of atomic scripts

A script should only do one thing. This practice promote better readability and reusability.

Then you can write top level script that compose all those atomic scripts to provide a functionnality.

Instead of doing:

"scripts": {
    "build": "rimraf dist && babel src -d dist"
}

Do:

"scripts": {
    "build": "run-s delete transpile",
    "delete": "rimraf dist",
    "transpile": "babel src -d dist"
}

A script should be executable from the root of the workspace

Make sure you add a script entry in the package.json file at the root of the workspace even if your script is already define in a package or the website.

Lerna scripts should be executed from the root of the workspace

Lerna provide the ability to run or execute a script through all the packages of the monorepo.

Those scripts must be added in the package.json file at the root of the workspace since Lerna is installed at the root.

Use run-p or run-s

To run multiple commands simultaneously, use run-p.

To run multiple commands sequentially, use run-s.

Otherwise use yarn.

Naming

If a script can be called in batch, separate the discriminant by ":"

Example:

"scripts": {
    "clean": "run-p clean:*",
    "clean:pkg": "...",
    "clean:sb": "..."
}

Otherwise, separare words with "-"

Example:

"scripts": {
    "deploy-sb": "..."
}

Gotchas to remember

Chromatic QA & custom font

The Storybook configuration doesn't load the Interphases custom font if the app is started by the chromatic CLI because visual tests offer inconsistent results when a custom font is loaded. Not sure why.

How Lerna collect updated packages

As a starting point to determine which packages changed, Lerna used the last Git annotated tag available. Without a tag, Lerna will infer that all the packages changed.

cross-env

The following will not work:

"prepublishOnly": "cross-env NODE_ENV=production && yarn build"

But the following work:

"prepublishOnly": "cross-env NODE_ENV=production yarn build"

For other variables that need to be pass accross tasks, please read the following issue: kentcdodds/cross-env#176

Lerna and npm-run-all

Never use npm-run-all (run-s, run-p) in a lifecycle scripts of a leaf projects. Instead of running in the leaf project scope, it will run at the root project scope.

For more information, read this issue: lerna/lerna#2145 (comment)

react-testing-library and user actions side effects

Some side effects happens in the browsers following a user actions.

For example, if a user click on a textbox, the textbox will then have focus and be the "active element".

The focus side effect doesn't happen with react-testing-library. For more information view issues https://github.com/testing-library/jest-dom/issues/53 and https://github.com/testing-library/jest-dom/issues/59.

The solution to this problem have been to create an higher level abstraction library called https://github.com/testing-library/user-event that will take care of triggering the event AND the side effects.

For more information on the topic view the issue https://github.com/testing-library/dom-testing-library/issues/107.

Netlify CI setup

To enable deploy previews on PR, Netlify sg-orbit and sg-storybook sites have been linked to the sg-orbit Github repository. Netlify will deploy a preview on every commits for any branches, even for master (which is Netlify production). This beging said, since the sites have been configured with "Auto Publish" disabled, even if a deploy is compiled for production IT IS NOT DEPLOY, it's only available for preview and must be deployed manually.

Having disabled "Auto Publish" is also the reason why our script that publish our sites to production "doesn't work anymore". It still works, the reason why the site doesn't update is because the script will create a new production build but WILL NOT PUBLISH IT, since it's auto publishing is disabled. It must be published manually throught Netlify web interface.

Storybook props Tables

The Storybook props tables somewhow doesn't play well if our types comes from an external packages (even if it's a package in our own mono-repo). Props from the external packages might not be list in the props tables.

Updating Jest Snapshots

It's straightforward to spot when a snapshot test fails after a bug has been introduced. When that happens, go ahead and fix the issue and make sure your snapshot tests are passing again.

You can run the command

yarn jest --updateSnapshot -u FILENAME

So if you want to update the useStyledSystem.test.tsx file

yarn jest --updateSnapshot -u useStyledSystem.test.tsx