Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .repokeeper.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# repokeeper configuration: https://github.com/vannt-dev/repokeeper
schema: 1
standard: 1.4.3
standard: 1.4.4
platform: github
stacks:
- node
Expand Down
4 changes: 2 additions & 2 deletions .repokeeper/lock.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"lockVersion": 1,
"standard": "1.4.3",
"standard": "1.4.4",
"entries": [
{
"id": "block:.gitattributes#editorconfig",
Expand Down Expand Up @@ -179,7 +179,7 @@
{
"id": "json:package.json#[\"devDependencies\",\"lefthook\"]",
"module": "hooks",
"hash": "634625aaac511fc861cf38d9742fb883ecb007120475e3ff1cc8bedd458e6f55",
"hash": "4175be08aee972e10e005bc5581bb25bc6cf650ffa32127bc965d7926f88befa",
"target": {
"kind": "json",
"path": "package.json",
Expand Down
2 changes: 1 addition & 1 deletion biome.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"$schema": "https://biomejs.dev/schemas/2.5.14/schema.json",
"$schema": "https://biomejs.dev/schemas/2.5.15/schema.json",
"vcs": { "enabled": true, "clientKind": "git", "useIgnoreFile": true },
"files": {
"includes": [
Expand Down
88 changes: 44 additions & 44 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@
"@commitlint/cli": "^21.2.3",
"@commitlint/config-conventional": "^21.2.3",
"@types/node": "^22.20.4",
"lefthook": "^2.1.14",
"lefthook": "^2.2.1",
"typescript": "^7.0.2",
"vitest": "^5.0.2"
},
Expand Down
6 changes: 3 additions & 3 deletions playground/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@
*/

/** The standard the generated file names; the test holds it to STANDARD_VERSION. */
export const STANDARD = "1.4.3";
export const STANDARD = "1.4.4";

/** The first repokeeper that writes everything the form offers: the last addition is strict on GitLab. */
export const NEEDS_VERSION = "0.8.0";
/** The first repokeeper that knows the standard the generated file names. */
export const NEEDS_VERSION = "0.8.2";

export const STACKS = [
{ id: "node", label: "Node.js" },
Expand Down
10 changes: 9 additions & 1 deletion src/commands/report.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ export function printResult(io: Io, result: SyncResult): void {

const WROTE: string[] = ["create", "write", "adopt"];

/** What the user still has to do after a write: install the hooks, renormalize line endings. */
/** What the user still has to do after a write: install the hooks or the dependencies, renormalize line endings. */
export async function nextSteps(root: string, ctx: ModuleContext, result: SyncResult): Promise<string[]> {
const steps: string[] = [];
const wrote = (path: string) => result.decisions.some((d) => d.output.path === path && WROTE.includes(d.action));
Expand All @@ -82,6 +82,14 @@ export async function nextSteps(root: string, ctx: ModuleContext, result: SyncRe
? "install dependencies; this installs the git hooks"
: `run \`npx --yes lefthook@${TOOL_VERSIONS.lefthook} install\` to enable the git hooks`,
);
} else if (
result.decisions.some(
(d) => d.output.kind === "json" && /(^|\/)package\.json$/.test(d.output.path) && WROTE.includes(d.action),
)
) {
// A range written into package.json is not in the lockfile yet, and a frozen install (`npm ci`) refuses a
// lockfile that disagrees with it. A new standard moves such a range without touching lefthook.yml.
steps.push("package.json changed; install dependencies and commit the lockfile with it");
}
if (wrote(".gitattributes")) {
const crlf = await crlfTrackedFiles(root);
Expand Down
6 changes: 3 additions & 3 deletions src/version.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@ export const PACKAGE_VERSION: string = (
).version;

/** The standard this build of repokeeper applies. Bump it whenever generated output changes. */
export const STANDARD_VERSION = "1.4.3";
export const STANDARD_VERSION = "1.4.4";

export const TOOL_VERSIONS = {
lefthook: "2.1.14",
lefthook: "2.2.1",
commitlintCli: "21.2.3",
commitlintConventional: "21.2.3",
semanticRelease: "25.0.9",
Expand All @@ -18,7 +18,7 @@ export const TOOL_VERSIONS = {
semanticReleaseGitlab: "13.3.3",
// 10.x needs conventional-changelog-writer 9, and semantic-release 25's notes generator bundles 8
conventionalCommitsPreset: "9.3.1",
renovate: "44.128.1",
renovate: "44.149.2",
} as const;

/** Repository hosting the reusable workflows that generated CI files call. */
Expand Down
6 changes: 4 additions & 2 deletions test/e2e.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { join } from "node:path";
import { describe, expect, it } from "vitest";
import { parse } from "yaml";
import { run } from "../src/cli.js";
import { STANDARD_VERSION } from "../src/version.js";
import { STANDARD_VERSION, TOOL_VERSIONS } from "../src/version.js";
import { capture, tempDir } from "./helpers.js";

const sh = (cwd: string, ...args: string[]) => execFileSync("git", args, { cwd, stdio: "pipe" });
Expand Down Expand Up @@ -49,7 +49,9 @@ describe("repokeeper end to end", () => {
expect(config.modules.health.codeowners).toEqual(["@demo-owner"]);
expect(config.modules.health.copyright).toMatch(/^\d{4} Demo User$/);
expect(existsSync(join(dir, "lefthook.yml"))).toBe(true);
expect(JSON.parse(await readFile(join(dir, "package.json"), "utf8")).devDependencies.lefthook).toBe("^2.1.14");
expect(JSON.parse(await readFile(join(dir, "package.json"), "utf8")).devDependencies.lefthook).toBe(
`^${TOOL_VERSIONS.lefthook}`,
);
commitAll(dir);

expect((await repokeeper(dir, "check")).code).toBe(0);
Expand Down
3 changes: 2 additions & 1 deletion test/modules-core.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { commitsModule } from "../src/modules/commits.js";
import { editorconfigModule } from "../src/modules/editorconfig.js";
import { gitignoreModule } from "../src/modules/gitignore.js";
import { hooksModule } from "../src/modules/hooks.js";
import { TOOL_VERSIONS } from "../src/version.js";
import { makeContext, nodeResolved, tempDir } from "./helpers.js";

const execFileAsync = promisify(execFile);
Expand Down Expand Up @@ -86,7 +87,7 @@ describe("hooks", () => {
});
expect(config["pre-push"]).toEqual({ jobs: [{ name: "node:test", run: "npm test" }] });
const json = outputs.find((o) => o.kind === "json") as JsonOutput;
expect([json.keyPath.join("."), json.value]).toEqual(["devDependencies.lefthook", "^2.1.14"]);
expect([json.keyPath.join("."), json.value]).toEqual(["devDependencies.lefthook", `^${TOOL_VERSIONS.lefthook}`]);
});

it("drops hooks that have nothing to run", () => {
Expand Down
4 changes: 2 additions & 2 deletions test/platforms-gitlab.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import { releaseModule } from "../src/modules/release.js";
import { planOutputs } from "../src/plan.js";
import { githubPlatform } from "../src/platforms/github.js";
import { platformFor } from "../src/platforms/index.js";
import { PACKAGE_VERSION } from "../src/version.js";
import { PACKAGE_VERSION, TOOL_VERSIONS } from "../src/version.js";
import { capture, gitlabContext, makeContext, nodeResolved, syncOnce, tempDir } from "./helpers.js";

const files = (outputs: Output[]) =>
Expand Down Expand Up @@ -282,7 +282,7 @@ describe("gitlab dependency updates", () => {
it("runs Renovate only in scheduled pipelines with RENOVATE_TOKEN", () => {
expect(keys(depsModule.outputs(gitlabContext())).renovate).toEqual({
stage: "test",
image: "renovate/renovate:44.128.1",
image: `renovate/renovate:${TOOL_VERSIONS.renovate}`,
rules: [{ if: '$CI_PIPELINE_SOURCE == "schedule" && $RENOVATE_TOKEN' }],
variables: {
RENOVATE_PLATFORM: "gitlab",
Expand Down
57 changes: 57 additions & 0 deletions test/report.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import { describe, expect, it } from "vitest";
import { nextSteps } from "../src/commands/report.js";
import type { Output } from "../src/model.js";
import type { SyncResult } from "../src/sync/sync.js";
import { TOOL_VERSIONS } from "../src/version.js";
import { makeContext } from "./helpers.js";

const hooksFile: Output = { kind: "file", module: "hooks", path: "lefthook.yml", content: "" };
const lefthookRange = (path = "package.json"): Output => ({
kind: "json",
module: "hooks",
path,
keyPath: ["devDependencies", "lefthook"],
value: `^${TOOL_VERSIONS.lefthook}`,
});

const result = (...decisions: SyncResult["decisions"]): SyncResult => ({ decisions, removals: [] });

describe("what to do after a write", () => {
// A new standard can move a dependency's range and nothing else. The lockfile then names a version the range no
// longer allows, and `npm ci` stops there.
it("says to install again when only a range in package.json moved", async () => {
const steps = await nextSteps(
".",
makeContext(),
result({ output: hooksFile, action: "unchanged" }, { output: lefthookRange(), action: "write" }),
);
expect(steps).toEqual(["package.json changed; install dependencies and commit the lockfile with it"]);
});

it("says it for a package.json in a folder too", async () => {
const steps = await nextSteps(
".",
makeContext(),
result({ output: lefthookRange("web/package.json"), action: "write" }),
);
expect(steps).toEqual(["package.json changed; install dependencies and commit the lockfile with it"]);
});

it("says it once when the hooks are new: installing them is the same step", async () => {
const steps = await nextSteps(
".",
makeContext(),
result({ output: hooksFile, action: "create" }, { output: lefthookRange(), action: "create" }),
);
expect(steps).toEqual(["install dependencies; this installs the git hooks"]);
});

it("says nothing when nothing in package.json was written", async () => {
const steps = await nextSteps(
".",
makeContext(),
result({ output: hooksFile, action: "unchanged" }, { output: lefthookRange(), action: "unchanged" }),
);
expect(steps).toEqual([]);
});
});
Loading