From f188ecfd62280151473d0000c8a1c4d6e49cf58f Mon Sep 17 00:00:00 2001 From: Webber Date: Thu, 1 Sep 2022 22:14:18 +0200 Subject: [PATCH] feat: add "config open" command --- README.md | 35 +++---------- deno.json | 25 +++++++--- src/cli.ts | 11 ++++- src/command/build/unity-build-command.ts | 49 +++++++++---------- src/command/command-base.ts | 13 ++--- src/command/command-factory.ts | 33 +++++++++---- src/command/command-interface.ts | 7 ++- .../config/open-config-folder-command.ts | 17 +++++++ src/command/null/non-existent-command.ts | 17 +++---- src/index.ts | 9 ++-- 10 files changed, 120 insertions(+), 96 deletions(-) create mode 100644 src/command/config/open-config-folder-command.ts diff --git a/README.md b/README.md index c188cae1..5487e003 100644 --- a/README.md +++ b/README.md @@ -1,39 +1,16 @@ -# Unity - Builder +# GameCI CLI -(Not affiliated with Unity Technologies) +The CLI is currently a work in progress. -GitHub Action to -[build Unity projects](https://github.com/marketplace/actions/unity-builder) -for different platforms. +We expect it to be working by the end of 2022. -Part of the GameCI open source project. -
-
- -[![Actions status](https://github.com/game-ci/unity-builder/workflows/Builds/badge.svg?event=push&branch=main)](https://github.com/game-ci/unity-builder/actions?query=branch%3Amain+event%3Apush+workflow%3A%22Builds) -[![lgtm - code quality](https://img.shields.io/lgtm/grade/javascript/g/webbertakken/unity-builder.svg?logo=lgtm&logoWidth=18)](https://lgtm.com/projects/g/webbertakken/unity-builder/context:javascript) -[![codecov - test coverage](https://codecov.io/gh/game-ci/unity-builder/branch/master/graph/badge.svg)](https://codecov.io/gh/game-ci/unity-builder) -
-
- -## How to use - -Find the -[docs](https://game.ci/docs/github/builder) -on the GameCI -[documentation website](https://game.ci/docs). - -## Related actions - -Visit the -GameCI Unity Actions -status repository for related Actions. +See [our roadmap](https://github.com/orgs/game-ci/projects/4/views/1) to follow our progress. ## Community Feel free to join us on -Discord -and engage with the community. +Discord and engage with the +community. ## Contributing diff --git a/deno.json b/deno.json index b5c8dced..ea6676af 100644 --- a/deno.json +++ b/deno.json @@ -1,27 +1,40 @@ { "tasks": { + "config": "deno run -A .tools/open-config-folder.ts", "test": "deno test -A ./src/integrity.test.ts", "coverage": "rm -rf .coverage ; deno test -A ./src/integrity.test.ts --coverage=.coverage/raw ; deno coverage .coverage/raw --lcov --output=.coverage/raw/.lcov ; perl .tools/lcov/genhtml.perl -q -o .coverage/report .coverage/raw/.lcov && deno run -A .tools/open-coverage-report.ts" }, "compilerOptions": { "allowJs": true, - "lib": ["deno.window"], + "lib": [ + "deno.window" + ], "strict": true }, "lint": { "files": { - "include": ["src/"], + "include": [ + "src/" + ], "exclude": [] }, "rules": { - "tags": ["recommended"], - "include": ["ban-untagged-todo"], - "exclude": ["no-unused-vars"] + "tags": [ + "recommended" + ], + "include": [ + "ban-untagged-todo" + ], + "exclude": [ + "no-unused-vars" + ] } }, "fmt": { "files": { - "include": ["src/"], + "include": [ + "src/" + ], "exclude": [] }, "options": { diff --git a/src/cli.ts b/src/cli.ts index 9191bf3a..2c0220c9 100644 --- a/src/cli.ts +++ b/src/cli.ts @@ -25,6 +25,7 @@ export class Cli { this.configureLogger(); this.globalOptions(); + await this.registerConfigCommand(); await this.registerBuildCommand(); await this.parse(); @@ -45,7 +46,7 @@ export class Cli { const defaultAbsolutePath = `${this.cliStorageAbsolutePath}/${this.configFileName}`; this.yargs - .config('config', `default: ${defaultCanonicalPath}`, async (override) => { + .config('config', `default: ${defaultCanonicalPath}`, async (override: string) => { const configPath = override || defaultAbsolutePath; return JSON.parse(await Deno.readTextFile(configPath)); @@ -150,6 +151,14 @@ export class Cli { }); } + private async registerConfigCommand() { + this.yargs.command('config', 'GameCI CLI configuration', async (yargs) => { + yargs + .command('open', 'Opens the CLI configuration folder', async (yargs) => {}) + .middleware([async (args) => this.registerCommand(args, yargs)]); + }); + } + private async registerCommand(args: YargsArguments, yargs: YargsInstance) { const { engine, engineVersion, _: command } = args; diff --git a/src/command/build/unity-build-command.ts b/src/command/build/unity-build-command.ts index cb83f2b3..8ec5ffec 100644 --- a/src/command/build/unity-build-command.ts +++ b/src/command/build/unity-build-command.ts @@ -4,36 +4,33 @@ import PlatformSetup from '../../model/platform-setup.ts'; import MacBuilder from '../../model/mac-builder.ts'; import { CommandBase } from '../command-base.ts'; import { UnityOptions } from '../../command-options/unity-options.ts'; -import { YargsInstance } from '../../dependencies.ts'; +import { YargsInstance, YargsArguments } from '../../dependencies.ts'; import { VersioningOptions } from '../../command-options/versioning-options.ts'; import { BuildOptions } from '../../command-options/build-options.ts'; export class UnityBuildCommand extends CommandBase implements CommandInterface { - public async execute(options): Promise { - try { - // Todo - rework this without needing this.options, use parameters from cli instead. - // const { workspace, actionFolder } = Action; - // const { parameters, env } = this.options; - // - // Action.checkCompatibility(); - // Cache.verify(); - // - // const baseImage = new ImageTag(options); - // log.debug('baseImage', baseImage); - // - // await PlatformSetup.setup(parameters, actionFolder); - // if (env.getOS() === 'darwin') { - // MacBuilder.run(actionFolder, workspace, parameters); - // } else { - // await Docker.run(baseImage, { workspace, actionFolder, ...parameters }); - // } - // - // // Set output - // await Output.setBuildVersion(parameters.buildVersion); - } catch (error) { - log.error(error); - Deno.exit(1); - } + public async execute(options: YargsArguments): Promise { + // Todo - rework this without needing this.options, use parameters from cli instead. + // const { workspace, actionFolder } = Action; + // const { parameters, env } = this.options; + // + // Action.checkCompatibility(); + // Cache.verify(); + // + // const baseImage = new ImageTag(options); + // log.debug('baseImage', baseImage); + // + // await PlatformSetup.setup(parameters, actionFolder); + // if (env.getOS() === 'darwin') { + // MacBuilder.run(actionFolder, workspace, parameters); + // } else { + // await Docker.run(baseImage, { workspace, actionFolder, ...parameters }); + // } + // + // // Set output + // await Output.setBuildVersion(parameters.buildVersion); + + return true; } public async configureOptions(yargs: YargsInstance): Promise { diff --git a/src/command/command-base.ts b/src/command/command-base.ts index 00c95ce6..1fb93e2a 100644 --- a/src/command/command-base.ts +++ b/src/command/command-base.ts @@ -1,17 +1,18 @@ -import { Options } from '../config/options.ts'; -import { Input } from '../model/index.ts'; -import Parameters from '../model/parameters.ts'; import { CommandInterface } from './command-interface.ts'; +import { YargsArguments, YargsInstance } from '../dependencies.ts'; export class CommandBase implements CommandInterface { public readonly name: string; - private options: Options; constructor(name: string) { - this.name = name; + this.name = name.charAt(0).toUpperCase() + name.slice(1); } - public async execute(): Promise { + public execute(options: YargsArguments): Promise { + throw new Error('Method not implemented.'); + } + + public configureOptions(yargs: YargsInstance): Promise { throw new Error('Method not implemented.'); } } diff --git a/src/command/command-factory.ts b/src/command/command-factory.ts index f9122b28..7c17159c 100644 --- a/src/command/command-factory.ts +++ b/src/command/command-factory.ts @@ -1,8 +1,8 @@ import { NonExistentCommand } from './null/non-existent-command.ts'; import { UnityBuildCommand } from './build/unity-build-command.ts'; import { CommandInterface } from './command-interface.ts'; -import { UnityRemoteBuildCommand } from './remote/unity-remote-build-command.ts'; import { Engine } from '../model/engine/engine.ts'; +import { OpenConfigFolderCommand } from './config/open-config-folder-command.ts'; export class CommandFactory { constructor() {} @@ -14,27 +14,40 @@ export class CommandFactory { return this; } - public createCommand(command: string[]): CommandInterface { - // Structure looks like: _: [ "build" ], - const commandName = command[0]; + public createCommand(commandArray: string[]): CommandInterface { + // Structure looks like: _: [ "build" ], or _: [ "config", "open" ] + const [command, ...subCommands] = commandArray; + + if (command === 'config') { + return this.createConfigCommand(command, subCommands); + } switch (this.engine) { case Engine.unity: - return this.createUnityCommand(commandName); + return this.createUnityCommand(command, subCommands); default: throw new Error(`Engine ${this.engine} is not yet supported.`); } } - private createUnityCommand(commandName: string) { - switch (commandName) { + private createConfigCommand(command: string, subCommands: string[]) { + switch (subCommands[0]) { + case 'open': + return new OpenConfigFolderCommand(command); + default: + return new NonExistentCommand([command, ...subCommands].join(' ')); + } + } + + private createUnityCommand(command: string, subCommands: string[]) { + switch (command) { case 'build': - return new UnityBuildCommand(commandName); + return new UnityBuildCommand(command); // case 'remote-build': // return new UnityRemoteBuildCommand(commandName); - // default: - // return new NonExistentCommand(commandName); + default: + return new NonExistentCommand([command, ...subCommands].join(' ')); } } } diff --git a/src/command/command-interface.ts b/src/command/command-interface.ts index fb8094a4..e32430b5 100644 --- a/src/command/command-interface.ts +++ b/src/command/command-interface.ts @@ -1,8 +1,7 @@ -import { Options } from '../config/options.ts'; -import { yargs } from '../dependencies.ts'; +import { YargsInstance, YargsArguments } from '../dependencies.ts'; export interface CommandInterface { name: string; - execute: (options: Options) => Promise; - configureOptions: (instance: yargs.Argv) => Promise; + execute: (options: YargsArguments) => Promise; + configureOptions: (instance: YargsInstance) => Promise; } diff --git a/src/command/config/open-config-folder-command.ts b/src/command/config/open-config-folder-command.ts new file mode 100644 index 00000000..0bfda4df --- /dev/null +++ b/src/command/config/open-config-folder-command.ts @@ -0,0 +1,17 @@ +import { CommandInterface } from '../command-interface.ts'; +import { CommandBase } from '../command-base.ts'; +import { YargsInstance, YargsArguments } from '../../dependencies.ts'; + +import { default as getHomeDir } from 'https://deno.land/x/dir@1.5.1/home_dir/mod.ts'; +import { open } from 'https://deno.land/x/opener@v1.0.1/mod.ts'; + +export class OpenConfigFolderCommand extends CommandBase implements CommandInterface { + public async execute(options: YargsArguments): Promise { + const cliStorageAbsolutePath = `${getHomeDir()}/.game-ci`; + await open(`file://${cliStorageAbsolutePath}/`); + + return true; + } + + public async configureOptions(yargs: YargsInstance): Promise {} +} diff --git a/src/command/null/non-existent-command.ts b/src/command/null/non-existent-command.ts index d69244fd..220959d3 100644 --- a/src/command/null/non-existent-command.ts +++ b/src/command/null/non-existent-command.ts @@ -1,16 +1,11 @@ import { CommandInterface } from '../command-interface.ts'; -import { Options } from '../../config/options.ts'; +import { YargsInstance, YargsArguments } from '../../dependencies.ts'; +import { CommandBase } from '../command-base.ts'; -export class NonExistentCommand implements CommandInterface { - public name: string; - - constructor(name: string) { - this.name = name; +export class NonExistentCommand extends CommandBase implements CommandInterface { + public execute(options: YargsArguments): Promise { + throw new Error(`Command "${this.name}" does not exist`); } - public async execute(options: Options): Promise { - throw new Error(`Command ${this.name} does not exist`); - } - - public async parseParameters() {} + public async configureOptions(yargs: YargsInstance): Promise {} } diff --git a/src/index.ts b/src/index.ts index b2d4c631..dfcac95e 100644 --- a/src/index.ts +++ b/src/index.ts @@ -7,10 +7,13 @@ class GameCI { const success = await command.execute(options); - if (!success) log.warning(`${command.constructor.name} failed.`); + if (success) { + log.info(`${command.name} done.`); + } else { + log.warning(`${command.constructor.name} failed.`); + } } catch (error) { - // eslint-disable-next-line no-console - console.error(error); + log.error(error); Deno.exit(1); } }