Skip to main content

Publishing Packages with Nx Release

Package Publishing Abstract

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:

  1. A .npmrc file to configure the package registry.
  2. A release configuration in the nx.json file.
  3. A nx:pub script in the package.json file.
  4. An nx-release-publish target in target project.json file(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.

See: Nx Release: Getting Started

Nx Release Workflow

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.

  1. 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.
  2. //npm.pkg.github.com/:_authToken=YOUR_GITHUB_TOKEN:

    • This line provides authentication information for the GitHub package registry. :_authToken=YOUR_GITHUB_TOKEN is a placeholder for your actual GitHub token, which is necessary for authentication. This token should have the appropriate scopes (usually repo and write:packages) to allow publishing and accessing private packages.
  3. @buildmotion:registry=https://npm.pkg.github.com/:

    • This line specifies that packages scoped under @buildmotion should be fetched from the GitHub registry. It's a scoped registry setting, which means that if you publish or fetch packages with the @buildmotion prefix, 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.

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

  1. Preparation and Configuration Reading

    • Load configuration from nx.json to understand which projects to release and the release strategy.
    • Set up the ReleaseVersionGeneratorSchema using this configuration.
  2. 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).
  3. 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.json files.
  4. Changelog Generation

    • Generate a changelog entry for the new version using the specified changelog configuration.
  5. 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.
  6. Publishing

    • Run the nx-release-publish executor to publish the updated packages to the specified registry.
  7. Error Handling and GitHub Release

    • If configured, create a GitHub release for the new version.
  8. 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 release command is invoked.
  • Description: At this stage, the Nx CLI reads the nx.json configuration 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 releaseVersionGenerator function in the release-version.ts file.
  • 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 deriveNewSemverVersion function and related logic in releaseVersionGenerator.
  • Variables/Inputs: projects, specifier, currentVersion.
  • Description: This involves computing the new version number and updating the package.json files accordingly.

Step 4: Changelog Generation

  • Code Reference: Changelog generation occurs in the conventional-commits or 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 releaseVersionGenerator workflow.
  • 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-publish executor 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 handleErrors and 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

  1. Error Handling: Improve error messages to provide direct instructions for common issues, such as missing configurations or API credentials.

  2. Logging Enhancements: Implement a more structured logging system to facilitate debugging, and roll it out to the changelog and version bumping logic.

  3. Support for Additional Resolvers: Expand support beyond the current set of version-resolving strategies, possibly including some additional insights from recent commits if applicable.

  4. Plugin Architecture: Consider a plugin-based architecture for custom release processes, 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.