├── .all-contributorsrc
├── .editorconfig
├── .eslintignore
├── .eslintrc.json
├── .github
└── workflows
│ ├── ci.yml
│ └── release.yml
├── .gitignore
├── .prettierignore
├── .prettierrc
├── .verdaccio
└── config.yml
├── .vscode
├── extensions.json
└── settings.json
├── CHANGELOG.md
├── CODE_OF_CONDUCT.md
├── CONTRIBUTING.md
├── LICENSE
├── README.md
├── apps
└── .gitkeep
├── jest.config.ts
├── jest.preset.js
├── libs
├── .gitkeep
└── nx-release
│ ├── .all-contributorsrc
│ ├── .eslintrc.json
│ ├── README.md
│ ├── assets
│ └── nx-release-logo.svg
│ ├── executors.json
│ ├── generators.json
│ ├── jest.config.ts
│ ├── package.json
│ ├── project.json
│ ├── src
│ ├── executors
│ │ ├── build-update-publish
│ │ │ ├── executor.spec.ts
│ │ │ ├── executor.ts
│ │ │ ├── schema.d.ts
│ │ │ └── schema.json
│ │ ├── helpers
│ │ │ ├── projects.helpers.spec.ts
│ │ │ └── projects.helpers.ts
│ │ ├── npm-publish
│ │ │ ├── executor.spec.ts
│ │ │ ├── executor.ts
│ │ │ ├── schema.d.ts
│ │ │ └── schema.json
│ │ └── update-version
│ │ │ ├── executor.spec.ts
│ │ │ ├── executor.ts
│ │ │ ├── schema.d.ts
│ │ │ └── schema.json
│ ├── generators
│ │ ├── configure-libraries
│ │ │ ├── generator.spec.ts
│ │ │ ├── generator.ts
│ │ │ ├── schema.d.ts
│ │ │ └── schema.json
│ │ ├── configure-library
│ │ │ ├── generator.spec.ts
│ │ │ ├── generator.ts
│ │ │ ├── schema.d.ts
│ │ │ └── schema.json
│ │ ├── configure-workspace
│ │ │ ├── generator.spec.ts
│ │ │ ├── generator.ts
│ │ │ ├── schema.d.ts
│ │ │ └── schema.json
│ │ ├── configure
│ │ │ ├── generator.spec.ts
│ │ │ ├── generator.ts
│ │ │ ├── schema.d.ts
│ │ │ └── schema.json
│ │ ├── generate-gh-actions
│ │ │ ├── files
│ │ │ │ └── .github
│ │ │ │ │ └── workflows
│ │ │ │ │ ├── ci.yml
│ │ │ │ │ └── release.yml
│ │ │ ├── generator.spec.ts
│ │ │ ├── generator.ts
│ │ │ ├── schema.d.ts
│ │ │ └── schema.json
│ │ ├── generate-release-config
│ │ │ ├── files
│ │ │ │ └── release.config.js.template
│ │ │ ├── generator.spec.ts
│ │ │ ├── generator.ts
│ │ │ ├── schema.d.ts
│ │ │ └── schema.json
│ │ └── helpers
│ │ │ ├── projects.helpers.spec.ts
│ │ │ ├── projects.helpers.ts
│ │ │ └── spinner.helper.ts
│ └── index.ts
│ ├── tsconfig.json
│ ├── tsconfig.lib.json
│ └── tsconfig.spec.json
├── nx.json
├── package-lock.json
├── package.json
├── project.json
├── release.config.js
├── tools
├── scripts
│ └── publish.mjs
└── tsconfig.tools.json
└── tsconfig.base.json
/.all-contributorsrc:
--------------------------------------------------------------------------------
1 | {
2 | "files": [
3 | "README.md"
4 | ],
5 | "imageSize": 100,
6 | "commit": false,
7 | "commitType": "docs",
8 | "commitConvention": "angular",
9 | "contributors": [
10 | {
11 | "login": "ajitzero",
12 | "name": "Ajit Panigrahi",
13 | "avatar_url": "https://avatars.githubusercontent.com/u/19947758?v=4",
14 | "profile": "https://beta.ajitpanigrahi.com",
15 | "contributions": [
16 | "doc"
17 | ]
18 | },
19 | {
20 | "login": "canserkanuren",
21 | "name": "Can Serkan UREN",
22 | "avatar_url": "https://avatars.githubusercontent.com/u/22659909?v=4",
23 | "profile": "https://github.com/canserkanuren",
24 | "contributions": [
25 | "code",
26 | "ideas",
27 | "test"
28 | ]
29 | },
30 | {
31 | "login": "markuczy",
32 | "name": "markuczy",
33 | "avatar_url": "https://avatars.githubusercontent.com/u/129275100?v=4",
34 | "profile": "https://github.com/markuczy",
35 | "contributions": [
36 | "code"
37 | ]
38 | }
39 | ],
40 | "contributorsPerLine": 7,
41 | "skipCi": true,
42 | "repoType": "github",
43 | "repoHost": "https://github.com",
44 | "projectName": "nx-release",
45 | "projectOwner": "nivekcode"
46 | }
47 |
--------------------------------------------------------------------------------
/.editorconfig:
--------------------------------------------------------------------------------
1 | # Editor configuration, see http://editorconfig.org
2 | root = true
3 |
4 | [*]
5 | charset = utf-8
6 | indent_style = space
7 | indent_size = 2
8 | insert_final_newline = true
9 | trim_trailing_whitespace = true
10 |
11 | [*.md]
12 | max_line_length = off
13 | trim_trailing_whitespace = false
14 |
--------------------------------------------------------------------------------
/.eslintignore:
--------------------------------------------------------------------------------
1 | node_modules
2 |
--------------------------------------------------------------------------------
/.eslintrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "root": true,
3 | "ignorePatterns": ["**/*"],
4 | "plugins": ["@nx"],
5 | "overrides": [
6 | {
7 | "files": ["*.ts", "*.tsx", "*.js", "*.jsx"],
8 | "rules": {
9 | "@nx/enforce-module-boundaries": [
10 | "error",
11 | {
12 | "enforceBuildableLibDependency": true,
13 | "allow": [],
14 | "depConstraints": [
15 | {
16 | "sourceTag": "*",
17 | "onlyDependOnLibsWithTags": ["*"]
18 | }
19 | ]
20 | }
21 | ]
22 | }
23 | },
24 | {
25 | "files": ["*.ts", "*.tsx"],
26 | "extends": ["plugin:@nx/typescript"],
27 | "rules": {}
28 | },
29 | {
30 | "files": ["*.js", "*.jsx"],
31 | "extends": ["plugin:@nx/javascript"],
32 | "rules": {}
33 | },
34 | {
35 | "files": ["*.spec.ts", "*.spec.tsx", "*.spec.js", "*.spec.jsx"],
36 | "env": {
37 | "jest": true
38 | },
39 | "rules": {}
40 | },
41 | {
42 | "files": "*.json",
43 | "parser": "jsonc-eslint-parser",
44 | "rules": {}
45 | }
46 | ]
47 | }
48 |
--------------------------------------------------------------------------------
/.github/workflows/ci.yml:
--------------------------------------------------------------------------------
1 | name: CI
2 | on:
3 | push:
4 | branches:
5 | - '*'
6 | - '*/*'
7 | - '**'
8 | - '!main'
9 | jobs:
10 | main:
11 | runs-on: ubuntu-latest
12 | steps:
13 | - uses: actions/checkout@v2
14 | with:
15 | fetch-depth: 0
16 | - uses: nrwl/nx-set-shas@v3
17 | - name: Install deps
18 | run: npm ci
19 | - name: Lint affected
20 | run: npx nx affected -t lint
21 | - name: Test affected
22 | run: npm run test:coverage
23 | - name: Report coverage
24 | uses: coverallsapp/github-action@v2
25 | - name: Build affected
26 | run: npx nx affected -t build
27 |
--------------------------------------------------------------------------------
/.github/workflows/release.yml:
--------------------------------------------------------------------------------
1 | name: RELEASE
2 | on: [workflow_dispatch]
3 | jobs:
4 | main:
5 | runs-on: ubuntu-latest
6 | steps:
7 | - uses: actions/checkout@v2
8 | with:
9 | fetch-depth: 0
10 | - uses: nrwl/nx-set-shas@v3
11 | - name: Install deps
12 | run: npm ci
13 | - name: Lint
14 | run: npx nx run-many -t lint
15 | - name: Test
16 | run: npm run test:coverage
17 | - name: Report coverage
18 | uses: coverallsapp/github-action@v2
19 | - name: Release
20 | run: npx semantic-release
21 | env:
22 | GITHUB_TOKEN: ${{ secrets.GH_TOKEN }}
23 | NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
24 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # See http://help.github.com/ignore-files/ for more about ignoring files.
2 |
3 | # compiled output
4 | dist
5 | tmp
6 | /out-tsc
7 |
8 | # dependencies
9 | node_modules
10 |
11 | # IDEs and editors
12 | /.idea
13 | .project
14 | .classpath
15 | .c9/
16 | *.launch
17 | .settings/
18 | *.sublime-workspace
19 |
20 | # IDE - VSCode
21 | .vscode/*
22 | !.vscode/settings.json
23 | !.vscode/tasks.json
24 | !.vscode/launch.json
25 | !.vscode/extensions.json
26 |
27 | # misc
28 | /.sass-cache
29 | /connect.lock
30 | /coverage
31 | /libpeerconnection.log
32 | npm-debug.log
33 | yarn-error.log
34 | testem.log
35 | /typings
36 |
37 | # System Files
38 | .DS_Store
39 | Thumbs.db
40 |
--------------------------------------------------------------------------------
/.prettierignore:
--------------------------------------------------------------------------------
1 | # Add files here to ignore them from prettier formatting
2 | /dist
3 | /coverage
--------------------------------------------------------------------------------
/.prettierrc:
--------------------------------------------------------------------------------
1 | {
2 | "singleQuote": true
3 | }
4 |
--------------------------------------------------------------------------------
/.verdaccio/config.yml:
--------------------------------------------------------------------------------
1 | # path to a directory with all packages
2 | storage: ../tmp/local-registry/storage
3 |
4 | # a list of other known repositories we can talk to
5 | uplinks:
6 | npmjs:
7 | url: https://registry.npmjs.org/
8 | maxage: 60m
9 |
10 | packages:
11 | '**':
12 | # give all users (including non-authenticated users) full access
13 | # because it is a local registry
14 | access: $all
15 | publish: $all
16 | unpublish: $all
17 |
18 | # if package is not available locally, proxy requests to npm registry
19 | proxy: npmjs
20 |
21 | # log settings
22 | logs:
23 | type: stdout
24 | format: pretty
25 | level: warn
26 |
27 | publish:
28 | allow_offline: true # set offline to true to allow publish offline
29 |
--------------------------------------------------------------------------------
/.vscode/extensions.json:
--------------------------------------------------------------------------------
1 | {
2 | "recommendations": [
3 | "nrwl.angular-console",
4 | "esbenp.prettier-vscode",
5 | "dbaeumer.vscode-eslint",
6 | "firsttris.vscode-jest-runner"
7 | ]
8 | }
9 |
--------------------------------------------------------------------------------
/.vscode/settings.json:
--------------------------------------------------------------------------------
1 | {
2 | "eslint.validate": ["json"]
3 | }
4 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | ## [3.4.0](https://github.com/kreuzerk/nx-release/compare/v3.3.0...v3.4.0) (2025-01-08)
2 |
3 |
4 | ### Features
5 |
6 | * npm publish uses distribution tags ([8715172](https://github.com/kreuzerk/nx-release/commit/8715172a939c524d2fcef37d8090b000891a096a))
7 |
8 |
9 | ### Refactoring
10 |
11 | * remove trailing semicolon ([ed04275](https://github.com/kreuzerk/nx-release/commit/ed042756c90dc84587f18eb2ff3d99e280916679))
12 | * revert formatting ([4b3005d](https://github.com/kreuzerk/nx-release/commit/4b3005d239fb4836ec290404002a80875d586a07))
13 | * revert further format changes ([a04186d](https://github.com/kreuzerk/nx-release/commit/a04186d853bd5feb36b96abc7e8471bb354dde4c))
14 |
15 | ## [3.3.0](https://github.com/kreuzerk/nx-release/compare/v3.2.0...v3.3.0) (2024-01-20)
16 |
17 |
18 | ### Features
19 |
20 | * **npm-publish:** do not override current .npmrc file ([c71f7dd](https://github.com/kreuzerk/nx-release/commit/c71f7dd000593d4ffb869a5d26db4850690adc76))
21 |
22 | ## [3.2.0](https://github.com/kreuzerk/nx-release/compare/v3.1.6...v3.2.0) (2024-01-18)
23 |
24 |
25 | ### Features
26 |
27 | * **npm-publish:** add option to specify npm registry ([f576088](https://github.com/kreuzerk/nx-release/commit/f5760886cb332702a7fb3e025ec3e2148f50bc16))
28 |
29 | ## [3.1.6](https://github.com/kreuzerk/nx-release/compare/v3.1.5...v3.1.6) (2023-09-27)
30 |
31 |
32 | ### Bug Fixes
33 |
34 | * 🐛 add missing inquirer dependency ([c05a44b](https://github.com/kreuzerk/nx-release/commit/c05a44bef872c0acce6c2d1f609dcb5db45c4782))
35 |
36 | ## [3.1.5](https://github.com/kreuzerk/nx-release/compare/v3.1.4...v3.1.5) (2023-07-13)
37 |
38 |
39 | ### Bug Fixes
40 |
41 | * 🐛 trigger release ([d5b78a3](https://github.com/kreuzerk/nx-release/commit/d5b78a3f1139147dc1374e7a1ffc4b25c1028f7b))
42 |
43 | ## [3.1.4](https://github.com/kreuzerk/nx-release/compare/v3.1.3...v3.1.4) (2023-07-12)
44 |
45 |
46 | ### Bug Fixes
47 |
48 | * 🐛 install missing conventional commits dep ([4671b5e](https://github.com/kreuzerk/nx-release/commit/4671b5e04d46edadba2221e510edd2e3fdb29b0b))
49 |
50 | ## [3.1.3](https://github.com/kreuzerk/nx-release/compare/v3.1.2...v3.1.3) (2023-07-11)
51 |
52 |
53 | ### Bug Fixes
54 |
55 | * 🐛 remove the all selection option ([2fc13d0](https://github.com/kreuzerk/nx-release/commit/2fc13d00bb43ec5f7378a002af6c6bc3f3965f6f))
56 |
57 | ## [3.1.2](https://github.com/kreuzerk/nx-release/compare/v3.1.1...v3.1.2) (2023-07-11)
58 |
59 |
60 | ### Bug Fixes
61 |
62 | * 🐛 generate files before installing ([928237f](https://github.com/kreuzerk/nx-release/commit/928237fab4d8b2771dc0918fbb351cccb5209641))
63 |
64 | ## [3.1.1](https://github.com/kreuzerk/nx-release/compare/v3.1.0...v3.1.1) (2023-07-11)
65 |
66 |
67 | ### Bug Fixes
68 |
69 | * 🐛 update tslib dep ([8464424](https://github.com/kreuzerk/nx-release/commit/84644240b9a34cf5babb0cb0bc7fdd3e1941ae1f))
70 |
71 | ## [3.1.0](https://github.com/kreuzerk/nx-release/compare/v3.0.0...v3.1.0) (2023-07-11)
72 |
73 |
74 | ### Features
75 |
76 | * 🎸 select all option on libraries configurator ([22a3208](https://github.com/kreuzerk/nx-release/commit/22a320857e423a95ec361dbf793cb2a6c4391f16))
77 |
78 |
79 | ### Chores
80 |
81 | * 🤖 add test libs ([0e29dd2](https://github.com/kreuzerk/nx-release/commit/0e29dd2abde2a32763fbb94cc1f53dc40b123d4b))
82 | * 🤖 remove release target from nx-release project.json ([c68b49e](https://github.com/kreuzerk/nx-release/commit/c68b49eb2d909305162bd1f736a57faf84d84fdb))
83 |
84 | ## [3.0.0](https://github.com/kreuzerk/nx-release/compare/v2.1.0...v3.0.0) (2023-07-11)
85 |
86 |
87 | ### ⚠ BREAKING CHANGES
88 |
89 | * 🧨 libName option input is removed
90 |
91 | ### Features
92 |
93 | * 🎸 add configure libraries generator ([ec61506](https://github.com/kreuzerk/nx-release/commit/ec61506593306bf56fe29c71600a5094a78db300))
94 | * 🎸 add configure libraries generator ([e445d24](https://github.com/kreuzerk/nx-release/commit/e445d24ee72ed70555c48179a029da8f390df4b1))
95 | * 🎸 add configure library generator ([e615fcf](https://github.com/kreuzerk/nx-release/commit/e615fcf82075199ffcdfbd3f684a45239b17aa0b))
96 | * 🎸 add configure-libraries generator ([ed1ba0b](https://github.com/kreuzerk/nx-release/commit/ed1ba0bb55d0033a76264cc1a68d3b6741e0d8e5))
97 | * 🎸 add required prompts ([f6d1a67](https://github.com/kreuzerk/nx-release/commit/f6d1a67410e558f7f39d49d7d3965116a6248276))
98 | * 🎸 add workspace configuration generator ([dbe072f](https://github.com/kreuzerk/nx-release/commit/dbe072f69a4c87e432c466142a97c1a892baac45))
99 | * 🎸 add workspace configurator generator ([92cca1c](https://github.com/kreuzerk/nx-release/commit/92cca1c710180b366e5342eac1d192b71a643e52))
100 | * 🎸 extract gh-action and release config into generators ([7dfd196](https://github.com/kreuzerk/nx-release/commit/7dfd196882032559708eae9c543a7611a9452115))
101 | * 🎸 improve executors ([b1410d7](https://github.com/kreuzerk/nx-release/commit/b1410d7097cc39cada83d46d8a5b609c0c0f818d))
102 |
103 |
104 | ### Bug Fixes
105 |
106 | * 🐛 remove lib path ([ad8d811](https://github.com/kreuzerk/nx-release/commit/ad8d811ddf0c91653122642892bcf10dd2da5628))
107 | * 🐛 remove required options ([94e8ee9](https://github.com/kreuzerk/nx-release/commit/94e8ee926d6a45a41dd30e3e6b9c1267858a7875))
108 | * 🐛 update generate GitHub actions workflow generator ([556fbc8](https://github.com/kreuzerk/nx-release/commit/556fbc8a30a1b0f8d2a1fb81a57f7d7fb00708a6))
109 | * 🐛 use correct source root ([c0f6933](https://github.com/kreuzerk/nx-release/commit/c0f693381948cda70ab35ddabb6791a55199faab))
110 | * 🐛 use root instead of src root ([0296ab9](https://github.com/kreuzerk/nx-release/commit/0296ab9ef9f887ccf3ad60220951f4ba9a6bbcb2))
111 |
112 |
113 | ### Chores
114 |
115 | * 🤖 add all-contributors as dep ([d64a92a](https://github.com/kreuzerk/nx-release/commit/d64a92a531633977ded5e7956137f7d7ef8221d2))
116 | * 🤖 adjust build scripts ([09b16e5](https://github.com/kreuzerk/nx-release/commit/09b16e5d2757ab82df1eb7dbe5ef68648e28127e))
117 | * 🤖 generate coverage report ([8f6dec1](https://github.com/kreuzerk/nx-release/commit/8f6dec1125f47086cd9aa1e9e2947f5f630dfdd0))
118 | * 🤖 remove test libraries ([bba255e](https://github.com/kreuzerk/nx-release/commit/bba255e96c1734f9055415db9066bd36a4801b86))
119 | * 🤖 run tests with release ([a12438d](https://github.com/kreuzerk/nx-release/commit/a12438dbadeca96aa72152d6e20652af5afd3820))
120 |
121 |
122 | ### Refactoring
123 |
124 | * 💡 generators and update docs ([f3b0d3d](https://github.com/kreuzerk/nx-release/commit/f3b0d3db0bf361e851eb4c11bb7f493fa66349f1))
125 |
126 | ## [2.1.0](https://github.com/kreuzerk/nx-release/compare/v2.0.0...v2.1.0) (2023-07-07)
127 |
128 |
129 | ### Features
130 |
131 | * 🎸 add build, update & publish executor ([80357c1](https://github.com/kreuzerk/nx-release/commit/80357c16c4a0b2484b754e34061e4ae080cb7a48))
132 |
133 | ## [2.0.0](https://github.com/kreuzerk/nx-release/compare/v1.0.1...v2.0.0) (2023-07-07)
134 |
135 |
136 | ### ⚠ BREAKING CHANGES
137 |
138 | * 🧨 version input is no longer supported
139 |
140 | ### Features
141 |
142 | * 🎸 access version from node env ([cc684d3](https://github.com/kreuzerk/nx-release/commit/cc684d348d8430eec09d6450df4b5285973f39f4))
143 |
144 | ## [1.0.1](https://github.com/kreuzerk/nx-release/compare/v1.0.0...v1.0.1) (2023-07-07)
145 |
146 |
147 | ### Bug Fixes
148 |
149 | * 🐛 use exec sync ([cae8041](https://github.com/kreuzerk/nx-release/commit/cae80410db9dde03d1ce13d96ef8fccee31bc46f))
150 |
151 | ## 1.0.0 (2023-07-07)
152 |
153 |
154 | ### Features
155 |
156 | * 🎸 implement executors ([f4bc2a7](https://github.com/kreuzerk/nx-release/commit/f4bc2a73860e2815da4ddbdee877edc52eef3f9f))
157 |
158 |
159 | ### Chores
160 |
161 | * 🤖 add dedicated release script ([4cb00ff](https://github.com/kreuzerk/nx-release/commit/4cb00ff0d32419a5d9e672378068a070984ad51a))
162 | * 🤖 add npm publish script ([9ec7052](https://github.com/kreuzerk/nx-release/commit/9ec705267e06def9a316bc690677a80124da8b05))
163 | * 🤖 prepare for release ([c19dc1f](https://github.com/kreuzerk/nx-release/commit/c19dc1fe47ea5343da9d32f7a502914d51cb3f9d))
164 |
--------------------------------------------------------------------------------
/CODE_OF_CONDUCT.md:
--------------------------------------------------------------------------------
1 | Contributor Covenant Code of Conduct Our Pledge In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation.
2 |
3 | Our Standards Examples of behavior that contributes to creating a positive environment include:
4 |
5 | Using welcoming and inclusive language Being respectful of differing viewpoints and experiences Gracefully accepting constructive criticism Focusing on what is best for the community Showing empathy towards other community members Examples of unacceptable behavior by participants include:
6 |
7 | The use of sexualized language or imagery and unwelcome sexual attention or advances Trolling, insulting/derogatory comments, and personal or political attacks Public or private harassment Publishing others' private information, such as a physical or electronic address, without explicit permission Other conduct which could reasonably be considered inappropriate in a professional setting Our Responsibilities Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior.
8 |
9 | Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful.
10 |
11 | Scope This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers.
12 |
13 | Enforcement Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at kevin.kreuzer90@icloud.com. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately.
14 |
15 | Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership.
16 |
17 | Attribution This Code of Conduct is adapted from the Contributor Covenant, version 1.4, available at http://contributor-covenant.org/version/1/4
18 |
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | Contributing
2 | A big welcome and thank you for considering contributing to the project.
3 |
4 | Reading and following these guidelines will help us make the contribution process easy and effective for everyone involved. It also communicates that you agree to respect the time of the developers managing and developing these open source projects. In return, we will reciprocate that respect by addressing your issue, assessing changes, and helping you finalize your pull requests.
5 |
6 | Quicklinks
7 | Code of Conduct
8 | Commit Convention
9 | Code of Conduct
10 | We take our open source community seriously and hold ourselves and other contributors to high standards of communication. By participating and contributing to this project, you agree to uphold our Code of Conduct.
11 |
12 | Commit Convention
13 | This project uses the conventional commit format and is commitizen friendly, using npm run commit instead of git commit will run you through a step by step command line process to generate a valid commit message.
14 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2018
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 | 
2 |
3 |
4 | [](#contributors-)
5 |
6 |
7 | This library contains executors and generators.
8 |
9 | Your go-to open-source library for effortless semantic releases of NPM libraries within a monorepo. This repository provides generators and executors for a fully automated release setup that contains commit analysis, automated versioning, changelog generation, and publishing.
10 |
11 | The library provides generators and executors:
12 |
13 | - Generators
14 | - Executors
15 |
16 |
17 |
18 | **Table of Contents** *generated with [DocToc](https://github.com/thlorenz/doctoc)*
19 |
20 | - [Getting started](#getting-started)
21 | - [Installation](#installation)
22 | - [Configuring the workspace](#configuring-the-workspace)
23 | - [GitHub repository setup](#github-repository-setup)
24 | - [1. Provide access tokens](#1-provide-access-tokens)
25 | - [2. Actions write permissions](#2-actions-write-permissions)
26 | - [Generators](#generators)
27 | - [configure](#configure)
28 | - [configure-workspace](#configure-workspace)
29 | - [configure-library](#configure-library)
30 | - [configure-libraries](#configure-libraries)
31 | - [generate-gh-actions](#generate-gh-actions)
32 | - [generate-release-config](#generate-release-config)
33 | - [Executors](#executors)
34 | - [npm-publish](#npm-publish)
35 | - [update-version](#update-version)
36 | - [build-update-publish](#build-update-publish)
37 | - [Contributors ✨](#contributors-)
38 |
39 |
40 |
41 | # Getting started
42 |
43 | ## Installation
44 |
45 | ```npm i -D nx-release```
46 |
47 | ## Configuring the workspace
48 |
49 | To configure your Nx workspace for releasing, you can invoke the main generator provided by `nx-release`.
50 |
51 | ```npx nx g nx-release:configure```
52 |
53 | This command will prompt all the required options.
54 |
55 | ## GitHub repository setup
56 |
57 | To enable full automated releases, you have to configure your GitHub repository in two steps:
58 |
59 | ### 1. Provide access tokens
60 |
61 | To enable a fully automated release, we need access rights to publish the artifact to npm and commit back to your repository. Therefore you have to provide the following tokens as action secrets.
62 |
63 | > To create an action secret navigate to your GitHub repository / Settings / Secrets and Variables / Actions / New Repository secret
64 |
65 | Here you have to provide the following two secrets:
66 |
67 | - **GH_TOKEN**: repo scope
68 | - **NPM_TOKEN**: scope CI automation
69 |
70 | Those tokens will then be picked up and provided as environment variables by the `release.yml` generated by `nx-release`.
71 |
72 | ### 2. Actions write permissions
73 |
74 | Since our workflow will commit back release artifacts such as `CHANGELOG`, tags, and update versions inside the `package.json`, our actions need write permissions. To give GitHub Actions write permissions, navigate again to your repository, then go to `Settings / Actions / General / Workflow Permissions / Read and write permissions / Save`.
75 |
76 | # Generators
77 |
78 | The provided generators help you set up an automated library-releasing process in an existing NX workspace. This process works for all kinds of libraries since it's framework-agnostic. The following generators are provided:
79 |
80 | ## configure
81 |
82 | The `configure` workspace generator allows you to set up the workspace plus the libraries of your choice. Internally this generator calls the `configure-workspace` as well as the `configure-libraries` generator. The generator can be invoked with the following command:
83 |
84 | ```npx nx g nx-release:configure```
85 |
86 | The generators provide the following options:
87 |
88 | | option | description | default | prompted |
89 | | --------------------- | ------------------------------------------------------------ | ------- | -------- |
90 | | installDeps | Should we install semantic-release and all the required plugins | true | yes |
91 | | generateReleaseConfig | Should we generate a semantic-release configuration at the root of your workspace | true | yes |
92 | | generateGhActions | Should we generate GitHub actions for feature branches and releases | true | yes |
93 | | publicPublishConfig | Should we add public publish config for your library | true | Yes |
94 |
95 | ## configure-workspace
96 |
97 | ```npx nx g nx-release:configure-workspace```
98 |
99 | The `configure-workspace` generator allows you to set up automated releases on a **workspace level only**. The generator will then prompt the following options:
100 |
101 | | option | description | default | prompted |
102 | | --------------------- | ------------------------------------------------------------ | ------- | -------- |
103 | | installDeps | Should we install semantic-release and all the required plugins | true | yes |
104 | | generateReleaseConfig | Should we generate a semantic-release configuration at the root of your workspace | true | yes |
105 | | generateGhActions | Should we generate GitHub actions for feature branches and releases | True | yes |
106 |
107 | ## configure-library
108 |
109 | ```npx nx g nx-release:configure-library```
110 |
111 | The `configure-library` generator sets up a library for semantic release. When setting up the library, it will use some of the executors provided by `nx-release`.
112 |
113 | | option | description | default | prompted |
114 | | ------------------- | ---------------------------------------------------- | ------- | ----------------------------------- |
115 | | publicPublishConfig | Should we add public publish config for your library | true | yes |
116 | | libName | The name of the library that should be configured | | only if nothing is passed initially |
117 |
118 | ## configure-libraries
119 |
120 | ```npx nx g nx-release:configure-libraries```
121 |
122 | The `configure-libraries` generator sets up multiple libraries for semantic release. When setting up the libraries, it will use some of the executors provided by `nx-release`.
123 |
124 | | option | description | default | prompted |
125 | | ------------------- | ---------------------------------------------------- | ------- | --------------------------------- |
126 | | publicPublishConfig | Should we add public publish config for your library | true | yes |
127 | | libName | The name of the library that should be configured | | will be prompted during execution |
128 |
129 | ## generate-gh-actions
130 |
131 | ```npx nx g nx-release:generate-gh-actions```
132 |
133 | This generator can be used to generate two workflow files for automated releases. This generator will generate the following two files:
134 |
135 | - ci.yml (this file configures a pipeline that is run on Pull request)
136 | - release.yml (file that releases the library / by default; it has to be triggered manually)
137 |
138 | ## generate-release-config
139 |
140 | ```npx nx g nx-release:generate-release-config```
141 |
142 | This generator generates a `release.config.js` file at the root of your project.
143 |
144 | # Executors
145 |
146 | ## npm-publish
147 |
148 | As the name indicates, the `npm-publish` generator can be used to publish a library to NPM. To
149 | do so, **the executor requires a `NPM_TOKEN` to be present as a Node environment variable**.
150 |
151 |
152 | ## update-version
153 | This executor updates the `package.json` version in the specified library. The executor **requires** the following config options.**The update-version executor expects a VERSION env variable to be present**.
154 |
155 | ## build-update-publish
156 | This executor combines the previous two executors and additionally performs a release.
157 |
158 | **This command expects a valid NPM token to be present as an `NPM_TOKEN` environment variable and the new release version to be present as a `VERSION` variable**.
159 |
160 | ## Contributors ✨
161 |
162 | Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/docs/en/emoji-key)):
163 |
164 |
165 |
166 |
175 |
176 |
177 |
178 |
179 |
180 |
181 |
182 |
183 |
184 |
200 |
201 |
202 |
203 |
204 |
205 |
206 | This project follows the [all-contributors](https://github.com/all-contributors/all-contributors) specification. Contributions of any kind are welcome!
207 |
--------------------------------------------------------------------------------
/apps/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nivekcode/nx-release/dec67fb7ff59167308c0161109874ce2a9b61da7/apps/.gitkeep
--------------------------------------------------------------------------------
/jest.config.ts:
--------------------------------------------------------------------------------
1 | import { getJestProjects } from '@nx/jest';
2 |
3 | export default {
4 | projects: getJestProjects(),
5 | };
6 |
--------------------------------------------------------------------------------
/jest.preset.js:
--------------------------------------------------------------------------------
1 | const nxPreset = require('@nx/jest/preset').default;
2 |
3 | module.exports = { ...nxPreset };
4 |
--------------------------------------------------------------------------------
/libs/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nivekcode/nx-release/dec67fb7ff59167308c0161109874ce2a9b61da7/libs/.gitkeep
--------------------------------------------------------------------------------
/libs/nx-release/.all-contributorsrc:
--------------------------------------------------------------------------------
1 | {
2 | "projectName": "nx-release",
3 | "projectOwner": "kreuzerk",
4 | "repoType": "github",
5 | "repoHost": "https://github.com",
6 | "files": ["README.md"],
7 | "imageSize": 100,
8 | "commit": true,
9 | "commitConvention": "angular",
10 | "contributors": [
11 | {
12 | "login": "kreuzerk",
13 | "name": "Nivek",
14 | "avatar_url": "https://avatars.githubusercontent.com/u/5468954?v=4",
15 | "profile": "https://medium.com/@kevinkreuzer",
16 | "contributions": ["code"]
17 | }
18 | ],
19 | "contributorsPerLine": 7,
20 | "linkToUsage": true
21 | }
22 |
23 |
--------------------------------------------------------------------------------
/libs/nx-release/.eslintrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": ["../../.eslintrc.json"],
3 | "ignorePatterns": ["!**/*"],
4 | "overrides": [
5 | {
6 | "files": ["*.ts", "*.tsx", "*.js", "*.jsx"],
7 | "rules": {}
8 | },
9 | {
10 | "files": ["*.d.ts"],
11 | "rules": {
12 | "@typescript-eslint/no-empty-interface": "off"
13 | }
14 | },
15 | {
16 | "files": ["*.ts", "*.tsx"],
17 | "rules": {}
18 | },
19 | {
20 | "files": ["*.spec.ts"],
21 | "rules": {
22 | "@typescript-eslint/no-empty-function": "off",
23 | "@typescript-eslint/no-explicit-any": "off"
24 | }
25 | },
26 | {
27 | "files": ["*.js", "*.jsx"],
28 | "rules": {}
29 | },
30 | {
31 | "files": ["./package.json", "./executors.json", "./generators.json"],
32 | "parser": "jsonc-eslint-parser",
33 | "rules": {
34 | "@nx/nx-plugin-checks": "error"
35 | }
36 | }
37 | ]
38 | }
39 |
--------------------------------------------------------------------------------
/libs/nx-release/README.md:
--------------------------------------------------------------------------------
1 | 
2 |
3 | [](#contributors-) [](https://coveralls.io/github/kreuzerk/nx-release?branch=feature/generators)
4 |
5 |
6 |
7 | This library contains executors and generators
8 |
9 | Your go-to open-source library for effortless semantic releases of NPM libraries within a monorepo. This repository provides generators and executors for a fully automated release setup that contains commit analyzation, automated versioning, changelog generation and publishing.
10 |
11 | The library provides generators and executors:
12 |
13 | - Generators
14 | - Executors
15 |
16 |
17 |
18 | **Table of Contents** *generated with [DocToc](https://github.com/thlorenz/doctoc)*
19 |
20 | - [Getting started](#getting-started)
21 | - [Installation](#installation)
22 | - [Configuring the workspace](#configuring-the-workspace)
23 | - [GitHub repository setup](#github-repository-setup)
24 | - [1. Provide access tokens](#1-provide-access-tokens)
25 | - [2. Actions write permissions](#2-actions-write-permissions)
26 | - [Generators](#generators)
27 | - [configure](#configure)
28 | - [configure-workspace](#configure-workspace)
29 | - [configure-library](#configure-library)
30 | - [configure-libraries](#configure-libraries)
31 | - [generate-gh-actions](#generate-gh-actions)
32 | - [generate-release-config](#generate-release-config)
33 | - [Executors](#executors)
34 | - [npm-publish](#npm-publish)
35 | - [update-version](#update-version)
36 | - [build-update-publish](#build-update-publish)
37 | - [Contributors ✨](#contributors-)
38 |
39 |
40 |
41 | # Getting started
42 |
43 | ## Installation
44 |
45 | ```npm i -D nx-release```
46 |
47 | ## Configuring the workspace
48 |
49 | To configure your Nx workspace for releasing you can invoke the main generator provided by `nx-release`.
50 |
51 | ```npx nx g nx-release:configure```
52 |
53 | This comman will prompt all the required options.
54 |
55 | ## GitHub repository setup
56 |
57 | To enable full automated releases you have to configure your GitHub repository in two steps:
58 |
59 | ### 1. Provide access tokens
60 |
61 | To enable fully automated release we need access rights to publish the artifact to npm and to commit back to your repository. Therefore you have to provide the following tokens as action secrets.
62 |
63 | > To create a action secret navigate to your GitHub repoistory / Settings / Secrets and Variables / Actions / New Repository secret
64 |
65 | Here you have to provide the following two secrets:
66 |
67 | - **GH_TOKEN**: repo scope
68 | - **NPM_TOKEN**: scope CI automation
69 |
70 | Those tokens will then be picked up and provided as environment variables by the `release.yml` generated by `nx-release`.
71 |
72 | ### 2. Actions write permissions
73 |
74 | Since our workflow will commit back release artifacts such as `CHANGELOG`, tags and update versions inside the `package.json` our actions need write permissions. To give GitHub actions write permissions navigate again to your repository then go to `Settings / Actions / General / Workflow Permissions / Read and write permissions / Save`.
75 |
76 | # Generators
77 |
78 | The provided generators help you setup automated library releasing in an existing NX workspace. This process works for all kind of libraries since its framework agnostic. The following generators are provided:
79 |
80 | ## configure
81 |
82 | The `configure` workspace generator allows you to setup the workspace plus the libraries of you choice. Internally this generator calls the `configure-workspace` as well as the `configure-libraries` generator. The generator can be invoked with the following command:
83 |
84 | ```npx nx g nx-release:configure```
85 |
86 | The generators provides the follwing options:
87 |
88 | | option | description | default | prompted |
89 | | --------------------- | ------------------------------------------------------------ | ------- | -------- |
90 | | installDeps | Should we install semantic-release and all the required plugins | true | yes |
91 | | generateReleaseConfig | Should we generate a semantic-release configuration at the root of your workspace | true | yes |
92 | | generateGhActions | Should we generate GitHub actions for feature branches and releases | true | yes |
93 | | publicPublishConfig | Should we add public publish config for your library | true | Yes |
94 |
95 | ## configure-workspace
96 |
97 | ```npx nx g nx-release:configure-workspace```
98 |
99 | The `configure-workspace` generator allows you to setup automated releases on a **workspace level only**. The generator will then prompt the following options:
100 |
101 | | option | description | default | prompted |
102 | | --------------------- | ------------------------------------------------------------ | ------- | -------- |
103 | | installDeps | Should we install semantic-release and all the required plugins | true | yes |
104 | | generateReleaseConfig | Should we generate a semantic-release configuration at the root of your workspace | true | yes |
105 | | generateGhActions | Should we generate GitHub actions for feature branches and releases | True | yes |
106 |
107 | ## configure-library
108 |
109 | ```npx nx g nx-release:configure-library```
110 |
111 | The `configure-library`generator sets up a library for semantic release. When setting up the library it will use some of the executors provided by `nx-release`.
112 |
113 | | option | description | default | prompted |
114 | | ------------------- | ---------------------------------------------------- | ------- | ----------------------------------- |
115 | | publicPublishConfig | Should we add public publish config for your library | true | yes |
116 | | libName | The name of the library that should be configured | | only if nothing is passed initially |
117 |
118 | ## configure-libraries
119 |
120 | ```npx nx g nx-release:configure-libraries```
121 |
122 | The `configure-libraries`generator sets up a multiple libraries for semantic release. When setting up the libraries it will use some of the executors provided by `nx-release`.
123 |
124 | | option | description | default | prompted |
125 | | ------------------- | ---------------------------------------------------- | ------- | --------------------------------- |
126 | | publicPublishConfig | Should we add public publish config for your library | true | yes |
127 | | libName | The name of the library that should be configured | | will be prompted during execution |
128 |
129 | ## generate-gh-actions
130 |
131 | ```npx nx g nx-release:generate-gh-actions```
132 |
133 | This generator can be used to generate two workflow files for automated releasing. This generator will generate the following two files:
134 |
135 | - ci.yml (this file configures a pipeline that is run on Pull request)
136 | - release.yml (file that releases the library / by default it has to be triggered manually)
137 |
138 | ## generate-release-config
139 |
140 | ```npx nx g nx-release:generate-release-config```
141 |
142 | This generator generates a `release.config.js` file at the root of your project.
143 |
144 | # Executors
145 |
146 | ## npm-publish
147 |
148 | As the name indicates the `npm-publish` generator can be used to publish a library to NPM. To
149 | do so **the executor requires a `NPM_TOKEN` to be present as a Node environment variable**.
150 |
151 |
152 | ## update-version
153 | This executor updates the `package.json` version in the specified library. The executor **requires** the following config options.**The update-version executor expects a VERSION env variable to be present**.
154 |
155 | ## build-update-publish
156 | This executor combines the previous two executors and additionally performs a release.
157 |
158 | **This command expects a valid NPM token to be present as a `NPM_TOKEN` environment variable and the new release version to be present as a `VERSION` variable**.
159 |
160 | ## Contributors ✨
161 |
162 | Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/docs/en/emoji-key)):
163 |
164 |
165 |
166 |
167 |
183 |
184 |
185 |
186 |
187 |
188 |
189 | This project follows the [all-contributors](https://github.com/all-contributors/all-contributors) specification. Contributions of any kind welcome!
190 |
--------------------------------------------------------------------------------
/libs/nx-release/assets/nx-release-logo.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/libs/nx-release/executors.json:
--------------------------------------------------------------------------------
1 | {
2 | "executors": {
3 | "npm-publish": {
4 | "implementation": "./src/executors/npm-publish/executor",
5 | "schema": "./src/executors/npm-publish/schema.json",
6 | "description": "npm-publish executor"
7 | },
8 | "update-version": {
9 | "implementation": "./src/executors/update-version/executor",
10 | "schema": "./src/executors/update-version/schema.json",
11 | "description": "update-version executor"
12 | },
13 | "build-update-publish": {
14 | "implementation": "./src/executors/build-update-publish/executor",
15 | "schema": "./src/executors/build-update-publish/schema.json",
16 | "description": "build-update-publish executor"
17 | }
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/libs/nx-release/generators.json:
--------------------------------------------------------------------------------
1 | {
2 | "generators": {
3 | "configure-workspace": {
4 | "factory": "./src/generators/configure-workspace/generator",
5 | "schema": "./src/generators/configure-workspace/schema.json",
6 | "description": "configure-workspace generator"
7 | },
8 | "configure-library": {
9 | "factory": "./src/generators/configure-library/generator",
10 | "schema": "./src/generators/configure-library/schema.json",
11 | "description": "configure-library generator"
12 | },
13 | "configure-libraries": {
14 | "factory": "./src/generators/configure-libraries/generator",
15 | "schema": "./src/generators/configure-libraries/schema.json",
16 | "description": "configure-libraries generator"
17 | },
18 | "configure": {
19 | "factory": "./src/generators/configure/generator",
20 | "schema": "./src/generators/configure/schema.json",
21 | "description": "configure generator"
22 | },
23 | "generate-release-config": {
24 | "factory": "./src/generators/generate-release-config/generator",
25 | "schema": "./src/generators/generate-release-config/schema.json",
26 | "description": "generate-release-config generator"
27 | },
28 | "generate-gh-actions": {
29 | "factory": "./src/generators/generate-gh-actions/generator",
30 | "schema": "./src/generators/generate-gh-actions/schema.json",
31 | "description": "generate-gh-actions generator"
32 | }
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/libs/nx-release/jest.config.ts:
--------------------------------------------------------------------------------
1 | /* eslint-disable */
2 | export default {
3 | displayName: 'nx-release',
4 | preset: '../../jest.preset.js',
5 | transform: {
6 | '^.+\\.[tj]s$': ['ts-jest', { tsconfig: '/tsconfig.spec.json' }],
7 | },
8 | moduleFileExtensions: ['ts', 'js', 'html'],
9 | coverageDirectory: '../../coverage/libs/nx-release',
10 | };
11 |
--------------------------------------------------------------------------------
/libs/nx-release/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "nx-release",
3 | "version": "0.0.1",
4 | "type": "commonjs",
5 | "executors": "./executors.json",
6 | "generators": "./generators.json",
7 | "peerDependencies": {
8 | "tslib": "^2.6.0"
9 | },
10 | "license": "MIT",
11 | "repository": "https://github.com/kreuzerk/nx-release",
12 | "readme": "https://github.com/kreuzerk/nx-release/blob/main/README.md",
13 | "bugs": "https://github.com/kreuzerk/nx-release/issues",
14 | "author": "kreuzerk"
15 | }
16 |
--------------------------------------------------------------------------------
/libs/nx-release/project.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "nx-release",
3 | "$schema": "../../node_modules/nx/schemas/project-schema.json",
4 | "sourceRoot": "libs/nx-release/src",
5 | "projectType": "library",
6 | "targets": {
7 | "build": {
8 | "executor": "@nx/js:tsc",
9 | "outputs": ["{options.outputPath}"],
10 | "options": {
11 | "outputPath": "dist/libs/nx-release",
12 | "main": "libs/nx-release/src/index.ts",
13 | "tsConfig": "libs/nx-release/tsconfig.lib.json",
14 | "assets": [
15 | "libs/nx-release/*.md",
16 | {
17 | "input": "./libs/nx-release/src",
18 | "glob": "**/!(*.ts)",
19 | "output": "./src"
20 | },
21 | {
22 | "input": "./libs/nx-release/src",
23 | "glob": "**/*.d.ts",
24 | "output": "./src"
25 | },
26 | {
27 | "input": "./libs/nx-release",
28 | "glob": "generators.json",
29 | "output": "."
30 | },
31 | {
32 | "input": "./libs/nx-release",
33 | "glob": "executors.json",
34 | "output": "."
35 | }
36 | ]
37 | }
38 | },
39 | "lint": {
40 | "executor": "@nx/linter:eslint",
41 | "outputs": ["{options.outputFile}"],
42 | "options": {
43 | "lintFilePatterns": [
44 | "libs/nx-release/**/*.ts",
45 | "libs/nx-release/package.json",
46 | "libs/nx-release/executors.json",
47 | "libs/nx-release/generators.json"
48 | ]
49 | }
50 | },
51 | "test": {
52 | "executor": "@nx/jest:jest",
53 | "outputs": ["{workspaceRoot}/coverage/{projectRoot}"],
54 | "options": {
55 | "jestConfig": "libs/nx-release/jest.config.ts",
56 | "passWithNoTests": true
57 | },
58 | "configurations": {
59 | "ci": {
60 | "ci": true,
61 | "codeCoverage": true
62 | }
63 | }
64 | },
65 | "publish": {
66 | "executor": "nx:run-commands",
67 | "options": {
68 | "command": "cd ./dist/libs/nx-release && echo '//registry.npmjs.org/:_authToken=${NPM_TOKEN}' > .npmrc && npm publish"
69 | }
70 | }
71 | },
72 | "tags": []
73 | }
74 |
--------------------------------------------------------------------------------
/libs/nx-release/src/executors/build-update-publish/executor.spec.ts:
--------------------------------------------------------------------------------
1 | import * as childProcess from 'child_process';
2 |
3 | import * as updateVersion from '../update-version/executor';
4 | import * as projectHelper from '../helpers/projects.helpers';
5 | import * as npmPublish from '../npm-publish/executor';
6 |
7 | import executor from './executor';
8 |
9 | describe('BuildUpdatePublish Executor', () => {
10 | it('should call update-version executor and npm publish executor with the options and context', async () => {
11 | const libName = 'foo';
12 | const mockContext = {bar: 'bar'} as any;
13 |
14 | /* eslint-disable */
15 | jest.spyOn(projectHelper, 'getProjectName').mockReturnValue(libName);
16 | /* eslint-disable */
17 | jest.spyOn(updateVersion, 'default').mockImplementation((() => {}) as any)
18 | /* eslint-disable */
19 | jest.spyOn(npmPublish, 'default').mockImplementation((() => {}) as any)
20 | /* eslint-disable */
21 | jest.spyOn(childProcess, 'execSync').mockImplementation((() => {}) as any)
22 |
23 |
24 | const output = await executor({}, mockContext as any);
25 |
26 | expect(updateVersion.default).toHaveBeenCalledWith({}, mockContext);
27 | expect(npmPublish.default).toHaveBeenCalledWith({}, mockContext);
28 | expect(childProcess.execSync).toHaveBeenCalledWith(`nx build --project ${libName}`);
29 | expect(output.success).toBe(true);
30 | });
31 | });
32 |
--------------------------------------------------------------------------------
/libs/nx-release/src/executors/build-update-publish/executor.ts:
--------------------------------------------------------------------------------
1 | import {ExecutorContext} from "@nx/devkit";
2 | import {execSync} from "child_process";
3 |
4 | import {getProjectName} from '../helpers/projects.helpers';
5 | import updateVersion from '../update-version/executor';
6 | import npmPublish from '../npm-publish/executor';
7 |
8 | import {BuildUpdatePublishExecutorSchema} from './schema';
9 |
10 | export default async function runExecutor(
11 | options: BuildUpdatePublishExecutorSchema,
12 | context: ExecutorContext
13 | ) {
14 |
15 | await updateVersion({}, context);
16 | execSync(`nx build --project ${getProjectName(context)}`);
17 | await npmPublish({}, context);
18 |
19 | return {
20 | success: true,
21 | };
22 | }
23 |
--------------------------------------------------------------------------------
/libs/nx-release/src/executors/build-update-publish/schema.d.ts:
--------------------------------------------------------------------------------
1 | export interface BuildUpdatePublishExecutorSchema {}
2 |
--------------------------------------------------------------------------------
/libs/nx-release/src/executors/build-update-publish/schema.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "http://json-schema.org/schema",
3 | "version": 2,
4 | "title": "BuildUpdatePublish executor",
5 | "description": "",
6 | "type": "object",
7 | "properties": {}
8 | }
9 |
--------------------------------------------------------------------------------
/libs/nx-release/src/executors/helpers/projects.helpers.spec.ts:
--------------------------------------------------------------------------------
1 | import * as nxDevKit from '@nx/devkit';
2 |
3 | import { getProjectName, getRoot } from './projects.helpers';
4 |
5 | describe('executor project helper', () => {
6 | it('should return the project name', () => {
7 | const projectName = 'foo';
8 | expect(getProjectName({projectName} as any)).toBe(projectName);
9 | });
10 |
11 | it('should get the root of the project', () => {
12 | const expectedRoot = 'libs/foo';
13 | const context = {
14 | projectName: 'foo',
15 | projectsConfigurations: {
16 | projects: {
17 | foo: {
18 | root: expectedRoot
19 | }
20 | }
21 | }
22 | } as any;
23 |
24 | expect(getRoot(context)).toBe(expectedRoot);
25 | });
26 | });
27 |
--------------------------------------------------------------------------------
/libs/nx-release/src/executors/helpers/projects.helpers.ts:
--------------------------------------------------------------------------------
1 | import {ExecutorContext} from "@nx/devkit";
2 |
3 | export function getProjectName(context: ExecutorContext): string {
4 | return context.projectName;
5 | }
6 |
7 | export function getRoot(context: ExecutorContext): string {
8 | const projectsConfiguration = context.projectsConfigurations.projects;
9 | const projectName = getProjectName(context);
10 | return projectsConfiguration[projectName].root;
11 | }
12 |
--------------------------------------------------------------------------------
/libs/nx-release/src/executors/npm-publish/executor.spec.ts:
--------------------------------------------------------------------------------
1 | import * as child_process from "child_process";
2 |
3 | import * as projectHelpers from "../helpers/projects.helpers";
4 |
5 | import executor from './executor';
6 |
7 | describe('NpmPublish Executor', () => {
8 | const OLD_ENV = process.env;
9 |
10 | beforeEach(() => {
11 | jest.resetModules();
12 | });
13 |
14 | afterEach(() => {
15 | process.env = { ...OLD_ENV };
16 | });
17 |
18 | it('should execSync with a default libPath if no libPath was provided', async () => {
19 | const mockRoot = 'libs/my-domain/foo';
20 | const context = {
21 | } as any;
22 |
23 | /* eslint-disable */
24 | jest.spyOn(child_process, 'execSync').mockImplementation((() => {}) as any);
25 | /* eslint-disable */
26 | jest.spyOn(projectHelpers, 'getRoot').mockReturnValue(mockRoot);
27 |
28 | const expectedCommand = `cd ./dist/${mockRoot} && echo '//registry.npmjs.org/:_authToken=${process.env.NPM_TOKEN}' >> .npmrc && npm publish --tag=latest`
29 | const output = await executor({}, context);
30 |
31 | expect(child_process.execSync).toHaveBeenCalledWith(expectedCommand);
32 | expect(output.success).toBe(true);
33 | });
34 |
35 | it('should execSync with a specific npm registry if provided with one', async () => {
36 | const mockRoot = 'libs/my-domain/foo';
37 | const context = {
38 | } as any;
39 | const registry = 'specific-npm-registry.org';
40 | process.env = Object.assign(process.env, { NPM_REGISTRY: registry });
41 |
42 | /* eslint-disable */
43 | jest.spyOn(child_process, 'execSync').mockImplementation((() => {}) as any);
44 | /* eslint-disable */
45 | jest.spyOn(projectHelpers, 'getRoot').mockReturnValue(mockRoot);
46 |
47 | const expectedCommand = `cd ./dist/${mockRoot} && echo '//${registry}/:_authToken=${process.env.NPM_TOKEN}' >> .npmrc && npm publish --tag=latest`
48 | const output = await executor({}, context);
49 |
50 | expect(child_process.execSync).toHaveBeenCalledWith(expectedCommand);
51 | expect(output.success).toBe(true);
52 | });
53 |
54 | it('should execSync with a specific npm channel if provided with one', async () => {
55 | const mockRoot = 'libs/my-domain/foo';
56 | const context = {
57 | } as any;
58 | const channel = 'beta';
59 | process.env = Object.assign(process.env, { CHANNEL: channel });
60 |
61 | /* eslint-disable */
62 | jest.spyOn(child_process, 'execSync').mockImplementation((() => {}) as any);
63 | /* eslint-disable */
64 | jest.spyOn(projectHelpers, 'getRoot').mockReturnValue(mockRoot);
65 |
66 | const expectedCommand = `cd ./dist/${mockRoot} && echo '//registry.npmjs.org/:_authToken=${process.env.NPM_TOKEN}' >> .npmrc && npm publish --tag=${channel}`
67 | const output = await executor({}, context);
68 |
69 | expect(child_process.execSync).toHaveBeenCalledWith(expectedCommand);
70 | expect(output.success).toBe(true);
71 | });
72 | });
73 |
--------------------------------------------------------------------------------
/libs/nx-release/src/executors/npm-publish/executor.ts:
--------------------------------------------------------------------------------
1 | import {execSync} from 'child_process';
2 | import {ExecutorContext} from "@nx/devkit";
3 |
4 | import {getRoot} from "../helpers/projects.helpers";
5 |
6 | import {NpmPublishExecutorSchema} from './schema';
7 |
8 | export default async function runExecutor(options: NpmPublishExecutorSchema,
9 | context: ExecutorContext
10 | ) {
11 | const sourceRoot = `./dist/${getRoot(context)}`;
12 | const registry: string = process.env.NPM_REGISTRY || 'registry.npmjs.org'
13 | const channel: string = process.env.CHANNEL || 'latest'
14 | execSync(
15 | `cd ${sourceRoot} && echo '//${registry}/:_authToken=${process.env.NPM_TOKEN}' >> .npmrc && npm publish --tag=${channel}`
16 | );
17 | return {
18 | success: true,
19 | };
20 | }
--------------------------------------------------------------------------------
/libs/nx-release/src/executors/npm-publish/schema.d.ts:
--------------------------------------------------------------------------------
1 | export interface NpmPublishExecutorSchema {}
2 |
--------------------------------------------------------------------------------
/libs/nx-release/src/executors/npm-publish/schema.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "http://json-schema.org/schema",
3 | "version": 2,
4 | "title": "NPM publish executor",
5 | "description": "",
6 | "type": "object",
7 | "properties": {}
8 | }
9 |
--------------------------------------------------------------------------------
/libs/nx-release/src/executors/update-version/executor.spec.ts:
--------------------------------------------------------------------------------
1 | import * as replaceJsonProp from 'replace-json-property';
2 | import * as process from "process";
3 |
4 | import * as projectHelpers from '../helpers/projects.helpers';
5 |
6 | import executor from './executor';
7 |
8 | describe('ReplaceVersion Executor', () => {
9 |
10 | it('should replace the version with in the default path if no path was provided', async () => {
11 | const version = '2.0.0';
12 | const libName = 'foo';
13 | const mockContext = {} as any;
14 |
15 | process.env.VERSION = version;
16 |
17 | const root = `libs/${libName}`;
18 |
19 | // eslint-disable-next-line @typescript-eslint/no-empty-function
20 | jest.spyOn(replaceJsonProp, 'replace').mockImplementation(() => {});
21 | jest.spyOn(projectHelpers, 'getRoot').mockReturnValue(root);
22 |
23 | const output = await executor({}, mockContext);
24 |
25 | expect(replaceJsonProp.replace).toHaveBeenCalledWith(`${root}/package.json`, 'version', version);
26 | expect(output.success).toBe(true);
27 | });
28 |
29 | });
30 |
--------------------------------------------------------------------------------
/libs/nx-release/src/executors/update-version/executor.ts:
--------------------------------------------------------------------------------
1 | import type {ExecutorContext} from '@nx/devkit';
2 | import {replace} from 'replace-json-property';
3 | import * as process from "process";
4 |
5 | import {getRoot} from "../helpers/projects.helpers";
6 |
7 | import {ReplaceVersionExecutorSchema} from './schema';
8 |
9 | export default async function runExecutor(
10 | options: ReplaceVersionExecutorSchema,
11 | context: ExecutorContext
12 | ) {
13 | const sourceRoot = getRoot(context);
14 | replace(`${sourceRoot}/package.json`, 'version', process.env.VERSION);
15 | return {
16 | success: true,
17 | };
18 | }
19 |
--------------------------------------------------------------------------------
/libs/nx-release/src/executors/update-version/schema.d.ts:
--------------------------------------------------------------------------------
1 | export interface ReplaceVersionExecutorSchema {}
2 |
--------------------------------------------------------------------------------
/libs/nx-release/src/executors/update-version/schema.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "http://json-schema.org/schema",
3 | "version": 2,
4 | "title": "Update version executor",
5 | "description": "",
6 | "type": "object",
7 | "properties": {}
8 | }
9 |
--------------------------------------------------------------------------------
/libs/nx-release/src/generators/configure-libraries/generator.spec.ts:
--------------------------------------------------------------------------------
1 | import { createTreeWithEmptyWorkspace } from '@nx/devkit/testing';
2 | import * as inquirer from 'inquirer'
3 | import { Tree } from '@nx/devkit';
4 |
5 | import * as libraryGenerator from '../configure-library/generator';
6 | import * as projectHelpers from '../helpers/projects.helpers';
7 | import * as spinnerHelper from '../helpers/spinner.helper';
8 |
9 | import { configureLibrariesGenerator } from './generator';
10 | import * as process from "process";
11 |
12 | describe('configure-libraries generator', () => {
13 | let tree: Tree;
14 |
15 | beforeEach(() => {
16 | tree = createTreeWithEmptyWorkspace();
17 | jest.spyOn(spinnerHelper, 'getSpinner').mockReturnValue(({
18 | start: jest.fn(),
19 | succeed: jest.fn(),
20 | fail: jest.fn(),
21 | }) as any
22 | );
23 | });
24 |
25 | it('should log an error message if no library projects are found', done => {
26 | jest.spyOn(console, 'error').mockImplementation(() => {});
27 | jest.spyOn(projectHelpers, 'getLibraryProjectNames').mockReturnValue([]);
28 | jest.spyOn(inquirer, 'prompt').mockImplementation(() => Promise.resolve({
29 | selectedProjects: []
30 | }));
31 | jest.spyOn(process, 'exit').mockImplementation((() => {
32 | done();
33 | }) as any);
34 |
35 | configureLibrariesGenerator(tree, {} as any);
36 | });
37 |
38 | it('should call the configureLibraryGenerator for each selected project', async () => {
39 | const selectedProjects = ['foo', 'bar'];
40 |
41 | jest.spyOn(libraryGenerator, 'configureLibraryGenerator').mockImplementation(() => Promise.resolve());
42 | jest.spyOn(inquirer, 'prompt').mockImplementation(() => Promise.resolve({
43 | selectedProjects
44 | }));
45 |
46 | await configureLibrariesGenerator(tree, {
47 | publicPublishConfig: true
48 | });
49 |
50 | expect(libraryGenerator.configureLibraryGenerator).toHaveBeenCalledTimes(2);
51 | expect(libraryGenerator.configureLibraryGenerator).toHaveBeenCalledWith(tree, {
52 | libName: selectedProjects[0],
53 | publicPublishConfig: true
54 | });
55 | expect(libraryGenerator.configureLibraryGenerator).toHaveBeenCalledWith(tree, {
56 | libName: selectedProjects[1],
57 | publicPublishConfig: true
58 | });
59 | });
60 | });
61 |
--------------------------------------------------------------------------------
/libs/nx-release/src/generators/configure-libraries/generator.ts:
--------------------------------------------------------------------------------
1 | import {formatFiles, Tree,} from '@nx/devkit';
2 | import * as inquirer from 'inquirer';
3 |
4 | import {getLibraryProjectNames} from "../helpers/projects.helpers";
5 | import {configureLibraryGenerator} from "../configure-library/generator";
6 |
7 | import {ConfigureLibrariesGeneratorSchema} from './schema';
8 | import * as chalk from "chalk";
9 |
10 | export async function configureLibrariesGenerator(
11 | tree: Tree,
12 | options: ConfigureLibrariesGeneratorSchema
13 | ) {
14 | const {publicPublishConfig} = options;
15 | const libraryProjects = getLibraryProjectNames(tree);
16 |
17 | if (libraryProjects.length === 0) {
18 | console.error(chalk.red(`🐋 nx-release: no library projects found in your workspace -> aborting`));
19 | process.exit(0);
20 | }
21 |
22 | const projectsPrompt = await inquirer.prompt({
23 | type: 'checkbox',
24 | name: 'selectedProjects',
25 | choices: libraryProjects
26 | });
27 | const selectedProjects = projectsPrompt.selectedProjects;
28 |
29 | for (const libName of selectedProjects) {
30 | await configureLibraryGenerator(tree, {libName, publicPublishConfig});
31 | }
32 |
33 | await formatFiles(tree);
34 | }
35 |
36 | export default configureLibrariesGenerator;
37 |
--------------------------------------------------------------------------------
/libs/nx-release/src/generators/configure-libraries/schema.d.ts:
--------------------------------------------------------------------------------
1 | export interface ConfigureLibrariesGeneratorSchema {
2 | publicPublishConfig: boolean;
3 | }
4 |
--------------------------------------------------------------------------------
/libs/nx-release/src/generators/configure-libraries/schema.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "http://json-schema.org/schema",
3 | "$id": "ConfigureLibraries",
4 | "title": "",
5 | "type": "object",
6 | "properties": {
7 | "publicPublishConfig": {
8 | "type": "boolean",
9 | "description": "Should we update the config for public publishing of a library",
10 | "x-prompt": {
11 | "type": "boolean",
12 | "message": "\uD83D\uDC0B nx-release: is your library publicly publishable"
13 | },
14 | "default": true
15 | }
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/libs/nx-release/src/generators/configure-library/generator.spec.ts:
--------------------------------------------------------------------------------
1 | import {createTreeWithEmptyWorkspace} from '@nx/devkit/testing';
2 | import {readJson, Tree} from '@nx/devkit';
3 | import * as inquirer from 'inquirer';
4 |
5 | import * as projectHelpers from '../helpers/projects.helpers';
6 | import * as spinnerHelper from "../helpers/spinner.helper";
7 |
8 | import {configureLibraryGenerator} from './generator';
9 | import {libraryGenerator} from "@nx/js";
10 |
11 | describe('configure-library generator', () => {
12 | let tree: Tree;
13 |
14 | beforeEach(() => {
15 | tree = createTreeWithEmptyWorkspace();
16 | jest.spyOn(spinnerHelper, 'getSpinner').mockReturnValue(({
17 | start: jest.fn(),
18 | succeed: jest.fn(),
19 | fail: jest.fn()
20 | }) as any
21 | );
22 | });
23 |
24 | it('should prompt for project if no library name was provided', async () => {
25 | const mockProjectNames = ['foo', 'bar'];
26 |
27 | jest.spyOn(inquirer, 'prompt').mockImplementation(() => Promise.resolve({name: 'test'}));
28 | jest.spyOn(projectHelpers, 'getLibraryProjectNames').mockReturnValue(mockProjectNames);
29 |
30 | await configureLibraryGenerator(tree, {});
31 |
32 | expect(inquirer.prompt).toHaveBeenCalledWith({
33 | type: 'list',
34 | name: 'selectedProject',
35 | choices: mockProjectNames
36 | });
37 | });
38 |
39 | it('should add the executor to the project.json', async () => {
40 | const libName = 'foo';
41 | const expectedExecutorConfig = {
42 | executor: 'nx-release:build-update-publish',
43 | options: {
44 | libName
45 | }
46 | };
47 |
48 | jest.spyOn(inquirer, 'prompt').mockImplementation(() => Promise.resolve({selectedProject: libName}));
49 | jest.spyOn(projectHelpers, 'getLibraryProjectNames').mockReturnValue([libName]);
50 | jest.spyOn(projectHelpers, 'getLibraryRoot').mockReturnValue(`${libName}`);
51 |
52 | await libraryGenerator(tree, {name: libName});
53 | await configureLibraryGenerator(tree, {libName});
54 |
55 | const projectJson = readJson(tree, `${libName}/project.json`)
56 | expect(projectJson.targets['release']).toEqual(expectedExecutorConfig);
57 | });
58 |
59 | it('should not add a public publish config if the "publicPublishConfig" was not set', async () => {
60 | const libName = 'foo';
61 |
62 | jest.spyOn(inquirer, 'prompt').mockImplementation(() => Promise.resolve({selectedProject: libName}));
63 | jest.spyOn(projectHelpers, 'getLibraryProjectNames').mockReturnValue([libName]);
64 | jest.spyOn(projectHelpers, 'getLibraryRoot').mockReturnValue(`${libName}`);
65 |
66 | await libraryGenerator(tree, {name: libName});
67 | await configureLibraryGenerator(tree, {libName});
68 |
69 | const packageJson = readJson(tree, `${libName}/package.json`)
70 | expect(packageJson.publishConfig).not.toBeDefined();
71 | });
72 |
73 | it('should add a public publish config if the "publicPublishConfig" was set to true', async () => {
74 | const libName = 'foo';
75 | const expectedPublishConfig = {access: 'public'}
76 |
77 | jest.spyOn(inquirer, 'prompt').mockImplementation(() => Promise.resolve({selectedProject: libName}));
78 | jest.spyOn(projectHelpers, 'getLibraryProjectNames').mockReturnValue([libName]);
79 | jest.spyOn(projectHelpers, 'getLibraryRoot').mockReturnValue(`${libName}`);
80 |
81 | await libraryGenerator(tree, {name: libName});
82 | await configureLibraryGenerator(tree, {libName, publicPublishConfig: true});
83 |
84 | const packageJson = readJson(tree, `${libName}/package.json`)
85 | expect(packageJson.publishConfig).toEqual(expectedPublishConfig);
86 | });
87 |
88 | it('should log an error message if no library projects are found', done => {
89 | jest.spyOn(console, 'error').mockImplementation(() => {});
90 | jest.spyOn(projectHelpers, 'getLibraryProjectNames').mockReturnValue([]);
91 | jest.spyOn(inquirer, 'prompt').mockImplementation(() => Promise.resolve({
92 | selectedProjects: []
93 | }));
94 | jest.spyOn(process, 'exit').mockImplementation((() => {
95 | done();
96 | }) as any);
97 |
98 | configureLibraryGenerator(tree, {} as any);
99 | });
100 | });
101 |
--------------------------------------------------------------------------------
/libs/nx-release/src/generators/configure-library/generator.ts:
--------------------------------------------------------------------------------
1 | import {formatFiles, Tree, updateJson} from '@nx/devkit';
2 | import * as inquirer from 'inquirer';
3 | import * as process from "process";
4 | import * as chalk from "chalk";
5 |
6 | import {getLibraryProjectNames, getLibraryRoot} from "../helpers/projects.helpers";
7 | import {getSpinner} from "../helpers/spinner.helper";
8 |
9 | import {ConfigureLibraryGeneratorSchema} from './schema';
10 |
11 | export async function configureLibraryGenerator(
12 | tree: Tree,
13 | options: ConfigureLibraryGeneratorSchema
14 | ) {
15 | let {libName} = options;
16 | const { publicPublishConfig } = options;
17 | const spinner = getSpinner();
18 |
19 | try {
20 | if (!libName) {
21 | const libraryProjects = getLibraryProjectNames(tree);
22 |
23 | if (libraryProjects.length === 0) {
24 | console.error(chalk.red(`🐋 nx-release: no library projects found in your workspace -> aborting`));
25 | process.exit(0);
26 | }
27 |
28 | const projectPrompt = await inquirer.prompt({
29 | type: 'list',
30 | name: 'selectedProject',
31 | choices: libraryProjects
32 | });
33 | libName = projectPrompt.selectedProject;
34 | }
35 |
36 | spinner.text = `🐋 nx-release: configuring executor for library ${libName}`;
37 | spinner.start();
38 |
39 | const libraryRoot = getLibraryRoot(tree, libName);
40 |
41 | updateJson(tree, `${libraryRoot}/project.json`, (packageJson: any) => {
42 | packageJson.targets.release = {
43 | executor: 'nx-release:build-update-publish',
44 | options: {
45 | libName
46 | }
47 | };
48 | return packageJson;
49 | });
50 |
51 | spinner.succeed();
52 |
53 | if (publicPublishConfig) {
54 | spinner.text = `🐋 nx-release: add public publish config for library ${libName}`;
55 | spinner.start();
56 |
57 | updateJson(tree, `${libraryRoot}/package.json`, (packageJson: any) => {
58 | packageJson.publishConfig = {
59 | access: 'public'
60 | };
61 | return packageJson;
62 | });
63 | spinner.succeed();
64 | }
65 | await formatFiles(tree);
66 | } catch (e) {
67 | spinner.fail(`🐋 nx-release: something went wrong: ${e.toString()}`)
68 | }
69 | }
70 |
71 | export default configureLibraryGenerator;
72 |
--------------------------------------------------------------------------------
/libs/nx-release/src/generators/configure-library/schema.d.ts:
--------------------------------------------------------------------------------
1 | export interface ConfigureLibraryGeneratorSchema {
2 | libName?: string;
3 | publicPublishConfig?: boolean;
4 | }
5 |
--------------------------------------------------------------------------------
/libs/nx-release/src/generators/configure-library/schema.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "http://json-schema.org/schema",
3 | "$id": "ConfigureLibrary",
4 | "title": "",
5 | "type": "object",
6 | "properties": {
7 | "publicPublishConfig": {
8 | "type": "boolean",
9 | "description": "Should we update the config for public publishing of a library",
10 | "x-prompt": {
11 | "type": "boolean",
12 | "message": "\uD83D\uDC0B nx-release: is your library publicly publishable"
13 | },
14 | "default": true
15 | }
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/libs/nx-release/src/generators/configure-workspace/generator.spec.ts:
--------------------------------------------------------------------------------
1 | import {createTreeWithEmptyWorkspace} from '@nx/devkit/testing';
2 | import * as childProcess from 'child_process';
3 | import * as nXdevKit from '@nx/devkit';
4 | import {Tree} from '@nx/devkit';
5 |
6 | import * as spinnerHelper from '../helpers/spinner.helper';
7 |
8 | import {configureWorkspaceGenerator} from './generator';
9 |
10 | describe('configure-workspace generator', () => {
11 | let tree: Tree;
12 |
13 | beforeEach(() => {
14 | tree = createTreeWithEmptyWorkspace();
15 | jest.spyOn(spinnerHelper, 'getSpinner').mockReturnValue(({
16 | start: jest.fn(),
17 | succeed: jest.fn(),
18 | }) as any
19 | );
20 | });
21 |
22 | it('should install the dependencies if the "installDeps" flag is set', async () => {
23 | const options = {
24 | installDeps: true
25 | };
26 |
27 | jest.spyOn(childProcess, 'execSync').mockImplementation((() => {
28 | }) as any);
29 |
30 | await configureWorkspaceGenerator(tree, options);
31 | expect(childProcess.execSync).toHaveBeenCalledWith(`npm i -D @semantic-release/changelog @semantic-release/commit-analyzer @semantic-release/exec @semantic-release/git @semantic-release/release-notes-generator nx-release replace-json-property conventional-changelog-conventionalcommits --force`);
32 | });
33 |
34 | it('should generate the release config if the "generateReleaseConfig" flag is set', async () => {
35 | const options = {
36 | generateReleaseConfig: true
37 | };
38 |
39 | jest.spyOn(childProcess, 'execSync').mockImplementation((() => {
40 | }) as any);
41 | jest.spyOn(nXdevKit, 'generateFiles').mockImplementation((() => {
42 | }) as any);
43 |
44 | await configureWorkspaceGenerator(tree, options);
45 | expect(nXdevKit.generateFiles).toHaveBeenCalled();
46 | });
47 | });
48 |
--------------------------------------------------------------------------------
/libs/nx-release/src/generators/configure-workspace/generator.ts:
--------------------------------------------------------------------------------
1 | import {execSync} from "child_process";
2 | import {formatFiles, Tree,} from '@nx/devkit';
3 |
4 | import {getSpinner} from "../helpers/spinner.helper";
5 | import generateReleaseConfigGenerator from "../generate-release-config/generator";
6 | import generateGhActionsGenerator from "../generate-gh-actions/generator";
7 |
8 | import {ConfigureWorkspaceGeneratorSchema} from './schema';
9 |
10 | export async function configureWorkspaceGenerator(
11 | tree: Tree,
12 | options: ConfigureWorkspaceGeneratorSchema
13 | ) {
14 | const {installDeps, generateReleaseConfig, generateGhActions} = options;
15 | const spinner = getSpinner();
16 | try {
17 | if (generateReleaseConfig) {
18 | await generateReleaseConfigGenerator(tree, {});
19 | }
20 |
21 | if (generateGhActions) {
22 | await generateGhActionsGenerator(tree, {});
23 | }
24 |
25 | if (installDeps) {
26 | spinner.text = '🐋 nx-release: Installing dependencies';
27 | spinner.start();
28 | execSync(`npm i -D @semantic-release/changelog @semantic-release/commit-analyzer @semantic-release/exec @semantic-release/git @semantic-release/release-notes-generator nx-release replace-json-property conventional-changelog-conventionalcommits --force`);
29 | spinner.succeed();
30 | }
31 |
32 | await formatFiles(tree);
33 | } catch (e) {
34 | spinner.fail(`🐋 nx-release: something went wrong: ${e.toString()}`)
35 | }
36 | }
37 |
38 | function getArtifacts(generateReleaseConfig: boolean, generateWorkflows: boolean) {
39 | let artifacts = '';
40 | if (generateReleaseConfig) {
41 | artifacts += 'release config';
42 | }
43 | if(generateWorkflows){
44 | artifacts += artifacts.length > 0 ? '& GitHub actions': 'GitHub actions'
45 | }
46 | return artifacts;
47 | }
48 |
49 | export default configureWorkspaceGenerator;
50 |
--------------------------------------------------------------------------------
/libs/nx-release/src/generators/configure-workspace/schema.d.ts:
--------------------------------------------------------------------------------
1 | export interface ConfigureWorkspaceGeneratorSchema {
2 | installDeps?: boolean;
3 | generateReleaseConfig?: boolean;
4 | generateGhActions?: boolean;
5 | }
6 |
--------------------------------------------------------------------------------
/libs/nx-release/src/generators/configure-workspace/schema.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "http://json-schema.org/schema",
3 | "$id": "ConfigureWorkspace",
4 | "title": "",
5 | "type": "object",
6 | "properties": {
7 | "installDeps": {
8 | "type": "boolean",
9 | "description": "Install semantic-release and dependencies",
10 | "x-prompt": {
11 | "type": "boolean",
12 | "message": "\uD83D\uDC0B nx-release: would you like to install semantic-release and the required plugins?"
13 | },
14 | "default": true
15 | },
16 | "generateReleaseConfig": {
17 | "type": "boolean",
18 | "description": "Generate release.config.js file",
19 | "x-prompt": {
20 | "type": "boolean",
21 | "message": "\uD83D\uDC0B nx-release: would you like to generate a release config"
22 | },
23 | "default": true
24 | },
25 | "generateGhActions": {
26 | "type": "boolean",
27 | "description": "Generate GitHub workflow files (ci.yml & release.yml)",
28 | "x-prompt": {
29 | "type": "boolean",
30 | "message": "\uD83D\uDC0B nx-release: would you like to generate GitHub workflows?"
31 | },
32 | "default": true
33 | }
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/libs/nx-release/src/generators/configure/generator.spec.ts:
--------------------------------------------------------------------------------
1 | import {createTreeWithEmptyWorkspace} from '@nx/devkit/testing';
2 | import {Tree} from '@nx/devkit';
3 |
4 | import * as workspaceGenerator from "../configure-workspace/generator";
5 | import * as libraryGenerator from "../configure-libraries/generator";
6 |
7 | import {configureGenerator} from './generator';
8 |
9 | describe('configure generator', () => {
10 | let tree: Tree;
11 |
12 | beforeEach(() => {
13 | tree = createTreeWithEmptyWorkspace();
14 | });
15 |
16 | it('should call the workspace and the library generator', async () => {
17 |
18 | const options = {
19 | installDeps: true,
20 | generateGhActions: true,
21 | generateReleaseConfig: true,
22 | publicPublishConfig: true
23 | }
24 |
25 | jest.spyOn(workspaceGenerator, 'configureWorkspaceGenerator').mockImplementation(() => Promise.resolve());
26 | jest.spyOn(libraryGenerator, 'configureLibrariesGenerator').mockImplementation(() => Promise.resolve());
27 |
28 | await configureGenerator(tree, options);
29 |
30 | expect(workspaceGenerator.configureWorkspaceGenerator).toHaveBeenCalledWith(tree, {
31 | installDeps: options.installDeps,
32 | generateGhActions: options.generateGhActions,
33 | generateReleaseConfig: options.generateReleaseConfig
34 | });
35 |
36 | expect(libraryGenerator.configureLibrariesGenerator).toHaveBeenCalledWith(tree, {
37 | publicPublishConfig: options.publicPublishConfig
38 | });
39 | });
40 | });
41 |
--------------------------------------------------------------------------------
/libs/nx-release/src/generators/configure/generator.ts:
--------------------------------------------------------------------------------
1 | import {formatFiles, Tree,} from '@nx/devkit';
2 |
3 | import {configureWorkspaceGenerator} from "../configure-workspace/generator";
4 | import {configureLibrariesGenerator} from "../configure-libraries/generator";
5 |
6 | import {ConfigureGeneratorSchema} from './schema';
7 |
8 | export async function configureGenerator(
9 | tree: Tree,
10 | options: ConfigureGeneratorSchema
11 | ) {
12 | const {publicPublishConfig, installDeps, generateGhActions, generateReleaseConfig} = options;
13 | await configureWorkspaceGenerator(tree, {installDeps, generateGhActions, generateReleaseConfig});
14 | await configureLibrariesGenerator(tree, {publicPublishConfig});
15 |
16 | await formatFiles(tree);
17 | }
18 |
19 | export default configureGenerator;
20 |
--------------------------------------------------------------------------------
/libs/nx-release/src/generators/configure/schema.d.ts:
--------------------------------------------------------------------------------
1 | export interface ConfigureGeneratorSchema {
2 | installDeps: boolean;
3 | generateReleaseConfig: boolean;
4 | generateGhActions
5 | publicPublishConfig: boolean;
6 | }
7 |
--------------------------------------------------------------------------------
/libs/nx-release/src/generators/configure/schema.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "http://json-schema.org/schema",
3 | "$id": "Configure",
4 | "title": "",
5 | "type": "object",
6 | "properties": {
7 | "installDeps": {
8 | "type": "boolean",
9 | "description": "Install semantic-release and dependencies",
10 | "x-prompt": {
11 | "type": "boolean",
12 | "message": "\uD83D\uDC0B nx-release: would you like to install semantic-release and the required plugins?"
13 | },
14 | "default": true
15 | },
16 | "generateReleaseConfig": {
17 | "type": "boolean",
18 | "description": "Generate release.config.js file",
19 | "x-prompt": {
20 | "type": "boolean",
21 | "message": "\uD83D\uDC0B nx-release: would you like to generate a release config"
22 | },
23 | "default": true
24 | },
25 | "generateGhActions": {
26 | "type": "boolean",
27 | "description": "Generate GitHub workflow files (ci.yml & release.yml)",
28 | "x-prompt": {
29 | "type": "boolean",
30 | "message": "\uD83D\uDC0B nx-release: would you like to generate GitHub workflows?"
31 | },
32 | "default": true
33 | },
34 | "publicPublishConfig": {
35 | "type": "boolean",
36 | "description": "Should we update the config for public publishing of a library",
37 | "x-prompt": {
38 | "type": "boolean",
39 | "message": "\uD83D\uDC0B nx-release: is your library publicly publishable"
40 | },
41 | "default": true
42 | }
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/libs/nx-release/src/generators/generate-gh-actions/files/.github/workflows/ci.yml:
--------------------------------------------------------------------------------
1 | name: CI
2 | on:
3 | push:
4 | branches:
5 | - '*'
6 | - '*/*'
7 | - '**'
8 | - '!main'
9 | jobs:
10 | main:
11 | runs-on: ubuntu-latest
12 | steps:
13 | - uses: actions/checkout@v2
14 | with:
15 | fetch-depth: 0
16 | - uses: nrwl/nx-set-shas@v3
17 | - name: Install deps
18 | run: npm ci
19 | - name: Lint affected
20 | run: npx nx affected -t lint
21 | - name: Test affected
22 | run: npx nx affected -t test --configuration=ci
23 | - name: Build affected
24 | run: npx nx affected -t build
25 |
--------------------------------------------------------------------------------
/libs/nx-release/src/generators/generate-gh-actions/files/.github/workflows/release.yml:
--------------------------------------------------------------------------------
1 | name: RELEASE
2 | on: [workflow_dispatch]
3 | jobs:
4 | main:
5 | runs-on: ubuntu-latest
6 | steps:
7 | - uses: actions/checkout@v2
8 | with:
9 | fetch-depth: 0
10 | - uses: nrwl/nx-set-shas@v3
11 | - name: Install deps
12 | run: npm ci
13 | - name: Lint
14 | run: npx nx run-many -t lint
15 | - name: Test
16 | run: npx nx run-many -t test --configuration=ci
17 | - name: Release
18 | run: npx semantic-release
19 | env:
20 | GITHUB_TOKEN: ${{ secrets.GH_TOKEN }}
21 | NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
22 |
--------------------------------------------------------------------------------
/libs/nx-release/src/generators/generate-gh-actions/generator.spec.ts:
--------------------------------------------------------------------------------
1 | import {createTreeWithEmptyWorkspace} from '@nx/devkit/testing';
2 | import * as nxDevkit from '@nx/devkit';
3 | import {Tree} from '@nx/devkit';
4 |
5 | import * as spinnerHelper from "../helpers/spinner.helper";
6 |
7 | import {GenerateGhActionsGeneratorSchema} from './schema';
8 | import generateGhActionsGenerator from "./generator";
9 |
10 | describe('generate-gh-actions generator', () => {
11 | let tree: Tree;
12 | const options: GenerateGhActionsGeneratorSchema = { name: 'test' };
13 |
14 | beforeEach(() => {
15 | tree = createTreeWithEmptyWorkspace();
16 | jest.spyOn(spinnerHelper, 'getSpinner').mockReturnValue(({
17 | start: jest.fn(),
18 | succeed: jest.fn(),
19 | fail: jest.fn(),
20 | }) as any
21 | );
22 | });
23 |
24 | it('should generate the GitHub actions', async () => {
25 | jest.spyOn(nxDevkit, 'generateFiles').mockImplementation(() => {});
26 |
27 | await generateGhActionsGenerator(tree, options);
28 | expect(nxDevkit.generateFiles).toHaveBeenCalled();
29 | });
30 | });
31 |
--------------------------------------------------------------------------------
/libs/nx-release/src/generators/generate-gh-actions/generator.ts:
--------------------------------------------------------------------------------
1 | import {formatFiles, generateFiles, Tree,} from '@nx/devkit';
2 | import * as path from 'path';
3 |
4 | import {getSpinner} from '../helpers/spinner.helper';
5 |
6 | import {GenerateGhActionsGeneratorSchema} from './schema';
7 |
8 | export async function generateGhActionsGenerator(
9 | tree: Tree,
10 | options: GenerateGhActionsGeneratorSchema
11 | ) {
12 | const spinner = getSpinner();
13 | try {
14 | spinner.text = `🐋 nx-release: generating GitHub actions workflow files`;
15 | spinner.start();
16 | generateFiles(tree, path.join(__dirname, 'files'), '.', options);
17 | spinner.succeed();
18 |
19 | await formatFiles(tree);
20 | } catch (e) {
21 | spinner.fail(`🐋 nx-release: something went wrong: ${e.toString()}`);
22 | }
23 | }
24 |
25 | export default generateGhActionsGenerator;
26 |
--------------------------------------------------------------------------------
/libs/nx-release/src/generators/generate-gh-actions/schema.d.ts:
--------------------------------------------------------------------------------
1 | export interface GenerateGhActionsGeneratorSchema {}
2 |
--------------------------------------------------------------------------------
/libs/nx-release/src/generators/generate-gh-actions/schema.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "http://json-schema.org/schema",
3 | "$id": "GenerateGhActions",
4 | "title": "",
5 | "type": "object",
6 | "properties": {
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/libs/nx-release/src/generators/generate-release-config/files/release.config.js.template:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | branches: ['main'],
3 | preset: 'conventionalcommits',
4 | presetConfig: {
5 | types: [
6 | { type: 'feat', section: 'Features' },
7 | { type: 'fix', section: 'Bug Fixes' },
8 | { type: 'chore', section: 'Chores' },
9 | { type: 'docs', hidden: true },
10 | { type: 'style', hidden: true },
11 | { type: 'refactor', section: 'Refactoring' },
12 | { type: 'perf', hidden: true },
13 | { type: 'test', hidden: true },
14 | ],
15 | },
16 | releaseRules: [{ type: 'refactor', release: 'patch' }],
17 | plugins: [
18 | '@semantic-release/commit-analyzer',
19 | '@semantic-release/release-notes-generator',
20 | [
21 | '@semantic-release/changelog',
22 | {
23 | changelogFile: `./CHANGELOG.md`,
24 | },
25 | ],
26 | ["@semantic-release/exec", {
27 | prepareCmd: `VERSION=\${nextRelease.version} npx nx run-many -t release && VERSION=\${nextRelease.version} npx -p replace-json-property rjp ./package.json version \${nextRelease.version}`,
28 | }],
29 | [
30 | '@semantic-release/git',
31 | {
32 | assets: [
33 | `libs/**/package.json`,
34 | `package.json`,
35 | `CHANGELOG.md`
36 | ],
37 | message:
38 | 'chore(release): -v${nextRelease.version} [skip ci]\n\n${nextRelease.notes}',
39 | },
40 | ],
41 | ],
42 | };
43 |
--------------------------------------------------------------------------------
/libs/nx-release/src/generators/generate-release-config/generator.spec.ts:
--------------------------------------------------------------------------------
1 | import {createTreeWithEmptyWorkspace} from '@nx/devkit/testing';
2 | import * as nxDevkit from '@nx/devkit';
3 | import {Tree} from '@nx/devkit';
4 |
5 | import * as spinnerHelper from "../helpers/spinner.helper";
6 |
7 | import {generateReleaseConfigGenerator} from './generator';
8 | import {GenerateReleaseConfigGeneratorSchema} from './schema';
9 |
10 | describe('generate-release-config generator', () => {
11 | let tree: Tree;
12 | const options: GenerateReleaseConfigGeneratorSchema = { name: 'test' };
13 |
14 | beforeEach(() => {
15 | tree = createTreeWithEmptyWorkspace();
16 | jest.spyOn(spinnerHelper, 'getSpinner').mockReturnValue(({
17 | start: jest.fn(),
18 | succeed: jest.fn(),
19 | fail: jest.fn(),
20 | }) as any
21 | );
22 | });
23 |
24 | it('should generate the release config', async () => {
25 | jest.spyOn(nxDevkit, 'generateFiles').mockImplementation(() => {});
26 |
27 | await generateReleaseConfigGenerator(tree, options);
28 | expect(nxDevkit.generateFiles).toHaveBeenCalled();
29 | });
30 | });
31 |
--------------------------------------------------------------------------------
/libs/nx-release/src/generators/generate-release-config/generator.ts:
--------------------------------------------------------------------------------
1 | import {
2 | addProjectConfiguration,
3 | formatFiles,
4 | generateFiles,
5 | Tree,
6 | } from '@nx/devkit';
7 | import * as path from 'path';
8 | import { GenerateReleaseConfigGeneratorSchema } from './schema';
9 | import { getSpinner } from '../helpers/spinner.helper';
10 |
11 | export async function generateReleaseConfigGenerator(
12 | tree: Tree,
13 | options: GenerateReleaseConfigGeneratorSchema
14 | ) {
15 | const spinner = getSpinner();
16 | try {
17 | spinner.text = `🐋 nx-release: generating a release config`;
18 | spinner.start();
19 | generateFiles(tree, path.join(__dirname, 'files'), '.', options);
20 | spinner.succeed();
21 |
22 | await formatFiles(tree);
23 | } catch (e) {
24 | spinner.fail(`🐋 nx-release: something went wrong: ${e.toString()}`);
25 | }
26 | }
27 |
28 | export default generateReleaseConfigGenerator;
29 |
--------------------------------------------------------------------------------
/libs/nx-release/src/generators/generate-release-config/schema.d.ts:
--------------------------------------------------------------------------------
1 | export interface GenerateReleaseConfigGeneratorSchema {}
2 |
--------------------------------------------------------------------------------
/libs/nx-release/src/generators/generate-release-config/schema.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "http://json-schema.org/schema",
3 | "$id": "GenerateReleaseConfig",
4 | "title": "",
5 | "type": "object",
6 | "properties": {}
7 | }
8 |
--------------------------------------------------------------------------------
/libs/nx-release/src/generators/helpers/projects.helpers.spec.ts:
--------------------------------------------------------------------------------
1 | import * as nxDevKit from '@nx/devkit';
2 |
3 | import { getLibraryProjectNames, getLibraryRoot } from './projects.helpers';
4 |
5 | describe('generator project helper', () => {
6 | it('should return the library project names', () => {
7 | const expectedLibraryNames = ['foo', 'bar'];
8 |
9 | const mockProjectConfigs = new Map();
10 | mockProjectConfigs.set('foo', {
11 | projectType: 'library',
12 | });
13 | mockProjectConfigs.set('bar', {
14 | projectType: 'library',
15 | });
16 | mockProjectConfigs.set('baz', {
17 | projectType: 'application',
18 | });
19 |
20 | jest.spyOn(nxDevKit, 'getProjects').mockReturnValue(mockProjectConfigs);
21 |
22 | expect(getLibraryProjectNames({} as any)).toEqual(expectedLibraryNames);
23 | });
24 |
25 | it('should get the library root', () => {
26 | const mockProjectConfigs = new Map();
27 | mockProjectConfigs.set('foo', {
28 | projectType: 'library',
29 | root: 'libs/foo',
30 | });
31 | mockProjectConfigs.set('bar', {
32 | projectType: 'library',
33 | root: 'libs/bar',
34 | });
35 |
36 | jest.spyOn(nxDevKit, 'getProjects').mockReturnValue(mockProjectConfigs);
37 |
38 | expect(getLibraryRoot({} as any, 'foo')).toEqual('libs/foo');
39 | });
40 | });
41 |
--------------------------------------------------------------------------------
/libs/nx-release/src/generators/helpers/projects.helpers.ts:
--------------------------------------------------------------------------------
1 | import {getProjects, Tree} from "@nx/devkit";
2 |
3 | export function getLibraryProjectNames(tree: Tree): string[]{
4 | const projectNames = [];
5 | getProjects(tree).forEach((projectConfiguration, projectName) => {
6 | if(projectConfiguration.projectType === 'library'){
7 | projectNames.push(projectName);
8 | }
9 | });
10 | return projectNames;
11 | }
12 |
13 | export function getLibraryRoot(tree: Tree, libraryName: string): string{
14 | return getProjects(tree).get(libraryName).root;
15 | }
16 |
--------------------------------------------------------------------------------
/libs/nx-release/src/generators/helpers/spinner.helper.ts:
--------------------------------------------------------------------------------
1 | import * as ora from "ora";
2 |
3 | export function getSpinner(): ora.Ora {
4 | return ora();
5 | }
6 |
--------------------------------------------------------------------------------
/libs/nx-release/src/index.ts:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nivekcode/nx-release/dec67fb7ff59167308c0161109874ce2a9b61da7/libs/nx-release/src/index.ts
--------------------------------------------------------------------------------
/libs/nx-release/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../../tsconfig.base.json",
3 | "compilerOptions": {
4 | "module": "commonjs"
5 | },
6 | "files": [],
7 | "include": [],
8 | "references": [
9 | {
10 | "path": "./tsconfig.lib.json"
11 | },
12 | {
13 | "path": "./tsconfig.spec.json"
14 | }
15 | ]
16 | }
17 |
--------------------------------------------------------------------------------
/libs/nx-release/tsconfig.lib.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "./tsconfig.json",
3 | "compilerOptions": {
4 | "outDir": "../../dist/out-tsc",
5 | "declaration": true,
6 | "types": ["node"]
7 | },
8 | "include": ["src/**/*.ts"],
9 | "exclude": ["jest.config.ts", "src/**/*.spec.ts", "src/**/*.test.ts"]
10 | }
11 |
--------------------------------------------------------------------------------
/libs/nx-release/tsconfig.spec.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "./tsconfig.json",
3 | "compilerOptions": {
4 | "outDir": "../../dist/out-tsc",
5 | "module": "commonjs",
6 | "types": ["jest", "node"]
7 | },
8 | "include": [
9 | "jest.config.ts",
10 | "src/**/*.test.ts",
11 | "src/**/*.spec.ts",
12 | "src/**/*.d.ts"
13 | ]
14 | }
15 |
--------------------------------------------------------------------------------
/nx.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "./node_modules/nx/schemas/nx-schema.json",
3 | "tasksRunnerOptions": {
4 | "default": {
5 | "runner": "nx-cloud",
6 | "options": {
7 | "cacheableOperations": ["build", "lint", "test", "e2e"],
8 | "accessToken": "NDI4ZGRjZmUtYjQ1NC00ODkxLWE2NTctNjA0MWQ4Y2VlY2NlfHJlYWQtd3JpdGU="
9 | }
10 | }
11 | },
12 | "targetDefaults": {
13 | "build": {
14 | "dependsOn": ["^build"],
15 | "inputs": ["production", "^production"]
16 | },
17 | "lint": {
18 | "inputs": [
19 | "default",
20 | "{workspaceRoot}/.eslintrc.json",
21 | "{workspaceRoot}/.eslintignore"
22 | ]
23 | },
24 | "test": {
25 | "inputs": ["default", "^production", "{workspaceRoot}/jest.preset.js"]
26 | }
27 | },
28 | "namedInputs": {
29 | "default": ["{projectRoot}/**/*", "sharedGlobals"],
30 | "production": [
31 | "default",
32 | "!{projectRoot}/.eslintrc.json",
33 | "!{projectRoot}/**/?(*.)+(spec|test).[jt]s?(x)?(.snap)",
34 | "!{projectRoot}/tsconfig.spec.json",
35 | "!{projectRoot}/jest.config.[jt]s",
36 | "!{projectRoot}/src/test-setup.[jt]s"
37 | ],
38 | "sharedGlobals": []
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@nx-release/source",
3 | "version": "3.4.0",
4 | "license": "MIT",
5 | "scripts": {
6 | "g:configure": "nx generate @nx-release/nx-release:configure",
7 | "g:configure-workspace": "nx generate @nx-release/nx-release:configure-workspace",
8 | "g:configure-library": "nx generate @nx-release/nx-release:configure-library",
9 | "g:configure-libraries": "nx generate @nx-release/nx-release:configure-libraries",
10 | "lint": "nx lint -p nx-release",
11 | "test": "nx test -p nx-release",
12 | "test:coverage": "nx test --coverage --coverageReporters=lcov -p nx-release",
13 | "build": "nx build -p nx-release",
14 | "bump-versions": "rjp package.json version $VERSION && rjp libs/nx-release/package.json version $VERSION",
15 | "release": "VERSION=$VERSION npm run bump-versions && npm run build && nx run-many -t publish"
16 | },
17 | "private": true,
18 | "dependencies": {
19 | "@nx/devkit": "16.5.0",
20 | "@nx/plugin": "^16.5.0",
21 | "@swc/helpers": "~0.5.0",
22 | "chalk": "^4.1.2",
23 | "inquirer": "^8.2.5",
24 | "ora": "^5.4.1",
25 | "tslib": "^2.6.0"
26 | },
27 | "devDependencies": {
28 | "@nx/eslint-plugin": "16.5.0",
29 | "@nx/jest": "16.5.0",
30 | "@nx/js": "16.5.0",
31 | "@nx/linter": "16.5.0",
32 | "@nx/workspace": "16.5.0",
33 | "@semantic-release/changelog": "^6.0.3",
34 | "@semantic-release/commit-analyzer": "^10.0.1",
35 | "@semantic-release/exec": "^6.0.3",
36 | "@semantic-release/git": "^10.0.1",
37 | "@semantic-release/release-notes-generator": "^11.0.4",
38 | "@swc-node/register": "~1.4.2",
39 | "@swc/cli": "~0.1.62",
40 | "@swc/core": "~1.3.51",
41 | "@types/jest": "^29.4.0",
42 | "@types/node": "18.7.1",
43 | "@typescript-eslint/eslint-plugin": "^5.60.1",
44 | "@typescript-eslint/parser": "^5.60.1",
45 | "all-contributors-cli": "^6.26.1",
46 | "conventional-changelog-conventionalcommits": "^6.1.0",
47 | "eslint": "~8.15.0",
48 | "eslint-config-prettier": "8.1.0",
49 | "jest": "^29.4.1",
50 | "jest-environment-jsdom": "^29.4.1",
51 | "jest-environment-node": "^29.4.1",
52 | "nx": "16.5.0",
53 | "nx-cloud": "latest",
54 | "nx-release": "^2.1.0",
55 | "prettier": "^2.6.2",
56 | "replace-json-property": "^1.9.0",
57 | "ts-jest": "^29.1.0",
58 | "ts-node": "10.9.1",
59 | "typescript": "~5.1.3",
60 | "verdaccio": "^5.0.4"
61 | },
62 | "repository": "https://github.com/kreuzerk/nx-release",
63 | "nx": {
64 | "includedScripts": []
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/project.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@nx-release/source",
3 | "$schema": "node_modules/nx/schemas/project-schema.json",
4 | "targets": {
5 | "local-registry": {
6 | "executor": "@nx/js:verdaccio",
7 | "options": {
8 | "port": 4873,
9 | "config": ".verdaccio/config.yml",
10 | "storage": "tmp/local-registry/storage"
11 | }
12 | }
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/release.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | branches: ['main'],
3 | preset: 'conventionalcommits',
4 | presetConfig: {
5 | types: [
6 | { type: 'feat', section: 'Features' },
7 | { type: 'fix', section: 'Bug Fixes' },
8 | { type: 'chore', section: 'Chores' },
9 | { type: 'docs', hidden: true },
10 | { type: 'style', hidden: true },
11 | { type: 'refactor', section: 'Refactoring' },
12 | { type: 'perf', hidden: true },
13 | { type: 'test', hidden: true },
14 | ],
15 | },
16 | releaseRules: [{ type: 'refactor', release: 'patch' }],
17 | plugins: [
18 | '@semantic-release/commit-analyzer',
19 | '@semantic-release/release-notes-generator',
20 | [
21 | '@semantic-release/changelog',
22 | {
23 | changelogFile: `./CHANGELOG.md`,
24 | },
25 | ],
26 | ["@semantic-release/exec", {
27 | prepareCmd: `VERSION=\${nextRelease.version} npm run release`,
28 | }],
29 | [
30 | '@semantic-release/git',
31 | {
32 | assets: [
33 | `libs/foo/package.json`,
34 | `libs/bar/package.json`,
35 | `libs/baz/package.json`,
36 | `package.json`,
37 | `CHANGELOG.md`
38 | ],
39 | message:
40 | 'chore(release): -v${nextRelease.version} [skip ci]\n\n${nextRelease.notes}',
41 | },
42 | ],
43 | ],
44 | };
45 |
--------------------------------------------------------------------------------
/tools/scripts/publish.mjs:
--------------------------------------------------------------------------------
1 | /**
2 | * This is a minimal script to publish your package to "npm".
3 | * This is meant to be used as-is or customize as you see fit.
4 | *
5 | * This script is executed on "dist/path/to/library" as "cwd" by default.
6 | *
7 | * You might need to authenticate with NPM before running this script.
8 | */
9 |
10 | import { execSync } from 'child_process';
11 | import { readFileSync, writeFileSync } from 'fs';
12 |
13 | import devkit from '@nx/devkit';
14 | const { readCachedProjectGraph } = devkit;
15 |
16 | function invariant(condition, message) {
17 | if (!condition) {
18 | console.error(message);
19 | process.exit(1);
20 | }
21 | }
22 |
23 | // Executing publish script: node path/to/publish.mjs {name} --version {version} --tag {tag}
24 | // Default "tag" to "next" so we won't publish the "latest" tag by accident.
25 | const [, , name, version, tag = 'next'] = process.argv;
26 |
27 | // A simple SemVer validation to validate the version
28 | const validVersion = /^\d+\.\d+\.\d+(-\w+\.\d+)?/;
29 | invariant(
30 | version && validVersion.test(version),
31 | `No version provided or version did not match Semantic Versioning, expected: #.#.#-tag.# or #.#.#, got ${version}.`
32 | );
33 |
34 | const graph = readCachedProjectGraph();
35 | const project = graph.nodes[name];
36 |
37 | invariant(
38 | project,
39 | `Could not find project "${name}" in the workspace. Is the project.json configured correctly?`
40 | );
41 |
42 | const outputPath = project.data?.targets?.build?.options?.outputPath;
43 | invariant(
44 | outputPath,
45 | `Could not find "build.options.outputPath" of project "${name}". Is project.json configured correctly?`
46 | );
47 |
48 | process.chdir(outputPath);
49 |
50 | // Updating the version in "package.json" before publishing
51 | try {
52 | const json = JSON.parse(readFileSync(`package.json`).toString());
53 | json.version = version;
54 | writeFileSync(`package.json`, JSON.stringify(json, null, 2));
55 | } catch (e) {
56 | console.error(`Error reading package.json file from library build output.`);
57 | }
58 |
59 | // Execute "npm publish" to publish
60 | execSync(`npm publish --access public --tag ${tag}`);
61 |
--------------------------------------------------------------------------------
/tools/tsconfig.tools.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../tsconfig.base.json",
3 | "compilerOptions": {
4 | "outDir": "../dist/out-tsc/tools",
5 | "rootDir": ".",
6 | "module": "commonjs",
7 | "target": "es5",
8 | "types": ["node"],
9 | "importHelpers": false
10 | },
11 | "include": ["**/*.ts"]
12 | }
13 |
--------------------------------------------------------------------------------
/tsconfig.base.json:
--------------------------------------------------------------------------------
1 | {
2 | "compileOnSave": false,
3 | "compilerOptions": {
4 | "rootDir": ".",
5 | "sourceMap": true,
6 | "declaration": false,
7 | "moduleResolution": "node",
8 | "emitDecoratorMetadata": true,
9 | "experimentalDecorators": true,
10 | "importHelpers": true,
11 | "target": "es2015",
12 | "module": "esnext",
13 | "lib": ["es2020", "dom"],
14 | "skipLibCheck": true,
15 | "skipDefaultLibCheck": true,
16 | "baseUrl": ".",
17 | "paths": {
18 | "@nx-release/nx-release": ["libs/nx-release/src/index.ts"]
19 | }
20 | },
21 | "exclude": ["node_modules", "tmp"]
22 | }
23 |
--------------------------------------------------------------------------------