Skip to content

Commit

Permalink
Clean up in prep for usint eslint fixer
Browse files Browse the repository at this point in the history
  • Loading branch information
pokey committed Apr 8, 2023
1 parent 5fe340f commit 5a937c6
Show file tree
Hide file tree
Showing 3 changed files with 76 additions and 18 deletions.
5 changes: 5 additions & 0 deletions packages/meta-updater/src/formats.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,11 @@ import { equals } from "ramda";
import yaml from "yaml";

export const formats = {
/**
* A format that today we just use for .pre-commit-config.yaml files. This is a yaml file, but we
* need to preserve comments, so we use the `yaml` library's document representation instead of
* parsing it into a plain js object.
*/
[".yaml"]: createFormat({
async read({ resolvedPath }) {
return yaml.parseDocument(await readFile(resolvedPath, "utf-8")).clone();
Expand Down
9 changes: 9 additions & 0 deletions packages/meta-updater/src/getPackageDeps.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,15 @@ import normalizePath from "normalize-path";
import path from "path";
import { Lockfile } from "@pnpm/lockfile-file";

/**
* Get the dependencies of the given package from the pnpm lockfile.
* @param workspaceDir The root of the workspace
* @param packageDir The directory of the package whose dependencies we are
* retrieving
* @param pnpmLockfile The parsed pnpm lockfile
* @returns A map of package names to package specs for the dependencies of the
* given package
*/
export function getPackageDeps(
workspaceDir: string,
packageDir: string,
Expand Down
80 changes: 62 additions & 18 deletions packages/meta-updater/src/updatePreCommit.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@ import { Document, ParsedNode } from "yaml";
import { Context } from "./Context";
import { getPackageDeps } from "./getPackageDeps";

/**
* Subset of the .pre-commit-config.yaml schema that we care about.
*/
interface PreCommitConfig {
repos: {
hooks: {
Expand All @@ -14,15 +17,19 @@ interface PreCommitConfig {
}

/**
* Given a tsconfig.json, update it to match our conventions. This function is
* called by the pnpm `meta-updater` plugin either to check if the tsconfig.json
* is up to date or to update it, depending on flags.
* Given a .pre-commit-config.yaml, update it to ensure that the versions of our
* hooks match the corresponding package versions in package.json. This
* function is called by the pnpm `meta-updater` plugin either to check if the
* .pre-commit-config.yaml is up to date or to update it, depending on flags.
* @param context Contains context such as workspace dir and parsed pnpm
* lockfile
* @param rawInput The input tsconfig.json that should be checked / updated
* @param rawInput The input .pre-commit-config.yaml that should be checked /
* updated. This is a parsed yaml document in the `yaml` library's document
* representation; not a plain js object like you'd get from a json parser. We
* need it like this so that we can preserve comments.
* @param options Extra information provided by pnpm; mostly just the directory
* of the package whose tsconfig.json we are updating
* @returns The updated tsconfig.json
* of the package whose .pre-commit-config.yaml we are updating
* @returns The updated .pre-commit-config.yaml
*/
export async function updatePreCommit(
{ workspaceDir, pnpmLockfile }: Context,
Expand All @@ -32,36 +39,73 @@ export async function updatePreCommit(
if (rawInput == null) {
return null;
}
/** Directory of the package whose tsconfig.json we are updating */
/** Directory of the package whose .pre-commit-config.yaml we are updating */
const packageDir = options.dir;

if (packageDir !== workspaceDir) {
throw new Error("updatePreCommit should only be called on root");
}

const deps = getPackageDeps(workspaceDir, packageDir, pnpmLockfile);
const prettierVersion = deps["prettier"];

const prettierHookIndex = (rawInput.toJS() as PreCommitConfig).repos
updateHook(deps, rawInput, "prettier", (name) => name === "prettier");

return rawInput;
}

/**
* Updates the additional_dependencies of a hook in a .pre-commit-config.yaml to
* match the versions from the lockfile.
* @param deps Dependencies of the package whose .pre-commit-config.yaml we are
* updating
* @param rawInput The input .pre-commit-config.yaml that should be checked /
* updated
* @param hookId The id of the hook to update
* @param packageMatcher A function that returns true if the given package name
* should be added to the hook's additional_dependencies
*/
function updateHook(
deps: { [x: string]: string },
rawInput: Document<ParsedNode>,
hookId: string,
packageMatcher: (name: string) => boolean,
) {
const packages = Object.entries(deps).filter(([name]) =>
packageMatcher(name),
);

// Find the hook in the .pre-commit-config.yaml. Easier to grab the indices
// from the raw js representation so that we can just use `setIn` to update
// the hook
const desiredHooks = (rawInput.toJS() as PreCommitConfig).repos
.flatMap(({ hooks }, repoIndex) =>
hooks.map((hook, hookIndex) => ({ hook, repoIndex, hookIndex })),
)
.filter(({ hook }) => hook.id === "prettier");
.filter(({ hook }) => hook.id === hookId);

if (prettierHookIndex.length === 0) {
throw new Error("No prettier hook found");
if (desiredHooks.length === 0) {
throw new Error(`No ${hookId} hook found`);
}

if (prettierHookIndex.length > 1) {
throw new Error("Multiple prettier hooks found");
if (desiredHooks.length > 1) {
throw new Error(`Multiple ${hookId} hooks found`);
}

const { repoIndex, hookIndex } = prettierHookIndex[0];
const { repoIndex, hookIndex } = desiredHooks[0];

rawInput.setIn(
["repos", repoIndex, "hooks", hookIndex, "additional_dependencies"],
rawInput.createNode([`prettier@${prettierVersion}`]),
rawInput.createNode(
packages
.map(([name, version]) => {
if (version.includes("(")) {
// pnpm includes the integrity hash in the version, which we don't
// need here
version = version.slice(0, version.indexOf("("));
}
return `${name}@${version}`;
})
.sort(),
),
);

return rawInput;
}

0 comments on commit 5a937c6

Please sign in to comment.