Skip to content

Commit

Permalink
feat(node-workspace): add root package-lock.json (#2162)
Browse files Browse the repository at this point in the history
  • Loading branch information
tada5hi authored Jan 2, 2024
1 parent deeef9d commit 8728d4a
Show file tree
Hide file tree
Showing 8 changed files with 150 additions and 15 deletions.
17 changes: 16 additions & 1 deletion __snapshots__/package-lock-json.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,24 @@ exports['PackageLockJson updateContent v3 monorepo updates the package version 1
"name": "release-please",
"version": "14.0.0"
},
"node_modules/release-please-foo": {
"resolved": "packages/foo",
"link": true
},
"node_modules/release-please-bar": {
"resolved": "packages/bar",
"link": true
},
"packages/foo": {
"name": "release-please-foo",
"version": "2.0.0"
"version": "2.0.0",
"dependencies": {
"release-please-bar": "3.0.0"
}
},
"packages/bar": {
"name": "release-please-bar",
"version": "3.0.0"
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
"scripts": {
"test": "cross-env ENVIRONMENT=test LC_ALL=en c8 mocha --node-option no-experimental-fetch --recursive --timeout=5000 build/test",
"docs": "echo add docs tests",
"test:snap": "SNAPSHOT_UPDATE=1 LC_ALL=en npm test",
"test:snap": "cross-env SNAPSHOT_UPDATE=1 LC_ALL=en npm test",
"clean": "gts clean",
"prepare": "npm run compile",
"lint": "gts check",
Expand Down
51 changes: 50 additions & 1 deletion src/plugins/node-workspace.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

import {GitHub} from '../github';
import {CandidateReleasePullRequest, RepositoryConfig} from '../manifest';
import {PackageLockJson} from '../updaters/node/package-lock-json';
import {Version, VersionsMap} from '../version';
import {PullRequestTitle} from '../util/pull-request-title';
import {PullRequestBody} from '../util/pull-request-body';
Expand Down Expand Up @@ -82,6 +83,7 @@ export class NodeWorkspace extends WorkspacePlugin<Package> {
options: NodeWorkspaceOptions = {}
) {
super(github, targetBranch, repositoryConfig, options);

this.alwaysLinkLocal = options.alwaysLinkLocal === false ? false : true;
this.updatePeerDependencies = options.updatePeerDependencies === true;
}
Expand Down Expand Up @@ -201,6 +203,13 @@ export class NodeWorkspace extends WorkspacePlugin<Package> {
existingCandidate.pullRequest.updates.map(update => {
if (update.path === addPath(existingCandidate.path, 'package.json')) {
update.updater = new CompositeUpdater(update.updater, updater);
} else if (
update.path === addPath(existingCandidate.path, 'package-lock.json')
) {
update.updater = new PackageLockJson({
version: newVersion,
versionsMap: updatedVersions,
});
} else if (update.updater instanceof Changelog) {
if (dependencyNotes) {
update.updater.changelogEntry =
Expand Down Expand Up @@ -303,6 +312,14 @@ export class NodeWorkspace extends WorkspacePlugin<Package> {
versionsMap: updatedVersions,
}),
},
{
path: addPath(updatedPackage.path, 'package-lock.json'),
createIfMissing: false,
updater: new PackageJson({
version: newVersion,
versionsMap: updatedVersions,
}),
},
{
path: addPath(updatedPackage.path, 'CHANGELOG.md'),
createIfMissing: false,
Expand Down Expand Up @@ -334,7 +351,39 @@ export class NodeWorkspace extends WorkspacePlugin<Package> {
candidates: CandidateReleasePullRequest[],
_updatedVersions: VersionsMap
): CandidateReleasePullRequest[] {
// NOP for node workspaces
if (candidates.length === 0) {
return candidates;
}

const [candidate] = candidates;

// check for root lock file in pull request
let hasRootLockFile: boolean | undefined;
for (let i = 0; i < candidate.pullRequest.updates.length; i++) {
if (
candidate.pullRequest.updates[i].path === '.package-lock.json' ||
candidate.pullRequest.updates[i].path === './package-lock.json' ||
candidate.pullRequest.updates[i].path === 'package-lock.json' ||
candidate.pullRequest.updates[i].path === '/package-lock.json'
) {
hasRootLockFile = true;
break;
}
}

// if there is a root lock file, then there is no additional pull request update necessary.
if (hasRootLockFile) {
return candidates;
}

candidate.pullRequest.updates.push({
path: 'package-lock.json',
createIfMissing: false,
updater: new PackageLockJson({
versionsMap: _updatedVersions,
}),
});

return candidates;
}

Expand Down
2 changes: 2 additions & 0 deletions src/strategies/node.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ export class Node extends BaseStrategy {
): Promise<Update[]> {
const updates: Update[] = [];
const version = options.newVersion;
const versionsMap = options.versionsMap;
const packageName = (await this.getPackageName()) ?? '';
const lockFiles = ['package-lock.json', 'npm-shrinkwrap.json'];
lockFiles.forEach(lockFile => {
Expand All @@ -39,6 +40,7 @@ export class Node extends BaseStrategy {
createIfMissing: false,
updater: new PackageLockJson({
version,
versionsMap,
}),
});
});
Expand Down
15 changes: 9 additions & 6 deletions src/updaters/node/package-json.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,13 @@

import {jsonStringify} from '../../util/json-stringify';
import {logger as defaultLogger, Logger} from '../../util/logger';
import {Version, VersionsMap} from '../../version';
import {DefaultUpdater} from '../default';
import {VersionsMap, Version} from '../../version';

type LockFile = {
export type PackageJsonDescriptor = {
name?: string;
resolved?: string;
link?: boolean;
version: string;
dependencies?: Record<string, string>;
devDependencies?: Record<string, string>;
Expand All @@ -32,10 +35,11 @@ export class PackageJson extends DefaultUpdater {
/**
* Given initial file contents, return updated contents.
* @param {string} content The initial content
* @param logger
* @returns {string} The updated content
*/
updateContent(content: string, logger: Logger = defaultLogger): string {
const parsed = JSON.parse(content) as LockFile;
const parsed = JSON.parse(content) as PackageJsonDescriptor;
logger.info(`updating from ${parsed.version} to ${this.version}`);
parsed.version = this.version.toString();

Expand Down Expand Up @@ -98,16 +102,15 @@ export function newVersionWithRange(
* where the key is the dependency name and the value is the dependency range
* @param {VersionsMap} updatedVersions Map of new versions (without dependency range prefixes)
*/
function updateDependencies(
export function updateDependencies(
dependencies: Record<string, string>,
updatedVersions: VersionsMap
) {
for (const depName of Object.keys(dependencies)) {
const newVersion = updatedVersions.get(depName);
if (newVersion) {
const oldVersion = dependencies[depName];
const newVersionString = newVersionWithRange(oldVersion, newVersion);
dependencies[depName] = newVersionString;
dependencies[depName] = newVersionWithRange(oldVersion, newVersion);
}
}
}
62 changes: 56 additions & 6 deletions src/updaters/node/package-lock-json.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,30 +12,80 @@
// See the License for the specific language governing permissions and
// limitations under the License.

import {Updater} from '../../update';
import {jsonStringify} from '../../util/json-stringify';
import {logger as defaultLogger, Logger} from '../../util/logger';
import {DefaultUpdater} from '../default';
import {Version, VersionsMap} from '../../version';
import {UpdateOptions} from '../default';
import {PackageJsonDescriptor, updateDependencies} from './package-json';

type LockFileV2 = {
version: string;
lockfileVersion?: number;
packages: Record<string, {version: string; name: string}>;
packages: Record<string, PackageJsonDescriptor>;
};

/**
* Updates a Node.js package-lock.json file's version and '' package
* version (for a v2 lock file).
*/
export class PackageLockJson extends DefaultUpdater {
export class PackageLockJson implements Updater {
version?: Version;
versionsMap?: VersionsMap;
constructor(options: Partial<UpdateOptions>) {
this.version = options.version;
this.versionsMap = options.versionsMap;
}
updateContent(content: string, logger: Logger = defaultLogger): string {
const parsed = JSON.parse(content) as LockFileV2;
logger.info(`updating from ${parsed.version} to ${this.version}`);
parsed.version = this.version.toString();
if (this.version) {
logger.info(`updating from ${parsed.version} to ${this.version}`);
parsed.version = this.version.toString();
}

if (parsed.lockfileVersion === 2 || parsed.lockfileVersion === 3) {
parsed.packages[''].version = this.version.toString();
if (this.version) {
parsed.packages[''].version = this.version.toString();
}

if (this.versionsMap) {
this.versionsMap.forEach((version, name) => {
let pkg = parsed.packages['node_modules/' + name];
if (!pkg) {
return;
}

// @see https://docs.npmjs.com/cli/v10/configuring-npm/package-lock-json#packages
if (pkg.link && pkg.resolved) {
pkg = parsed.packages[pkg.resolved];
if (!pkg) {
return;
}
}

pkg.version = version.toString();

if (pkg.dependencies) {
updateDependencies(pkg.dependencies, this.versionsMap!);
}
if (pkg.devDependencies) {
updateDependencies(pkg.devDependencies, this.versionsMap!);
}
if (pkg.peerDependencies) {
updateDependencies(pkg.peerDependencies, this.versionsMap!);
}
if (pkg.optionalDependencies) {
updateDependencies(pkg.optionalDependencies, this.versionsMap!);
}
});
}
}
if (this.versionsMap) {
for (const [, obj] of Object.entries(parsed.packages)) {
if (!obj.name) {
continue;
}

const ver = this.versionsMap.get(obj.name);
if (ver) {
obj.version = ver.toString();
Expand Down
15 changes: 15 additions & 0 deletions test/updaters/fixtures/package-lock-v3-workspace.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,23 @@
"name": "release-please",
"version": "11.1.0"
},
"node_modules/release-please-foo": {
"resolved": "packages/foo",
"link": true
},
"node_modules/release-please-bar": {
"resolved": "packages/bar",
"link": true
},
"packages/foo": {
"name": "release-please-foo",
"version": "1.0.0",
"dependencies": {
"release-please-bar": "1.0.0"
}
},
"packages/bar": {
"name": "release-please-bar",
"version": "1.0.0"
}
}
Expand Down
1 change: 1 addition & 0 deletions test/updaters/package-lock-json.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ describe('PackageLockJson', () => {
);
const versionsMap = new Map();
versionsMap.set('release-please-foo', new Version(2, 0, 0));
versionsMap.set('release-please-bar', new Version(3, 0, 0));
const packageJson = new PackageLockJson({
version: Version.parse('14.0.0'),
versionsMap,
Expand Down

0 comments on commit 8728d4a

Please sign in to comment.