Skip to content
This repository has been archived by the owner on Aug 2, 2023. It is now read-only.

Commit

Permalink
feat: add lots of bump functionality
Browse files Browse the repository at this point in the history
  • Loading branch information
Lotus authored and Lotus committed Jul 18, 2021
1 parent 2737e89 commit 078863c
Show file tree
Hide file tree
Showing 12 changed files with 346 additions and 1 deletion.
61 changes: 61 additions & 0 deletions src/bump/bump-check.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import chalk from "chalk";
import latestVersion from "latest-version";

import { bumpCheck } from "./bump-check";

import { BumpObject } from "./interfaces/bump-object";

describe("Bump check", () => {
let results: any;

beforeEach(() => {
results = [];
jest
.spyOn(process.stdout, "write")
.mockImplementation(val => results.push(String(val).trim()));
});

afterEach(() => jest.restoreAllMocks());

test("No updates needed", async () => {
jest.spyOn(latestVersion, "default").mockResolvedValue("1.0.0");

const validList: BumpObject[] = [
{
packageFile: { name: "test-1", version: "1.0.0" },
packagePath: "src/test",
bumpedVersion: "1.0.1",
},
];

const checkedList = await bumpCheck(validList);
expect(checkedList).toEqual(validList);
});

test("Updates needed", async () => {
jest.spyOn(latestVersion, "default").mockResolvedValue("1.0.1");

const bumpList: BumpObject[] = [
{
packageFile: { name: "test-1", version: "1.0.0" },
packagePath: "src/test",
bumpedVersion: "1.0.1",
},
];
const validList: BumpObject[] = [
{
packageFile: { name: "test-1", version: "1.0.0" },
packagePath: "src/test",
bumpedVersion: "1.0.2",
},
];

const checkedList = await bumpCheck(bumpList);
expect(checkedList).toEqual(validList);
expect(results).toEqual(
chalk.red(
"test-1 version mismatch. NPM version 1.0.1. Bump value 1.0.1. Auto-bumping..."
)
);
});
});
56 changes: 56 additions & 0 deletions src/bump/bump-check.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import chalk from "chalk";
import latestVersion from "latest-version";
import PQueue from "p-queue";
import semver from "semver";

import { bumpValue } from "./bump-value";
import log from "../utils/log";

import { BumpObject } from "./interfaces/bump-object";

const queue = new PQueue({ concurrency: 6 });

const validate = async (item: BumpObject) => {
let npmVersion: string | boolean;

try {
// Get latest version from NPM registry and compare if bumped version is greater than NPM
npmVersion = await latestVersion(item.packageFile.name);
if (semver.gt(item.bumpedVersion, npmVersion)) {
return item;
}
} catch {
// Assume package isn't published on NPM yet
return item;
}

// If bumped value is not greater than NPM, auto bump with patch
const newItem = item;
const newVersion = bumpValue(npmVersion, "patch");
if (newVersion) {
newItem.bumpedVersion = newVersion;
return newItem;
}

// If failed to bump again, will not publish
newItem.failedValidation = true;
log(
chalk.red(
`${newItem.packageFile.name} version mismatch. Failed to bump. Not publishing.`
)
);
return newItem;
};

const bumpCheck = async (bumpList: BumpObject[]): Promise<BumpObject[]> => {
const checkedList: Promise<BumpObject>[] = [];

for (const item of bumpList) {
const validatedItem = queue.add(() => validate(item));
checkedList.push(validatedItem);
}

return Promise.all(checkedList);
};

export { bumpCheck };
28 changes: 28 additions & 0 deletions src/bump/bump-value.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { bumpValue } from "./bump-value";

describe("Bump Value", () => {
test("Patch", () => {
const newVersion = bumpValue("1.0.0", "patch");
expect(newVersion).toBe("1.0.1");
});

test("Minor", () => {
const newVersion = bumpValue("1.0.0", "minor");
expect(newVersion).toBe("1.1.0");
});

test("Major", () => {
const newVersion = bumpValue("1.0.0", "major");
expect(newVersion).toBe("2.0.0");
});

test("Version number", () => {
const newVersion = bumpValue("1.0.0", "2.5.1");
expect(newVersion).toBe("2.5.1");
});

test("False", () => {
const newVersion = bumpValue("a.b.c", "major");
expect(newVersion).toBeFalsy();
});
});
32 changes: 32 additions & 0 deletions src/bump/bump-value.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import semver from "semver";

const bumpValue = (oldVersion: string, bumpArg: string): string | false => {
// Check if valid semver version and if invalid return false
const arr = semver.valid(oldVersion)?.split(".");
if (arr) {
if (bumpArg === "patch") {
const newNum = Number(arr[2]) + 1;
arr[2] = String(newNum);
return arr.join(".");
}
if (bumpArg === "minor") {
const newNum = Number(arr[1]) + 1;
arr[1] = String(newNum);
return arr.join(".");
}
if (bumpArg === "major") {
const newNum = Number(arr[0]) + 1;
arr[0] = String(newNum);
return arr.join(".");
}
// Else just return number version
if (semver.valid(bumpArg)) {
return bumpArg;
}

return false;
}
return false;
};

export { bumpValue };
25 changes: 25 additions & 0 deletions src/bump/bump-write.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import jsonfile from "jsonfile";

import { bumpWrite } from "./bump-write";

import { BumpObject } from "./interfaces/bump-object";

describe("Bump write function", () => {
test("Should not throw", async () => {
jest.spyOn(jsonfile, "writeFile").mockResolvedValue();

const bumpList: BumpObject[] = [
{
packageFile: { name: "test-package", version: "1.0.0" },
packagePath: "src/publish/fixtures/",
bumpedVersion: "1.1.0",
},
{
packageFile: { name: "test-package2", version: "1.1.0" },
packagePath: "src/publish/fixtures/",
bumpedVersion: "1.2.0",
},
];
await expect(bumpWrite(bumpList)).resolves.not.toThrow();
});
});
24 changes: 24 additions & 0 deletions src/bump/bump-write.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import jsonfile from "jsonfile";
import path from "path";

import { BumpObject } from "./interfaces/bump-object";

const writeUpdate = async (item: BumpObject) => {
const newPackageFile = item.packageFile;
newPackageFile.version = item.bumpedVersion;

await jsonfile.writeFile(
path.join(item.packagePath, "package.json"),
newPackageFile
);
};

const bumpWrite = (bumpList: BumpObject[]): Promise<void[]> => {
const promises = [];
for (const item of bumpList) {
promises.push(writeUpdate(item));
}
return Promise.all(promises);
};

export { bumpWrite };
58 changes: 58 additions & 0 deletions src/bump/bump.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import async from "async";
import chalk from "chalk";
import latestVersion from "latest-version";
import path from "path";
import jsonfile from "jsonfile";
import semver from "semver";

import log from "../utils/log";
import { pathToPackage } from "../utils/path-to-package";

import { PackageJson } from "../utils/interfaces/package-json";
import { QueueObject } from "./interfaces/queue-object";
import { BumpObject } from "./interfaces/bump-object";

const processQueue = async ({
packagePath,
packageFile,
bumpArg,
verify,
}: QueueObject) => {
let npmVersion: string | false;
// Get latest version from NPM registry
try {
npmVersion = await latestVersion(packageFile.name);
} catch {
// Assume package isn't published
npmVersion = false;
}

// Bump current package.json
const currentVersion = packageFile.version;
const bumpedVersion = bumpValue(currentVersion, bumpArg);

if (bumpedVersion && npmVersion) {
// Compare if bumped version is greater than version on NPM
if (semver.gt(bumpedVersion, npmVersion)) {
await writeUpdate(packageFile, packagePath, bumpedVersion);
} else {
// Try bumping one more time this time
const newBumpedVersion = bumpValue(bumpedVersion, "patch");
if (newBumpedVersion && semver.gt(newBumpedVersion, npmVersion)) {
await writeUpdate(packageFile, packagePath, newBumpedVersion);
} else {
log(
chalk.red(
`${packageFile.name} failed to bump. Specified bump version is less than NPM version.`
)
);
}
}
} else {
log(
chalk.red(
`${packageFile.name} failed to bump. Possible failure due to bump value or incompatible existing package.json value.`
)
);
}
};
8 changes: 8 additions & 0 deletions src/bump/interfaces/bump-object.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { PackageJson } from "../../utils/interfaces/package-json";

export interface BumpObject {
packageFile: PackageJson;
packagePath: string;
bumpedVersion: string;
failedValidation?: boolean;
}
8 changes: 8 additions & 0 deletions src/bump/interfaces/queue-object.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { PackageJson } from "../../utils/interfaces/package-json";

export interface QueueObject {
packageFile: PackageJson;
packagePath: string;
bumpArg: string;
verify: boolean;
}
3 changes: 3 additions & 0 deletions src/changed/interfaces/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,7 @@ export interface Config {
commitMessage: string;
commitFrom: string;
commitTo?: string;
noVerify?: boolean;
autoBump?: boolean;
yes?: boolean;
}
43 changes: 43 additions & 0 deletions src/commands/bump.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
import { Command, flags } from "@oclif/command";
import { cli } from "cli-ux";

import chalk from "chalk";
import { readConfig } from "../changed/read-config";
import { findDiff } from "../changed/find-diff";

export default class Bump extends Command {
static description = "Bumps package versions";
Expand All @@ -9,11 +14,49 @@ export default class Bump extends Command {
"no-verify": flags.boolean({
description: "Skip checking NPM registry for conflicting versions",
}),
// flag to patch auto-bump a package if version matches NPM version --auto-bump
"auto-bump": flags.boolean({
description: "Auto-bump package if specified version is too low",
}),
// flag to skip confirmation to write package bumps --yes
yes: flags.boolean({
description: "Skip confirmation to write bumped versions to package.json",
}),
};

static args = [{ name: "version" }];

async run(): Promise<void> {
const { args, flags } = this.parse(Bump);

const config = await readConfig();
const diff = await findDiff(config);

// Args
const bumpArg = args.version;

// Flags
let verify = true || config.noVerify;
if (flags["no-verify"]) verify = false;

let autoBump = false || config.autoBump;
if (flags["auto-bump"]) autoBump = true;

// If there are no packages to publish, no need for confirmation prompt
let skipPrompt = false || config.yes;
if (flags.yes) skipPrompt = true;

/* const bumpedFiles = await bumpList(diff, bumpArg, verify);
if (bumpedFiles) {
if (skipPrompt) {
await bumpPackages(bumpedFiles);
} else {
const input = await cli.confirm(`Bump ${bumpedFiles.length} packages?`);
if (input) {
await bumpPackages(bumpedFiles);
cli.log(chalk.green.bold(`Packages bumped!`));
}
}
} */
}
}
1 change: 0 additions & 1 deletion src/publish/bump.ts

This file was deleted.

0 comments on commit 078863c

Please sign in to comment.