mirror of
https://github.com/AikidoSec/safe-chain.git
synced 2026-05-26 12:10:49 +00:00
Add rushx support too
Co-authored-by: Copilot <copilot@github.com>
This commit is contained in:
parent
5cf2ffe201
commit
98a1ba7d10
16 changed files with 101 additions and 27 deletions
|
|
@ -26,6 +26,7 @@ Aikido Safe Chain supports the following package managers:
|
||||||
- 📦 **pnpm**
|
- 📦 **pnpm**
|
||||||
- 📦 **pnpx**
|
- 📦 **pnpx**
|
||||||
- 📦 **rush**
|
- 📦 **rush**
|
||||||
|
- 📦 **rushx**
|
||||||
- 📦 **bun**
|
- 📦 **bun**
|
||||||
- 📦 **bunx**
|
- 📦 **bunx**
|
||||||
- 📦 **pip**
|
- 📦 **pip**
|
||||||
|
|
@ -76,7 +77,7 @@ You can find all available versions on the [releases page](https://github.com/Ai
|
||||||
### Verify the installation
|
### Verify the installation
|
||||||
|
|
||||||
1. **❗Restart your terminal** to start using the Aikido Safe Chain.
|
1. **❗Restart your terminal** to start using the Aikido Safe Chain.
|
||||||
- This step is crucial as it ensures that the shell aliases for npm, npx, yarn, pnpm, pnpx, rush, bun, bunx, pip, pip3, poetry, uv, uvx and pipx are loaded correctly. If you do not restart your terminal, the aliases will not be available.
|
- This step is crucial as it ensures that the shell aliases for npm, npx, yarn, pnpm, pnpx, rush, rushx, bun, bunx, pip, pip3, poetry, uv, uvx and pipx are loaded correctly. If you do not restart your terminal, the aliases will not be available.
|
||||||
|
|
||||||
2. **Verify the installation** by running the verification command:
|
2. **Verify the installation** by running the verification command:
|
||||||
|
|
||||||
|
|
@ -107,7 +108,7 @@ You can find all available versions on the [releases page](https://github.com/Ai
|
||||||
|
|
||||||
- The output should show that Aikido Safe Chain is blocking the installation of these test packages as they are flagged as malware.
|
- The output should show that Aikido Safe Chain is blocking the installation of these test packages as they are flagged as malware.
|
||||||
|
|
||||||
When running `npm`, `npx`, `yarn`, `pnpm`, `pnpx`, `rush`, `bun`, `bunx`, `pip`, `pip3`, `uv`, `uvx`, `poetry` and `pipx` commands, the Aikido Safe Chain will automatically check for malware in the packages you are trying to install. It also intercepts Python module invocations for pip when available (e.g., `python -m pip install ...`, `python3 -m pip download ...`). If any malware is detected, it will prompt you to exit the command.
|
When running `npm`, `npx`, `yarn`, `pnpm`, `pnpx`, `rush`, `rushx`, `bun`, `bunx`, `pip`, `pip3`, `uv`, `uvx`, `poetry` and `pipx` commands, the Aikido Safe Chain will automatically check for malware in the packages you are trying to install. It also intercepts Python module invocations for pip when available (e.g., `python -m pip install ...`, `python3 -m pip download ...`). If any malware is detected, it will prompt you to exit the command.
|
||||||
|
|
||||||
You can check the installed version by running:
|
You can check the installed version by running:
|
||||||
|
|
||||||
|
|
@ -119,7 +120,7 @@ safe-chain --version
|
||||||
|
|
||||||
### Malware Blocking
|
### Malware Blocking
|
||||||
|
|
||||||
The Aikido Safe Chain works by running a lightweight proxy server that intercepts package downloads from the npm registry and PyPI. When you run npm, npx, yarn, pnpm, pnpx, rush, bun, bunx, pip, pip3, uv, uvx, poetry or pipx commands, all package downloads are routed through this local proxy, which verifies packages in real-time against **[Aikido Intel - Open Sources Threat Intelligence](https://intel.aikido.dev/?tab=malware)**. If malware is detected in any package (including deep dependencies), the proxy blocks the download before the malicious code reaches your machine.
|
The Aikido Safe Chain works by running a lightweight proxy server that intercepts package downloads from the npm registry and PyPI. When you run npm, npx, yarn, pnpm, pnpx, rush, rushx, bun, bunx, pip, pip3, uv, uvx, poetry or pipx commands, all package downloads are routed through this local proxy, which verifies packages in real-time against **[Aikido Intel - Open Sources Threat Intelligence](https://intel.aikido.dev/?tab=malware)**. If malware is detected in any package (including deep dependencies), the proxy blocks the download before the malicious code reaches your machine.
|
||||||
|
|
||||||
### Minimum package age
|
### Minimum package age
|
||||||
|
|
||||||
|
|
@ -138,7 +139,7 @@ By default, the minimum package age is 48 hours. This provides an additional sec
|
||||||
|
|
||||||
### Shell Integration
|
### Shell Integration
|
||||||
|
|
||||||
The Aikido Safe Chain integrates with your shell to provide a seamless experience when using npm, npx, yarn, pnpm, pnpx, rush, bun, bunx, and Python package managers (pip, uv, uvx, poetry, pipx). It sets up aliases for these commands so that they are wrapped by the Aikido Safe Chain commands, which manage the proxy server before executing the original commands. We currently support:
|
The Aikido Safe Chain integrates with your shell to provide a seamless experience when using npm, npx, yarn, pnpm, pnpx, rush, rushx, bun, bunx, and Python package managers (pip, uv, uvx, poetry, pipx). It sets up aliases for these commands so that they are wrapped by the Aikido Safe Chain commands, which manage the proxy server before executing the original commands. We currently support:
|
||||||
|
|
||||||
- ✅ **Bash**
|
- ✅ **Bash**
|
||||||
- ✅ **Zsh**
|
- ✅ **Zsh**
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
## Overview
|
## Overview
|
||||||
|
|
||||||
The shell integration automatically wraps common package manager commands (`npm`, `npx`, `yarn`, `pnpm`, `pnpx`, `bun`, `bunx`, `pip`, `pip3`, `uv`, `uvx`, `poetry`, `pipx`) with Aikido's security scanning functionality. It also intercepts Python module invocations for pip when available: `python -m pip`, `python -m pip3`, `python3 -m pip`, `python3 -m pip3`. This is achieved by sourcing startup scripts that define shell functions to wrap these commands with their Aikido-protected equivalents.
|
The shell integration automatically wraps common package manager commands (`npm`, `npx`, `yarn`, `pnpm`, `pnpx`, `rush`, `rushx`, `bun`, `bunx`, `pip`, `pip3`, `uv`, `uvx`, `poetry`, `pipx`) with Aikido's security scanning functionality. It also intercepts Python module invocations for pip when available: `python -m pip`, `python -m pip3`, `python3 -m pip`, `python3 -m pip3`. This is achieved by sourcing startup scripts that define shell functions to wrap these commands with their Aikido-protected equivalents.
|
||||||
|
|
||||||
## Supported Shells
|
## Supported Shells
|
||||||
|
|
||||||
|
|
@ -28,7 +28,7 @@ This command:
|
||||||
|
|
||||||
- Copies necessary startup scripts to Safe Chain's installation directory (`~/.safe-chain/scripts`)
|
- Copies necessary startup scripts to Safe Chain's installation directory (`~/.safe-chain/scripts`)
|
||||||
- Detects all supported shells on your system
|
- Detects all supported shells on your system
|
||||||
- Sources each shell's startup file to add Safe Chain functions for `npm`, `npx`, `yarn`, `pnpm`, `pnpx`, `bun`, `bunx`, `pip`, `pip3`, `uv`, `uvx`, `poetry` and `pipx`
|
- Sources each shell's startup file to add Safe Chain functions for `npm`, `npx`, `yarn`, `pnpm`, `pnpx`, `rush`, `rushx`, `bun`, `bunx`, `pip`, `pip3`, `uv`, `uvx`, `poetry` and `pipx`
|
||||||
- Adds lightweight interceptors so `python -m pip[...]` and `python3 -m pip[...]` route through Safe Chain when invoked by name
|
- Adds lightweight interceptors so `python -m pip[...]` and `python3 -m pip[...]` route through Safe Chain when invoked by name
|
||||||
|
|
||||||
❗ After running this command, **you must restart your terminal** for the changes to take effect. This ensures that the startup scripts are sourced correctly.
|
❗ After running this command, **you must restart your terminal** for the changes to take effect. This ensures that the startup scripts are sourced correctly.
|
||||||
|
|
@ -78,7 +78,7 @@ The system modifies the following files to source Safe Chain startup scripts:
|
||||||
This means the shell functions are working but the Aikido commands aren't installed or available in your PATH:
|
This means the shell functions are working but the Aikido commands aren't installed or available in your PATH:
|
||||||
|
|
||||||
- Make sure Aikido Safe Chain is properly installed on your system
|
- Make sure Aikido Safe Chain is properly installed on your system
|
||||||
- Verify the `aikido-npm`, `aikido-npx`, `aikido-yarn`, `aikido-pnpm`, `aikido-pnpx`, `aikido-bun`, `aikido-bunx`, `aikido-pip`, `aikido-pip3`, `aikido-uv`, `aikido-uvx`, `aikido-poetry` and `aikido-pipx` commands exist
|
- Verify the `aikido-npm`, `aikido-npx`, `aikido-yarn`, `aikido-pnpm`, `aikido-pnpx`, `aikido-rush`, `aikido-rushx`, `aikido-bun`, `aikido-bunx`, `aikido-pip`, `aikido-pip3`, `aikido-uv`, `aikido-uvx`, `aikido-poetry` and `aikido-pipx` commands exist
|
||||||
- Check that these commands are in your system's PATH
|
- Check that these commands are in your system's PATH
|
||||||
|
|
||||||
### Manual Verification
|
### Manual Verification
|
||||||
|
|
@ -121,7 +121,7 @@ npm() {
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
Repeat this pattern for `npx`, `yarn`, `pnpm`, `pnpx`, `bun`, `bunx`, `pip`, `pip3`, `uv`, `uvx`, `poetry` and `pipx` using their respective `aikido-*` commands. After adding these functions, restart your terminal to apply the changes.
|
Repeat this pattern for `npx`, `yarn`, `pnpm`, `pnpx`, `rush`, `rushx`, `bun`, `bunx`, `pip`, `pip3`, `uv`, `uvx`, `poetry` and `pipx` using their respective `aikido-*` commands. After adding these functions, restart your terminal to apply the changes.
|
||||||
|
|
||||||
To intercept Python module invocations for pip without altering Python itself, you can add small forwarding functions:
|
To intercept Python module invocations for pip without altering Python itself, you can add small forwarding functions:
|
||||||
|
|
||||||
|
|
|
||||||
14
packages/safe-chain/bin/aikido-rushx.js
Executable file
14
packages/safe-chain/bin/aikido-rushx.js
Executable file
|
|
@ -0,0 +1,14 @@
|
||||||
|
#!/usr/bin/env node
|
||||||
|
|
||||||
|
import { main } from "../src/main.js";
|
||||||
|
import { initializePackageManager } from "../src/packagemanager/currentPackageManager.js";
|
||||||
|
import { setEcoSystem, ECOSYSTEM_JS } from "../src/config/settings.js";
|
||||||
|
|
||||||
|
setEcoSystem(ECOSYSTEM_JS);
|
||||||
|
const packageManagerName = "rushx";
|
||||||
|
initializePackageManager(packageManagerName);
|
||||||
|
|
||||||
|
(async () => {
|
||||||
|
var exitCode = await main(process.argv.slice(2));
|
||||||
|
process.exit(exitCode);
|
||||||
|
})();
|
||||||
|
|
@ -108,7 +108,7 @@ function writeHelp() {
|
||||||
ui.writeInformation(
|
ui.writeInformation(
|
||||||
`- ${chalk.cyan(
|
`- ${chalk.cyan(
|
||||||
"safe-chain setup",
|
"safe-chain setup",
|
||||||
)}: This will setup your shell to wrap safe-chain around npm, npx, yarn, pnpm, pnpx, rush, bun, bunx, pip and pip3.`,
|
)}: This will setup your shell to wrap safe-chain around npm, npx, yarn, pnpm, pnpx, rush, rushx, bun, bunx, pip and pip3.`,
|
||||||
);
|
);
|
||||||
ui.writeInformation(
|
ui.writeInformation(
|
||||||
`- ${chalk.cyan(
|
`- ${chalk.cyan(
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,7 @@
|
||||||
"aikido-pnpm": "bin/aikido-pnpm.js",
|
"aikido-pnpm": "bin/aikido-pnpm.js",
|
||||||
"aikido-pnpx": "bin/aikido-pnpx.js",
|
"aikido-pnpx": "bin/aikido-pnpx.js",
|
||||||
"aikido-rush": "bin/aikido-rush.js",
|
"aikido-rush": "bin/aikido-rush.js",
|
||||||
|
"aikido-rushx": "bin/aikido-rushx.js",
|
||||||
"aikido-bun": "bin/aikido-bun.js",
|
"aikido-bun": "bin/aikido-bun.js",
|
||||||
"aikido-bunx": "bin/aikido-bunx.js",
|
"aikido-bunx": "bin/aikido-bunx.js",
|
||||||
"aikido-uv": "bin/aikido-uv.js",
|
"aikido-uv": "bin/aikido-uv.js",
|
||||||
|
|
@ -38,7 +39,7 @@
|
||||||
"keywords": [],
|
"keywords": [],
|
||||||
"author": "Aikido Security",
|
"author": "Aikido Security",
|
||||||
"license": "AGPL-3.0-or-later",
|
"license": "AGPL-3.0-or-later",
|
||||||
"description": "The Aikido Safe Chain wraps around the [npm cli](https://github.com/npm/cli), [npx](https://github.com/npm/cli/blob/latest/docs/content/commands/npx.md), [yarn](https://yarnpkg.com/), [pnpm](https://pnpm.io/), [pnpx](https://pnpm.io/cli/dlx), [rush](https://rushjs.io/), [bun](https://bun.sh/), [bunx](https://bun.sh/docs/cli/bunx), [uv](https://docs.astral.sh/uv/) (Python), and [pip](https://pip.pypa.io/) to provide extra checks before installing new packages. This tool will detect when a package contains malware and prompt you to exit, preventing npm, npx, yarn, pnpm, pnpx, rush, bun, bunx, uv, uvx, or pip/pip3 from downloading or running the malware.",
|
"description": "The Aikido Safe Chain wraps around the [npm cli](https://github.com/npm/cli), [npx](https://github.com/npm/cli/blob/latest/docs/content/commands/npx.md), [yarn](https://yarnpkg.com/), [pnpm](https://pnpm.io/), [pnpx](https://pnpm.io/cli/dlx), [rush](https://rushjs.io/), [rushx](https://rushjs.io/pages/commands/rushx/), [bun](https://bun.sh/), [bunx](https://bun.sh/docs/cli/bunx), [uv](https://docs.astral.sh/uv/) (Python), and [pip](https://pip.pypa.io/) to provide extra checks before installing new packages. This tool will detect when a package contains malware and prompt you to exit, preventing npm, npx, yarn, pnpm, pnpx, rush, rushx, bun, bunx, uv, uvx, or pip/pip3 from downloading or running the malware.",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"certifi": "14.5.15",
|
"certifi": "14.5.15",
|
||||||
"chalk": "5.4.1",
|
"chalk": "5.4.1",
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,7 @@ import { createUvPackageManager } from "./uv/createUvPackageManager.js";
|
||||||
import { createPoetryPackageManager } from "./poetry/createPoetryPackageManager.js";
|
import { createPoetryPackageManager } from "./poetry/createPoetryPackageManager.js";
|
||||||
import { createPipXPackageManager } from "./pipx/createPipXPackageManager.js";
|
import { createPipXPackageManager } from "./pipx/createPipXPackageManager.js";
|
||||||
import { createRushPackageManager } from "./rush/createRushPackageManager.js";
|
import { createRushPackageManager } from "./rush/createRushPackageManager.js";
|
||||||
|
import { createRushxPackageManager } from "./rushx/createRushxPackageManager.js";
|
||||||
import { createUvxPackageManager } from "./uvx/createUvxPackageManager.js";
|
import { createUvxPackageManager } from "./uvx/createUvxPackageManager.js";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -70,6 +71,8 @@ export function initializePackageManager(packageManagerName, context) {
|
||||||
state.packageManagerName = createPipXPackageManager();
|
state.packageManagerName = createPipXPackageManager();
|
||||||
} else if (packageManagerName === "rush") {
|
} else if (packageManagerName === "rush") {
|
||||||
state.packageManagerName = createRushPackageManager();
|
state.packageManagerName = createRushPackageManager();
|
||||||
|
} else if (packageManagerName === "rushx") {
|
||||||
|
state.packageManagerName = createRushxPackageManager();
|
||||||
} else {
|
} else {
|
||||||
throw new Error("Unsupported package manager: " + packageManagerName);
|
throw new Error("Unsupported package manager: " + packageManagerName);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@ import { resolvePackageVersion } from "../../api/npmApi.js";
|
||||||
*/
|
*/
|
||||||
export function createRushPackageManager() {
|
export function createRushPackageManager() {
|
||||||
return {
|
return {
|
||||||
runCommand: runRushCommand,
|
runCommand: (args) => runRushCommand("rush", args),
|
||||||
// We pre-scan rush add commands and rely on MITM for install/update flows.
|
// We pre-scan rush add commands and rely on MITM for install/update flows.
|
||||||
isSupportedCommand: (args) => getRushCommand(args) === "add",
|
isSupportedCommand: (args) => getRushCommand(args) === "add",
|
||||||
getDependencyUpdatesForCommand: scanRushAddCommand,
|
getDependencyUpdatesForCommand: scanRushAddCommand,
|
||||||
|
|
|
||||||
|
|
@ -3,23 +3,24 @@ import { safeSpawn } from "../../utils/safeSpawn.js";
|
||||||
import { reportCommandExecutionFailure } from "../_shared/commandErrors.js";
|
import { reportCommandExecutionFailure } from "../_shared/commandErrors.js";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* @param {"rush" | "rushx"} executableName
|
||||||
* @param {string[]} args
|
* @param {string[]} args
|
||||||
* @returns {Promise<{status: number}>}
|
* @returns {Promise<{status: number}>}
|
||||||
*/
|
*/
|
||||||
export async function runRushCommand(args) {
|
export async function runRushCommand(executableName, args) {
|
||||||
try {
|
try {
|
||||||
const env = normalizeProxyEnvironmentVariables(
|
const env = normalizeProxyEnvironmentVariables(
|
||||||
mergeSafeChainProxyEnvironmentVariables(process.env),
|
mergeSafeChainProxyEnvironmentVariables(process.env),
|
||||||
);
|
);
|
||||||
|
|
||||||
const result = await safeSpawn("rush", args, {
|
const result = await safeSpawn(executableName, args, {
|
||||||
stdio: "inherit",
|
stdio: "inherit",
|
||||||
env,
|
env,
|
||||||
});
|
});
|
||||||
|
|
||||||
return { status: result.status };
|
return { status: result.status };
|
||||||
} catch (/** @type any */ error) {
|
} catch (/** @type any */ error) {
|
||||||
return reportCommandExecutionFailure(error, "rush");
|
return reportCommandExecutionFailure(error, executableName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -64,7 +64,7 @@ describe("runRushCommand", () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it("spawns rush with merged proxy env", async () => {
|
it("spawns rush with merged proxy env", async () => {
|
||||||
const res = await runRushCommand(["install"]);
|
const res = await runRushCommand("rush", ["install"]);
|
||||||
|
|
||||||
assert.strictEqual(res.status, 0);
|
assert.strictEqual(res.status, 0);
|
||||||
assert.strictEqual(safeSpawnMock.mock.calls.length, 1);
|
assert.strictEqual(safeSpawnMock.mock.calls.length, 1);
|
||||||
|
|
@ -88,7 +88,7 @@ describe("runRushCommand", () => {
|
||||||
it("returns spawn result status", async () => {
|
it("returns spawn result status", async () => {
|
||||||
nextSpawnStatus = 7;
|
nextSpawnStatus = 7;
|
||||||
|
|
||||||
const res = await runRushCommand(["update"]);
|
const res = await runRushCommand("rush", ["update"]);
|
||||||
|
|
||||||
assert.strictEqual(res.status, 7);
|
assert.strictEqual(res.status, 7);
|
||||||
});
|
});
|
||||||
|
|
@ -98,7 +98,7 @@ describe("runRushCommand", () => {
|
||||||
code: "ENOENT",
|
code: "ENOENT",
|
||||||
});
|
});
|
||||||
|
|
||||||
const res = await runRushCommand(["install"]);
|
const res = await runRushCommand("rush", ["install"]);
|
||||||
|
|
||||||
assert.strictEqual(res.status, 1);
|
assert.strictEqual(res.status, 1);
|
||||||
});
|
});
|
||||||
|
|
@ -108,7 +108,7 @@ describe("runRushCommand", () => {
|
||||||
HTTPS_PROXY: "http://localhost:8080",
|
HTTPS_PROXY: "http://localhost:8080",
|
||||||
};
|
};
|
||||||
|
|
||||||
await runRushCommand(["install"]);
|
await runRushCommand("rush", ["install"]);
|
||||||
|
|
||||||
assert.deepStrictEqual(mergeResultEnv, {
|
assert.deepStrictEqual(mergeResultEnv, {
|
||||||
HTTPS_PROXY: "http://localhost:8080",
|
HTTPS_PROXY: "http://localhost:8080",
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,18 @@
|
||||||
|
import { runRushCommand } from "../rush/runRushCommand.js";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @returns {import("../currentPackageManager.js").PackageManager}
|
||||||
|
*/
|
||||||
|
export function createRushxPackageManager() {
|
||||||
|
return {
|
||||||
|
/**
|
||||||
|
* @param {string[]} args
|
||||||
|
*/
|
||||||
|
runCommand: (args) => {
|
||||||
|
return runRushCommand("rushx", args);
|
||||||
|
},
|
||||||
|
// For rushx, rely solely on MITM.
|
||||||
|
isSupportedCommand: () => false,
|
||||||
|
getDependencyUpdatesForCommand: () => [],
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,14 @@
|
||||||
|
import { test } from "node:test";
|
||||||
|
import assert from "node:assert";
|
||||||
|
import { createRushxPackageManager } from "./createRushxPackageManager.js";
|
||||||
|
|
||||||
|
test("createRushxPackageManager returns valid package manager interface", () => {
|
||||||
|
const pm = createRushxPackageManager();
|
||||||
|
|
||||||
|
assert.ok(pm);
|
||||||
|
assert.strictEqual(typeof pm.runCommand, "function");
|
||||||
|
assert.strictEqual(typeof pm.isSupportedCommand, "function");
|
||||||
|
assert.strictEqual(typeof pm.getDependencyUpdatesForCommand, "function");
|
||||||
|
assert.strictEqual(pm.isSupportedCommand(), false);
|
||||||
|
assert.deepStrictEqual(pm.getDependencyUpdatesForCommand(), []);
|
||||||
|
});
|
||||||
|
|
@ -54,6 +54,12 @@ export const knownAikidoTools = [
|
||||||
ecoSystem: ECOSYSTEM_JS,
|
ecoSystem: ECOSYSTEM_JS,
|
||||||
internalPackageManagerName: "rush",
|
internalPackageManagerName: "rush",
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
tool: "rushx",
|
||||||
|
aikidoCommand: "aikido-rushx",
|
||||||
|
ecoSystem: ECOSYSTEM_JS,
|
||||||
|
internalPackageManagerName: "rushx",
|
||||||
|
},
|
||||||
{
|
{
|
||||||
tool: "bun",
|
tool: "bun",
|
||||||
aikidoCommand: "aikido-bun",
|
aikidoCommand: "aikido-bun",
|
||||||
|
|
|
||||||
|
|
@ -48,9 +48,8 @@ describe("Setup CI shell integration", () => {
|
||||||
knownAikidoTools: [
|
knownAikidoTools: [
|
||||||
{ tool: "npm", aikidoCommand: "aikido-npm" },
|
{ tool: "npm", aikidoCommand: "aikido-npm" },
|
||||||
{ tool: "yarn", aikidoCommand: "aikido-yarn" },
|
{ tool: "yarn", aikidoCommand: "aikido-yarn" },
|
||||||
{ tool: "rush", aikidoCommand: "aikido-rush" },
|
|
||||||
],
|
],
|
||||||
getPackageManagerList: () => "npm, yarn, rush",
|
getPackageManagerList: () => "npm, yarn",
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -108,10 +107,6 @@ describe("Setup CI shell integration", () => {
|
||||||
const yarnShimPath = path.join(mockShimsDir, "yarn");
|
const yarnShimPath = path.join(mockShimsDir, "yarn");
|
||||||
assert.ok(fs.existsSync(yarnShimPath), "yarn shim should exist");
|
assert.ok(fs.existsSync(yarnShimPath), "yarn shim should exist");
|
||||||
|
|
||||||
// Check if rush shim was created
|
|
||||||
const rushShimPath = path.join(mockShimsDir, "rush");
|
|
||||||
assert.ok(fs.existsSync(rushShimPath), "rush shim should exist");
|
|
||||||
|
|
||||||
// Check content of npm shim
|
// Check content of npm shim
|
||||||
const npmShimContent = fs.readFileSync(npmShimPath, "utf-8");
|
const npmShimContent = fs.readFileSync(npmShimPath, "utf-8");
|
||||||
assert.ok(npmShimContent.includes("aikido-npm"), "npm shim should contain aikido-npm");
|
assert.ok(npmShimContent.includes("aikido-npm"), "npm shim should contain aikido-npm");
|
||||||
|
|
@ -138,9 +133,6 @@ describe("Setup CI shell integration", () => {
|
||||||
const yarnShimPath = path.join(mockShimsDir, "yarn.cmd");
|
const yarnShimPath = path.join(mockShimsDir, "yarn.cmd");
|
||||||
assert.ok(fs.existsSync(yarnShimPath), "yarn.cmd shim should exist");
|
assert.ok(fs.existsSync(yarnShimPath), "yarn.cmd shim should exist");
|
||||||
|
|
||||||
const rushShimPath = path.join(mockShimsDir, "rush.cmd");
|
|
||||||
assert.ok(fs.existsSync(rushShimPath), "rush.cmd shim should exist");
|
|
||||||
|
|
||||||
// Check content of npm.cmd shim
|
// Check content of npm.cmd shim
|
||||||
const npmShimContent = fs.readFileSync(npmShimPath, "utf-8");
|
const npmShimContent = fs.readFileSync(npmShimPath, "utf-8");
|
||||||
assert.ok(npmShimContent.includes("aikido-npm"), "npm.cmd should contain aikido-npm");
|
assert.ok(npmShimContent.includes("aikido-npm"), "npm.cmd should contain aikido-npm");
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,14 @@ function pnpx
|
||||||
wrapSafeChainCommand "pnpx" $argv
|
wrapSafeChainCommand "pnpx" $argv
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function rush
|
||||||
|
wrapSafeChainCommand "rush" $argv
|
||||||
|
end
|
||||||
|
|
||||||
|
function rushx
|
||||||
|
wrapSafeChainCommand "rushx" $argv
|
||||||
|
end
|
||||||
|
|
||||||
function bun
|
function bun
|
||||||
wrapSafeChainCommand "bun" $argv
|
wrapSafeChainCommand "bun" $argv
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -28,6 +28,14 @@ function pnpx() {
|
||||||
wrapSafeChainCommand "pnpx" "$@"
|
wrapSafeChainCommand "pnpx" "$@"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function rush() {
|
||||||
|
wrapSafeChainCommand "rush" "$@"
|
||||||
|
}
|
||||||
|
|
||||||
|
function rushx() {
|
||||||
|
wrapSafeChainCommand "rushx" "$@"
|
||||||
|
}
|
||||||
|
|
||||||
function bun() {
|
function bun() {
|
||||||
wrapSafeChainCommand "bun" "$@"
|
wrapSafeChainCommand "bun" "$@"
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,14 @@ function pnpx {
|
||||||
Invoke-WrappedCommand "pnpx" $args $MyInvocation.Line $MyInvocation.OffsetInLine
|
Invoke-WrappedCommand "pnpx" $args $MyInvocation.Line $MyInvocation.OffsetInLine
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function rush {
|
||||||
|
Invoke-WrappedCommand "rush" $args $MyInvocation.Line $MyInvocation.OffsetInLine
|
||||||
|
}
|
||||||
|
|
||||||
|
function rushx {
|
||||||
|
Invoke-WrappedCommand "rushx" $args $MyInvocation.Line $MyInvocation.OffsetInLine
|
||||||
|
}
|
||||||
|
|
||||||
function bun {
|
function bun {
|
||||||
Invoke-WrappedCommand "bun" $args $MyInvocation.Line $MyInvocation.OffsetInLine
|
Invoke-WrappedCommand "bun" $args $MyInvocation.Line $MyInvocation.OffsetInLine
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue