-
Notifications
You must be signed in to change notification settings - Fork 1
Allow cli from nested folders #305
Changes from all commits
d31e658
d768621
1fb7930
c8fb90e
f9aae62
69077f7
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,123 @@ | ||
| import { existsSync, mkdirSync, readdirSync, rmdirSync } from "node:fs"; | ||
| import path from "node:path"; | ||
|
|
||
| import { promptUser, resolveTestTargetId } from "./helpers"; | ||
| import { getTestTargets } from "./tools"; | ||
| import { toFileSystemCompatibleCamelCase } from "./tools/sync/yml"; | ||
|
|
||
| export const OCTOMIND_DIR = ".octomind"; | ||
|
|
||
| export const getPathToOctomindDirWithActiveTestTarget = async (options: { | ||
| startDir?: string; | ||
| providedTestTargetId?: string; | ||
| allowCreation?: boolean; | ||
| }): Promise<string | null> => { | ||
| const testTargetId = await resolveTestTargetId(options.providedTestTargetId); | ||
| const octomindDir = await getPathToOctomindDir({ | ||
| allowCreation: options.allowCreation, | ||
| startDir: options.startDir, | ||
| }); | ||
| if (!octomindDir) { | ||
| return null; | ||
| } | ||
| const testTargets = await getTestTargets(); | ||
| const testTarget = testTargets.find((tt) => tt.id === testTargetId); | ||
| if (!testTarget) { | ||
| throw new Error(`Configured test target with id ${testTargetId} not found`); | ||
| } | ||
| const testTargetDirName = toFileSystemCompatibleCamelCase(testTarget.app); | ||
| const testTargetFolderPath = path.resolve( | ||
| path.join(octomindDir, testTargetDirName), | ||
| ); | ||
| if (!existsSync(testTargetFolderPath)) { | ||
| mkdirSync(testTargetFolderPath, { recursive: true }); | ||
| } | ||
| return testTargetFolderPath; | ||
| }; | ||
|
|
||
| export const getPathToOctomindDir = async ({ | ||
| allowCreation, | ||
| startDir = process.cwd(), | ||
| }: { | ||
| allowCreation?: boolean; | ||
| startDir?: string; | ||
| } = {}): Promise<string | null> => { | ||
| let currentDir = startDir; | ||
| // Make loop stop when reaching the root directory, in an OS-independent way | ||
| while (currentDir !== path.dirname(currentDir)) { | ||
| if (checkForOctomindDir(currentDir)) { | ||
| return path.resolve(path.join(currentDir, OCTOMIND_DIR)); | ||
| } | ||
| currentDir = path.dirname(currentDir); | ||
| } | ||
| if (allowCreation) { | ||
| return createOctomindDirInteractive({ dir: startDir }); | ||
| } | ||
| return null; | ||
| }; | ||
|
|
||
| const checkForOctomindDir = (dir: string): boolean => { | ||
| const octomindDir = path.join(dir, OCTOMIND_DIR); | ||
| try { | ||
| return existsSync(octomindDir); | ||
| } catch (error) { | ||
| console.debug(`Error checking for octomind dir in ${dir}:`, error); | ||
| // likely a permission issue, so we return false | ||
| return false; | ||
| } | ||
| }; | ||
|
|
||
| export const createOctomindDirInteractive = async ( | ||
| options: { dir?: string; recreateOctomindDir?: boolean } = {}, | ||
| ): Promise<string> => { | ||
| const dir = path.resolve( | ||
| path.join(options.dir ?? process.cwd(), OCTOMIND_DIR), | ||
| ); | ||
| const existingOctomindDir = await getPathToOctomindDir({ | ||
| allowCreation: false, | ||
| startDir: options.dir, | ||
| }); | ||
|
|
||
| if ( | ||
| existingOctomindDir && | ||
| existingOctomindDir !== dir && | ||
| !options.recreateOctomindDir | ||
| ) { | ||
| console.log(`Octomind directory already exists: ${existingOctomindDir}.`); | ||
| console.log(`Using existing octomind directory.`); | ||
| return existingOctomindDir; | ||
| } | ||
|
|
||
| if (existingOctomindDir !== null) { | ||
| console.log(`Octomind directory already exists: ${dir}.`); | ||
| const removeExisting = | ||
| options.recreateOctomindDir || | ||
| ( | ||
| await promptUser(`Remove and recreate empty directory? (y/N): `) | ||
| ).toLowerCase() === "y"; | ||
| if (removeExisting) { | ||
| console.log(`Removing and recreating empty directory...`); | ||
| rmdirSync(existingOctomindDir); | ||
| mkdirSync(dir, { recursive: true }); | ||
| } else { | ||
| console.log(`Using existing octomind directory.`); | ||
| } | ||
| } else { | ||
| mkdirSync(dir, { recursive: true }); | ||
| console.log(`✨ Created octomind directory: ${dir}`); | ||
| } | ||
| return dir; | ||
| }; | ||
|
|
||
| export const showOctomindDir = async (): Promise<void> => { | ||
| const octomindDir = await getPathToOctomindDirWithActiveTestTarget({ | ||
| allowCreation: false, | ||
| }); | ||
| if (!octomindDir) { | ||
| console.log( | ||
| "You are not in an octomind directory or one of its children. Please run `octomind pull` to create one.", | ||
| ); | ||
| return; | ||
| } | ||
| console.log(`Octomind directory: ${octomindDir}`); | ||
| }; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,5 +1,9 @@ | ||
| import path from "path"; | ||
|
|
||
| import { | ||
| getPathToOctomindDir, | ||
| getPathToOctomindDirWithActiveTestTarget, | ||
| } from "../dirManagement"; | ||
| import { getUrl } from "../url"; | ||
| import { client, handleError, ListOptions, logJson } from "./client"; | ||
| import { push } from "./sync/push"; | ||
|
|
@@ -44,7 +48,7 @@ export const listTestTargets = async (options: ListOptions): Promise<void> => { | |
| }; | ||
|
|
||
| export const pullTestTarget = async ( | ||
| options: { testTargetId: string; destination?: string } & ListOptions, | ||
| options: { testTargetId: string } & ListOptions, | ||
| ): Promise<void> => { | ||
| const { data, error } = await client.GET( | ||
| "/apiKey/beta/test-targets/{testTargetId}/pull", | ||
|
|
@@ -68,21 +72,32 @@ export const pullTestTarget = async ( | |
| return; | ||
| } | ||
|
|
||
| writeYaml(data, options.destination); | ||
| const destination = await getPathToOctomindDirWithActiveTestTarget({ | ||
| allowCreation: true, | ||
| providedTestTargetId: options.testTargetId, | ||
| }); | ||
| if (!destination) { | ||
| throw new Error("No octomind directory found"); | ||
| } | ||
| writeYaml(data, destination); | ||
|
|
||
| console.log("Test Target pulled successfully"); | ||
| }; | ||
|
|
||
| export const pushTestTarget = async ( | ||
| options: { testTargetId: string; source?: string } & ListOptions, | ||
| options: { testTargetId: string } & ListOptions, | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. fyi, currently https://github.com/OctoMind-dev/automagically-action-execute/blob/v2.8.4/.github/workflows/main.yml#L126 this workflow relies on it being possible to configure a different source (so that the OTHER steps in that workflow do NOT use ymls) We can solve that differently (by writing the ymls only in the step they should be used), but just so you are aware
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't get this comment, please come up with a solution in january ;) |
||
| ): Promise<void> => { | ||
| const sourceDir = options.source | ||
| ? path.resolve(options.source) | ||
| : process.cwd(); | ||
| const source = await getPathToOctomindDirWithActiveTestTarget({ | ||
| allowCreation: false, | ||
| providedTestTargetId: options.testTargetId, | ||
| }); | ||
| if (!source) { | ||
| throw new Error("No octomind directory found"); | ||
| } | ||
|
|
||
| const data = await push({ | ||
| ...options, | ||
| sourceDir, | ||
| sourceDir: source, | ||
| testTargetId: options.testTargetId, | ||
| onError: handleError, | ||
| client, | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.