savory
Version:
A command-line interface for operating your Codefresh account
124 lines (118 loc) • 6.28 kB
JavaScript
const
fp = require('lodash/fp'),
chalk = require('chalk'),
moment = require('moment'),
jsYaml = require('js-yaml'),
{ middleware: httpClientMiddleware } = require('../../lib/api_client'),
{ timeSpanFormatter } = require('../../lib/util'),
{
errorFormatter,
tableFormatter,
jsonFormatter
} = require('../style');
const
DEFAULT_API_RESULT_LIMIT = 25,
STATUS_SUCCESS = "success",
STATUS_ERROR = "error",
STATUS_TERMINATED = "terminated",
STATUS_RUNNING = "running",
STATUS_ELECTED = "elected",
CAPTION_UKNOWN = "Unknown",
CAPTION_ALL = "all",
CAPTION_NOT_AVAILABLE = "N/A",
CHARS_ID = 25,
CHARS_REPOSITORY = 100,
CHARS_BRANCH = 25;
module.exports = {
command: ["list [id..]", "ls"],
builder: (yargs)=> {
return yargs
.option('pipeline-id', {
type: "string",
conflicts: ["pipeline"],
describe: "Filter by a pipeline id"
})
.option('pipeline', {
type: "string",
conflicts: ["pipeline-id"],
describe: "Filter by a pipeline name"
})
.option('trigger', {
type: "string",
describe: "Filter by a trigger name"
})
.option('status', {
choices: ["success", "failed", "aborted", "running", "pending"],
type: "array",
describe: "Filter by a specific build status(es)"
})
.option('output', {
choices: ["summary", "yaml", "json"],
default: "summary",
describe: "Choose a output format for the returned data"
})
.option('api-limit', {
type: "number",
default: DEFAULT_API_RESULT_LIMIT,
describe: "Limit the amount of results returned from the API"
})
.example('$0 builds ls')
.example('$0 builds ls --pipeline=mypipeline')
.example('$0 builds ls --status=running success')
.example('$0 builds ls --trigger=build')
.group(["status", "trigger", "pipeline", "pipeline-id"], "Build filter options:");
},
describe: "Retrieve a list of builds",
handler: fp.pipe(httpClientMiddleware, ({ _httpClient, apiLimit, output, id, status: statusFilter, pipeline, pipelineId, trigger })=> {
Promise
.all([pipeline && _httpClient('pipelines', { id: pipeline }).then(fp.pipe(fp.get('docs'), fp.map(fp.get('metadata.id')))), pipelineId])
.then(fp.pipe(fp.flatten, fp.compact))
.then((pipelineFilter)=> {
return (id
? Promise.all(fp.uniq(id).map((id)=> _httpClient(`builds/${id}`)))
: _httpClient('workflow', Object.assign({ limit: apiLimit, pipeline: pipelineFilter }, trigger && { trigger })).then(fp.get('workflows.docs')))
.then((rawResult)=> {
let summary = fp.pipe(
fp.sortBy([fp.pipe(fp.get('created'), (str)=> (new Date(str)).getTime())]),
fp.reverse,
fp.map(({ id, serviceName, status, trigger, started, finished, project, created, branchName } = {})=> [
fp.truncate({ length: CHARS_ID, omission: ".." }, id),
{
[STATUS_SUCCESS]: chalk.green('SUCCESS ✓'),
[STATUS_ERROR]: chalk.red('FAILED ✗'),
[STATUS_TERMINATED]: chalk.yellow('ABORTED ✗'),
[STATUS_RUNNING]: chalk.whiteBright('RUNNING *'),
[STATUS_ELECTED]: chalk.whiteBright('PENDING *')
}[status] || chalk.gray(CAPTION_UKNOWN),
serviceName,
trigger,
moment(created).format('DD/MM/YYYY HH:mm'),
started ? (([STATUS_RUNNING, STATUS_ELECTED].includes(status)) ? chalk.whiteBright : fp.identity)(timeSpanFormatter([finished || new Date(), started].map((stamp)=> (new Date(stamp)).getTime()).reduce(fp.subtract))) : chalk.gray(CAPTION_NOT_AVAILABLE),
fp.truncate({ length: CHARS_REPOSITORY, omission: ".." }, project),
fp.truncate({ length: CHARS_BRANCH, omission: ".." }, branchName)
]),
(processedResult)=> {
return [
processedResult.length ? `\n Displaying ${processedResult.length} build(s) out of ${ rawResult.length } returned value(s):\n` : `No viewable items returned`,
processedResult.length && (pipeline || pipelineId) && ` Including results from ${pipelineFilter.length || CAPTION_ALL} pipeline(s)\n`,
processedResult.length && tableFormatter({ title: ["Id", "Status", "Pipeline", "Trigger", "Created", "Run-Time\nHH:MM:SS", "Project", "Branch"] }, processedResult),
].filter(Boolean).join('\n');
}
);
return { summary, json: jsonFormatter, yaml: jsYaml.safeDump }[output](
(!statusFilter ? fp.identity : (function(statusFilter){
return fp.filter(({ status })=> statusFilter.includes(status))
})(statusFilter.map((caption)=> ({
"success": STATUS_SUCCESS,
"failed": STATUS_ERROR,
"aborted": STATUS_TERMINATED,
"running": STATUS_RUNNING,
"pending": STATUS_ELECTED
})[caption])))(rawResult)
);
});
})
.then(console.log)
.catch(fp.pipe(errorFormatter, console.warn));
})
};