Skip to content

Commit 5c97a84

Browse files
committed
Add fetchTypesPackageVersionInfo() tests
1 parent 39e0d00 commit 5c97a84

File tree

3 files changed

+97
-20
lines changed

3 files changed

+97
-20
lines changed

packages/publisher/src/calculate-versions.ts

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -48,9 +48,9 @@ async function computeAndSaveChangedPackages(
4848
async function computeChangedPackages(allPackages: AllPackages, log: LoggerWithErrors): Promise<ChangedPackages> {
4949
log.info("# Computing changed packages...");
5050
const changedTypings = await mapDefinedAsync(allPackages.allTypings(), async (pkg) => {
51-
const { version, needsPublish } = await fetchTypesPackageVersionInfo(pkg, /*publish*/ true, log);
52-
if (needsPublish) {
53-
log.info(`Need to publish: ${pkg.desc}@${version}`);
51+
const { incipientVersion } = await fetchTypesPackageVersionInfo(pkg, log);
52+
if (incipientVersion) {
53+
log.info(`Need to publish: ${pkg.desc}@${incipientVersion}`);
5454
for (const { name } of pkg.packageJsonDependencies) {
5555
// Assert that dependencies exist on npm.
5656
// Also checked when we install the dependencies, in dtslint-runner.
@@ -65,8 +65,12 @@ async function computeChangedPackages(allPackages: AllPackages, log: LoggerWithE
6565
}
6666
const latestVersion = pkg.isLatest
6767
? undefined
68-
: (await fetchTypesPackageVersionInfo(allPackages.getLatest(pkg), /*publish*/ true)).version;
69-
return { pkg, version, latestVersion };
68+
: await fetchTypesPackageVersionInfo(allPackages.getLatest(pkg), log);
69+
return {
70+
pkg,
71+
version: incipientVersion,
72+
latestVersion: latestVersion?.incipientVersion || latestVersion?.maxVersion,
73+
};
7074
}
7175
return undefined;
7276
});

packages/retag/src/index.ts

Lines changed: 24 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -60,18 +60,22 @@ async function tag(dry: boolean, nProcesses: number, name?: string) {
6060
const publishClient = await NpmPublishClient.create(token, {});
6161
if (name) {
6262
const pkg = await AllPackages.readSingle(name);
63-
const version = await getLatestTypingVersion(pkg);
64-
await updateTypeScriptVersionTags(pkg, version, publishClient, consoleLogger.info, dry);
65-
await updateLatestTag(pkg.fullNpmName, version, publishClient, consoleLogger.info, dry);
63+
const { maxVersion } = await fetchTypesPackageVersionInfo(pkg);
64+
if (maxVersion) {
65+
await updateTypeScriptVersionTags(pkg, maxVersion, publishClient, consoleLogger.info, dry);
66+
await updateLatestTag(pkg.fullNpmName, maxVersion, publishClient, consoleLogger.info, dry);
67+
}
6668
} else {
6769
await Promise.all(
6870
(
6971
await AllPackages.readLatestTypings()
7072
).map(async (pkg) => {
7173
// Only update tags for the latest version of the package.
72-
const version = await getLatestTypingVersion(pkg);
73-
await updateTypeScriptVersionTags(pkg, version, publishClient, consoleLogger.info, dry);
74-
await updateLatestTag(pkg.fullNpmName, version, publishClient, consoleLogger.info, dry);
74+
const { maxVersion } = await fetchTypesPackageVersionInfo(pkg);
75+
if (maxVersion) {
76+
await updateTypeScriptVersionTags(pkg, maxVersion, publishClient, consoleLogger.info, dry);
77+
await updateLatestTag(pkg.fullNpmName, maxVersion, publishClient, consoleLogger.info, dry);
78+
}
7579
})
7680
);
7781
}
@@ -112,15 +116,16 @@ export async function updateLatestTag(
112116
}
113117
}
114118

115-
export async function getLatestTypingVersion(pkg: TypingsData): Promise<string> {
116-
return (await fetchTypesPackageVersionInfo(pkg, /*publish*/ false)).version;
117-
}
118-
119+
/**
120+
* 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.
121+
* 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).
122+
* Because the decider is the content hash, this isn't applicable to other npm packages.
123+
* Target JS packages and not-needed stubs don't have content hashes.
124+
*/
119125
export async function fetchTypesPackageVersionInfo(
120126
pkg: TypingsData,
121-
canPublish: boolean,
122127
log?: LoggerWithErrors
123-
): Promise<{ version: string; needsPublish: boolean }> {
128+
): Promise<{ maxVersion?: string; incipientVersion?: string }> {
124129
const spec = `${pkg.fullNpmName}@~${pkg.major}.${pkg.minor}`;
125130
let info = await pacote.manifest(spec, { cache: cacheDir, fullMetadata: true, offline: true }).catch((reason) => {
126131
if (reason.code !== "ENOTCACHED" && reason.code !== "ETARGET") throw reason;
@@ -135,7 +140,7 @@ export async function fetchTypesPackageVersionInfo(
135140
return undefined;
136141
});
137142
if (!info) {
138-
return { version: `${pkg.major}.${pkg.minor}.0`, needsPublish: true };
143+
return { incipientVersion: `${pkg.major}.${pkg.minor}.0` };
139144
}
140145
}
141146

@@ -146,6 +151,10 @@ export async function fetchTypesPackageVersionInfo(
146151
`Package ${pkg.name} has been deprecated, so we shouldn't have parsed it. Was it re-added?`
147152
);
148153
}
149-
const needsPublish = canPublish && pkg.contentHash !== info.typesPublisherContentHash;
150-
return { version: needsPublish ? semver.inc(info.version, "patch")! : info.version, needsPublish };
154+
return {
155+
maxVersion: info.version,
156+
...(((pkg.contentHash === info.typesPublisherContentHash) as {}) || {
157+
incipientVersion: semver.inc(info.version, "patch")!,
158+
}),
159+
};
151160
}

packages/retag/test/index.test.ts

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

0 commit comments

Comments
 (0)