github-action-readme-generator
Version:
The docs generator for GitHub Actions. Auto-syncs action.yml to README.md with 8 sections: inputs, outputs, usage, badges, branding & more. Works as CLI or GitHub Action.
128 lines (127 loc) • 4.33 kB
JavaScript
/**
* This class represents the metadata of a GitHub action defined in the action.yml file.
* It provides properties and methods for accessing and manipulating the metadata.
* [Further reading on the metadata can be found here](https://docs.github.com/en/actions/creating-actions/metadata-syntax-for-github-actions#inputs)
*/
import * as fs from 'node:fs';
import * as path from 'node:path';
import YAML from 'yaml';
import { DEFAULT_BRAND_COLOR, DEFAULT_BRAND_ICON } from './constants.js';
import LogTask from './logtask/index.js';
/**
* Parses and represents metadata from action.yml.
*/
export default class Action {
static validate(obj) {
if (typeof obj !== 'object' || obj === null) {
return false;
}
const record = obj;
if ('name' in record && 'description' in record && 'runs' in record) {
const runs = record.runs;
if (runs && 'using' in runs) {
return (typeof record.name === 'string' &&
typeof record.description === 'string' &&
typeof runs.using === 'string');
}
}
return false;
}
log;
/** Name of the action */
name;
author;
/** Description of the action */
description;
/** Branding information */
branding;
/** Input definitions */
inputs;
/** Output definitions */
outputs;
/** How the action is run */
runs;
/** Path to the action */
path;
/** the original file content */
rawYamlString = '';
/**
* Creates a new instance of the Action class by loading and parsing action.yml.
*
* @param actionPath The path to the action.yml file.
*/
constructor(actionPath, log) {
// Load and parse action.yml
this.log = log ?? new LogTask(actionPath);
this.path = actionPath;
let actionYaml;
this.log.debug(`Constucting ${actionPath}`);
try {
actionYaml = this.loadActionFrom(actionPath);
}
catch (error) {
throw new Error(`Failed to load ${actionPath}. ${error}`);
}
this.log.debug(`Action YAML: ${JSON.stringify(actionYaml)}`);
this.name = actionYaml.name;
this.author = actionYaml.author;
this.description = actionYaml.description;
this.branding = {
color: actionYaml.branding?.color ?? DEFAULT_BRAND_COLOR,
icon: actionYaml.branding?.icon ?? DEFAULT_BRAND_ICON,
};
this.inputs = actionYaml.inputs;
this.outputs = actionYaml.outputs;
this.runs = actionYaml.runs;
}
loadActionFrom(actionPath) {
const actionDir = path.dirname(path.resolve(actionPath));
this.log.debug(`Load ${actionPath} from ${actionDir}`);
// Check if the action file exists
if (!fs.existsSync(actionPath)) {
throw new Error(`${actionPath} does not exist in ${actionDir}`);
}
// Ensure the path is a file and not a directory
if (!fs.statSync(actionPath).isFile()) {
throw new Error(`${actionPath} is not a file type at ${actionDir}`);
}
this.rawYamlString = fs.readFileSync(actionPath, 'utf8');
this.log.debug(`Parse ${actionPath} from ${actionDir}`);
const actionObj = YAML.parse(this.rawYamlString);
if (Action.validate(actionObj)) {
return actionObj;
}
throw new Error(`Invalid action metadata syntax in ${actionPath}.`);
}
/**
* Gets the value of an input.
}
/**
* Gets the default value for an input.
*
* @param inputName The name of the input.
* @returns The default value if defined,or undefined
*/
inputDefault(inputName) {
if (this.inputs) {
return this.inputs[inputName]?.default ?? undefined;
}
return undefined;
}
/**
* Stringifies the action back to YAML.
*
* @returns The YAML string for debugging.
*/
stringify() {
try {
return YAML.stringify(this);
}
catch (error) {
this.log.error(`Failed to stringify Action. ${error}`);
// this is just for debugging, continue on error
return '';
}
}
}
//# sourceMappingURL=Action.js.map