Files
setup-php/src/core.ts

113 lines
2.6 KiB
TypeScript
Raw Normal View History

import {EOL} from 'os';
/**
* Commands
*
* Command Format:
* ::name key=value,key=value::message
*
* @see https://docs.github.com/en/actions/using-workflows/workflow-commands-for-github-actions
*/
interface CommandProperties {
[key: string]: string;
}
/**
* Sanitizes the message for use in a workflow command.
* @param message
*/
function toCommandValue(message: string | Error): string {
if (message instanceof Error) {
return message.toString();
}
return message;
}
/**
* Escapes data for safe use in workflow command messages.
* @param s
*/
function escapeData(s: string | Error): string {
return toCommandValue(s)
.replace(/%/g, '%25')
.replace(/\r/g, '%0D')
.replace(/\n/g, '%0A');
}
/**
* Escapes property values for safe use in workflow command properties.
* @param s
*/
function escapeProperty(s: string): string {
return s
.replace(/%/g, '%25')
.replace(/\r/g, '%0D')
.replace(/\n/g, '%0A')
.replace(/:/g, '%3A')
.replace(/,/g, '%2C');
}
/**
* Issues a command to the GitHub Actions runner.
*
* @param command - The command name to issue
* @param properties - Additional properties for the command (key-value pairs)
* @param message - The message to include with the command
*/
export function issueCommand(
command: string,
properties: CommandProperties,
message: string | Error
): void {
let cmdStr = `::${command}`;
if (properties && Object.keys(properties).length > 0) {
cmdStr += ' ';
const props = Object.entries(properties)
.filter(([, val]) => val)
.map(([key, val]) => `${key}=${escapeProperty(val)}`)
.join(',');
cmdStr += props;
}
cmdStr += `::${escapeData(message)}`;
process.stdout.write(cmdStr + EOL);
}
/**
* Adds an error issue.
* @param message - error issue message
*/
export function error(message: string | Error): void {
issueCommand('error', {}, message);
}
/**
* Sets the action status to failed.
* When the action exits it will be with an exit code of 1.
* @param message - add error issue message
*/
export function setFailed(message: string | Error): void {
process.exitCode = 1;
error(message);
}
/**
* Gets the value of an input.
* The value is trimmed.
* Returns an empty string if the value is not defined.
*
* @param name - name of the input to get
* @param required - whether the input is required
* @returns string
*/
export function getInput(name: string, required = false): string {
const val: string =
process.env[`INPUT_${name.replace(/ /g, '_').toUpperCase()}`] || '';
if (required && !val) {
throw new Error(`Input required and not supplied: ${name}`);
}
return val.trim();
}