Skip to content

Commit

Permalink
Add fetchTypesPackageVersionInfo() tests
Browse files Browse the repository at this point in the history
  • Loading branch information
jablko committed Jul 14, 2022
1 parent 39e0d00 commit 5c97a84
Show file tree
Hide file tree
Showing 3 changed files with 97 additions and 20 deletions.
14 changes: 9 additions & 5 deletions packages/publisher/src/calculate-versions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,9 @@ async function computeAndSaveChangedPackages(
async function computeChangedPackages(allPackages: AllPackages, log: LoggerWithErrors): Promise<ChangedPackages> {
log.info("# Computing changed packages...");
const changedTypings = await mapDefinedAsync(allPackages.allTypings(), async (pkg) => {
const { version, needsPublish } = await fetchTypesPackageVersionInfo(pkg, /*publish*/ true, log);
if (needsPublish) {
log.info(`Need to publish: ${pkg.desc}@${version}`);
const { incipientVersion } = await fetchTypesPackageVersionInfo(pkg, log);
if (incipientVersion) {
log.info(`Need to publish: ${pkg.desc}@${incipientVersion}`);
for (const { name } of pkg.packageJsonDependencies) {
// Assert that dependencies exist on npm.
// Also checked when we install the dependencies, in dtslint-runner.
Expand All @@ -65,8 +65,12 @@ async function computeChangedPackages(allPackages: AllPackages, log: LoggerWithE
}
const latestVersion = pkg.isLatest
? undefined
: (await fetchTypesPackageVersionInfo(allPackages.getLatest(pkg), /*publish*/ true)).version;
return { pkg, version, latestVersion };
: await fetchTypesPackageVersionInfo(allPackages.getLatest(pkg), log);
return {
pkg,
version: incipientVersion,
latestVersion: latestVersion?.incipientVersion || latestVersion?.maxVersion,
};
}
return undefined;
});
Expand Down
39 changes: 24 additions & 15 deletions packages/retag/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,18 +60,22 @@ async function tag(dry: boolean, nProcesses: number, name?: string) {
const publishClient = await NpmPublishClient.create(token, {});
if (name) {
const pkg = await AllPackages.readSingle(name);
const version = await getLatestTypingVersion(pkg);
await updateTypeScriptVersionTags(pkg, version, publishClient, consoleLogger.info, dry);
await updateLatestTag(pkg.fullNpmName, version, publishClient, consoleLogger.info, dry);
const { maxVersion } = await fetchTypesPackageVersionInfo(pkg);
if (maxVersion) {
await updateTypeScriptVersionTags(pkg, maxVersion, publishClient, consoleLogger.info, dry);
await updateLatestTag(pkg.fullNpmName, maxVersion, publishClient, consoleLogger.info, dry);
}
} else {
await Promise.all(
(
await AllPackages.readLatestTypings()
).map(async (pkg) => {
// Only update tags for the latest version of the package.
const version = await getLatestTypingVersion(pkg);
await updateTypeScriptVersionTags(pkg, version, publishClient, consoleLogger.info, dry);
await updateLatestTag(pkg.fullNpmName, version, publishClient, consoleLogger.info, dry);
const { maxVersion } = await fetchTypesPackageVersionInfo(pkg);
if (maxVersion) {
await updateTypeScriptVersionTags(pkg, maxVersion, publishClient, consoleLogger.info, dry);
await updateLatestTag(pkg.fullNpmName, maxVersion, publishClient, consoleLogger.info, dry);
}
})
);
}
Expand Down Expand Up @@ -112,15 +116,16 @@ export async function updateLatestTag(
}
}

export async function getLatestTypingVersion(pkg: TypingsData): Promise<string> {
return (await fetchTypesPackageVersionInfo(pkg, /*publish*/ false)).version;
}

/**
* 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.
* 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).
* Because the decider is the content hash, this isn't applicable to other npm packages.
* Target JS packages and not-needed stubs don't have content hashes.
*/
export async function fetchTypesPackageVersionInfo(
pkg: TypingsData,
canPublish: boolean,
log?: LoggerWithErrors
): Promise<{ version: string; needsPublish: boolean }> {
): Promise<{ maxVersion?: string; incipientVersion?: string }> {
const spec = `${pkg.fullNpmName}@~${pkg.major}.${pkg.minor}`;
let info = await pacote.manifest(spec, { cache: cacheDir, fullMetadata: true, offline: true }).catch((reason) => {
if (reason.code !== "ENOTCACHED" && reason.code !== "ETARGET") throw reason;
Expand All @@ -135,7 +140,7 @@ export async function fetchTypesPackageVersionInfo(
return undefined;
});
if (!info) {
return { version: `${pkg.major}.${pkg.minor}.0`, needsPublish: true };
return { incipientVersion: `${pkg.major}.${pkg.minor}.0` };
}
}

Expand All @@ -146,6 +151,10 @@ export async function fetchTypesPackageVersionInfo(
`Package ${pkg.name} has been deprecated, so we shouldn't have parsed it. Was it re-added?`
);
}
const needsPublish = canPublish && pkg.contentHash !== info.typesPublisherContentHash;
return { version: needsPublish ? semver.inc(info.version, "patch")! : info.version, needsPublish };
return {
maxVersion: info.version,
...(((pkg.contentHash === info.typesPublisherContentHash) as {}) || {
incipientVersion: semver.inc(info.version, "patch")!,
}),
};
}
64 changes: 64 additions & 0 deletions packages/retag/test/index.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import * as util from "util";
import { TypingsData } from "@definitelytyped/definitions-parser";
import * as pacote from "pacote";
import { fetchTypesPackageVersionInfo } from "../src/";

jest.mock("pacote", () => ({
async manifest(spec: string, opts: pacote.Options) {
switch (spec) {
case "@types/already-published@~1.2": // An already-published @types package.
return { version: "1.2.3", typesPublisherContentHash: "already-published-content-hash" };
case "@types/first-publish@~1.2": // A new, not-yet-published @types package.
// eslint-disable-next-line no-throw-literal
throw { code: opts.offline ? "ENOTCACHED" : "E404" };
}
throw new Error(`Unexpected npm registry fetch: ${util.inspect(spec)}`);
},
}));

const unchanged = new TypingsData(
{
typingsPackageName: "already-published",
libraryMajorVersion: 1,
libraryMinorVersion: 2,
contentHash: "already-published-content-hash",
} as never,
/*isLatest*/ true
);
const changed = new TypingsData(
{
typingsPackageName: "already-published",
libraryMajorVersion: 1,
libraryMinorVersion: 2,
contentHash: "changed-content-hash",
} as never,
/*isLatest*/ true
);
const firstPublish = new TypingsData(
{
typingsPackageName: "first-publish",
libraryMajorVersion: 1,
libraryMinorVersion: 2,
contentHash: "first-publish-content-hash",
} as never,
/*isLatest*/ true
);

test("Increments already-published patch version", () => {
return expect(fetchTypesPackageVersionInfo(changed)).resolves.toEqual({
maxVersion: "1.2.3",
incipientVersion: "1.2.4",
});
});

test("Doesn't increment unchanged @types package version", () => {
return expect(fetchTypesPackageVersionInfo(unchanged)).resolves.toEqual({
maxVersion: "1.2.3",
});
});

test("First-publish version", () => {
return expect(fetchTypesPackageVersionInfo(firstPublish)).resolves.toEqual({
incipientVersion: "1.2.0",
});
});

0 comments on commit 5c97a84

Please sign in to comment.