Skip to content

Commit

Permalink
0.2.0
Browse files Browse the repository at this point in the history
  • Loading branch information
hamlim committed May 17, 2024
1 parent c5a6eeb commit fb57e03
Show file tree
Hide file tree
Showing 13 changed files with 334 additions and 30 deletions.
23 changes: 14 additions & 9 deletions apps/docs/app/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,10 @@ export default function Home() {
One Version is a strict dependency conformance tool for monorepos, managing dependencies across repos has
never been easier!
</P>
<P>
This tool ensures that all workspaces in your monorepo are using the same version of a dependency, and also an
(opt-in) strict versioning strategy to ensure that all dependencies are pinned to an exact version.
</P>

<div className="pt-10 flex row justify-evenly items-center">
<Button asChild>
Expand Down Expand Up @@ -142,21 +146,22 @@ export default function Home() {

<Code lang="json">
{`{
// The schema for the configuration file
"$schema": "https://one-version.vercel.app/schema.json",
// One of the supported package managers:
// 'bun', 'pnpm', 'npm', 'yarn-classic', 'yarn-berry'
// one of: "bun", "yarn-berry", "yarn-classic", "pnpm", "npm"
// by default it will try to detect the package manager based on the presence of a lockfile
"packageManager": "bun",
// A mapping of overrides, where the key is the dependency name, and the value is a map of
// version specifier to an array of workspaces that are allowed to use that version.
// A mapping of dependencies, and which workspaces are "allowed" to use different versions
"overrides": {
"react": {
// in this example, pkg-a is allowed to use react@18
// and pkg-b is allowed to use react@17
"18.0.0": ["pkg-a"],
"17.0.0": ["pkg-b"]
// Wildcards are supported, and will capture any workspaces!
"17.0.0": ["*"]
}
}
},
// one of: "pin", "loose", defaults to "loose" if not provided
// pin: all dependencies and devDependencies must use an exact version
// meaning no ranges (\`^\`, \`~\`, \`.x\`, etc.) are allowed
"versionStrategy": "pin"
}`}
</Code>
</section>
Expand Down
5 changes: 5 additions & 0 deletions apps/docs/public/schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,11 @@
},
"additionalProperties": false,
"description": "A mapping of dependencies and which workspaces are allowed to use different versions."
},
"versionStrategy": {
"type": "string",
"enum": ["pin", "loose"],
"description": "The versioning strategy to use across the repo, defaults to 'loose'."
}
},
"required": ["packageManager"],
Expand Down
16 changes: 16 additions & 0 deletions packages/one-version/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,21 @@
### Unreleased:

### [0.2.0] - May 17th, 2024

Added support for pinned version strategy checking.

To enable, you can add `"versionStrategy": "pin"` to your `one-version.config.(json|jsonc)` configuration file:

```jsonc
{
"$schema": "https://one-version.vercel.app/schema.json",
"packageManager": "bun",
"versionStrategy": "pin"
}
```

Notably, this respects your existing `overrides` configuration - if you want to allow some specific loose versions for specific dependencies.

### [0.1.1] - May 15th, 2024

- Added homepage to package.json, and repo info
Expand Down
18 changes: 15 additions & 3 deletions packages/one-version/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,16 +28,22 @@ Add a `one-version:check` script to your root `package.json`:

```jsonc
{
"$schema": "https://one-version.vercel.app/schema.json",
// one of: "bun", "yarn-berry", "yarn-classic", "pnpm", "npm"
// by default it will try to detect the package manager based on the presence of a lockfile
"packageManager": "bun",
// A mapping of dependencies, and which workspaces are "allowed" to use different versions
"overrides": {
"react": {
"18.0.0": ["pkg-a"],
"17.0.0": ["pkg-b"]
// Wildcards are supported, and will capture any workspaces!
"17.0.0": ["*"]
}
}
},
// one of: "pin", "loose", defaults to `loose` if not provided
// pin: all dependencies and devDependencies must use an exact version
// meaning no ranges (`^`, `~`, `.x`, etc.) are allowed
"versionStrategy": "pin"
}
```

Expand All @@ -51,10 +57,16 @@ Add a `one-version:check` script to your root `package.json`:

## Inspiration:

This is effectively a fork of the [wayfair/one-version](https://github.com/wayfair/one-version) project, which I had partially contributed to while I was at Wayfair. This fork is intended to be a slimmer re-write of the original project, aiming to support the same functionality (eventually), with also supporting `bun`!
This is effectively a fork of the [wayfair/one-version](https://github.com/wayfair/one-version) project, which I had partially contributed to while I was at Wayfair. This fork is intended to be a slimmer re-write of the original project, aiming to support the same functionality (eventually)!

This tool should be a drop-in replacement for `@wayfair/one-version`, if you run into any issues or collisions, please open an issue!

This package also notably includes a few additional features:

- Support for `npm` and `bun` package managers
- Support for wildcards (`"*"`) within the `overrides` configuration
- Support for `"versionStrategy"` configuration to enforce strict versioning across the repo!

## Contributing:

This library does not have a build step currently.
Expand Down
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"name": "pkg-a",
"version": "0.0.0",
"dependencies": {
"react": "18.3.1",
"react-dom": "18.3.1"
},
"peerDependencies": {
"next": "14.3.0-canary.61"
},
"devDependencies": {
"typescript": "^5"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"name": "pkg-b",
"version": "0.0.0",
"dependencies": {
"react": "18.3.1",
"react-dom": "18.3.1"
},
"peerDependencies": {
"next": "14.3.0-canary.61"
},
"devDependencies": {
"typescript": "^5.4"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"name": "pkg-c",
"version": "0.0.0",
"dependencies": {
"react": "18.3.1",
"react-dom": "18.3.1"
},
"peerDependencies": {
"next": "14.3.0-canary.61"
},
"devDependencies": {
"typescript": "5.4.5"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"$schema": "../../../../apps/docs/public/schema.json",
"packageManager": "bun",
"versionStrategy": "pin"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"private": true,
"workspaces": [
"libs/*"
]
}
128 changes: 121 additions & 7 deletions packages/one-version/__tests__/one-version.test.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ import assert from "node:assert";
import path from "node:path";
import { describe, test } from "node:test";
import { fileURLToPath } from "node:url";
import { start } from "../one-version.mjs";
import { getUnpinnedDependencies, start } from "../one-version.mjs";

describe("one-version", () => {
describe("one-version unit tests", () => {
test("supports help command", async () => {
let logs = [];
const logger = {
Expand Down Expand Up @@ -32,6 +32,104 @@ describe("one-version", () => {

assert.match(logs[0], /Unknown command:/);
});

describe("getUnpinnedDependencies", () => {
test("returns empty array when no dependencies are found", () => {
const workspaceDependencies = [{
name: "testing",
dependencies: {},
devDependencies: {},
peerDependencies: {},
}];
const result = getUnpinnedDependencies({ workspaceDependencies, overrides: undefined });

assert.deepEqual(result, {});
});

test("Covers the core edge cases", () => {
const workspaceDependencies = [{
name: "testing",
dependencies: {
foo: "^1.0.0",
},
devDependencies: {
bar: "2.0.x",
baz: "3.X",
react: "17.0.0 - 18.0.0",
"react-dom": "17.0.0 || 18.0.0",
"react-native": ">=0.64.0",
"react-native-web": "<0.17.0",
"one-version": "workspace:^*",
turbo: "workspace:~*",
next: "canary",
abc: "next",
def: "beta",
ghi: "alpha",
jkl: "rc",
mno: "dev",
// All below shouldn't show up!
hohoro: "workspace:*",
"react-router": "file:../react-router",
"left-pad": "git://github.com/jonschlinkert/left-pad.git#1.2.0",
"right-pad": "link:../right-pad",
"top-pad": "url:../top-pad",
},
peerDependencies: {
"peer-dep": "*",
},
}];
const result = getUnpinnedDependencies({ workspaceDependencies, overrides: undefined });

// peer-dep is omitted because it's a peer dependency
assert.deepEqual(result, {
testing: [
"foo@^1.0.0",
"[email protected]",
"[email protected]",
"[email protected] - 18.0.0",
"[email protected] || 18.0.0",
"react-native@>=0.64.0",
"react-native-web@<0.17.0",
"one-version@workspace:^*",
"turbo@workspace:~*",
"next@canary",
"abc@next",
"def@beta",
"ghi@alpha",
"jkl@rc",
"mno@dev",
],
});
});

test("Allows overriding dependencies", () => {
const workspaceDependencies = [{
name: "testing",
dependencies: {
foo: "^1.0.0",
},
devDependencies: {},
peerDependencies: {
next: "canary",
},
}];
const result = getUnpinnedDependencies({
workspaceDependencies,
overrides: {
next: {
canary: ["*"],
},
},
});

// Next not included because it's overridden
assert.deepEqual(result, {
testing: [
"foo@^1.0.0",
],
});
});
});
});

let __filename = fileURLToPath(import.meta.url);
Expand All @@ -54,7 +152,6 @@ describe("one-version integration tests", () => {

// should fail - mismatch of typescript dependencies
assert.equal(statusCode, 1);
assert.match(errors[0], /More than one version of dependencies found. See above output/);
// single log line with multiple new-lines
assert.match(logs[0], /One Version Rule Failure/);
assert.match(logs[0], /typescript/);
Expand All @@ -76,7 +173,6 @@ describe("one-version integration tests", () => {

// should fail - mismatch of typescript dependencies
assert.equal(statusCode, 1);
assert.match(errors[0], /More than one version of dependencies found. See above output/);
// single log line with multiple new-lines
assert.match(logs[0], /One Version Rule Failure/);
assert.match(logs[0], /typescript/);
Expand All @@ -98,7 +194,6 @@ describe("one-version integration tests", () => {

// should fail - mismatch of typescript dependencies
assert.equal(statusCode, 1);
assert.match(errors[0], /More than one version of dependencies found. See above output/);
// single log line with multiple new-lines
assert.match(logs[0], /One Version Rule Failure/);
assert.match(logs[0], /typescript/);
Expand All @@ -120,7 +215,6 @@ describe("one-version integration tests", () => {

// should fail - mismatch of typescript dependencies
assert.equal(statusCode, 1);
assert.match(errors[0], /More than one version of dependencies found. See above output/);
// single log line with multiple new-lines
assert.match(logs[0], /One Version Rule Failure/);
assert.match(logs[0], /typescript/);
Expand All @@ -142,7 +236,6 @@ describe("one-version integration tests", () => {

// should fail - mismatch of typescript dependencies
assert.equal(statusCode, 1);
assert.match(errors[0], /More than one version of dependencies found. See above output/);
// single log line with multiple new-lines
assert.match(logs[0], /One Version Rule Failure/);
assert.match(logs[0], /typescript/);
Expand Down Expand Up @@ -188,4 +281,25 @@ describe("one-version integration tests", () => {
// single log line with multiple new-lines
assert.match(logs[0], /One Version Rule Success/);
});

test("bun - configured and pinned versions", async () => {
const targetDir = path.join(__dirname, "..", "__fixtures__", "bun-configured-pinned");
let logs = [];
let errors = [];
let logger = {
log(...args) {
logs.push(args.join(" "));
},
error(...args) {
errors.push(args.join(" "));
},
};
let { statusCode } = await start({ rootDirectory: targetDir, logger, args: ["check"] });

// should fail because of loose deps
assert.equal(statusCode, 1);

assert.equal(logs.length, 2);
assert.match(logs[0], /One Version Rule Failure/);
});
});
Loading

0 comments on commit fb57e03

Please sign in to comment.