Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add root package-lock.json support #2162

Merged
merged 6 commits into from
Jan 2, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading