feat: add "config open" command

pull/413/head
Webber 2022-09-01 22:14:18 +02:00
parent 0ac9b8034b
commit f188ecfd62
10 changed files with 120 additions and 96 deletions

View File

@ -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 <a href="https://game.ci">GameCI</a> open source project.
<br />
<br />
[![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)
<br />
<br />
## 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 <a href="https://github.com/game-ci/unity-actions">Unity Actions</a>
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
<a href="http://game.ci/discord"><img height="30" src="media/Discord-Logo.svg" alt="Discord" /></a>
and engage with the community.
<a href="http://game.ci/discord"><img height="30" src="media/Discord-Logo.svg" alt="Discord" /></a> and engage with the
community.
## Contributing

View File

@ -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": {

View File

@ -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;

View File

@ -4,13 +4,12 @@ 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<boolean> {
try {
public async execute(options: YargsArguments): Promise<boolean> {
// Todo - rework this without needing this.options, use parameters from cli instead.
// const { workspace, actionFolder } = Action;
// const { parameters, env } = this.options;
@ -30,10 +29,8 @@ export class UnityBuildCommand extends CommandBase implements CommandInterface {
//
// // Set output
// await Output.setBuildVersion(parameters.buildVersion);
} catch (error) {
log.error(error);
Deno.exit(1);
}
return true;
}
public async configureOptions(yargs: YargsInstance): Promise<void> {

View File

@ -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<boolean> {
public execute(options: YargsArguments): Promise<boolean> {
throw new Error('Method not implemented.');
}
public configureOptions(yargs: YargsInstance): Promise<void> {
throw new Error('Method not implemented.');
}
}

View File

@ -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(' '));
}
}
}

View File

@ -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<boolean>;
configureOptions: (instance: yargs.Argv) => Promise<void>;
execute: (options: YargsArguments) => Promise<boolean>;
configureOptions: (instance: YargsInstance) => Promise<void>;
}

View File

@ -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<boolean> {
const cliStorageAbsolutePath = `${getHomeDir()}/.game-ci`;
await open(`file://${cliStorageAbsolutePath}/`);
return true;
}
public async configureOptions(yargs: YargsInstance): Promise<void> {}
}

View File

@ -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<boolean> {
throw new Error(`Command "${this.name}" does not exist`);
}
public async execute(options: Options): Promise<boolean> {
throw new Error(`Command ${this.name} does not exist`);
}
public async parseParameters() {}
public async configureOptions(yargs: YargsInstance): Promise<void> {}
}

View File

@ -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);
}
}