Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Test for hard-to-detect recursive CLI calls #996

Merged
merged 14 commits into from
May 3, 2024
Merged
84 changes: 84 additions & 0 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -147,3 +147,87 @@ jobs:
runs-on: ubuntu-latest
steps:
- run: echo OK

test-cli-wrapper:
name: "Test CLI Wrapper"
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 1

- name: Set up Node 20
uses: actions/setup-node@v4
with:
node-version: 20

- name: Set up Deno
uses: denoland/setup-deno@v1
with:
deno-version: v1.x

- name: Install EdgeDB
uses: edgedb/setup-edgedb@6763b6de72782d9c2e5ecc1095986a1c707da68f
with:
cli-version: stable
server-version: none

- name: Install dev deps
run: |
yarn --frozen-lockfile

- name: Build and pack CLI wrapper
run: |
yarn workspace edgedb run build
yarn workspace edgedb pack --filename=${{ github.workspace }}/edgedb-cli.tar.gz

- name: Test CLI wrapper with npm
run: |
mkdir temp-npm
cd temp-npm
npm init -y
npm install ${{ github.workspace }}/edgedb-cli.tar.gz
npm exec edgedb -- --version

- name: Test CLI wrapper with yarn
run: |
mkdir temp-yarn
cd temp-yarn
yarn init -y
yarn add ${{ github.workspace}}/edgedb-cli.tar.gz
yarn edgedb --version

- uses: threeal/setup-yarn-action@ec8c075e62bc497968de40011c2b766f5e8f1ac5
with:
version: latest
cache: false
- name: Test CLI wrapper with yarn-berry
run: |
mkdir temp-yarn-berry
cd temp-yarn-berry
yarn set version berry
yarn init -y
touch yarn.lock
yarn add ${{ github.workspace }}/edgedb-cli.tar.gz
yarn edgedb --version

- uses: pnpm/action-setup@a3252b78c470c02df07e9d59298aecedc3ccdd6d
with:
version: latest
run_install: false
- name: Test CLI wrapper with pnpm
run: |
mkdir temp-pnpm
cd temp-pnpm
pnpm init
pnpm add ${{ github.workspace }}/edgedb-cli.tar.gz
pnpm exec edgedb --version

- uses: oven-sh/setup-bun@8f24390df009a496891208e5e36b8a1de1f45135
- name: Test CLI wrapper with bun
run: |
mkdir temp-bun
cd temp-bun
bun init
bun add ${{ github.workspace }}/edgedb-cli.tar.gz
bun edgedb --version
72 changes: 65 additions & 7 deletions packages/driver/src/cli.mts
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,22 @@ await main(args);
async function main(args: string[]) {
debug(`Running CLI wrapper from: ${fileURLToPath(import.meta.url)}`);
debug("Starting main function with args:", args);
debug(` - IS_TTY: ${IS_TTY}`);
debug(` - SCRIPT_LOCATION: ${SCRIPT_LOCATION}`);
debug(` - EDGEDB_PKG_ROOT: ${EDGEDB_PKG_ROOT}`);
debug(` - CACHE_DIR: ${CACHE_DIR}`);
debug(` - TEMPORARY_CLI_PATH: ${TEMPORARY_CLI_PATH}`);
debug(` - CLI_LOCATION_CACHE_FILE_PATH: ${CLI_LOCATION_CACHE_FILE_PATH}`);

// check to see if we are being tested as a CLI binary wrapper
if (args.length === 1 && args[0] === "--succeed-if-cli-bin-wrapper") {
process.exit(0);
}

const maybeCachedCliLocation = await getCliLocationFromCache();
const cliLocation =
maybeCachedCliLocation ??
(await whichEdgeDbCli()) ??
(await getCliLocationFromCache()) ??
(await getCliLocationFromTempCli()) ??
(await selfInstallFromTempCli()) ??
null;
Expand All @@ -52,6 +65,14 @@ async function main(args: string[]) {

try {
runEdgeDbCli(args, cliLocation);
if (cliLocation !== maybeCachedCliLocation) {
debug("CLI location not cached.");
debug(` - Cached location: ${maybeCachedCliLocation}`);
debug(` - CLI location: ${cliLocation}`);
debug(`Updating cache with new CLI location: ${cliLocation}`);
await writeCliLocationToCache(cliLocation);
debug("Cache updated.");
}
} catch (err) {
if (
typeof err === "object" &&
Expand Down Expand Up @@ -102,6 +123,16 @@ async function whichEdgeDbCli() {
continue;
}

try {
runEdgeDbCli(["--succeed-if-cli-bin-wrapper"], actualLocation, {
stdio: "ignore",
});
debug(" - CLI found in PATH is wrapper script. Ignoring.");
continue;
} catch (err) {
debug(" - CLI found in PATH is not a wrapper script. Using.");
}

return location;
}
debug(" - No CLI found in PATH.");
Expand All @@ -111,9 +142,29 @@ async function whichEdgeDbCli() {
async function getCliLocationFromCache(): Promise<string | null> {
debug("Checking CLI cache...");
try {
const cachedBinaryPath = (
await fs.readFile(CLI_LOCATION_CACHE_FILE_PATH, { encoding: "utf8" })
).trim();
let cachedBinaryPath: string | null = null;
try {
cachedBinaryPath = (
await fs.readFile(CLI_LOCATION_CACHE_FILE_PATH, { encoding: "utf8" })
).trim();
} catch (err: unknown) {
if (
typeof err === "object" &&
err !== null &&
"code" in err &&
err.code === "ENOENT"
) {
debug(" - Cache file does not exist.");
} else if (
typeof err === "object" &&
err !== null &&
"code" in err &&
err.code === "EACCES"
) {
debug(" - No permission to read cache file.");
}
return null;
}
debug(" - CLI path in cache at:", cachedBinaryPath);

try {
Expand All @@ -136,9 +187,7 @@ async function getCliLocationFromTempCli(): Promise<string | null> {

const installDir = getInstallDir(TEMPORARY_CLI_PATH);
const binaryPath = path.join(installDir, "edgedb");
await fs.writeFile(CLI_LOCATION_CACHE_FILE_PATH, binaryPath, {
encoding: "utf8",
});
await writeCliLocationToCache(binaryPath);
debug(" - CLI installed at:", binaryPath);

try {
Expand All @@ -151,6 +200,15 @@ async function getCliLocationFromTempCli(): Promise<string | null> {
}
}

async function writeCliLocationToCache(cliLocation: string) {
debug("Writing CLI location to cache:", cliLocation);
const dir = path.dirname(CLI_LOCATION_CACHE_FILE_PATH);
await fs.mkdir(dir, { recursive: true });
await fs.writeFile(CLI_LOCATION_CACHE_FILE_PATH, cliLocation, {
encoding: "utf8",
});
}

async function selfInstallFromTempCli(): Promise<string | null> {
debug("Self-installing EdgeDB CLI...");
runEdgeDbCli(["_self_install"], TEMPORARY_CLI_PATH);
Expand Down