From 2697357344e14ad6af08a8c3ce1b1eba2578394f Mon Sep 17 00:00:00 2001 From: Bryan MacFarlane Date: Thu, 16 May 2019 18:45:34 -0700 Subject: [PATCH 1/3] Spec for tool config apis (#3) * creating an initial branch for config apis spec * Add package specs * mkdirP should return promise * Which should return a promise * Respond to feedback * export => exportVariable * Respond to feedback on spec * Remove code for now * trailing space * Clarify throwing --- docs/package-specs.md | 200 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 200 insertions(+) create mode 100644 docs/package-specs.md diff --git a/docs/package-specs.md b/docs/package-specs.md new file mode 100644 index 00000000..21861fb0 --- /dev/null +++ b/docs/package-specs.md @@ -0,0 +1,200 @@ +# Package Specs + +In order to support the node-config action, I propose adding the following into 4 libraries (tool-cache, core, io, exec), with tool-cache having dependencies on the other 3 libs: + +### Core spec + +Holds all the functions necessary for interacting with the runner/environment. + +``` +// Logging functions +export function debug(message: string): void +export function warning(message: string): void +export function error(message: string): void + +/** + * Interface for exportVariable options + */ +export interface ExportOptions { + /** Optional. Whether the variable should be marked as secret (will be masked from logs). Defaults to false */ + isSecret?: bool; +} + +/** + * sets env variable for this action and future actions in the job + * + * @param name the name of the variable to set + * @param val the value of the variable + * @param options optional. See ExportOptions. + */ +export function exportVariable(name: string, val: string, options?: ExportOptions): void + +/** + * Interface for getInput options + */ +export interface InputOptions { + /** Optional. Whether the input is required. If required and not present, will throw. Defaults to false */ + required?: bool; +} + +/** + * Gets the value of an input. The value is also trimmed. + * + * @param name name of the input to get + * @param options optional. See InputOptions. + * @returns string + */ +export function getInput(name: string, options?: InputOptions): string | undefined + +/** + * fail the action + * @param message + */ +export function setFailure(message: string): void +``` + +### IO spec + +Holds all the functions necessary for file system manipulation (cli scenarios, not fs replacements): + +``` +/** + * Interface for cp/mv options + */ +export interface CopyOptions { + /** Optional. Whether to recursively copy all subdirectories. Defaults to false */ + recursive?: boolean; + /** Optional. Whether to overwrite existing files in the destination. Defaults to true */ + force?: boolean; +} + +/** + * Copies a file or folder. + * + * @param source source path + * @param dest destination path + * @param options optional. See CopyOptions. + */ +export function cp(source: string, dest: string, options?: CopyOptions): Promise + +/** + * Remove a path recursively with force + * + * @param path path to remove + */ +export function rmRF(path: string): Promise + +/** + * Make a directory. Creates the full path with folders in between + * + * @param p path to create + * @returns Promise + */ +export function mkdirP(p: string): Promise + +/** + * Moves a path. + * + * @param source source path + * @param dest destination path + * @param options optional. See CopyOptions. + */ +export function mv(source: string, dest: string, options?: CopyOptions): Promise + +/** + * Interface for which options + */ +export interface WhichOptions { + /** Optional. Whether to check if tool exists. If true, will throw if it fails. Defaults to false */ + check?: boolean; +} + +/** + * Returns path of a tool had the tool actually been invoked. Resolves via paths. + * + * @param tool name of the tool + * @param options optional. See WhichOptions. + * @returns Promise path to tool + */ +export function which(tool: string, options?: WhichOptions): Promise +``` + +### Exec spec + +Holds all the functions necessary for running the tools node-config depends on (aka 7-zip and tar) + +``` +/** + * Interface for exec options + */ +export interface IExecOptions + +/** +* Exec a command. +* Output will be streamed to the live console. +* Returns promise with return code +* +* @param commandLine command to execute +* @param args optional additional arguments +* @param options optional exec options. See IExecOptions +* @returns Promise return code +*/ +export function exec(commandLine: string, args?: string[], options?: IExecOptions): Promise +``` + +### Tool-Cache spec: + +Holds all the functions necessary for downloading and caching node. + +``` +/** + * Download a tool from an url and stream it into a file + * + * @param url url of tool to download + * @returns path to downloaded tool + */ +export async function downloadTool(url: string): Promise + +/** + * Extract a .7z file + * + * @param file path to the .7z file + * @param dest destination directory. Optional. + * @returns path to the destination directory + */ +export async function extract7z(file: string, dest?: string): Promise + +/** + * Extract a tar + * + * @param file path to the tar + * @param dest destination directory. Optional. + * @returns path to the destination directory + */ +export async function extractTar(file: string, destination?: string): Promise + +/** + * Caches a directory and installs it into the tool cacheDir + * + * @param sourceDir the directory to cache into tools + * @param tool tool name + * @param version version of the tool. semver format + * @param arch architecture of the tool. Optional. Defaults to machine architecture + */ +export async function cacheDir(sourceDir: string, tool: string, version: string, arch?: string): Promise + +/** + * finds the path to a tool in the local installed tool cache + * + * @param toolName name of the tool + * @param versionSpec version of the tool + * @param arch optional arch. defaults to arch of computer + */ +export function find(toolName: string, versionSpec: string, arch?: string): string + +/** + * Prepends inputPath to the PATH + * @param inputPath + */ +export function addPath(inputPath: string): void +``` From d7423efd98754922df234848eba17398db59356c Mon Sep 17 00:00:00 2001 From: Bryan MacFarlane Date: Fri, 17 May 2019 10:04:20 -0400 Subject: [PATCH 2/3] spec update --- docs/package-specs.md | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/docs/package-specs.md b/docs/package-specs.md index 21861fb0..115df9e2 100644 --- a/docs/package-specs.md +++ b/docs/package-specs.md @@ -12,14 +12,6 @@ export function debug(message: string): void export function warning(message: string): void export function error(message: string): void -/** - * Interface for exportVariable options - */ -export interface ExportOptions { - /** Optional. Whether the variable should be marked as secret (will be masked from logs). Defaults to false */ - isSecret?: bool; -} - /** * sets env variable for this action and future actions in the job * @@ -27,7 +19,7 @@ export interface ExportOptions { * @param val the value of the variable * @param options optional. See ExportOptions. */ -export function exportVariable(name: string, val: string, options?: ExportOptions): void +export function exportVariable(name: string, val: string): void /** * Interface for getInput options @@ -47,10 +39,16 @@ export interface InputOptions { export function getInput(name: string, options?: InputOptions): string | undefined /** - * fail the action + * sets the status of the action to neutral * @param message */ -export function setFailure(message: string): void +export function setFailed(message: string): void + +/** + * sets the status of the action to failed + * @param message + */ +export function setFailed(message: string): void ``` ### IO spec From a97380e90dadcf56ed35a6d638002c420507f0c0 Mon Sep 17 00:00:00 2001 From: Bryan MacFarlane Date: Fri, 17 May 2019 10:23:01 -0400 Subject: [PATCH 3/3] update inputs and variables --- packages/core/README.md | 10 ++++++++-- packages/core/src/core.ts | 35 ++++++++++++++++++++++++--------- packages/core/src/interfaces.ts | 8 ++++---- 3 files changed, 38 insertions(+), 15 deletions(-) diff --git a/packages/core/README.md b/packages/core/README.md index 6a1807fb..8baaab5f 100644 --- a/packages/core/README.md +++ b/packages/core/README.md @@ -5,18 +5,24 @@ ## Usage ``` +//----------------------------------------------------------------------- +// Variables, Inputs and Outputs +//----------------------------------------------------------------------- + /** * sets env variable for this action and future actions in the job * @param name the name of the variable to set * @param val the value of the variable */ -export function exportVariable(name: string, val: string, options?:im.ExportOptions); +export function exportVariable(name: string, val: string); /** * registers a secret which will get masked from logs * @param val value of the secret */ -export function setSecret(val: string); +export function setSecret(name: string, val: string); + +// TODO: follow up and see if we need anything for outputs //----------------------------------------------------------------------- // Results diff --git a/packages/core/src/core.ts b/packages/core/src/core.ts index 87910a0c..013a9a28 100644 --- a/packages/core/src/core.ts +++ b/packages/core/src/core.ts @@ -2,25 +2,46 @@ import im = require('./interfaces'); import intm = require('./internal'); import process = require('process'); +//----------------------------------------------------------------------- +// Variables +//----------------------------------------------------------------------- + /** * sets env variable for this action and future actions in the job * @param name the name of the variable to set * @param val the value of the variable */ -export function exportVariable(name: string, val: string, options?:im.ExportOptions) { +export function exportVariable(name: string, val: string) { process.env[name] = val; - let props = {'name': name, 'isSecret': options? options.isSecret : false}; - intm._issueCommand('set-variable', props, val); + intm._issueCommand('set-variable', {'name': name}, val); } /** - * registers a secret which will get masked from logs + * exports the variable and registers a secret which will get masked from logs + * @param name the name of the variable to set * @param val value of the secret */ -export function setSecret(val: string) { +export function setSecret(name: string, val: string) { + exportVariable(name, val); intm._issueCommand('set-secret', {}, val); } +/** + * Gets the value of an input. The value is also trimmed. + * + * @param name name of the input to get + * @param options optional. See InputOptions. + * @returns string + */ +export function getInput(name: string, options?: im.InputOptions): string { + let val:string = process.env['INPUT_' + name]; + if (options && options.required && !val) { + throw new Error(`Input required and not supplied: ${name}`); + } + + return val; +} + //----------------------------------------------------------------------- // Results //----------------------------------------------------------------------- @@ -44,10 +65,6 @@ export function setFailed(message: string) { //----------------------------------------------------------------------- // Logging Commands -// -// error and warning issues do not take FileDetails because while possible, -// that's typically reserved for the agent and the problem matchers. -// //----------------------------------------------------------------------- /** diff --git a/packages/core/src/interfaces.ts b/packages/core/src/interfaces.ts index 16696ed9..bca96a40 100644 --- a/packages/core/src/interfaces.ts +++ b/packages/core/src/interfaces.ts @@ -19,9 +19,9 @@ export enum ExitCode { } /** - * Interface for exportVariable options + * Interface for getInput options */ -export interface ExportOptions { - /** Optional. Whether the variable should be marked as secret (will be masked from logs). Defaults to false */ - isSecret?: boolean; +export interface InputOptions { + /** Optional. Whether the input is required. If required and not present, will throw. Defaults to false */ + required?: boolean; } \ No newline at end of file