Skip to content

Latest commit

 

History

History
279 lines (196 loc) · 15.4 KB

CONTRIBUTING.md

File metadata and controls

279 lines (196 loc) · 15.4 KB

Contributing

Welcome!

We're excited for your interest in Greenwood, and maybe even your contribution!

We encourage all contributors to first read about the project's vision and motivation's on the website's About page. Greenwood is opinionated in the sense that it is designed to support development for the modern web platform and aims to deliver a first class developer experience tailored for that expectation. So if that page is the "why", this page is the "how".

Setup

To develop for the project, you'll want to follow these steps:

  1. Have NodeJS LTS installed and Yarn
  2. Clone the repository
  3. Run yarn install

If developing with Node Version Manager:

You can confirm by running the following

$ nvm use
Found '/Users/<directory_location>/greenwood/.nvmrc' with version <14.17.0>
Now using node v14.17.0 (npm v6.14.13)

Technical Design Overview

The Greenwood GitHub repository is a combination Yarn workspace and Lerna monorepo. The root level package.json defines the workspaces and shared tooling used throughout the project, like for linting, testing, etc.

The two main directories are:

  • packages/ - Packages published to NPM under the @greenwood/ scope
  • www/ - website / documentation code

This guide is mainly intended to walk through the cli package; it being the principal package within the project supporting all other packages.

CLI

The CLI is the main entry point for Greenwood, similar to how the front-controller pattern works. When users run a command like greenwood build, they are effectively invoking the file src/index.js within the @greenwood/cli package.

At a high level, this is how a command goes through the CLI:

  1. Each documented command a user can run maps to a script in the commands/ directory.
  2. Each command can invoke any number of lifecycles from the lifecycles/ directory.
  3. Lifecycles capture specific steps needed to build a site, serve it, generate a content dependency graph, etc.

Layout

The layout of the CLI package is as follows:

  • index.js - Front controller
  • commands/ - map to runnable userland commands
  • config/ - Tooling configuration that Greenwood creates
  • data/ - Custom GraphQL server and client side utilities
  • lib/ - Custom utility and client facing files
  • lifecycles/ - Tasks that can be composed by commands to support the full needs of that command
  • plugins/ - Custom default plugins maintained by the CLI project
  • templates/ - Default templates and / or pages provided by Greenwood.

Lifecycles

Aside from the config and graph lifecycles, all lifecycles (and config files and plugins) typically expect a compilation object to be passed in.

Lifeycles include handling:

  • starting a production or development server for a compilation
  • optimizing a compilation for production
  • prerendering a compilation for production
  • fetching external (content) data sources

Project Management

We take advantage of quite a few features on GitHub to assist in tracking issues, bugs, ideas and more for the project. We feel that being organized not only helps the team in planning out priorities and ownership, it's also a great way to add visibility and transparency to those following the project.

Project Boards

Our sequentially named project boards help us organize work into quarterly buckets that will generally include a small handful of "top line" goals and objectives we would like to focus on for that particular time box. It also serves as a catch-all for the usual work and bug fixes that happens throughout general maintenance of the project. Additionally, we leverage this as a means to shine insight into good opportunities for those interested in contributing as what the Greenwood team would appreciate help with the most.

Discussions

We believe good collaboration starts with good communication. As with most of the open source community, Greenwood is a 100% volunteer project and so we understand the importance of respecting everyone's time and expectations when it comes to contributing and investing in a project. Although we don't mind issues being made, unless the issue is clearly actionable and falls in-line with the motivations and trajectory of the project, then feel free to go ahead an open a Discussion first.

We encourage discussions as we believe it is better to hash out technical discussions and proposals ahead of time since coding and reviewing PRs are very time consuming activities. As maintainer's, we want to make sure everyone gets the time they are desire for contributing and this this workflow helps us plan our time in advance to best ensure a smooth flow of contributions through the project.

Put another way, we like to think of this approach as measure twice, cut once.

Issues

We like to reserve issues for features and requests that are more or less "shovel" ready with clear implementation details at hand. This could include prior discussions with the team or action items coming out from an existing discussion.

Our standard issue template requests some of the following information to be prepared (where applicable)

  1. High Level Overview
  2. Code Sample or API Design
  3. Links / references for more context

For bugs, please provide steps to reproduce and expected vs actual behavior including screenshots.

Pull Requests

Pull requests are the best! To best help facilitate contributions to the project, here are some requests:

  • We generally prefer an issue be opened first, to help facilitate general discussion outside of the code review process itself and align on the ask and any expectations. However, for typos in docs and minor "chore" like tasks a PR is usually sufficient. When in doubt, open an issue.
  • For bugs, please consider reviewing the issue tracker first.
  • For branching, we generally follow the convention <issue-label>/issue-<number>-<issue-title>, e.g. bug/issue-12-fixed-bug-with-yada-yada-yada
  • To test the CI build scripts locally, run the yarn commands mentioned in the below section on CI.

Continuous Integration

Greenwood makes active use of testing tools like GitHub Actions and Netlify deploy previews as part of the workflow. Each time a PR is opened, a sequence of build steps defined .github/workflows/ci..yml are run:

  1. Linting: yarn lint
  2. Running unit tests: yarn test
  3. Building the Greenwood website: yarn build

A preview is also made available within the status checks section of the PR in GitHub and can be used to validate work in a live environment before having to merge.

Local Development

To develop for the project, you'll want to follow these steps:

  1. Have NodeJS LTS installed (>= 12.x) and Yarn
  2. Clone the repository
  3. Run yarn install
  4. Run yarn lerna bootstrap

NPM Scripts

The Greenwood website is currently built by Greenwood, and all files for it are located in this repository under the www/ directory workspace. In addition to unit tests, you will want to verify any changes by running the website locally.

Below are the development tasks available for working on this project:

  • yarn develop - Develop for the website locally using the dev server at localhost:1984 in your browser.
  • yarn build - Builds the website for production.
  • yarn serve - Builds the website for production and runs it on a local webserver at localhost:8000

Packages

As mentioned above, Greenwood is organized into packages as a monorepo, managed by Lerna and Yarn Workspaces. You can find all of these in the packages/ directory. Each package will manage its own:

  • Dependencies
  • README
  • Test Cases

Lerna (specifically lerna publish) will be used to release all packages under a single version. Lerna configuration can be found in lerna.json.

Dependencies

To yarn add / yarn remove packages from anything in packages/ or www/, please make sure you cd into the directory with the package.json first.

For example

$ cd packages/cli
$ yarn add <package>

Yarn workspaces will automatically handle installing node_modules in the appropriate directory.

Testing

TDD is the recommended approach for developing for Greenwood and for the style of test writing we use BDD style testing; "cases". Cases are used to capture the various configurations and expected outputs of Greenwood when running its commands, in a way that mimics how a user would themselves be using Greenwood.

Running Tests

To run tests in watch mode, use:

$ yarn test:tdd

To verify compliance with coverage and watermark thresholds (what CI server runs), use:

$ yarn test

Below are some tips to help with running / debugging tests:

  • describe.only / it.only: only runs this block
  • xdescribe / xit: don't run this block
  • Uncomment runner.teardown() in a case to see the build output without it getting cleaned up post test run
  • Use new Runner(true) get debug output from Greenwood when running tests

PLEASE DO NOT COMMIT ANY OF THESE ABOVE CHANGES THOUGH

Writing Tests

Cases follow a convention starting with the command (e.g. build) and and the capability and features being tested, like configuration with a particular option (e.g. port):

<command>.<capability>.<feature>.spec.js

Examples:

  • build.default.spec.js - Would test greenwood build with no config and no workspace.
  • build.config.workspace-custom.spec.js - Would test greenwood build with a config that had a custom workspace
  • build.config.workspace-dev-server-port.spec.js - Would test greenwood build with a config that had a custom workspace and devServer.port set.

Notes

Here are some things to keep in mind while writing your tests, due to the asynchronous nature of Greenwood:

  • Make sure to wrap all calls to TestBed with async
  • All usages of JSDOM should be wrapped in async
  • Avoid arrow functions in mocha tests (e.g. () => ) as this can cause unexpected behaviors.. Just use function instead.

Supplemental Information

Some additional information and context to help assist with developing for and contributing to Greenwood.

Internet Explorer / Windows

For situations that require testing Internet Explorer or Edge browser, Microsoft provides Virtual Machines for various combinations of Windows and Internet Explorer versions. VirtualBox is a good platform to use for these VMs.

To test from a VM, you can

  1. Run yarn serve
  2. From the VM, open http://10.0.2.2:8000 in the browser

You can disable plugins in webpack.config.prod.js to remove production optimizations for testing purposes.

npx Testing

npx is a useful CLI utility bundled with NodeJS that allows users to run npm packages globally but without having to install them.

% npx http-server
Starting up http-server, serving ./public
Available on:
  http://127.0.0.1:8080
  http://192.168.1.153:8080
Hit CTRL-C to stop the server

It's featured on the Greenwood website home page and in the Quick Start guide as an option for using Greenwood. There is a spec for it to try and simulate running it.

You can use it for local development with Greenwood by using npm link to make greenwood available to your local CLI.

# From the root of the Greenwood repo
$ npm link

# then say in a test case folder
$ cd packages/cli/test/cases/build.default.quick-start-npx
$ npx greenwood
-------------------------------------------------------
Welcome to Greenwood (v0.14.1) ♻️
-------------------------------------------------------
Running Greenwood with the  command.

          Error: not able to detect command. try using the --help flag if
          you're encountering issues running Greenwood.  Visit our docs for more
          info at https://www.greenwoodjs.io/docs/.

Docker

A Docker container is available within the project to use as a development environment if you like. It is configured to use the same image that runs as part of the project's Continuous Integration environment.

First make sure you have Docker installed.

Then from the root of this repository do the following:

  1. Build the container: $ docker build -t nodejs-dev .
  2. Connect to the container: $ docker run --name greenwood -v $(pwd):/workspace -i -t nodejs-dev
  3. Now you can run all the usual commands, e.g.
  • $ yarn install
  • $ yarn build
  • $ yarn test

This will create a 2 way binding between your host and the container, so file changes will go both ways between the host and container.

When you're done with the container:

  1. Exit the container: $ exit
  2. Destroy the container: $ docker rm greenwood

Note: If you have issues running tests due to timeouts, you can increase the setting in package.json

Release Management

Lerna is used to manage the publishing of packages within the workspace under a single unified version. Assuming you are logged into npm locally and have 2FA access to publish, the following workflows should be used

After running these commands, Lerna should then prompt you through the steps to pick the version and all packages that will get updated.

Alpha Release

Greenwood typically works on new minor versions in a dedicated branch and release line called "alpha". This leverages NPM's concept of dist tags. While on a release branch, run the following to publish a new alpha release.

# from the root of the repo
$ yarn lerna publish --force-publish --dist-tag alpha

Typically you will want to select the Custom Preminor option from the list, which Lerna should appropriately yield the expected version.

Standard Release

For a normal release (e.g. "latest") the following command can be run from the mainline branch of the repo.

# from the root of the repo
$ yarn lerna publish --force-publish