From ea0dd28ea794123383a132d1a7cf7f4118db032a Mon Sep 17 00:00:00 2001 From: Danny McCormick Date: Tue, 21 May 2019 14:38:29 -0400 Subject: [PATCH] Clean up/respond to feedback --- packages/core/__tests__/lib.test.ts | 12 +-- packages/core/src/command.ts | 81 +++++++++++++++ packages/core/src/core.ts | 14 +-- packages/core/src/internal.ts | 154 ---------------------------- 4 files changed, 94 insertions(+), 167 deletions(-) create mode 100644 packages/core/src/command.ts delete mode 100644 packages/core/src/internal.ts diff --git a/packages/core/__tests__/lib.test.ts b/packages/core/__tests__/lib.test.ts index b1202d1c..c15132bd 100644 --- a/packages/core/__tests__/lib.test.ts +++ b/packages/core/__tests__/lib.test.ts @@ -46,8 +46,8 @@ describe('@actions/core', () => { assertWriteCalls([`##[set-variable name=my var2;]var val%0D%0A${os.EOL}`]) }) - it('setSecret produces the correct commands and sets the env', () => { - core.setSecret('my secret', 'secret val') + it('exportSecret produces the correct commands and sets the env', () => { + core.exportSecret('my secret', 'secret val') expect(process.env['my secret']).toBe('secret val') assertWriteCalls([ `##[set-variable name=my secret;]secret val${os.EOL}`, @@ -55,8 +55,8 @@ describe('@actions/core', () => { ]) }) - it('setSecret escapes secret names', () => { - core.setSecret('special char secret \r\n];', 'special secret val') + it('exportSecret escapes secret names', () => { + core.exportSecret('special char secret \r\n];', 'special secret val') expect(process.env['special char secret \r\n];']).toBe('special secret val') assertWriteCalls([ `##[set-variable name=special char secret %0D%0A%5D%3B;]special secret val${ @@ -66,8 +66,8 @@ describe('@actions/core', () => { ]) }) - it('setSecret escapes secret values', () => { - core.setSecret('my secret2', 'secret val\r\n') + it('exportSecret escapes secret values', () => { + core.exportSecret('my secret2', 'secret val\r\n') expect(process.env['my secret2']).toBe('secret val\r\n') assertWriteCalls([ `##[set-variable name=my secret2;]secret val%0D%0A${os.EOL}`, diff --git a/packages/core/src/command.ts b/packages/core/src/command.ts new file mode 100644 index 00000000..0f949779 --- /dev/null +++ b/packages/core/src/command.ts @@ -0,0 +1,81 @@ +import * as os from 'os' + +/** + * Commands + * + * Command Format: + * ##[name key=value;key=value]message + * + * Examples: + * ##[warning]This is the user warning message + * ##[set-secret name=mypassword]definatelyNotAPassword! + */ +export function issueCommand( + command: string, + properties: any, + message: string +) { + const cmd = new Command(command, properties, message) + process.stdout.write(cmd.toString() + os.EOL) +} + +export function issue(name: string, message: string) { + issueCommand(name, {}, message) +} + +const CMD_PREFIX = '##[' + +class Command { + constructor(command: string, properties: {[key: string]: string}, message: string) { + if (!command) { + command = 'missing.command' + } + + this.command = command + this.properties = properties + this.message = message + } + + public command: string + public message: string + public properties: {[key: string]: string} + + public toString() { + let cmdStr = CMD_PREFIX + this.command + + if (this.properties && Object.keys(this.properties).length > 0) { + cmdStr += ' ' + for (const key in this.properties) { + if (this.properties.hasOwnProperty(key)) { + const val = this.properties[key] + if (val) { + // safely append the val - avoid blowing up when attempting to + // call .replace() if message is not a string for some reason + cmdStr += `${key}=${escape(`${val || ''}`)};` + } + } + } + } + + cmdStr += ']' + + // safely append the message - avoid blowing up when attempting to + // call .replace() if message is not a string for some reason + const message: string = `${this.message || ''}` + cmdStr += escapedata(message) + + return cmdStr + } +} + +function escapedata(s: string): string { + return s.replace(/\r/g, '%0D').replace(/\n/g, '%0A') +} + +function escape(s: string): string { + return s + .replace(/\r/g, '%0D') + .replace(/\n/g, '%0A') + .replace(/]/g, '%5D') + .replace(/;/g, '%3B') +} \ No newline at end of file diff --git a/packages/core/src/core.ts b/packages/core/src/core.ts index 23ee6770..6e6c548c 100644 --- a/packages/core/src/core.ts +++ b/packages/core/src/core.ts @@ -1,5 +1,5 @@ import {ExitCode} from '@actions/exit' -import * as intm from './internal' +import * as intm from './command' /** * Interface for getInput options @@ -20,7 +20,7 @@ export interface InputOptions { */ export function exportVariable(name: string, val: string) { process.env[name] = val - intm._issueCommand('set-variable', {name}, val) + intm.issueCommand('set-variable', {name}, val) } /** @@ -28,9 +28,9 @@ export function exportVariable(name: string, val: string) { * @param name the name of the variable to set * @param val value of the secret */ -export function setSecret(name: string, val: string) { +export function exportSecret(name: string, val: string) { exportVariable(name, val) - intm._issueCommand('set-secret', {}, val) + intm.issueCommand('set-secret', {}, val) } /** @@ -80,7 +80,7 @@ export function setFailed(message: string) { * @param message debug message */ export function debug(message: string) { - intm._issueCommand('debug', {}, message) + intm.issueCommand('debug', {}, message) } /** @@ -88,7 +88,7 @@ export function debug(message: string) { * @param message error issue message */ export function error(message: string) { - intm._issue('error', message) + intm.issue('error', message) } /** @@ -96,5 +96,5 @@ export function error(message: string) { * @param message warning issue message */ export function warning(message: string) { - intm._issue('warning', message) + intm.issue('warning', message) } diff --git a/packages/core/src/internal.ts b/packages/core/src/internal.ts deleted file mode 100644 index 032ee4ff..00000000 --- a/packages/core/src/internal.ts +++ /dev/null @@ -1,154 +0,0 @@ -import * as os from 'os' - -/** - * Commands - * - * Command Format: - * ##[name key=value;key=value]message - * - * Examples: - * ##[warning]This is the user warning message - * ##[set-secret name=mypassword]definatelyNotAPassword! - */ -export function _issueCommand( - command: string, - properties: any, - message: string -) { - const cmd = new _Command(command, properties, message) - _writeLine(cmd.toString()) -} - -export function _issue(name: string, message: string) { - _issueCommand(name, {}, message) -} - -const CMD_PREFIX = '##[' - -export class _Command { - constructor(command: string, properties: any, message: string) { - if (!command) { - command = 'missing.command' - } - - this.command = command - this.properties = properties - this.message = message - } - - public command: string - public message: string - public properties: any - - public toString() { - let cmdStr = CMD_PREFIX + this.command - - if (this.properties && Object.keys(this.properties).length > 0) { - cmdStr += ' ' - for (const key in this.properties) { - if (this.properties.hasOwnProperty(key)) { - const val = this.properties[key] - if (val) { - // safely append the val - avoid blowing up when attempting to - // call .replace() if message is not a string for some reason - cmdStr += `${key}=${escape(`${val || ''}`)};` - } - } - } - } - - cmdStr += ']' - - // safely append the message - avoid blowing up when attempting to - // call .replace() if message is not a string for some reason - const message: string = `${this.message || ''}` - cmdStr += escapedata(message) - - return cmdStr - } -} - -export function _commandFromString(commandLine: string) { - const lbPos = commandLine.indexOf('[') - const rbPos = commandLine.indexOf(']') - - if (lbPos === -1 || rbPos === -1 || rbPos - lbPos < 3) { - throw new Error('Invalid command brackets') - } - const cmdInfo = commandLine.substring(lbPos + 1, rbPos) - const spaceIdx = cmdInfo.indexOf(' ') - - let command = cmdInfo - const properties: {[key: string]: string} = {} - - if (spaceIdx > 0) { - command = cmdInfo.trim().substring(0, spaceIdx) - const propSection = cmdInfo.trim().substring(spaceIdx + 1) - - const propLines: string[] = propSection.split(';') - - for (let propLine of propLines) { - propLine = propLine.trim() - - if (propLine.length > 0) { - const eqIndex = propLine.indexOf('=') - - if (eqIndex === -1) { - throw new Error(`Invalid property: ${propLine}`) - } - - const key: string = propLine.substring(0, eqIndex) - const val: string = propLine.substring(eqIndex + 1) - - properties[key] = unescape(val) - } - } - } - - const msg: string = unescapedata(commandLine.substring(rbPos + 1)) - const cmd = new _Command(command, properties, msg) - return cmd -} - -function escapedata(s: string): string { - return s.replace(/\r/g, '%0D').replace(/\n/g, '%0A') -} - -function unescapedata(s: string): string { - return s.replace(/%0D/g, '\r').replace(/%0A/g, '\n') -} - -function escape(s: string): string { - return s - .replace(/\r/g, '%0D') - .replace(/\n/g, '%0A') - .replace(/]/g, '%5D') - .replace(/;/g, '%3B') -} - -function unescape(s: string): string { - return s - .replace(/%0D/g, '\r') - .replace(/%0A/g, '\n') - .replace(/%5D/g, ']') - .replace(/%3B/g, ';') -} - -//----------------------------------------------------- -// Streams: allow to override the stream -//----------------------------------------------------- - -let _outStream = process.stdout -let _errStream = process.stderr // eslint-disable-line @typescript-eslint/no-unused-vars - -export function _writeLine(str: string): void { - _outStream.write(str + os.EOL) -} - -export function _setStdStream(stdStream: NodeJS.WriteStream): void { - _outStream = stdStream -} - -export function _setErrStream(errStream: NodeJS.WriteStream): void { - _errStream = errStream -}