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

Updated release flow #118 #141

Merged
merged 10 commits into from
May 18, 2020
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 21 additions & 30 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,38 +1,29 @@
# Changelog

All notable changes to this project will be documented in this file.
All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
Copy link
Contributor

Choose a reason for hiding this comment

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

When is the changelog to be updated now? Is there still a manual change needed when merging new work? i.e. the developer should update changelog with unreleased changes before merging into develop? Or are we only updating the changelog now on version releases with standard-version?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The latter - changelog will only be updated on version releases using standard-version


The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## 1.2.0 (2020-04-30)

## UNRELEASED
- feat: Added new Alert styles (slim, no icon) and allow the Alert to accept `div` attributes as props
- feat: Add additional CSS utility classes for background colors and text colors
- docs: Added additional examples of Form templates (Sign In form, Reset Password form) to Storybook
- chore: Turn off USWDS SCSS notifications on compile
- chore: Updated CODEOWNERS and contributors
- chore: Auto-approve Dependabot PRs
- chore: Deploy Storybook static site on merge to master
- chore: Run `yarn upgrade` to update all out of date dependencies
- chore: Add [DangerJS](https://danger.systems/js/) to automate some checks for contribution standards
- ci: Fixed Jest running in CI

- Added search component
## 1.1.0 (2020-03-19)

## [1.2.0] - 2020-04-30
- feat: Add initial set of USWDS form components (Checkbox, Dropdown, ErrorMessage, Fieldset, Form, FormGroup, Label, Radio, TextInput, Textarea)
- feat: Add native HTML attributes to existing Tag & Button components in order to support custom CSS classes
- feat: Added new Modal component (designed by Truss) and related Overlay and ModalContainer components
- chore: Configured use of SASS/SCSS and SASS/SCSS modules so that we can use USWDS SCSS
- chore: Configure Dependabot for automated dependency updates

- Added new Alert styles (slim, no icon) and allow the Alert to accept `div` attributes as props
- Added additional examples of Form templates (Sign In form, Reset Password form) to Storybook
- Turn off USWDS SCSS notifications on compile
- Updated CODEOWNERS and contributors
- Fixed Jest running in CI
- Auto-approve Dependabot PRs
- Deploy Storybook static site on merge to master
- Run `yarn upgrade` to update all out of date dependencies
- Add [DangerJS](https://danger.systems/js/) to automate some checks for contribution standards
- Add additional CSS utility classes for background colors and text colors
## 1.0.0 (2019-01-10)

## [1.1.0] - 2020-03-19

- Add initial set of USWDS form components (Checkbox, Dropdown, ErrorMessage, Fieldset, Form, FormGroup, Label, Radio, TextInput, Textarea)
- Add native HTML attributes to existing Tag & Button components in order to support custom CSS classes
- Added new Modal component (designed by Truss) and related Overlay and ModalContainer components
- Configured use of SASS/SCSS and SASS/SCSS modules so that we can use USWDS SCSS
- Configure Dependabot for automated dependency updates

## [1.0.0] - 2019-01-10

### Added

- Initial set of USWDS components (Accordion, Alert, Button, GovBanner, SideNav, Table, Tag)
- Initial documentation and dev configuration for contributing & usage
- feat!: Initial set of USWDS components (Accordion, Alert, Button, GovBanner, SideNav, Table, Tag)
- feat!: Initial documentation and dev configuration for contributing & usage
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

[![CircleCI](https://circleci.com/gh/trussworks/react-uswds.svg?style=svg&circle-token=a003f78b224f32fcab60155e3c0917a8040c5b96)](https://circleci.com/gh/trussworks/react-uswds)

[![Commitizen friendly](https://img.shields.io/badge/commitizen-friendly-brightgreen.svg)](http://commitizen.github.io/cz-cli/)

## Summary

This is a front end component library whose aim is to develop [React](https://reactjs.org/) implementations of the design patterns defined by the [United States Web Design System (USWDS) 2.0](https://designsystem.digital.gov/). The primary goal of this library is to document and provide common UI components that can be included in other projects that adhere to or are based off of the USWDS, removing a significant amount of overhead UI development from such projects.
Expand Down
3 changes: 3 additions & 0 deletions commitlint.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
module.exports = {
extends: ['@commitlint/config-conventional'],
}
47 changes: 20 additions & 27 deletions dangerfile.ts
Original file line number Diff line number Diff line change
@@ -1,46 +1,39 @@
import { includes } from 'lodash';
import { danger, warn, fail } from 'danger';
import { includes } from 'lodash'
import { danger, warn } from 'danger'

// No PR is too small to include a description of why you made a change
if (danger.github && danger.github.pr.body.length < 10) {
warn('Please include a description of your PR changes.');
warn('Please include a description of your PR changes.')
}

// load all modified and new files
const allFiles = danger.git.modified_files.concat(danger.git.created_files);
const allFiles = danger.git.modified_files.concat(danger.git.created_files)

// Request changes to package source code to also include changes to tests.
const hasCodeChanges = allFiles.some(p => !!p.match(/src\/.*\.[jt]sx?/));
const hasTestChanges = allFiles.some(p => !!p.match(/src\/.*\.test\.[jt]sx?/));
const hasCodeChanges = allFiles.some((p) => !!p.match(/src\/.*\.[jt]sx?/))
const hasTestChanges = allFiles.some((p) => !!p.match(/src\/.*\.test\.[jt]sx?/))
if (hasCodeChanges && !hasTestChanges) {
warn('This PR does not include changes to tests, even though it affects source code.');
warn(
'This PR does not include changes to tests, even though it affects source code.'
)
}

// Require new src/components files to include changes to storybook
const hasStorybookChanges = allFiles.some(p => !!p.match(/src\/.*\.stories\.[jt]sx?/));
const hasStorybookChanges = allFiles.some(
(p) => !!p.match(/src\/.*\.stories\.[jt]sx?/)
)

if (hasCodeChanges && !hasStorybookChanges) {
warn('This PR does not include changes to storybook, even though it affects component code.');
warn(
'This PR does not include changes to storybook, even though it affects component code.'
)
}

// Request update of yarn.lock if package.json changed but yarn.lock isn't
const packageChanged = includes(allFiles, 'package.json');
const lockfileChanged = includes(allFiles, 'yarn.lock');
const packageChanged = includes(allFiles, 'package.json')
const lockfileChanged = includes(allFiles, 'yarn.lock')
if (packageChanged && !lockfileChanged) {
const message = 'Changes were made to package.json, but not to yarn.lock';
const idea = 'Perhaps you need to run `yarn install`?';
warn(`${message} - <i>${idea}</i>`);
}

// ensure we have access to github for this check
let isTrivial = false;
if (danger.github) {
isTrivial = includes((danger.github.pr.body + danger.github.pr.title), "#trivial")
}

// Add a CHANGELOG entry for app changes
const hasChangelog = includes(danger.git.modified_files, "CHANGELOG.md")

if (!hasChangelog && !isTrivial) {
warn("Please add a changelog entry for your changes.")
const message = 'Changes were made to package.json, but not to yarn.lock'
const idea = 'Perhaps you need to run `yarn install`?'
warn(`${message} - <i>${idea}</i>`)
}
98 changes: 33 additions & 65 deletions docs/contributing.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Contributing

### Environment Setup
## Environment Setup

1. Clone this repo!

Expand Down Expand Up @@ -28,84 +28,52 @@ These should all be run from within the project directory.
- Builds files from `/src` and outputs to `/lib` using webpack and UMD library target
- `yarn build:watch` is also available

## Development & Release Workflow
## Development

Because this project exports a library that will be used by other projects, it is important to make sure that updates follow a set of standard practices, and new versions are tagged with an accurate description of changes. In order to ensure this, we use the following standards:
To start working on a new issue, make sure you've assigned yourself to the issue in Github and marked it as "In Progress." Create a new branch off `develop` using the naming convention:

### Branching model
`{your initials or username}-{summary}-{issue #}`

Summary from [a successful git branching model](https://nvie.com/posts/a-successful-git-branching-model/)
For example: `sr-accordion-component-112`

- **`master`**: Always reflects the current _production-ready_ version.
- Each commit to `master` represents a release (see "Release branches" below).
- **`develop`**: The latest delivered development changes for the next release, a.k.a. the "integration branch". This is configured to be the main branch in this repo, and all development branches branch off of `develop` by default.
- When the code on `develop` reaches a stable point and is ready to be released, it will be merged back into `master` via a release branch, and tagged with a version. This is described in more detail under "Release branches" below.
- **Feature branches**: Branch off of `develop` and merge back into `develop`. Naming convention is your initials + brief description of the feature.
- Example: `sr-accordion-component`
- It is recommended that during development, each engineer updates their feature branches from `develop` regularly, so that merging back in does not result in conflicts.
- **Release (candidate) branches**: Branch off of `develop` and merge back into both `develop` and `master`. These are created in preparation of a new version. Release notes, version number, and any other meta-data should be updated on this branch, smoke tests should be run, and any relevant bug fixes can be made. Performing this work on a release branch frees up the `develop` branch to continue work.
- Once a release branch has been created, any new work completed on `develop` will not be included until the next release.
- Release versions are determined at the creation of a new release branch (see more on [versioning below](#releasing)).
- Once the release branch is ready for production, it is merged into `master` and tagged with the version, as well as merged back into `develop`.
- Naming convention is `release-` and the new version number. Example: `release-1.0.0`
- **Hotfix branches**: Branch off of `master` and merge back into both `develop` and `master`. When a bug makes its way into a release, sometimes an urgent fix is required immediately. Hotfix branches allow for small changes to be made to production releases, without having to pull in other work that has been ongoing in `develop`.
- Once the fix has been completed and tested, this branch is treated identically to a release branch. It is merged into `master`, tagged with the new version, and also merged back into `develop`.
- Naming convention is `fix-` and the new version number (usually a patch from the previous version number). Example: `fix-1.0.1`
When you commit your changes, several hooks will run to check and format staged files. In order to be eligible for merging, all branches must pass testing and linting standards. Additionally, this project follows the [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/#summary) specification in order to standardize contributions and streamline the release flow. More information about the tools we're using:

Copy link
Contributor

@haworku haworku May 5, 2020

Choose a reason for hiding this comment

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

I think we should either describe or link here to examples of how commit messages should look for this standard.

The most important part (in my mind) is that people are aware of how to highlight a breaking changes specifically in their message. Particularly since we may use that to eventually automate the version bump down the road.

### Passing Builds
- [Prettier](https://prettier.io/), [TypeScript compilation](https://www.typescriptlang.org/), [eslint](https://eslint.org/) and [stylelint](https://stylelint.io/) are run on _staged files_ as a pre-commit hook
- For an optimal developer experience, it's recommended that you configure your editor to run linting & formatting inline.
- These checks will also be run on all files in CI, and must pass before the branch can be merged
- [`commitlint`](https://github.com/conventional-changelog/commitlint) is run on your commit message, using the [conventional commits config](https://github.com/conventional-changelog/commitlint/tree/master/%40commitlint/config-conventional)
- We also have set up [`commitizen`](https://commitizen.github.io/cz-cli/) CLI for making it easy to write standard commit messages. You can use `yarn commit` instead of `git commit` to start the commitizen prompt
- All [Jest tests](https://jestjs.io/) will be run in CI and must pass before the branch can be merged
- [`standard-version`](https://github.com/conventional-changelog/standard-version) is used during releases to auto-generate version numbers and changelog based on commit messages

In order to be eligible for merging, all branches must pass testing and linting standards. The following checks are in place:
When your branch is ready for review, open a PR into `develop` and request reviews from relevant team members. Reviews from codeowners will automatically be requested. Address any failing tests, lint errors, PR feedback, etc., and once your branch is approved you can squash & merge it into `develop`.

- Prettier (auto-formatting) and eslint are run on _staged files_ as a pre-commit hook
- For an optimal developer experience, it's recommended that you configure your editor to run linting/formatting inline.
- All tests must pass, and eslint is run on all files in CircleCI
(TODO) Passing `develop` builds will automatically be published to the `next` tag on NPM. This allows users to easily test out the latest version in their applications, which may be unstable.
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Calling this out as a TODO - need to add GH workflow for this


### Releasing
## Releasing

Steps for a new release (these should be automated as much as possible):
Steps for a new release (these are in the process of being automated):

1. Determine the new version number based on the scale of changes following [Semantic Versioning](https://semver.org/):
1. Check out `develop` and make sure you have pulled down the latest changes.

> Given a version number MAJOR.MINOR.PATCH, increment the:
>
> - MAJOR version when you make incompatible API changes,
> - MINOR version when you add functionality in a backwards compatible manner, and
> - PATCH version when you make backwards compatible bug fixes.
1. Run `yarn release` which uses [`standard-version`](https://github.com/conventional-changelog/standard-version) to:

2. Create the release candidate branch (note that version numbers should _never_ be prefixed with `v`):
- Determine the new version based on new commits.
- Generate a new entry in the changelog with the version, release notes, and today's date.
- Commit all of the above changes
- Note: Creating a new tag is **skipped** (this will happen as part of the publish flow)

```
git checkout -b release-<version>
```
1. Push changes to a new branch following the naming pattern: `release-<version>`

For example:
- For example: `git checkout -b release-1.1.0`

```
git checkout -b release-1.1.0
```
1. Open a PR for the release branch against **`master`** (not `develop`, which is the default branch), with the new set of changes generated by the previous step included in the PR description. Ask for approvals from stakeholders, perform testing on applications, etc. Any hot fixes from testing or PR feedback can be made to the release branch directly if appropriate.

3. Make sure the [change log](../CHANGELOG.md) is up to date with all of the changes in the new version. It can be helpful to compare `develop` with the latest version to see what commits have been made since. For example: https://github.com/trussworks/react-uswds/compare/1.0.0...develop
![image](./release_PR.png)

4. Update the package version number in [`package.json`](../package.json)

5. Open a PR for the release branch against **`master`** (not `develop`, which is the default branch), and ask for approvals from stakeholders, perform testing on applications, etc. Any hot fixes from testing or PR feedback can be made to the release branch directly if appropriate. This is also a good time to check for any pending Dependabot PRs and merge those.

![image](./release_PR.png)

6. Once the release PR is approved, complete the release by merging into master, and creating a release on Github (https://github.com/trussworks/react-uswds/releases). The tag version should be the new version number (again, _not_ prefixed with `v`) and the changelog should be included in the description. Immediately merge master into develop so that develop is up to date with the new version.

![image](./github_release.png)

7. Finally, publish the new package to npm. You can do a dry run with:

```
npm publish --dry-run
```

This will output the resulting .tar package without actually publishing it to the npm registry. If everything looks good, you can then run:

```
npm publish
```

Publishing access is limited to package owners. If you need access and don't have it, please contact `@npm-admins` on Slack.
1. Once the release PR is approved, complete the release and publish the new version (this should be automated by GH - TODO):
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Calling this out as a TODO - need to add GH workflow for this

- Merge the PR into master
- Create a release tag on Github (https://github.com/trussworks/react-uswds/releases)
- Merge master into develop so that develop is up to date with the new version.
- Finally, publish the new package to npm: `npm publish`
- Publishing access is limited to package owners. If you need access and don't have it, please contact `@npm-admins` on Truss Slack.
19 changes: 16 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,15 +20,17 @@
"node": "^12.16.2"
},
"scripts": {
"commit": "git-cz",
"test": "jest",
"test:watch": "jest --watch",
"test:coverage": "jest --coverage",
"storybook": "start-storybook",
"storybook:deploy": "storybook-to-ghpages",
"build": "webpack",
"build": "webpack -p",
"build:watch": "webpack --watch",
"lint": "tsc --noEmit && eslint --ext js,jsx,ts,tsx src",
"prepare": "yarn build"
"lint": "tsc --noEmit && eslint --ext js,jsx,ts,tsx src && stylelint \"src/**/*.{css,scss}\"",
"release": "standard-version -t",
"prepublishOnly": "build"
},
"repository": {
"type": "git",
Expand Down Expand Up @@ -61,6 +63,8 @@
"devDependencies": {
"@babel/core": "^7.6.2",
"@babel/preset-react": "^7.0.0",
"@commitlint/cli": "^8.3.5",
"@commitlint/config-conventional": "^8.3.4",
"@storybook/addon-info": "^5.2.3",
"@storybook/react": "^5.2.1",
"@storybook/storybook-deployer": "^2.8.5",
Expand All @@ -78,8 +82,10 @@
"babel-eslint": "^10.0.3",
"babel-jest": "^25.1.0",
"babel-loader": "^8.0.6",
"commitizen": "^4.1.2",
"css-loader": "^3.2.0",
"css-modules-typescript-loader": "^4.0.0",
"cz-conventional-changelog": "3.2.0",
"danger": "^10.0.0",
"eslint": "^6.5.1",
"eslint-config-prettier": "^6.3.0",
Expand All @@ -101,6 +107,7 @@
"sass-loader": "^8.0.2",
"sass-resources-loader": "^2.0.1",
"source-map-loader": "^0.2.4",
"standard-version": "^7.1.0",
"stylelint": "^13.3.0",
"stylelint-config-css-modules": "^2.2.0",
"stylelint-config-prettier": "^8.0.1",
Expand All @@ -121,6 +128,7 @@
"husky": {
"hooks": {
"pre-commit": "tsc --noEmit && lint-staged",
"commit-msg": "commitlint -E HUSKY_GIT_PARAMS",
"pre-push": "yarn danger local --failOnErrors"
}
},
Expand All @@ -133,5 +141,10 @@
"prettier --write",
"stylelint"
]
},
"config": {
"commitizen": {
"path": "./node_modules/cz-conventional-changelog"
}
}
}
Loading