Publishing Packages with Nx Release

Publishing a package is no small feat. It requires a well-defined process to ensure that the package is versioned correctly, the changelog is updated, the package is committed to the repository, the commit is tagged, the changes are pushed to the remote repository, and a GitHub release is created. This process is automated using the Nx release workflow.
The entire workflow below is automated using the Nx release workflow. The release workflow. You will need:
- A
.npmrcfile to configure the package registry. - A
releaseconfiguration in thenx.jsonfile. - A
nx:pubscript in thepackage.jsonfile. - An
nx-release-publishtarget in targetproject.jsonfile(s).
Sequence Diagram
The sequence diagram below illustrates the process for publishing a package to a GitHub Package Registry using Nx Release. Imagine if you had to do all of this manually. It would be a nightmare. The Nx release workflow automates the entire process.

Workflow
This document describes the process for publishing packages to a GitHub Package Registry. The process includes updating the package version, updating the changelog, committing the changes, tagging the commit, pushing the changes to the remote repository, and creating a GitHub release.
Package Registry
This sample .npmrc file configures the package registry to use the GitHub Package Registry. The .npmrc file is located at the root of the workspace. If you have a scoped package, you must include the scope in the .npmrc file.
registry=https://npm.pkg.github.com/
//npm.pkg.github.com/:_authToken=YOUR_GITHUB_TOKEN
@buildmotion:registry=https://npm.pkg.github.com/
The .npmrc file is a configuration file for npm (Node Package Manager) where you can specify various parameters and settings for npm behavior. This example is configured for publishing packages to GitHub's npm registry.
-
registry=https://npm.pkg.github.com/:- This line defines the default npm registry to be used. By providing
https://npm.pkg.github.com/, it tells npm to use GitHub's npm registry for publishing packages. This is important when you want to manage your packages on GitHub rather than the default npm registry.
- This line defines the default npm registry to be used. By providing
-
//npm.pkg.github.com/:_authToken=YOUR_GITHUB_TOKEN:- This line provides authentication information for the GitHub package registry.
:_authToken=YOUR_GITHUB_TOKENis a placeholder for your actual GitHub token, which is necessary for authentication. This token should have the appropriate scopes (usuallyrepoandwrite:packages) to allow publishing and accessing private packages.
- This line provides authentication information for the GitHub package registry.
-
@buildmotion:registry=https://npm.pkg.github.com/:- This line specifies that packages scoped under
@buildmotionshould be fetched from the GitHub registry. It's a scoped registry setting, which means that if you publish or fetch packages with the@buildmotionprefix, they will be directed to this specific registry. This is useful if you want only certain packages (those under a specific scope) to use a different registry than the default one.
- This line specifies that packages scoped under
In summary, while the lines may look similar, each serves a different purpose:
- The first line sets the global registry for npm commands.
- The second provides necessary authentication with a token for accessing and publishing to GitHub's registry.
- The third line specifies a scoped registry for packages under a certain scope (in this case,
@buildmotion), allowing you to keep using the default registry for others.
This configuration ensures controlled access and publish actions specifically targeted to GitHub's npm registry.
Package Script
The root-level package.json contains a script to perform a release. The nx:pub script is used to publish the package to the GitHub Package Registry.
"nx:pub": "nx release --verbose=true --first-release=true",
Release Generator
The CLI command nx release begins the process of releasing a package. The nx.json file contains a release section with configuration options for the release process. The nx.json file is located at the root of the workspace.
"release": {
"projects": ["packages/github-motion"],
"releaseTagPattern": "{version}",
"changelog": {
"workspaceChangelog": {
"createRelease": "github",
"file": "CHANGELOG.md"
},
"projectChangelogs": true
},
"version": {
"generatorOptions": {
"currentVersionResolver": "git-tag",
"skipLockFileUpdate": true,
"specifierSource": "conventional-commits"
}
}
}
Project Target
Update your publishable projects with the nx-release-publish target in the project.json file. The project.json file is located in the root of the specific library project directory.
"nx-release-publish": {
"options": {
"packageRoot": "dist/{projectRoot}",
"registry": "https://npm.pkg.github.com",
"tag": "next"
}
},
CLI Output
The CLI output below shows the release process for the github-motion package. The release process includes updating the package version, updating the changelog, committing the changes, tagging the commit, pushing the changes to the remote repository, and creating a GitHub release.
yarn nx:pub
Debugger listening on ws://127.0.0.1:53683/59600096-120c-47c3-af4a-d53541add47b
For help, see: https://nodejs.org/en/docs/inspector
Debugger attached.
yarn run v1.22.22
$ nx release --verbose=true --first-release=true
Debugger listening on ws://127.0.0.1:53690/8759bf14-05bc-4bf5-8475-8e73b7626337
For help, see: https://nodejs.org/en/docs/inspector
Debugger attached.
NX Running release version for project: github-motion
github-motion 🔍 Reading data for package "@buildmotion/github-motion" from packages/github-motion/package.json
github-motion 📄 Resolved the current version as 13.0.0 from git tag "v13.0.0".
github-motion 📄 Resolved the specifier as "patch" using git history and the conventional commits standard.
github-motion ✍️ New version 13.0.1 written to packages/github-motion/package.json
UPDATE packages/github-motion/package.json
"name": "@buildmotion/github-motion",
- "version": "13.0.0",
+ "version": "13.0.1",
"dependencies": {
Skipped lock file update because skipLockFileUpdate was set.
NX Staging changed files with git
Staging files in git with the following command:
git add packages/github-motion/package.json
NX Generating an entry in CHANGELOG.md for v13.0.1
UPDATE CHANGELOG.md
+ ## 13.0.1 (2024-12-27)
+
+
+ ### 🩹 Fixes
+
+ - **nx:** change first-release to false ([517631d](https://github.com/buildmotion/github-motion/commit/517631d))
+ - **nx:** change verbose to false ([a713a0d](https://github.com/buildmotion/github-motion/commit/a713a0d))
+ - **nx:** update version options ([5b56545](https://github.com/buildmotion/github-motion/commit/5b56545))
+ - **nx:** update version options ([933ee76](https://github.com/buildmotion/github-motion/commit/933ee76))
+ - **nx:** back in the hole again ([f8eaf59](https://github.com/buildmotion/github-motion/commit/f8eaf59))
+
+ ### ❤️ Thank You
+
+ - Matt Vaughn @buildmotion
+
# 13.0.0 (2024-12-27)
NX Generating an entry in packages/github-motion/CHANGELOG.md for v13.0.1
UPDATE packages/github-motion/CHANGELOG.md
+ ## 13.0.1 (2024-12-27)
+
+
+ ### 🩹 Fixes
+
+ - **nx:** back in the hole again ([f8eaf59](https://github.com/buildmotion/github-motion/commit/f8eaf59))
+
+
+ ### ❤️ Thank You
+
+ - Matt Vaughn @buildmotion
+
# 13.0.0 (2024-12-27)
NX Staging changed files with git
Staging files in git with the following command:
git add CHANGELOG.md packages/github-motion/CHANGELOG.md
NX Committing changes with git
Committing files in git with the following command:
git commit --message chore(release): publish 13.0.1
NX Tagging commit with git
Tagging the current commit in git with the following command:
git tag --annotate v13.0.1 --message v13.0.1
NX Pushing to git remote
Pushing the current branch to the remote with the following command:
git push --follow-tags --no-verify --atomic
NX Creating GitHub Release
CREATE https://github.com/buildmotion/github-motion/releases/tag/v13.0.1
+ ## 13.0.1 (2024-12-27)
+
+
+ ### 🩹 Fixes
+
+ - **nx:** change first-release to false ([517631d](https://github.com/buildmotion/github-motion/commit/517631d))
+ - **nx:** change verbose to false ([a713a0d](https://github.com/buildmotion/github-motion/commit/a713a0d))
+ - **nx:** update version options ([5b56545](https://github.com/buildmotion/github-motion/commit/5b56545))
+ - **nx:** update version options ([933ee76](https://github.com/buildmotion/github-motion/commit/933ee76))
+ - **nx:** back in the hole again ([f8eaf59](https://github.com/buildmotion/github-motion/commit/f8eaf59))
+
+ ### ❤️ Thank You
+
+ - Matt Vaughn @buildmotion
NX A GitHub API Error occurred when creating/updating the release
GitHub Error: {"message":"Not Found","documentation_url":"https://docs.github.com/rest/releases/releases#create-a-release","status":"404"}
---
Request Data:
Repo: buildmotion/github-motion
Token: null
Body: {"tag_name":"v13.0.1","name":"v13.0.1","body":"## 13.0.1 (2024-12-27)\n\n\n### 🩹 Fixes\n\n- **nx:** change first-release to false ([517631d](https://github.com/buildmotion/github-motion/commit/517631d))\n- **nx:** change verbose to false ([a713a0d](https://github.com/buildmotion/github-motion/commit/a713a0d))\n- **nx:** update version options ([5b56545](https://github.com/buildmotion/github-motion/commit/5b56545))\n- **nx:** update version options ([933ee76](https://github.com/buildmotion/github-motion/commit/933ee76))\n- **nx:** back in the hole again ([f8eaf59](https://github.com/buildmotion/github-motion/commit/f8eaf59))\n\n### ❤️ Thank You\n\n- Matt Vaughn @buildmotion","prerelease":false}
✔ Do you want to finish creating the release manually in your browser? · Yes
Follow up in the browser to manually create the release:
https://github.com/buildmotion/github-motion/releases/new?tag=v13.0.1&title=v13.0.1&body=%23%23%2013.0.1%20(2024-12-27)%0A%0A%0A%23%23%23%20%F0%9F%A9%B9%20Fixes%0A%0A-%20**nx%3A**%20change%20first-release%20to%20false%20(%5B517631d%5D(https%3A%2F%2Fgithub.com%2Fbuildmotion%2Fgithub-motion%2Fcommit%2F517631d))%0A-%20**nx%3A**%20change%20verbose%20to%20false%20(%5Ba713a0d%5D(https%3A%2F%2Fgithub.com%2Fbuildmotion%2Fgithub-motion%2Fcommit%2Fa713a0d))%0A-%20**nx%3A**%20update%20version%20options%20(%5B5b56545%5D(https%3A%2F%2Fgithub.com%2Fbuildmotion%2Fgithub-motion%2Fcommit%2F5b56545))%0A-%20**nx%3A**%20update%20version%20options%20(%5B933ee76%5D(https%3A%2F%2Fgithub.com%2Fbuildmotion%2Fgithub-motion%2Fcommit%2F933ee76))%0A-%20**nx%3A**%20back%20in%20the%20hole%20again%20(%5Bf8eaf59%5D(https%3A%2F%2Fgithub.com%2Fbuildmotion%2Fgithub-motion%2Fcommit%2Ff8eaf59))%0A%0A%23%23%23%20%E2%9D%A4%EF%B8%8F%20%20Thank%20You%0A%0A-%20Matt%20Vaughn%20%40buildmotion&target=8a859d8cc59910dcec3e5f7f66aa4a369983928f
AxiosError: Request failed with status code 404
at settle (/Users/valencia/work/github/buildmotion-github-motion/node_modules/axios/lib/core/settle.js:19:12)
at Unzip.handleStreamEnd (/Users/valencia/work/github/buildmotion-github-motion/node_modules/axios/lib/adapters/http.js:599:11)
at Unzip.emit (node:events:530:35)
at endReadableNT (node:internal/streams/readable:1696:12)
at processTicksAndRejections (node:internal/process/task_queues:82:21)
at Axios.request (/Users/valencia/work/github/buildmotion-github-motion/node_modules/axios/lib/core/Axios.js:45:41)
at processTicksAndRejections (node:internal/process/task_queues:95:5)
at makeGithubRequest (/Users/valencia/work/github/buildmotion-github-motion/node_modules/nx/src/command-line/release/utils/github.js:272:13)
at createGithubRelease (/Users/valencia/work/github/buildmotion-github-motion/node_modules/nx/src/command-line/release/utils/github.js:282:12)
at syncGithubRelease (/Users/valencia/work/github/buildmotion-github-motion/node_modules/nx/src/command-line/release/utils/github.js:214:30)
at createOrUpdateGithubReleaseInternal (/Users/valencia/work/github/buildmotion-github-motion/node_modules/nx/src/command-line/release/utils/github.js:115:20)
at createOrUpdateGithubRelease (/Users/valencia/work/github/buildmotion-github-motion/node_modules/nx/src/command-line/release/utils/github.js:106:9)
at release (/Users/valencia/work/github/buildmotion-github-motion/node_modules/nx/src/command-line/release/release.js:171:13)
at handleErrors (/Users/valencia/work/github/buildmotion-github-motion/node_modules/nx/src/utils/handle-errors.js:9:24)
at Object.handler (/Users/valencia/work/github/buildmotion-github-motion/node_modules/nx/src/command-line/release/command-object.js:98:24) {
code: 'ERR_BAD_REQUEST',
config: {
transitional: {
silentJSONParsing: true,
forcedJSONParsing: true,
clarifyTimeoutError: false
},
adapter: [ 'xhr', 'http', 'fetch' ],
transformRequest: [ [Function: transformRequest] ],
transformResponse: [ [Function: transformResponse] ],
timeout: 0,
xsrfCookieName: 'XSRF-TOKEN',
xsrfHeaderName: 'X-XSRF-TOKEN',
maxContentLength: -1,
maxBodyLength: -1,
env: { FormData: [Function], Blob: [class Blob] },
validateStatus: [Function: validateStatus],
headers: Object [AxiosHeaders] {
Accept: 'application/json, text/plain, */*',
'Content-Type': 'application/json',
Authorization: undefined,
'User-Agent': 'axios/1.7.9',
'Content-Length': '772',
'Accept-Encoding': 'gzip, compress, deflate, br'
},
method: 'post',
data: '{"tag_name":"v13.0.1","name":"v13.0.1","body":"## 13.0.1 (2024-12-27)\\n\\n\\n### 🩹 Fixes\\n\\n- **nx:** change first-release to false ([517631d](https://github.com/buildmotion/github-motion/commit/517631d))\\n- **nx:** change verbose to false ([a713a0d](https://github.com/buildmotion/github-motion/commit/a713a0d))\\n- **nx:** update version options ([5b56545](https://github.com/buildmotion/github-motion/commit/5b56545))\\n- **nx:** update version options ([933ee76](https://github.com/buildmotion/github-motion/commit/933ee76))\\n- **nx:** back in the hole again ([f8eaf59](https://github.com/buildmotion/github-motion/commit/f8eaf59))\\n\\n### ❤️ Thank You\\n\\n- Matt Vaughn @buildmotion","prerelease":false,"target_commitish":"8a859d8cc59910dcec3e5f7f66aa4a369983928f"}',
baseURL: 'https://api.github.com',
url: '/repos/buildmotion/github-motion/releases'
},
request: <ref *1> ClientRequest {
_events: [Object: null prototype] {
abort: [Function (anonymous)],
aborted: [Function (anonymous)],
connect: [Function (anonymous)],
error: [Function (anonymous)],
socket: [Function (anonymous)],
timeout: [Function (anonymous)],
finish: [Function: requestOnFinish]
},
_eventsCount: 7,
_maxListeners: undefined,
outputData: [],
outputSize: 0,
writable: true,
destroyed: true,
_last: false,
chunkedEncoding: false,
shouldKeepAlive: true,
maxRequestsOnConnectionReached: false,
_defaultKeepAlive: true,
useChunkedEncodingByDefault: true,
sendDate: false,
_removedConnection: false,
_removedContLen: false,
_removedTE: false,
strictContentLength: false,
_contentLength: '772',
_hasBody: true,
_trailer: '',
finished: true,
_headerSent: true,
_closed: true,
socket: TLSSocket {
_tlsOptions: [Object],
_secureEstablished: true,
_securePending: false,
_newSessionPending: false,
_controlReleased: true,
secureConnecting: false,
_SNICallback: null,
servername: 'api.github.com',
alpnProtocol: false,
authorized: true,
authorizationError: null,
encrypted: true,
_events: [Object: null prototype],
_eventsCount: 9,
connecting: false,
_hadError: false,
_parent: null,
_host: 'api.github.com',
_closeAfterHandlingError: false,
_readableState: [ReadableState],
_writableState: [WritableState],
allowHalfOpen: false,
_maxListeners: undefined,
_sockname: null,
_pendingData: null,
_pendingEncoding: '',
server: undefined,
_server: null,
ssl: null,
_requestCert: true,
_rejectUnauthorized: true,
timeout: 5000,
parser: null,
_httpMessage: null,
[Symbol(alpncallback)]: null,
[Symbol(res)]: null,
[Symbol(verified)]: true,
[Symbol(pendingSession)]: null,
[Symbol(async_id_symbol)]: -1,
[Symbol(kHandle)]: null,
[Symbol(lastWriteQueueSize)]: 0,
[Symbol(timeout)]: Timeout {
_idleTimeout: -1,
_idlePrev: null,
_idleNext: null,
_idleStart: 7754,
_onTimeout: null,
_timerArgs: undefined,
_repeat: null,
_destroyed: true,
[Symbol(refed)]: false,
[Symbol(kHasPrimitive)]: false,
[Symbol(asyncId)]: 1685,
[Symbol(triggerId)]: 1683
},
[Symbol(kBuffer)]: null,
[Symbol(kBufferCb)]: null,
[Symbol(kBufferGen)]: null,
[Symbol(shapeMode)]: true,
[Symbol(kCapture)]: false,
[Symbol(kSetNoDelay)]: false,
[Symbol(kSetKeepAlive)]: true,
[Symbol(kSetKeepAliveInitialDelay)]: 1,
[Symbol(kBytesRead)]: 2466,
[Symbol(kBytesWritten)]: 1275,
[Symbol(connect-options)]: [Object]
},
_header: 'POST /repos/buildmotion/github-motion/releases HTTP/1.1\r\n' +
'Accept: application/json, text/plain, */*\r\n' +
'Content-Type: application/json\r\n' +
'User-Agent: axios/1.7.9\r\n' +
'Content-Length: 772\r\n' +
'Accept-Encoding: gzip, compress, deflate, br\r\n' +
'Host: api.github.com\r\n' +
'Connection: keep-alive\r\n' +
'\r\n',
_keepAliveTimeout: 0,
_onPendingData: [Function: nop],
agent: Agent {
_events: [Object: null prototype],
_eventsCount: 2,
_maxListeners: undefined,
defaultPort: 443,
protocol: 'https:',
options: [Object: null prototype],
requests: [Object: null prototype] {},
sockets: [Object: null prototype] {},
freeSockets: [Object: null prototype] {},
keepAliveMsecs: 1000,
keepAlive: true,
maxSockets: Infinity,
maxFreeSockets: 256,
scheduling: 'lifo',
maxTotalSockets: Infinity,
totalSocketCount: 0,
maxCachedSessions: 100,
_sessionCache: [Object],
[Symbol(shapeMode)]: false,
[Symbol(kCapture)]: false
},
socketPath: undefined,
method: 'POST',
maxHeaderSize: undefined,
insecureHTTPParser: undefined,
joinDuplicateHeaders: undefined,
path: '/repos/buildmotion/github-motion/releases',
_ended: true,
res: IncomingMessage {
_events: [Object],
_readableState: [ReadableState],
_maxListeners: undefined,
socket: null,
httpVersionMajor: 1,
httpVersionMinor: 1,
httpVersion: '1.1',
complete: true,
rawHeaders: [Array],
rawTrailers: [],
joinDuplicateHeaders: undefined,
aborted: false,
upgrade: false,
url: '',
method: null,
statusCode: 404,
statusMessage: 'Not Found',
client: [TLSSocket],
_consuming: false,
_dumped: false,
req: [Circular *1],
_eventsCount: 4,
responseUrl: 'https://api.github.com/repos/buildmotion/github-motion/releases',
redirects: [],
[Symbol(shapeMode)]: true,
[Symbol(kCapture)]: false,
[Symbol(kHeaders)]: [Object],
[Symbol(kHeadersCount)]: 44,
[Symbol(kTrailers)]: null,
[Symbol(kTrailersCount)]: 0
},
aborted: false,
timeoutCb: null,
upgradeOrConnect: false,
parser: null,
maxHeadersCount: null,
reusedSocket: true,
host: 'api.github.com',
protocol: 'https:',
_redirectable: Writable {
_events: [Object],
_writableState: [WritableState],
_maxListeners: undefined,
_options: [Object],
_ended: true,
_ending: true,
_redirectCount: 0,
_redirects: [],
_requestBodyLength: 772,
_requestBodyBuffers: [],
_eventsCount: 3,
_onNativeResponse: [Function (anonymous)],
_currentRequest: [Circular *1],
_currentUrl: 'https://api.github.com/repos/buildmotion/github-motion/releases',
[Symbol(shapeMode)]: true,
[Symbol(kCapture)]: false
},
[Symbol(shapeMode)]: false,
[Symbol(kCapture)]: false,
[Symbol(kBytesWritten)]: 0,
[Symbol(kNeedDrain)]: false,
[Symbol(corked)]: 0,
[Symbol(kOutHeaders)]: [Object: null prototype] {
accept: [Array],
'content-type': [Array],
'user-agent': [Array],
'content-length': [Array],
'accept-encoding': [Array],
host: [Array]
},
[Symbol(errored)]: null,
[Symbol(kHighWaterMark)]: 16384,
[Symbol(kRejectNonStandardBodyWrites)]: false,
[Symbol(kUniqueHeaders)]: null
},
response: {
status: 404,
statusText: 'Not Found',
headers: Object [AxiosHeaders] {
date: 'Fri, 27 Dec 2024 08:02:18 GMT',
'content-type': 'application/json; charset=utf-8',
'x-github-media-type': 'github.v3',
'x-github-api-version-selected': '2022-11-28',
'access-control-expose-headers': 'ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Used, X-RateLimit-Resource, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval, X-GitHub-Media-Type, X-GitHub-SSO, X-GitHub-Request-Id, Deprecation, Sunset',
'access-control-allow-origin': '*',
'strict-transport-security': 'max-age=31536000; includeSubdomains; preload',
'x-frame-options': 'deny',
'x-content-type-options': 'nosniff',
'x-xss-protection': '0',
'referrer-policy': 'origin-when-cross-origin, strict-origin-when-cross-origin',
'content-security-policy': "default-src 'none'",
vary: 'Accept-Encoding, Accept, X-Requested-With',
server: 'github.com',
'x-ratelimit-limit': '60',
'x-ratelimit-remaining': '58',
'x-ratelimit-reset': '1735290138',
'x-ratelimit-resource': 'core',
'x-ratelimit-used': '2',
'content-length': '122',
'x-github-request-id': 'D1D2:321F92:8671174:10C41030:676E5F0A'
},
config: {
transitional: [Object],
adapter: [Array],
transformRequest: [Array],
transformResponse: [Array],
timeout: 0,
xsrfCookieName: 'XSRF-TOKEN',
xsrfHeaderName: 'X-XSRF-TOKEN',
maxContentLength: -1,
maxBodyLength: -1,
env: [Object],
validateStatus: [Function: validateStatus],
headers: [Object [AxiosHeaders]],
method: 'post',
data: '{"tag_name":"v13.0.1","name":"v13.0.1","body":"## 13.0.1 (2024-12-27)\\n\\n\\n### 🩹 Fixes\\n\\n- **nx:** change first-release to false ([517631d](https://github.com/buildmotion/github-motion/commit/517631d))\\n- **nx:** change verbose to false ([a713a0d](https://github.com/buildmotion/github-motion/commit/a713a0d))\\n- **nx:** update version options ([5b56545](https://github.com/buildmotion/github-motion/commit/5b56545))\\n- **nx:** update version options ([933ee76](https://github.com/buildmotion/github-motion/commit/933ee76))\\n- **nx:** back in the hole again ([f8eaf59](https://github.com/buildmotion/github-motion/commit/f8eaf59))\\n\\n### ❤️ Thank You\\n\\n- Matt Vaughn @buildmotion","prerelease":false,"target_commitish":"8a859d8cc59910dcec3e5f7f66aa4a369983928f"}',
baseURL: 'https://api.github.com',
url: '/repos/buildmotion/github-motion/releases'
},
request: <ref *1> ClientRequest {
_events: [Object: null prototype],
_eventsCount: 7,
_maxListeners: undefined,
outputData: [],
outputSize: 0,
writable: true,
destroyed: true,
_last: false,
chunkedEncoding: false,
shouldKeepAlive: true,
maxRequestsOnConnectionReached: false,
_defaultKeepAlive: true,
useChunkedEncodingByDefault: true,
sendDate: false,
_removedConnection: false,
_removedContLen: false,
_removedTE: false,
strictContentLength: false,
_contentLength: '772',
_hasBody: true,
_trailer: '',
finished: true,
_headerSent: true,
_closed: true,
socket: [TLSSocket],
_header: 'POST /repos/buildmotion/github-motion/releases HTTP/1.1\r\n' +
'Accept: application/json, text/plain, */*\r\n' +
'Content-Type: application/json\r\n' +
'User-Agent: axios/1.7.9\r\n' +
'Content-Length: 772\r\n' +
'Accept-Encoding: gzip, compress, deflate, br\r\n' +
'Host: api.github.com\r\n' +
'Connection: keep-alive\r\n' +
'\r\n',
_keepAliveTimeout: 0,
_onPendingData: [Function: nop],
agent: [Agent],
socketPath: undefined,
method: 'POST',
maxHeaderSize: undefined,
insecureHTTPParser: undefined,
joinDuplicateHeaders: undefined,
path: '/repos/buildmotion/github-motion/releases',
_ended: true,
res: [IncomingMessage],
aborted: false,
timeoutCb: null,
upgradeOrConnect: false,
parser: null,
maxHeadersCount: null,
reusedSocket: true,
host: 'api.github.com',
protocol: 'https:',
_redirectable: [Writable],
[Symbol(shapeMode)]: false,
[Symbol(kCapture)]: false,
[Symbol(kBytesWritten)]: 0,
[Symbol(kNeedDrain)]: false,
[Symbol(corked)]: 0,
[Symbol(kOutHeaders)]: [Object: null prototype],
[Symbol(errored)]: null,
[Symbol(kHighWaterMark)]: 16384,
[Symbol(kRejectNonStandardBodyWrites)]: false,
[Symbol(kUniqueHeaders)]: null
},
data: {
message: 'Not Found',
documentation_url: 'https://docs.github.com/rest/releases/releases#create-a-release',
status: '404'
}
},
status: 404
}
Follow up in the browser to manually create the release.
✔ Do you want to publish these versions? (y/N) · true
[NX CLOUD] Verifying current cloud bundle
[NX CLOUD] A local bundle currently exists: {
version: '2412.18.5.hotfix5',
fullPath: '/Users/valencia/work/github/buildmotion-github-motion/.nx/cache/cloud/2412.18.5.hotfix5'
}
[NX CLOUD] Last verification was within the past 30 minutes, will not verify this time
[NX CLOUD] Done: /Users/valencia/work/github/buildmotion-github-motion/.nx/cache/cloud/2412.18.5.hotfix5
NX Running target nx-release-publish for project github-motion:
- github-motion
With additional flags:
--firstRelease=true
————————————————————————————————————————————————————————————————————————————— ———————————————————————————————————————————————————————————————————————————————————————————
[Nx Cloud Debug] Attempting to acquire filesystem lock with path: /var/folders/r5/1trjjx6939zdgn94wv_gv7tm0000gn/T/client-instance-id.lock
[Nx Cloud Debug] Failed to create folder lock at path: /var/folders/r5/1trjjx6939zdgn94wv_gv7tm0000gn/T/client-instance-id.lock
[Nx Cloud] Unable to detect a VCS context from the environment.
NX RunStart
{
"meta": {},
"branch": null,
"runGroup": "8a859d8cc59910dcec3e5f7f66aa4a369983928f",
"ciExecutionId": null,
"ciExecutionEnv": "",
"hashes": [
"13656818729309818022"
],
"machineInfo": {
"machineId": "3OeIVTYRErdeo7I4W9L3Lg==",
"platform": "darwin",
"version": "Darwin Kernel Version 24.1.0: Thu Oct 10 21:05:14 PDT 2024; root:xnu-11215.41.3~2/RELEASE_ARM64_T8103",
"cpuCores": 8
},
"vcsContext": null,
"clientInstanceSource": "CLOUD_RUNNER",
"clientInstanceId": "272b0569-a42c-46ee-8fab-b24985eed48e"
}
RunStart duration: 111
> nx run github-motion:nx-release-publish
Debugger listening on ws://127.0.0.1:53824/d3e33956-ebef-4dbc-acbb-faed4593e3d8
For help, see: https://nodejs.org/en/docs/inspector
Debugger attached.
Skipped npm view because --first-release was set
📦 @buildmotion/github-motion@13.0.0
=== Tarball Contents ===
361B CHANGELOG.md
261B README.md
275B executors.json
289B package.json
209B src/executors/github-repository/executor.d.ts
1.1kB src/executors/github-repository/executor.js
1.2kB src/executors/github-repository/executor.js.map
77B src/executors/github-repository/schema.d.ts
384B src/executors/github-repository/schema.json
0B src/index.d.ts
33B src/index.js
134B src/index.js.map
=== Tarball Details ===
name: @buildmotion/github-motion
version: 13.0.0
filename: buildmotion-github-motion-13.0.0.tgz
package size: 2.0 kB
unpacked size: 4.2 kB
shasum: 25ab50d1b510162c25c16f65f00beeb8991b24dd
integrity: sha512-4zWymylXxIJnb[...]lYt2qJ9Mvc5pA==
total files: 12
Published to https://npm.pkg.github.com with tag "next"
Waiting for the debugger to disconnect...
————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————
NX Successfully ran target nx-release-publish for project github-motion
NX Storing terminal outputs for github-motion:nx-release-publish with hash 13656818729309818022
View logs and investigate cache misses at https://nx.app/runs/gBmTX7L28G
Debugger listening on ws://127.0.0.1:53839/775ed71c-6d4d-42b5-af36-783c490a3933
For help, see: https://nodejs.org/en/docs/inspector
Debugger attached.
Waiting for the debugger to disconnect...
Waiting for the debugger to disconnect...
✨ Done in 52.90s.
Code Review
Analysis and Outline of the Nx Release Process
Context Overview
The Nx release process described here involves multiple steps, primarily using the Nx Release CLI command (nx release) to automate the package version update, changelog generation, and publishing process.
Sequence of Operations
-
Preparation and Configuration Reading
- Load configuration from
nx.jsonto understand which projects to release and the release strategy. - Set up the
ReleaseVersionGeneratorSchemausing this configuration.
- Load configuration from
-
Version Resolution
- Determine the current version of packages using the specified
currentVersionResolver(e.g.,git-tag). - Validate or resolve the version specifier based on the chosen strategy (e.g.,
conventional-commits).
- Determine the current version of packages using the specified
-
Version Bumping
- Calculate the new version for each project using the resolved specifier and bump the version in
package.json. - Write the new version back to the respective
package.jsonfiles.
- Calculate the new version for each project using the resolved specifier and bump the version in
-
Changelog Generation
- Generate a changelog entry for the new version using the specified changelog configuration.
-
Commit and Tagging
- Stage the modified files and commit changes to git with a message reflecting the version increment.
- Tag the commit with the new version in git.
-
Publishing
- Run the
nx-release-publishexecutor to publish the updated packages to the specified registry.
- Run the
-
Error Handling and GitHub Release
- If configured, create a GitHub release for the new version.
-
Manual Follow-Up (if errors occurred)
- If the automated release fails (e.g., due to API issues), prompt the user for manual follow-up actions.
Detailed Steps with Source Code Reference
Step 1: Preparation and Configuration Reading
- Code Reference: This is handled implicitly when the
nx releasecommand is invoked. - Description: At this stage, the Nx CLI reads the
nx.jsonconfiguration to determine the workflow. This includes setting the projects to release, version resolution strategy, and changelog rules.
Step 2: Version Resolution
- Code Reference: Look at the
releaseVersionGeneratorfunction in therelease-version.tsfile. - Variables/Inputs:
options.currentVersionResolver,options.specifierSource,projects. - Description: Here, we determine the current version of the packages based on the specified resolver (e.g.,
git-tag) and validate the specifier.
Step 3: Version Bumping
- Code Reference: The
deriveNewSemverVersionfunction and related logic inreleaseVersionGenerator. - Variables/Inputs:
projects,specifier,currentVersion. - Description: This involves computing the new version number and updating the
package.jsonfiles accordingly.
Step 4: Changelog Generation
- Code Reference: Changelog generation occurs in the
conventional-commitsor by custom logic in the workflow derived from nx.json. - Variables/Inputs:
options.changelog,projects. - Description: A changelog entry is created to document changes introduced in this version.
Step 5: Commit and Tagging
- Code Reference: Git operations are performed as part of the larger
releaseVersionGeneratorworkflow. - Variables/Inputs:
newVersion,spec. - Description: Files with version updates are committed, and a corresponding version tag is created in git.
Step 6: Publishing
- Code Reference: The
nx-release-publishexecutor setup and invocation. - Variables/Inputs:
projects,options.registry. - Description: Publishes the updated package versions to the registry specified in the configuration.
Step 7: Error Handling and GitHub Release
- Code Reference: Error handling logic in
handleErrorsand potential retry/confirmation prompts. - Description: Attempts to create or update a GitHub release with the new version if configured, handling any API errors gracefully.
Suggestions for Improvement
-
Error Handling: Improve error messages to provide direct instructions for common issues, such as missing configurations or API credentials.
-
Logging Enhancements: Implement a more structured logging system to facilitate debugging, and roll it out to the changelog and version bumping logic.
-
Support for Additional Resolvers: Expand support beyond the current set of version-resolving strategies, possibly including some additional insights from recent commits if applicable.
-
Plugin Architecture: Consider a plugin-based architecture for custom
releaseprocesses, allowing users to define custom steps or custom version resolution strategies.
These detailed insights and improvements aim to enhance usability and reliability in complex monorepo setups which Nx targets.