Skip to content

Commit 07e7b45

Browse files
committed
Add fetchTypesPackageVersionInfo() tests
1 parent b7dd694 commit 07e7b45

File tree

3 files changed

+96
-16
lines changed

3 files changed

+96
-16
lines changed

packages/publisher/src/calculate-versions.ts

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -42,9 +42,9 @@ async function computeAndSaveChangedPackages(
4242
async function computeChangedPackages(allPackages: AllPackages, log: LoggerWithErrors): Promise<ChangedPackages> {
4343
log.info("# Computing changed packages...");
4444
const changedTypings = await mapDefinedAsync(allPackages.allTypings(), async (pkg) => {
45-
const { version, needsPublish } = await fetchTypesPackageVersionInfo(pkg, /*publish*/ true, log);
46-
if (needsPublish) {
47-
log.info(`Need to publish: ${pkg.desc}@${version}`);
45+
const { incipientVersion } = await fetchTypesPackageVersionInfo(pkg, log);
46+
if (incipientVersion) {
47+
log.info(`Need to publish: ${pkg.desc}@${incipientVersion}`);
4848
for (const { name } of pkg.packageJsonDependencies) {
4949
await pacote.manifest(name, { cache: defaultCacheDir }).catch((cause) => {
5050
throw cause.code === "E404"
@@ -57,8 +57,12 @@ async function computeChangedPackages(allPackages: AllPackages, log: LoggerWithE
5757
}
5858
const latestVersion = pkg.isLatest
5959
? undefined
60-
: (await fetchTypesPackageVersionInfo(allPackages.getLatest(pkg), /*publish*/ true)).version;
61-
return { pkg, version, latestVersion };
60+
: await fetchTypesPackageVersionInfo(allPackages.getLatest(pkg), log);
61+
return {
62+
pkg,
63+
version: incipientVersion,
64+
latestVersion: latestVersion?.incipientVersion || latestVersion?.publishedVersion,
65+
};
6266
}
6367
return undefined;
6468
});

packages/retag/src/index.ts

Lines changed: 24 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -62,14 +62,18 @@ async function tag(dry: boolean, nProcesses: number, name?: string) {
6262
if (name) {
6363
const pkg = await AllPackages.readSingle(name);
6464
const version = await getLatestTypingVersion(pkg);
65-
await updateTypeScriptVersionTags(pkg, version, publishClient, consoleLogger.info, dry);
66-
await updateLatestTag(pkg.fullNpmName, version, publishClient, consoleLogger.info, dry);
65+
if (version) {
66+
await updateTypeScriptVersionTags(pkg, version, publishClient, consoleLogger.info, dry);
67+
await updateLatestTag(pkg.fullNpmName, version, publishClient, consoleLogger.info, dry);
68+
}
6769
} else {
6870
await nAtATime(10, await AllPackages.readLatestTypings(), async (pkg) => {
6971
// Only update tags for the latest version of the package.
7072
const version = await getLatestTypingVersion(pkg);
71-
await updateTypeScriptVersionTags(pkg, version, publishClient, consoleLogger.info, dry);
72-
await updateLatestTag(pkg.fullNpmName, version, publishClient, consoleLogger.info, dry);
73+
if (version) {
74+
await updateTypeScriptVersionTags(pkg, version, publishClient, consoleLogger.info, dry);
75+
await updateLatestTag(pkg.fullNpmName, version, publishClient, consoleLogger.info, dry);
76+
}
7377
});
7478
}
7579
// Don't tag notNeeded packages
@@ -109,23 +113,28 @@ export async function updateLatestTag(
109113
}
110114
}
111115

112-
export async function getLatestTypingVersion(pkg: TypingsData): Promise<string> {
113-
return (await fetchTypesPackageVersionInfo(pkg, /*publish*/ false)).version;
116+
export async function getLatestTypingVersion(pkg: TypingsData): Promise<string | undefined> {
117+
return (await fetchTypesPackageVersionInfo(pkg)).publishedVersion;
114118
}
115119

120+
/**
121+
* Used for two purposes: to determine whether a @types package has changed since it was last published, and to get a package's version in the npm registry.
122+
* We ignore whether the cached metadata is fresh or stale: We always revalidate if the content hashes differ (fresh or not) and never revalidate if they match (stale or not).
123+
* Because the decider is the content hash, this isn't applicable to other npm packages.
124+
* Target JS packages and not-needed stubs don't have content hashes.
125+
*/
116126
export async function fetchTypesPackageVersionInfo(
117127
pkg: TypingsData,
118-
canPublish: boolean,
119128
log?: LoggerWithErrors
120-
): Promise<{ version: string; needsPublish: boolean }> {
129+
): Promise<{ publishedVersion?: string; incipientVersion?: string }> {
121130
const spec = `${pkg.fullNpmName}@~${pkg.major}.${pkg.minor}`;
122131
let info = await pacote
123132
.manifest(spec, { cache: defaultCacheDir, fullMetadata: true, preferOffline: true })
124133
.catch((cause) => {
125134
if (cause.code !== "E404" && cause.code !== "ETARGET") throw cause;
126135
});
127136
if (!info) {
128-
return { version: `${pkg.major}.${pkg.minor}.0`, needsPublish: true };
137+
return { incipientVersion: `${pkg.major}.${pkg.minor}.0` };
129138
}
130139
if (info._cached && info.typesPublisherContentHash !== pkg.contentHash) {
131140
if (log) {
@@ -141,6 +150,10 @@ export async function fetchTypesPackageVersionInfo(
141150
`Package ${pkg.name} has been deprecated, so we shouldn't have parsed it. Was it re-added?`
142151
);
143152
}
144-
const needsPublish = canPublish && pkg.contentHash !== info.typesPublisherContentHash;
145-
return { version: needsPublish ? semver.inc(info.version, "patch")! : info.version, needsPublish };
153+
return {
154+
publishedVersion: info.version,
155+
...(((pkg.contentHash === info.typesPublisherContentHash) as {}) || {
156+
incipientVersion: semver.inc(info.version, "patch")!,
157+
}),
158+
};
146159
}

packages/retag/test/index.test.ts

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
import * as util from "util";
2+
import { TypingsData } from "@definitelytyped/definitions-parser";
3+
import { fetchTypesPackageVersionInfo } from "../src/";
4+
5+
jest.mock("pacote", () => ({
6+
async manifest(spec: string) {
7+
switch (spec) {
8+
case "@types/already-published@~1.2": // An already-published @types package.
9+
return { version: "1.2.3", typesPublisherContentHash: "already-published-content-hash" };
10+
case "@types/first-publish@~1.2": // A new, not-yet-published @types package.
11+
// eslint-disable-next-line no-throw-literal
12+
throw { code: "E404" };
13+
}
14+
throw new Error(`Unexpected npm registry fetch: ${util.inspect(spec)}`);
15+
},
16+
}));
17+
18+
const unchanged = new TypingsData(
19+
{
20+
typingsPackageName: "already-published",
21+
libraryMajorVersion: 1,
22+
libraryMinorVersion: 2,
23+
contentHash: "already-published-content-hash",
24+
} as never,
25+
/*isLatest*/ true
26+
);
27+
const changed = new TypingsData(
28+
{
29+
typingsPackageName: "already-published",
30+
libraryMajorVersion: 1,
31+
libraryMinorVersion: 2,
32+
contentHash: "changed-content-hash",
33+
} as never,
34+
/*isLatest*/ true
35+
);
36+
const firstPublish = new TypingsData(
37+
{
38+
typingsPackageName: "first-publish",
39+
libraryMajorVersion: 1,
40+
libraryMinorVersion: 2,
41+
contentHash: "first-publish-content-hash",
42+
} as never,
43+
/*isLatest*/ true
44+
);
45+
46+
test("Increments already-published patch version", () => {
47+
return expect(fetchTypesPackageVersionInfo(changed)).resolves.toEqual({
48+
publishedVersion: "1.2.3",
49+
incipientVersion: "1.2.4",
50+
});
51+
});
52+
53+
test("Doesn't increment unchanged @types package version", () => {
54+
return expect(fetchTypesPackageVersionInfo(unchanged)).resolves.toEqual({
55+
publishedVersion: "1.2.3",
56+
});
57+
});
58+
59+
test("First-publish version", () => {
60+
return expect(fetchTypesPackageVersionInfo(firstPublish)).resolves.toEqual({
61+
incipientVersion: "1.2.0",
62+
});
63+
});

0 commit comments

Comments
 (0)