From cd3128149aa2e071afa04d503f768cc2f0e758bf Mon Sep 17 00:00:00 2001 From: Webber Date: Tue, 9 Aug 2022 23:53:46 +0200 Subject: [PATCH] chore: make Versioning.branch compatible with local --- src/commands/command-factory.ts | 6 +++--- src/config/options.ts | 2 +- src/index.ts | 1 + src/model/parameters.ts | 7 ++++++- src/model/system.ts | 23 +++++++++++++++++++++-- src/model/versioning.test.ts | 12 ++++++------ src/model/versioning.ts | 19 +++++++++++++++---- 7 files changed, 53 insertions(+), 17 deletions(-) diff --git a/src/commands/command-factory.ts b/src/commands/command-factory.ts index 597c6fc7..b3c296f0 100644 --- a/src/commands/command-factory.ts +++ b/src/commands/command-factory.ts @@ -5,12 +5,12 @@ import { BuildRemoteCommand } from './command/build-remote-command.ts'; export class CommandFactory { constructor() {} - public createCommand(commandName) { + public createCommand(commandName: string) { switch (commandName) { case 'build': - return new BuildCommand(); + return new BuildCommand(commandName); case 'build-remote': - return new BuildRemoteCommand(); + return new BuildRemoteCommand(commandName); default: return new NonExistentCommand(commandName); } diff --git a/src/config/options.ts b/src/config/options.ts index c1a2b2ee..9ec764f2 100644 --- a/src/config/options.ts +++ b/src/config/options.ts @@ -14,7 +14,7 @@ export class Options { public async generateParameters(args: CliArguments) { this.input = new Input(args); - this.parameters = await new Parameters(this.input).parse(); + this.parameters = await new Parameters(this.input, this.env).parse(); log.debug('Parameters generated.'); diff --git a/src/index.ts b/src/index.ts index 525cda03..76334636 100644 --- a/src/index.ts +++ b/src/index.ts @@ -4,6 +4,7 @@ import type { EnvVariables } from './core/env/env-variables.ts'; import { Options } from './config/options.ts'; import { CommandFactory } from './commands/command-factory.ts'; import { ArgumentsParser } from './core/cli/arguments-parser.ts'; +import System from './model/system.ts'; export class GameCI { private readonly commandFactory: CommandFactory; diff --git a/src/model/parameters.ts b/src/model/parameters.ts index 891ad32a..c2de8981 100644 --- a/src/model/parameters.ts +++ b/src/model/parameters.ts @@ -9,6 +9,7 @@ import Versioning from './versioning.ts'; import { GitRepoReader } from './input-readers/git-repo.ts'; import { GithubCliReader } from './input-readers/github-cli.ts'; import { Cli } from './cli/cli.ts'; +import { EnvVariables } from '../core/env/env-variables.ts'; class Parameters { public editorVersion!: string; @@ -65,8 +66,12 @@ class Parameters { public cloudRunnerBuilderPlatform!: string | undefined; public isCliMode!: boolean; - constructor(input: Input) { + private readonly input: Input; + private readonly env: EnvVariables; + + constructor(input: Input, env: EnvVariables) { this.input = input; + this.env = env; } public async parse(): Promise { diff --git a/src/model/system.ts b/src/model/system.ts index 516d2152..f9704f9d 100644 --- a/src/model/system.ts +++ b/src/model/system.ts @@ -1,7 +1,22 @@ import { exec } from '../dependencies.ts'; +export interface ShellRunOptions { + pwd: string; +} + class System { - static async shellRun(command) { + /** + * Run any command as if you're typing in shell. + * Make sure it's Windows/MacOS/Ubuntu compatible or has alternative commands. + * + * Intended to always be silent and capture the output. + */ + static async shellRun(rawCommand: string, options: ShellRunOptions = {}) { + const { pwd } = options; + + let command = rawCommand; + if (pwd) command = `cd ${pwd} ; ${command}`; + return System.newRun('sh', ['-c', command]); } @@ -33,13 +48,17 @@ class System { const result = { status, output }; const symbol = status.success ? '✅' : '❗'; - log.debug('Command:', command, argsString, symbol, result); + const truncatedOutput = output.length >= 30 ? `${output.slice(0, 27)}...` : output; + log.debug('Command:', command, argsString, symbol, { status, output: truncatedOutput }); if (error) throw new Error(error); return result; } + /** + * @deprecated use more simplified `shellRun` if possible. + */ static async run(command, arguments_: any = [], options = {}, shouldLog = true) { let result = ''; let error = ''; diff --git a/src/model/versioning.test.ts b/src/model/versioning.test.ts index 765eed28..bef68c63 100644 --- a/src/model/versioning.test.ts +++ b/src/model/versioning.test.ts @@ -56,10 +56,10 @@ describe('Versioning', () => { }); describe('branch', () => { - it('returns headRef when set', () => { + it('returns headRef when set', async () => { const headReference = jest.spyOn(Versioning, 'headRef', 'get').mockReturnValue('feature-branch-1'); - expect(Versioning.branch).toStrictEqual('feature-branch-1'); + await expect(Versioning.getCurrentBranch).resolves.toStrictEqual('feature-branch-1'); expect(headReference).toHaveBeenCalledTimes(1); }); @@ -67,7 +67,7 @@ describe('Versioning', () => { jest.spyOn(Versioning, 'headRef', 'get').mockImplementation(); const reference = jest.spyOn(Versioning, 'ref', 'get').mockReturnValue('refs/heads/feature-branch-2'); - expect(Versioning.branch).toStrictEqual('feature-branch-2'); + await expect(Versioning.getCurrentBranch).resolves.toStrictEqual('feature-branch-2'); expect(reference).toHaveBeenCalledTimes(2); }); @@ -75,16 +75,16 @@ describe('Versioning', () => { const headReference = jest.spyOn(Versioning, 'headRef', 'get').mockReturnValue('feature-branch-1'); const reference = jest.spyOn(Versioning, 'ref', 'get').mockReturnValue('refs/heads/feature-2'); - expect(Versioning.branch).toStrictEqual('feature-branch-1'); + await expect(Versioning.getCurrentBranch).resolves.toStrictEqual('feature-branch-1'); expect(headReference).toHaveBeenCalledTimes(1); expect(reference).toHaveBeenCalledTimes(0); }); - it('returns undefined when headRef and ref are not set', () => { + it('returns undefined when headRef and ref are not set', async () => { const headReference = jest.spyOn(Versioning, 'headRef', 'get').mockImplementation(); const reference = jest.spyOn(Versioning, 'ref', 'get').mockImplementation(); - expect(Versioning.branch).not.toBeDefined(); + await expect(Versioning.getCurrentBranch).resolves.not.toBeDefined(); expect(headReference).toHaveBeenCalledTimes(1); expect(reference).toHaveBeenCalledTimes(1); diff --git a/src/model/versioning.ts b/src/model/versioning.ts index 97b3d641..ca8c65d9 100644 --- a/src/model/versioning.ts +++ b/src/model/versioning.ts @@ -19,9 +19,18 @@ export default class Versioning { /** * Get the branch name of the (related) branch */ - static get branch() { - // Todo - use optional chaining (https://github.com/zeit/ncc/issues/534) - return this.headRef || (this.ref && this.ref.slice(11)); + static async getCurrentBranch() { + // GitHub pull request, GitHub non pull request + let branchName = this.headRef || this.ref?.slice(11); + + // Local + if (!branchName) { + const { status, output } = await System.shellRun('git branch --show-current'); + if (!status.success) throw new Error('did not expect "git branch --show-current"'); + branchName = output; + } + + return branchName; } /** @@ -144,7 +153,8 @@ export default class Versioning { const [major, minor, patch] = `${tag}.${commits}`.split('.'); const threeDigitVersion = /^\d+$/.test(patch) ? `${major}.${minor}.${patch}` : `${major}.0.${minor}`; - log.info(`Found semantic version ${threeDigitVersion} for ${this.branch}@${hash}`); + const branch = await this.getCurrentBranch(); + log.info(`Found semantic version ${threeDigitVersion} for ${branch}@${hash}`); return `${threeDigitVersion}`; } @@ -280,6 +290,7 @@ export default class Versioning { */ static async hasAnyVersionTags() { const command = `git tag --list --merged HEAD | grep -E '${this.grepCompatibleInputVersionRegex}' | wc -l`; + // Todo - make sure this cwd is actually passed in somehow const result = await System.shellRun(command, { cwd: this.projectPath, silent: false }); log.debug(result);