Skip to content

Commit d483e8c

Browse files
make it work for monorepos
1 parent cab45ea commit d483e8c

File tree

1 file changed

+70
-11
lines changed

1 file changed

+70
-11
lines changed

plugins/update-repo/src/index.ts

Lines changed: 70 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -6,16 +6,30 @@ import path from "path";
66
import parseGitHubUrl from "parse-github-url";
77
import * as t from "io-ts";
88

9+
/** Determine if the current directory is an NPM package */
10+
const isNpmPackage = (dir?: string) =>
11+
fs.existsSync(dir ? path.join(dir, "package.json") : "package.json");
12+
13+
/** Determine if the current directory is an lerna monorepo */
14+
const isLernaMonorepo = (dir?: string) =>
15+
fs.existsSync(dir ? path.join(dir, "package.json") : "package.json");
16+
17+
/** Read a NPM package.json */
18+
const readPackageJson = (dir?: string) =>
19+
JSON.parse(
20+
fs.readFileSync(dir ? path.join(dir, "package.json") : "package.json", {
21+
encoding: "utf-8",
22+
})
23+
);
24+
925
/** Update package in an npm package */
1026
const updateNpmPackage = (
1127
dir: string,
1228
name: string,
1329
version: string,
1430
isYarn: boolean
1531
) => {
16-
const { dependencies, devDependencies } = JSON.parse(
17-
fs.readFileSync(path.join(dir, "package.json"), { encoding: "utf-8" })
18-
);
32+
const { dependencies, devDependencies } = readPackageJson(dir);
1933

2034
const isDep = Boolean(dependencies[name]);
2135
const isDevDep = Boolean(devDependencies[name]);
@@ -30,21 +44,65 @@ const updateNpmPackage = (
3044
}
3145
};
3246

47+
/** Update a dependency in a monorepo */
48+
const updateLernaMonorepo = (dir: string, name: string, version: string) =>
49+
execSync(
50+
`npx lernaupdate --non-interactive --dependency ${name}@${version}`,
51+
{ cwd: dir }
52+
);
53+
54+
/** Update a dependency in a JS project */
55+
const updateJsProject = (dir: string, name: string, version: string) => {
56+
if (isLernaMonorepo()) {
57+
updateLernaMonorepo(dir, name, version);
58+
} else {
59+
const hasLock = fs.existsSync("yarn.lock");
60+
updateNpmPackage(dir, name, version, hasLock);
61+
}
62+
};
63+
64+
interface LernaPackage {
65+
/** The name of the package */
66+
name: string;
67+
/** The current version of the package */
68+
version: string;
69+
/** Whether the package is private */
70+
private: boolean;
71+
}
72+
3373
/** Get a package name + updater to use with updateRepo */
34-
function getUpdater(): [string, (dir: string) => void] | undefined {
35-
if (fs.existsSync("package.json")) {
36-
const { name, version } = JSON.parse(
37-
fs.readFileSync("package.json", { encoding: "utf-8" })
74+
async function getUpdater(
75+
auto: Auto
76+
): Promise<[string, (dir: string) => void] | undefined> {
77+
// We are in a lerna monorepo so we should try to make updates for all of the
78+
// packages in it. We assume that the thing we are updating is also a JS project
79+
if (isLernaMonorepo()) {
80+
const { name } = readPackageJson();
81+
// Since we have already tagged the release we need to calculate from the previous tag
82+
const lastRelease = await auto.git!.getPreviousTagInBranch();
83+
const changedPackages: LernaPackage[] = JSON.parse(
84+
execSync(`lerna ls --json --since ${lastRelease}`, { encoding: "utf8" })
3885
);
3986

4087
return [
4188
name,
4289
(dir) => {
43-
const hasLock = fs.existsSync("yarn.lock");
44-
updateNpmPackage(dir, name, version, hasLock);
90+
changedPackages.forEach((p) => {
91+
if (p.private) {
92+
return;
93+
}
94+
95+
updateJsProject(dir, p.name, p.version);
96+
});
4597
},
4698
];
4799
}
100+
101+
// We are in NPM package. We assume that the thing we are updating is also a JS project.
102+
if (isNpmPackage()) {
103+
const { name, version } = readPackageJson();
104+
return [name, (dir) => updateJsProject(dir, name, version)];
105+
}
48106
}
49107

50108
const optionalOptions = t.interface({
@@ -102,14 +160,15 @@ export default class UpdateRepoPlugin implements IPlugin {
102160
}
103161

104162
for await (const config of this.options) {
105-
await this.updateRepo(newVersion, releaseNotes, config);
163+
await this.updateRepo(auto, newVersion, releaseNotes, config);
106164
}
107165
}
108166
);
109167
}
110168

111169
/** Open a pr with a dependency update */
112170
private async updateRepo(
171+
auto: Auto,
113172
newVersion: string,
114173
releaseNotes: string,
115174
config: UpdateRepoConfiguration
@@ -122,7 +181,7 @@ export default class UpdateRepoPlugin implements IPlugin {
122181
);
123182
}
124183

125-
const updater = getUpdater();
184+
const updater = await getUpdater(auto);
126185

127186
if (!updater) {
128187
throw new Error(

0 commit comments

Comments
 (0)