diff --git a/Dockerfile b/Dockerfile index cb9739bc2..0685125fa 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,6 +1,6 @@ # go hub binary FROM golang:alpine AS go -RUN apk --update add ca-certificates git +RUN apk --update add --no-scripts ca-certificates git RUN go install github.com/github/hub@latest # python yq binary diff --git a/Dockerfile-debian b/Dockerfile-debian index 0dd37c4da..85f586166 100644 --- a/Dockerfile-debian +++ b/Dockerfile-debian @@ -1,6 +1,6 @@ # go hub binary FROM golang:alpine as go -RUN apk --update add ca-certificates git +RUN apk --update add --no-scripts ca-certificates git RUN go install github.com/github/hub@latest # python yq binary diff --git a/Dockerfile-debian-rootless b/Dockerfile-debian-rootless index 12e056ee1..cc0859b37 100644 --- a/Dockerfile-debian-rootless +++ b/Dockerfile-debian-rootless @@ -1,6 +1,6 @@ # go hub binary FROM golang:alpine as go -RUN apk --update add ca-certificates git +RUN apk --update add --no-scripts ca-certificates git RUN go install github.com/github/hub@latest # python yq binary diff --git a/Dockerfile-rootless b/Dockerfile-rootless index cab1c3fd4..5577118d9 100644 --- a/Dockerfile-rootless +++ b/Dockerfile-rootless @@ -1,6 +1,6 @@ # go hub binary FROM golang:alpine as go -RUN apk --update add ca-certificates git +RUN apk --update add --no-scripts ca-certificates git RUN go install github.com/github/hub@latest # python yq binary diff --git a/lib/interface/cli/commands/root/get.cmd.js b/lib/interface/cli/commands/root/get.cmd.js index cd1dc8451..06d874fba 100644 --- a/lib/interface/cli/commands/root/get.cmd.js +++ b/lib/interface/cli/commands/root/get.cmd.js @@ -22,7 +22,7 @@ const get = new Command({ .option('output', { describe: 'Output format', alias: 'o', - choices: ['json', 'yaml', 'wide', 'name', 'id'], + choices: ['json', 'yaml', 'wide', 'name', 'id', 'jsonArray', 'yamlArray'], group: 'Output Options', }) .option('date-format', { diff --git a/lib/interface/cli/commands/root/get.completion.js b/lib/interface/cli/commands/root/get.completion.js index a0c3b1c86..0570a0f7e 100644 --- a/lib/interface/cli/commands/root/get.completion.js +++ b/lib/interface/cli/commands/root/get.completion.js @@ -8,7 +8,7 @@ function optionHandler({ word, argv, option }) { return fileDir(word); } if (OUTPUT_OPTIONS.includes(option)) { - return ['json', 'yaml', 'wide', 'name', 'id']; + return ['json', 'yaml', 'wide', 'name', 'id', 'jsonArray', 'yamlArray']; } return []; } diff --git a/lib/output/Output.js b/lib/output/Output.js index 3b4befcc8..8fe5ce77b 100644 --- a/lib/output/Output.js +++ b/lib/output/Output.js @@ -13,6 +13,8 @@ const TYPES = { table: require('./types/table.output'), id: require('./types/id.output'), name: require('./types/name.output'), + jsonArray: require('./types/jsonArray.output'), + yamlArray: require('./types/yamlArray.output'), }; const TABLE_TYPES = ['default', 'wide']; diff --git a/lib/output/types/jsonArray.output.js b/lib/output/types/jsonArray.output.js new file mode 100644 index 000000000..02ca152ba --- /dev/null +++ b/lib/output/types/jsonArray.output.js @@ -0,0 +1,19 @@ +const CFError = require('cf-errors'); // eslint-disable-line +const Entity = require('../../logic/entities/Entity'); +const _ = require('lodash'); + +function output(data) { + const entities = _.isArray(data) ? data : [data]; + const jsonArray = []; + + _.forEach(entities, (entity) => { + if (!(entity instanceof Entity)) { + throw new CFError('Cannot extract data for "jsonArray" output -- data contains not Entity'); + } + jsonArray.push(entity.info); + }); + + return JSON.stringify(jsonArray, null, '\t'); +} + +module.exports = output; diff --git a/lib/output/types/jsonArray.output.spec.js b/lib/output/types/jsonArray.output.spec.js new file mode 100644 index 000000000..6a2be058d --- /dev/null +++ b/lib/output/types/jsonArray.output.spec.js @@ -0,0 +1,37 @@ +const CFError = require('cf-errors'); +const Entity = require('../../logic/entities/Entity'); +const output = require('./jsonArray.output'); + +describe('jsonArray output', () => { + it('should return empty array for an empty array', () => { + expect(output([])).toBe('[]'); + }); + + it('should wrap single Entity into array', () => { + const entity = new Entity(); + entity.info = { id: '1', status: 'ok' }; + + const result = JSON.parse(output(entity)); + expect(Array.isArray(result)).toBe(true); + expect(result).toHaveLength(1); + expect(result[0]).toEqual(entity.info); + }); + + it('should keep multiple Entities as array', () => { + const entity1 = new Entity(); + entity1.info = { id: '1' }; + const entity2 = new Entity(); + entity2.info = { id: '2' }; + + const result = JSON.parse(output([entity1, entity2])); + expect(Array.isArray(result)).toBe(true); + expect(result).toHaveLength(2); + expect(result[0]).toEqual(entity1.info); + expect(result[1]).toEqual(entity2.info); + }); + + it('should throw CFError if element is not an Entity', () => { + expect(() => output({ id: '1' })).toThrow(CFError); + expect(() => output([new Entity(), {}])).toThrow(CFError); + }); +}); diff --git a/lib/output/types/yamlArray.output.js b/lib/output/types/yamlArray.output.js new file mode 100644 index 000000000..4a8798bd2 --- /dev/null +++ b/lib/output/types/yamlArray.output.js @@ -0,0 +1,20 @@ +const CFError = require('cf-errors'); +const Entity = require('../../logic/entities/Entity'); +const _ = require('lodash'); +const yaml = require('js-yaml'); + +function output(data) { + const entities = _.isArray(data) ? data : [data]; + const yamlArray = []; + + _.forEach(entities, (entity) => { + if (!(entity instanceof Entity)) { + throw new CFError('Cannot extract data for "yamlArray" output -- data contains not Entity'); + } + yamlArray.push(entity.info); + }); + + return yaml.dump(yamlArray); +} + +module.exports = output; diff --git a/lib/output/types/yamlArray.output.spec.js b/lib/output/types/yamlArray.output.spec.js new file mode 100644 index 000000000..37e853d76 --- /dev/null +++ b/lib/output/types/yamlArray.output.spec.js @@ -0,0 +1,40 @@ +const CFError = require('cf-errors'); +const yaml = require('js-yaml'); +const Entity = require('../../logic/entities/Entity'); +const output = require('./yamlArray.output'); + +describe('yamlArray output', () => { + it('should return empty array for an empty array', () => { + const result = yaml.load(output([])); + expect(Array.isArray(result)).toBe(true); + expect(result).toHaveLength(0); + }); + + it('should wrap single Entity into array', () => { + const entity = new Entity(); + entity.info = { id: '1', status: 'ok' }; + + const result = yaml.load(output(entity)); + expect(Array.isArray(result)).toBe(true); + expect(result).toHaveLength(1); + expect(result[0]).toEqual(entity.info); + }); + + it('should keep multiple Entities as array', () => { + const entity1 = new Entity(); + entity1.info = { id: '1' }; + const entity2 = new Entity(); + entity2.info = { id: '2' }; + + const result = yaml.load(output([entity1, entity2])); + expect(Array.isArray(result)).toBe(true); + expect(result).toHaveLength(2); + expect(result[0]).toEqual(entity1.info); + expect(result[1]).toEqual(entity2.info); + }); + + it('should throw CFError if element is not an Entity', () => { + expect(() => output({ id: '1' })).toThrow(CFError); + expect(() => output([new Entity(), {}])).toThrow(CFError); + }); +}); diff --git a/package.json b/package.json index c33c0967f..36bce895a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "codefresh", - "version": "0.89.5", + "version": "0.89.6", "description": "Codefresh command line utility", "main": "index.js", "preferGlobal": true, diff --git a/yarn.lock b/yarn.lock index 168cf2a59..166dddf8b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3558,7 +3558,7 @@ forever-agent@~0.6.1: resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91" integrity sha512-j0KLYPhm6zeac4lz3oJ3o65qvgQCcPubiyotZrXqEaG4hNagNYO8qdlUrX5vwqv9ohqeT/Z3j6+yW067yWWdUw== -form-data@^2.3.2, form-data@^2.5.4, form-data@~2.3.2: +form-data@^2.3.2, form-data@^2.5.5, form-data@~2.3.2: version "2.5.5" resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.5.5.tgz#a5f6364ad7e4e67e95b4a07e2d8c6f711c74f624" integrity sha512-jqdObeR2rxZZbPSGL+3VckHMYtu+f9//KXBsVny6JSX/pa38Fy+bGjuG8eW/H6USNQWhLi8Num++cU2yOCNz4A==