-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit 0cc67dd
Showing
25 changed files
with
1,775 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
module.exports = { | ||
extends: [ | ||
'eslint:recommended', | ||
'plugin:@typescript-eslint/recommended', | ||
'plugin:prettier/recommended', | ||
], | ||
parser: '@typescript-eslint/parser', | ||
plugins: [ | ||
'@typescript-eslint', | ||
'prettier', | ||
], | ||
rules: { | ||
'prettier/prettier': [ | ||
1, | ||
{ | ||
trailingComma: 'es5', | ||
singleQuote: true, | ||
}, | ||
], | ||
}, | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
name: On push | ||
|
||
on: push | ||
|
||
jobs: | ||
ci: | ||
runs-on: ubuntu-latest | ||
|
||
steps: | ||
- uses: actions/checkout@v2 | ||
- run: yarn install --frozen-lockfile | ||
- run: yarn ci |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
# Logs | ||
logs | ||
*.log | ||
npm-debug.log* | ||
yarn-debug.log* | ||
yarn-error.log* | ||
pnpm-debug.log* | ||
lerna-debug.log* | ||
|
||
node_modules | ||
dist | ||
dist-ssr | ||
*.local | ||
tsconfig.tsbuildinfo | ||
|
||
# Editor directories and files | ||
.vscode/* | ||
!.vscode/extensions.json | ||
.idea | ||
.DS_Store | ||
*.suo | ||
*.ntvs* | ||
*.njsproj | ||
*.sln | ||
*.sw? | ||
|
||
.yarn-bisect-DO-NOT-COMMIT |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
MIT License | ||
|
||
Copyright (c) Joe Anderson | ||
|
||
Permission is hereby granted, free of charge, to any person obtaining a copy | ||
of this software and associated documentation files (the "Software"), to deal | ||
in the Software without restriction, including without limitation the rights | ||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
copies of the Software, and to permit persons to whom the Software is | ||
furnished to do so, subject to the following conditions: | ||
|
||
The above copyright notice and this permission notice shall be included in all | ||
copies or substantial portions of the Software. | ||
|
||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
SOFTWARE. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
# yarn-bisect | ||
|
||
Bisect an NPM package to locate the version where an error first occurred | ||
|
||
## Installation | ||
|
||
```bash | ||
git clone https://github.com/12joan/yarn-bisect | ||
cd yarn-bisect | ||
npm install --global | ||
# To uninstall: | ||
# npm uninstall --global yarn-bisect | ||
``` | ||
|
||
## Usage | ||
|
||
For usage instructions, see `yarn-bisect help`. | ||
|
||
## Example | ||
|
||
In the following example, we use `yarn-bisect` to locate the first version `typescript` that fails to build our project. | ||
|
||
```bash | ||
$ yarn-bisect start typescript --no-filter-versions # Include dev versions | ||
Preparing to bisect typescript | ||
|
||
Good version: null (Specify this with `yarn-bisect good [version]`) | ||
Bad version: null (Specify this with `yarn-bisect bad [version]`) | ||
|
||
Currently testing version 5.5.2. Run `yarn-bisect reset` to stop bisecting. | ||
$ yarn-bisect bad | ||
Preparing to bisect typescript | ||
|
||
Good version: null (Specify this with `yarn-bisect good [version]`) | ||
Bad version: 5.5.2 | ||
|
||
Currently testing version 5.5.2. Run `yarn-bisect reset` to stop bisecting. | ||
$ yarn-bisect good 5.4.5 | ||
Installing typescript@5.5.0-dev.20240414 | ||
|
||
Bisecting typescript | ||
|
||
Good version: 5.4.5 | ||
Bad version: 5.5.2 | ||
|
||
103 version(s) left to check | ||
|
||
Currently testing version 5.5.0-dev.20240414. Run `yarn-bisect reset` to stop bisecting. | ||
$ yarn typecheck && yarn-bisect good || yarn-bisect bad | ||
# After several iterations | ||
$ yarn typecheck && yarn-bisect good || yarn-bisect bad | ||
Finised bisecting typescript | ||
|
||
Good version: 5.5.0-dev.20240304 | ||
Bad version: 5.5.0-dev.20240305 | ||
|
||
0 version(s) left to check | ||
|
||
First bad version is 5.5.0-dev.20240305 | ||
|
||
Currently testing version 5.5.0-dev.20240304. Run `yarn-bisect reset` to stop bisecting. | ||
$ yarn-bisect reset | ||
Installing typescript@^5.5.2 | ||
``` | ||
|
||
## Compatibility | ||
|
||
Tested with the following versions of Yarn: | ||
|
||
- 1.22.19 | ||
- 4.1.1 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
{ | ||
"name": "yarn-bisect", | ||
"version": "1.0.0", | ||
"description": "Bisect an NPM package to locate the version where an error first occurred", | ||
"repository": "https://github.com/12joan/yarn-bisect", | ||
"author": "Joe Anderson", | ||
"license": "MIT", | ||
"bin": { | ||
"yarn-bisect": "./dist/index.js" | ||
}, | ||
"scripts": { | ||
"build": "tsc", | ||
"dev": "ts-node src/index.ts", | ||
"typecheck": "tsc --incremental --noEmit", | ||
"typecheck:watch": "yarn typecheck --watch", | ||
"lint": "eslint src --max-warnings 0", | ||
"ci": "yarn typecheck && yarn lint" | ||
}, | ||
"devDependencies": { | ||
"@types/node": "^20.14.8", | ||
"ts-node": "^10.9.2", | ||
"typescript": "^5.5.2" | ||
}, | ||
"dependencies": { | ||
"commander": "^12.1.0", | ||
"regex-escape": "^3.4.10", | ||
"@typescript-eslint/eslint-plugin": "^5.62.0", | ||
"@typescript-eslint/parser": "^5.62.0", | ||
"eslint": "^8.57.0", | ||
"eslint-config-prettier": "^8.10.0", | ||
"eslint-plugin-prettier": "^4.2.1", | ||
"prettier": "^2.8.8" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
import { assertBisecting } from '../utils/assertBisecting'; | ||
import { state, setState } from '../utils/state'; | ||
import { validateVersion } from '../utils/validateVersion'; | ||
import { getCurrentVersion } from '../utils/getCurrentVersion'; | ||
import { statusCommand } from './status'; | ||
import { updateVersionsToCheck } from '../utils/updateVersionsToCheck'; | ||
import { installMidpointVersion } from '../utils/installMidpointVersion'; | ||
|
||
export const goodBadCommand = | ||
(key: 'goodVersion' | 'badVersion') => async (versionOption?: string) => { | ||
assertBisecting(state); | ||
const { packageName, filterVersions } = state; | ||
|
||
const version = versionOption ?? getCurrentVersion(packageName); | ||
validateVersion(packageName, version, filterVersions); | ||
|
||
setState((state) => ({ | ||
...state, | ||
[key]: version, | ||
})); | ||
|
||
const hasGoodAndBad = state.goodVersion && state.badVersion; | ||
|
||
if (hasGoodAndBad) { | ||
await updateVersionsToCheck(); | ||
|
||
const installedVersion = await installMidpointVersion(); | ||
|
||
if (installedVersion) { | ||
console.log(''); | ||
} | ||
} | ||
|
||
statusCommand(); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
import { installVersion } from '../utils/installVersion'; | ||
import { state, resetState } from '../utils/state'; | ||
|
||
export const resetCommand = async ({ install }: { install: boolean }) => { | ||
if (state.status === 'null') { | ||
console.log('Nothing to do'); | ||
return; | ||
} | ||
|
||
if (install) { | ||
const { initialVersionSpec } = state; | ||
await installVersion(initialVersionSpec); | ||
} | ||
|
||
resetState(); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
import { getAllVersions } from '../utils/getAllVersions'; | ||
import { getCurrentVersionSpec } from '../utils/getCurrentVersionSpec'; | ||
import { setState } from '../utils/state'; | ||
import { statusCommand } from './status'; | ||
|
||
export const startCommand = async ( | ||
packageName: string, | ||
{ filterVersions }: { filterVersions: boolean } | ||
) => { | ||
const versions = await getAllVersions(packageName, filterVersions); | ||
const { versionSpec: initialVersionSpec, isDev } = | ||
getCurrentVersionSpec(packageName); | ||
|
||
setState({ | ||
status: 'bisecting', | ||
packageName, | ||
filterVersions, | ||
isDev, | ||
initialVersionSpec, | ||
versionsToCheck: versions, | ||
}); | ||
|
||
statusCommand(); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
import { getCurrentVersion } from '../utils/getCurrentVersion'; | ||
import { state } from '../utils/state'; | ||
|
||
export const statusCommand = () => { | ||
if (state.status === 'null') { | ||
console.log( | ||
'Not bisecting. Run `yarn-bisect start <package>` to get started.' | ||
); | ||
return; | ||
} | ||
|
||
const { packageName, versionsToCheck, goodVersion, badVersion } = state; | ||
const hasGoodAndBad = goodVersion && badVersion; | ||
const finished = hasGoodAndBad && versionsToCheck.length === 0; | ||
const currentVersion = getCurrentVersion(packageName); | ||
|
||
const lines: string[] = []; | ||
|
||
const statusDescriptor = (() => { | ||
if (finished) return 'Finised bisecting'; | ||
if (hasGoodAndBad) return 'Bisecting'; | ||
return 'Preparing to bisect'; | ||
})(); | ||
|
||
lines.push(`${statusDescriptor} ${packageName}`); | ||
|
||
lines.push(''); | ||
|
||
[ | ||
['Good version', 'good', goodVersion], | ||
['Bad version', 'bad', badVersion], | ||
].forEach(([label, command, value]) => { | ||
const valueDescription = | ||
value ?? `null (Specify this with \`yarn-bisect ${command} [version]\`)`; | ||
lines.push(`${label}: ${valueDescription}`); | ||
}); | ||
|
||
lines.push(''); | ||
|
||
if (hasGoodAndBad) { | ||
lines.push(`${versionsToCheck.length} version(s) left to check`); | ||
lines.push(''); | ||
} | ||
|
||
if (finished) { | ||
lines.push(`First bad version is ${badVersion}`); | ||
lines.push(''); | ||
} | ||
|
||
lines.push( | ||
`Currently testing version ${currentVersion}. Run \`yarn-bisect reset\` to stop bisecting.` | ||
); | ||
|
||
console.log(lines.join('\n')); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
#!/usr/bin/env node | ||
|
||
import { program } from 'commander'; | ||
import packageJson from '../package.json'; | ||
import { startCommand } from './commands/start'; | ||
import { statusCommand } from './commands/status'; | ||
import { resetCommand } from './commands/reset'; | ||
import { goodBadCommand } from './commands/goodBad'; | ||
|
||
program | ||
.name(packageJson.name) | ||
.description(packageJson.description) | ||
.version(packageJson.version); | ||
|
||
program | ||
.command('status') | ||
.description('Show the current state of the bisection') | ||
.action(statusCommand); | ||
|
||
program | ||
.command('start') | ||
.option( | ||
'--no-filter-versions', | ||
'Do not filter versions. By default, only versions matching the format x.y.z[.w] are included in the bisection.' | ||
) | ||
.argument('<package>', 'The package to bisect') | ||
.description('Start bisecting a package') | ||
.action(startCommand); | ||
|
||
program | ||
.command('good') | ||
.argument('[version]', 'The version to mark as good') | ||
.description( | ||
'Mark a version as good. If no version is specified, uses the currently installed version.' | ||
) | ||
.action(goodBadCommand('goodVersion')); | ||
|
||
program | ||
.command('bad') | ||
.argument('[version]', 'The version to mark as bad') | ||
.description( | ||
'Mark a version as bad. If no version is specified, uses the currently installed version.' | ||
) | ||
.action(goodBadCommand('badVersion')); | ||
|
||
program | ||
.command('reset') | ||
.option( | ||
'--no-install', | ||
'Do not reinstall the version that was used prior to bisecting.' | ||
) | ||
.description('Reset the bisection') | ||
.action(resetCommand); | ||
|
||
program.parse(); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
declare module 'regex-escape' { | ||
export default function regexEscape(input: string): string; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
import { State, BisectingState } from './state'; | ||
import { fail } from './fail'; | ||
|
||
export function assertBisecting(state: State): asserts state is BisectingState { | ||
if (state.status !== 'bisecting') { | ||
fail( | ||
'not currently bisecting', | ||
'Run `yarn-bisect start <package>` to get started.' | ||
); | ||
} | ||
} |
Oops, something went wrong.