├── .github └── workflows │ └── release.yml ├── .gitignore ├── LICENSE ├── README.md ├── lerna.json ├── package.json ├── packages ├── package-a │ ├── CHANGELOG.md │ ├── README.md │ ├── index.js │ └── package.json └── package-b │ ├── CHANGELOG.md │ ├── README.md │ ├── index.js │ └── package.json └── yarn.lock /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | name: Release 2 | 3 | on: 4 | push: 5 | branches: 6 | - master 7 | 8 | jobs: 9 | publish-gpr: 10 | name: Publish to GPR 11 | runs-on: ubuntu-latest 12 | steps: 13 | - uses: actions/checkout@v2 14 | with: 15 | fetch-depth: 0 16 | 17 | - uses: actions/setup-node@v1 18 | with: 19 | node-version: 12 20 | registry-url: 'https://npm.pkg.github.com/' 21 | 22 | - name: Ensure access 23 | run: npm whoami --registry https://npm.pkg.github.com/ 24 | env: 25 | NODE_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }} 26 | 27 | - name: Config git user 28 | run: | 29 | git config --global user.name "${{ github.actor }}" 30 | git config --global user.email "${{ github.actor }}@users.noreply.github.com" 31 | 32 | - name: Bootstrap lerna 33 | run: yarn bootstrap 34 | 35 | - name: Bump versions and publish packages 36 | run: | 37 | yarn version:ci 38 | yarn publish:ci 39 | env: 40 | GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} 41 | NODE_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }} 42 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | # Created by https://www.gitignore.io/api/node,react 3 | # Edit at https://www.gitignore.io/?templates=node,react 4 | 5 | ### Node ### 6 | # Logs 7 | logs 8 | *.log 9 | npm-debug.log* 10 | yarn-debug.log* 11 | yarn-error.log* 12 | lerna-debug.log* 13 | 14 | # Diagnostic reports (https://nodejs.org/api/report.html) 15 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json 16 | 17 | # Runtime data 18 | pids 19 | *.pid 20 | *.seed 21 | *.pid.lock 22 | 23 | # Directory for instrumented libs generated by jscoverage/JSCover 24 | lib-cov 25 | 26 | # Coverage directory used by tools like istanbul 27 | coverage 28 | *.lcov 29 | 30 | # nyc test coverage 31 | .nyc_output 32 | 33 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) 34 | .grunt 35 | 36 | # Bower dependency directory (https://bower.io/) 37 | bower_components 38 | 39 | # node-waf configuration 40 | .lock-wscript 41 | 42 | # Compiled binary addons (https://nodejs.org/api/addons.html) 43 | build/Release 44 | 45 | # Dependency directories 46 | node_modules/ 47 | jspm_packages/ 48 | 49 | # TypeScript v1 declaration files 50 | typings/ 51 | 52 | # TypeScript cache 53 | *.tsbuildinfo 54 | 55 | # Optional npm cache directory 56 | .npm 57 | 58 | # Optional eslint cache 59 | .eslintcache 60 | 61 | # Optional REPL history 62 | .node_repl_history 63 | 64 | # Output of 'npm pack' 65 | *.tgz 66 | 67 | # Yarn Integrity file 68 | .yarn-integrity 69 | 70 | # dotenv environment variables file 71 | .env 72 | .env.test 73 | 74 | # parcel-bundler cache (https://parceljs.org/) 75 | .cache 76 | 77 | # next.js build output 78 | .next 79 | 80 | # nuxt.js build output 81 | .nuxt 82 | 83 | # Serverless directories 84 | .serverless/ 85 | 86 | # FuseBox cache 87 | .fusebox/ 88 | 89 | # DynamoDB Local files 90 | .dynamodb/ 91 | 92 | ### react ### 93 | .DS_* 94 | **/*.backup.* 95 | **/*.back.* 96 | .env.local 97 | .env.development.local 98 | .env.test.local 99 | .env.production.local 100 | 101 | node_modules 102 | bower_componets 103 | 104 | *.sublime* 105 | 106 | psd 107 | thumb 108 | sketch 109 | 110 | build/ 111 | lib/ 112 | es/ 113 | 114 | # End of https://www.gitignore.io/api/node,react 115 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Jon Wahlström 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Lerna Release Workflow 2 | 3 | A basic [Lerna](https://lerna.js.org/) monorepo with [Yarn Workspaces](https://classic.yarnpkg.com/en/docs/workspaces/), [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/) and [GitHub Actions workflow](https://github.com/features/actions) configuration to achieve fully automated package publishing to the GitHub Package Registry. 4 | 5 | ## Create a new repository from this template 6 | 7 | Click the `Use this template` button and provide the new repository details. 8 | 9 | ## Getting Started 10 | 11 | Let's start by setting up the new repository: 12 | 13 | 1. Update the root `package.json` with your repository name and url. 14 | 15 | 2. Modify the sample packages as needed and remember to update their `package.json`. 16 | 17 | > **NOTE:** For a package to be releasable to GitHub Package Registry, it must be scoped to match the owner of the repository. The package name is optional, as long as it is unique under that scope. In addition, the `repository.url` field needs to be consistent in all package.json files. 18 | 19 | 3. Run `yarn bootstrap` to bootstrap the packages. This will install all of their dependencies and links any cross-dependencies. 20 | 21 | ## How it works 22 | 23 | Each push to `master` branch will generate a version number, git tag, Conventional Changelog, release commit, pushing changes to the origin and publish to GitHub Package Registry. 24 | 25 | ## Protected branches 26 | 27 | If you're using the protected branches feature, you'll need a Personal Access Token because the `GITHUB_TOKEN` generate by the CI won't have enough permission (that's by design). You can generate one in your [account settings](https://github.com/settings/tokens) and set it in the repository secrets. 28 | 29 | You'll also need to modify your action to: 30 | 31 | - Use `persist-credentials: false` when checking out the branch; 32 | - Set the repository remote to https format with the newly generated token. 33 | 34 | 35 | ```yml 36 | # ... 37 | - uses: actions/checkout@v3 38 | with: 39 | persist-credentials: false 40 | fetch-depth: 0 41 | # ... 42 | - name: Config git user 43 | run: | 44 | git config --global user.name "${{ github.actor }}" 45 | git config --global user.email "${{ github.actor }}@users.noreply.github.com" 46 | git remote set-url origin https://${{ github.actor }}:${{ secrets.PERSONAL_ACCESS_TOKEN }}@github.com/${{ github.repository }} 47 | # ... 48 | ``` 49 | -------------------------------------------------------------------------------- /lerna.json: -------------------------------------------------------------------------------- 1 | { 2 | "packages": ["packages/*"], 3 | "npmClient": "yarn", 4 | "useWorkspaces": true, 5 | "version": "independent", 6 | "command": { 7 | "publish": { 8 | "registry": "https://npm.pkg.github.com/" 9 | }, 10 | "version": { 11 | "allowBranch": "master", 12 | "ignoreChanges": ["**/*.md"] 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "lerna-release-workflow", 3 | "private": true, 4 | "author": "Jon Wahlström ", 5 | "repository": { 6 | "type": "git", 7 | "url": "https://github.com/jonwa/lerna-release-workflow.git" 8 | }, 9 | "workspaces": [ 10 | "packages/*" 11 | ], 12 | "scripts": { 13 | "commit": "git-cz", 14 | "bootstrap": "npx lerna bootstrap", 15 | "publish:ci": "lerna publish from-package --yes", 16 | "version:ci": "lerna version --yes --conventional-commits --create-release github --message 'chore(release): publish'" 17 | }, 18 | "devDependencies": { 19 | "commitizen": "^4.2.4", 20 | "cz-conventional-changelog": "^3.1.0", 21 | "lerna": "^4.0.0" 22 | }, 23 | "config": { 24 | "commitizen": { 25 | "path": "./node_modules/cz-conventional-changelog" 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /packages/package-a/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Change Log 2 | 3 | All notable changes to this project will be documented in this file. 4 | See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. 5 | 6 | # 0.1.0 (2020-03-29) 7 | 8 | 9 | ### Features 10 | 11 | * add package-a & package-b ([ad3ac32](https://github.com/jonwa/lerna-release-workflow/commit/ad3ac32b960f58ca7618a3d08a28295a4fabcccb)) 12 | -------------------------------------------------------------------------------- /packages/package-a/README.md: -------------------------------------------------------------------------------- 1 | # @jonwa/package-a 2 | 3 | ## Install 4 | 5 | Using npm: 6 | 7 | ``` 8 | npm install @jonwa/package-a 9 | ``` 10 | 11 | or using yarn: 12 | 13 | ``` 14 | yarn add @jonwa/package-a 15 | ``` 16 | 17 | ## Usage 18 | 19 | ``` 20 | const packageA = require('@jonwa/package-a'); 21 | ``` 22 | -------------------------------------------------------------------------------- /packages/package-a/index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | module.exports = packageA; 4 | 5 | function packageA() { 6 | // TODO 7 | } 8 | -------------------------------------------------------------------------------- /packages/package-a/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@jonwa/package-a", 3 | "version": "0.1.0", 4 | "main": "index.js", 5 | "license": "MIT", 6 | "repository": { 7 | "type": "git", 8 | "url": "git@github.com:jonwa/lerna-release-workflow.git", 9 | "directory": "packages/package-a" 10 | }, 11 | "scripts": { 12 | "prepublish": "yarn build", 13 | "build": "echo \"Build me!\"", 14 | "test": "echo \"Error: no test specified\" && exit 1" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /packages/package-b/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Change Log 2 | 3 | All notable changes to this project will be documented in this file. 4 | See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. 5 | 6 | ## [0.1.1](https://github.com/jonwa/lerna-release-workflow/compare/@jonwa/package-b@0.1.0...@jonwa/package-b@0.1.1) (2020-09-10) 7 | 8 | **Note:** Version bump only for package @jonwa/package-b 9 | 10 | 11 | 12 | 13 | 14 | # 0.1.0 (2020-03-29) 15 | 16 | 17 | ### Features 18 | 19 | * add package-a & package-b ([ad3ac32](https://github.com/jonwa/lerna-release-workflow/commit/ad3ac32b960f58ca7618a3d08a28295a4fabcccb)) 20 | -------------------------------------------------------------------------------- /packages/package-b/README.md: -------------------------------------------------------------------------------- 1 | # @jonwa/package-b 2 | 3 | ## Install 4 | 5 | Using npm: 6 | 7 | ``` 8 | npm install @jonwa/package-b 9 | ``` 10 | 11 | or using yarn: 12 | 13 | ``` 14 | yarn add @jonwa/package-b 15 | ``` 16 | 17 | ## Usage 18 | 19 | ``` 20 | const packageB = require('@jonwa/package-b'); 21 | ``` 22 | -------------------------------------------------------------------------------- /packages/package-b/index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | module.exports = packageB; 4 | 5 | function packageB() { 6 | // TODO 7 | } 8 | -------------------------------------------------------------------------------- /packages/package-b/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@jonwa/package-b", 3 | "version": "0.1.1", 4 | "main": "index.js", 5 | "license": "MIT", 6 | "repository": { 7 | "type": "git", 8 | "url": "git@github.com:jonwa/lerna-release-workflow.git", 9 | "directory": "packages/package-b" 10 | }, 11 | "scripts": { 12 | "prepublish": "yarn build", 13 | "build": "echo \"Build me!\"", 14 | "test": "echo \"Error: no test specified\" && exit 1" 15 | }, 16 | "dependencies": { 17 | "@jonwa/package-a": "^0.1.0" 18 | } 19 | } 20 | --------------------------------------------------------------------------------