Skip to content

Commit

Permalink
CR-17813 (#800)
Browse files Browse the repository at this point in the history
* CR-17813

* WIP

* WIP

* WIP

* WIP

* WIP

* WIP

* WIP

* WIP

* add tests

* add tests files

* wip

* add documentation

* add documentation

* wip documentation

* wip documentation

* wip documentation

* address Kim comments

* address Daniel comments

* address Daniel comments

* wip
  • Loading branch information
eti-codefresh authored Apr 23, 2023
1 parent 28f40bf commit acbce01
Show file tree
Hide file tree
Showing 10 changed files with 197 additions and 54 deletions.
38 changes: 30 additions & 8 deletions docs/content/pipelines/Run Pipeline.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,22 +15,44 @@ The pipeline will be triggered multiple times according to the array length.

#### Variable yaml file with 2 sets of variables
```yaml
- key: value
key2: key1
- key: value
key2: key2
- VARIABLE_A: value_a_for_the_first_build
VARIABLE_B: value_b_for_the_first_build
- VARIABLE_A: value_a_for_the_first_build
VARIABLE_B: value_b_for_the_first_build
```
#### Variable json file with 2 sets of variables
```json
[
{
"key": "value",
"key2": "key1"
"VARIABLE_A": "value_a_for_the_first_build",
"VARIABLE_B": "value_b_for_the_first_build"
},
{
"key": "value",
"key2": "key2"
"VARIABLE_A": "value_a_for_the_first_build",
"VARIABLE_B": "value_b_for_the_first_build"
}
]
```
### Use encrypted variables in Codefresh build runs; supported from CLI version: 0.82.8
#### Variable yaml file with single variable set with encrypted variables
```yaml
- key:
val: value
encrypted: true
key2: key1

```

#### Variable json file single variable set with encrypted variables
```json
[
{
"key": {
"val": "value",
"encrypted": true
},
"key2": "key1"
}
]
```
Expand Down
82 changes: 76 additions & 6 deletions lib/interface/cli/commands/pipeline/pipeline.sdk.spec.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
const yaml = require('js-yaml');
const request = require('requestretry');
const fs = require('fs');
const DEFAULTS = require('../../defaults');
const getCmd = require('./get.cmd').toCommand();
const deleteCmd = require('./delete.cmd').toCommand();
Expand All @@ -10,18 +13,16 @@ jest.mock('../../helpers/validation'); // eslint-disable-line
jest.mock('../../../../../check-version');
jest.mock('../../completion/helpers', () => { // eslint-disable-line
return {
authContextWrapper: func => func,
authContextWrapper: (func) => func,
};
});

jest.mock('../../../../logic/entities/Pipeline', () => { // eslint-disable-line
return {
fromResponse: res => res,
fromResponse: (res) => res,
};
});

const request = require('requestretry');

const DEFAULT_RESPONSE = request.__defaultResponse();

describe('pipeline', () => {
Expand Down Expand Up @@ -57,11 +58,11 @@ describe('pipeline', () => {
});

it('should return default limit', async () => {
expect(_getLimit(undefined,false)).toEqual(DEFAULTS.GET_LIMIT_RESULTS);
expect(_getLimit(undefined, false)).toEqual(DEFAULTS.GET_LIMIT_RESULTS);
});

it('should return `unlimited` value', async () => {
expect(_getLimit(undefined,true)).toEqual(DEFAULTS.GET_ALL_PIPELINES_LIMIT);
expect(_getLimit(undefined, true)).toEqual(DEFAULTS.GET_ALL_PIPELINES_LIMIT);
});
});

Expand All @@ -84,6 +85,75 @@ describe('pipeline', () => {
});
});

describe('run', () => {
it('should handle running pipeline with encrypted variables', async () => {
const argv = { name: 'some name',
detach: true,
annotation: [],
variable:
[{
key: 'secret',
value: 'secret',
},
{
key: 'VAR1',
value: 'VAL1',
},
],
encrypted: ['secret'],
};
const pip = new CfPipeline(argv);
await pip.run();
expect(pip.executionRequests[0].options.variables).toEqual([
{
key: 'secret',
value: 'secret',
encrypted: true,
},
{
key: 'VAR1',
value: 'VAL1',
},
]);
await verifyResponsesReturned([DEFAULT_RESPONSE]); // eslint-disable-line
});

it('should handle running pipeline with encrypted variables passing inside json file', async () => {
const rawFile = fs.readFileSync('lib/interface/cli/commands/pipeline/var.json', 'utf8');

const argv = { name: 'some name',
detach: true,
annotation: [],
'var-file': JSON.parse(rawFile),
};
const pip = new CfPipeline(argv);
await pip.run();
expect(pip.executionRequests[0].options.variables).toEqual(
[{ key: 'help6', value: '85858' },
{ key: 'should_be_encrepted', value: '0000' },
{ encrypted: true, key: 'help7', value: 'test' }],
);
await verifyResponsesReturned([DEFAULT_RESPONSE]); // eslint-disable-line
});

it('should handle running pipeline with encrypted variables passing inside yaml file', async () => {
const rawFile = fs.readFileSync('lib/interface/cli/commands/pipeline/var.yml', 'utf8');

const argv = { name: 'some name',
detach: true,
annotation: [],
'var-file': yaml.safeLoad(rawFile),
};
const pip = new CfPipeline(argv);
await pip.run();
expect(pip.executionRequests[0].options.variables).toEqual(
[{ key: 'VAR1', value: 'VAL1' },
{ encrypted: true, key: 'VAR2', value: 'VAL2' }],
);
await verifyResponsesReturned([DEFAULT_RESPONSE]); // eslint-disable-line
});
});

describe('runImpl', () => {
it('should handle running pipeline', async () => {
const argv = { name: 'some name', detach: true };
Expand Down
12 changes: 7 additions & 5 deletions lib/interface/cli/commands/pipeline/run.base.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
const _ = require('lodash');
const Promise = require('bluebird');
const { prepareKeyValueFromCLIEnvOption } = require('../../helpers/general');
const CFError = require('cf-errors');
const { prepareKeyValueFromCLIEnvOption,
markEncryptedFlagOnRequestedVariables,
prepareKeyValueObjectsFromEnvFileOption } = require('../../helpers/general');
const { validatePipelineYaml } = require('../../helpers/validation');
const { printResult } = require('../root/validate.cmd');
const CFError = require('cf-errors');
const { sdk } = require('../../../../logic');

class RunBaseCommand {
Expand Down Expand Up @@ -59,18 +61,18 @@ class RunBaseCommand {
if (variablesFromFile) {
_.forEach(variablesFromFile, (variables) => {
const request = _.cloneDeep(executionRequestTemplate);
request.options.variables = variables;
request.options.variables = prepareKeyValueObjectsFromEnvFileOption(variables);
this.executionRequests.push(request);
});
} else {
const variables = prepareKeyValueFromCLIEnvOption(this.argv.variable);
const variables = markEncryptedFlagOnRequestedVariables(this.argv.variable, this.argv.encrypted);
const request = _.cloneDeep(executionRequestTemplate);
request.options.variables = variables;
request.options.contexts = contexts;
this.executionRequests.push(request);
}

const results = await Promise.all(this.executionRequests.map(request => this.runImpl(request)));
const results = await Promise.all(this.executionRequests.map((request) => this.runImpl(request)));
const findMaxReducer = (accumulator, currentValue) => (currentValue > accumulator ? currentValue : accumulator);
const exitCode = results.reduce(findMaxReducer);
await this.postRunRequest();
Expand Down
11 changes: 9 additions & 2 deletions lib/interface/cli/commands/pipeline/run.cmd.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
const debug = require('debug')('codefresh:cli:run:pipeline');
const Command = require('../../Command');
const { crudFilenameOption } = require('../../helpers/general');
const { crudFilenameOption, prepareKeyValueObjectsFromCLIEnvOption } = require('../../helpers/general');
const RunLocalCommand = require('./run.local');
const RunExternalCommand = require('./run.cf');

Expand Down Expand Up @@ -85,6 +84,13 @@ const run = new Command({
describe: 'Set build variables',
default: [],
alias: 'v',
coerce: prepareKeyValueObjectsFromCLIEnvOption,
})
.option('encrypted', {
array: true,
alias: 'e',
describe: 'Variable names to encrypt',
default: [],
})
.option('detach', {
alias: 'd',
Expand Down Expand Up @@ -126,6 +132,7 @@ const run = new Command({
.example('codefresh run PIPELINE_ID | PIPELINE_NAME -b=master', 'Defining the source control context using a branch')
.example('codefresh run PIPELINE_ID | PIPELINE_NAME -s=52b992e783d2f84dd0123c70ac8623b4f0f938d1', 'Defining the source control context using a commit')
.example('codefresh run PIPELINE_ID | PIPELINE_NAME -b=master -v key1=value1 -v key2=value2', 'Setting variables through the command')
.example('codefresh run PIPELINE_ID | PIPELINE_NAME -b=master -v key1=value1 -v key2=value2 -e key1', 'Setting variables through the command with encrypted option')
.example('codefresh run PIPELINE_ID | PIPELINE_NAME -b=master --var-file ./var_file.yml', 'Settings variables through a yml file')
.example('codefresh run PIPELINE_ID | PIPELINE_NAME -b=master --context context', 'Inject contexts to the pipeline execution')
.example('codefresh run PIPELINE_ID | PIPELINE_NAME --skip step1 step2 step3', 'Skip specific steps');
Expand Down
12 changes: 12 additions & 0 deletions lib/interface/cli/commands/pipeline/var.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"build1": {
"help6": "85858",
"should_be_encrepted": "0000",
"help7": {
"value": "test",
"encrypted": true
}
}
}


5 changes: 5 additions & 0 deletions lib/interface/cli/commands/pipeline/var.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
build1:
VAR1: 'VAL1'
VAR2:
value: VAL2
encrypted: true
13 changes: 3 additions & 10 deletions lib/interface/cli/commands/project/apply.cmd.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ const _ = require('lodash');
const { sdk } = require('../../../../logic');

const applyRoot = require('../root/apply.cmd');
const { prepareKeyValueObjectsFromCLIEnvOption, ignoreHttpError } = require('../../helpers/general');
const { prepareKeyValueObjectsFromCLIEnvOption, ignoreHttpError, markEncryptedFlagOnRequestedVariables } = require('../../helpers/general');

const command = new Command({
command: 'project [id|name]',
Expand Down Expand Up @@ -61,14 +61,7 @@ const command = new Command({
encrypted,
} = argv;

const variableMap = _.reduce(variables, (acc, v) => _.assign(acc, { [v.key]: v }), {});
_.forEach(encrypted, (varName) => {
const variable = variableMap[varName];
if (!variable) {
throw new CFError(`Variable is not provided: "${varName}"`);
}
variable.encrypted = true;
});
const requestedProjectVariables = markEncryptedFlagOnRequestedVariables(variables, encrypted);

let project = await sdk.projects.get({ id }).catch(ignoreHttpError);
project = project || await sdk.projects.getByName({ name }).catch(ignoreHttpError);
Expand All @@ -81,7 +74,7 @@ const command = new Command({
const updatePayload = _.pickBy({
projectName,
tags: tags || existingTags,
variables: variables || existingVariables,
variables: requestedProjectVariables || existingVariables,
}, _.identity);

await sdk.projects.patch({ id: project.id }, updatePayload);
Expand Down
15 changes: 3 additions & 12 deletions lib/interface/cli/commands/project/create.cmd.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
const Command = require('../../Command');
const CFError = require('cf-errors');
const _ = require('lodash');
const { sdk } = require('../../../../logic');
const createRoot = require('../root/create.cmd');
const { checkOrProjectExists } = require('../../helpers/validation');
const { prepareKeyValueObjectsFromCLIEnvOption } = require('../../helpers/general');
const { prepareKeyValueObjectsFromCLIEnvOption, markEncryptedFlagOnRequestedVariables } = require('../../helpers/general');

const command = new Command({
command: 'project <name>',
Expand Down Expand Up @@ -52,17 +50,10 @@ const command = new Command({
encrypted,
} = argv;

const variableMap = _.reduce(variables, (acc, v) => _.assign(acc, { [v.key]: v }), {});
_.forEach(encrypted, (varName) => {
const variable = variableMap[varName];
if (!variable) {
throw new CFError(`Variable is not provided: "${varName}"`);
}
variable.encrypted = true;
});
const requestedProjectVariables = markEncryptedFlagOnRequestedVariables(variables, encrypted);

await checkOrProjectExists(projectName);
await sdk.projects.create({ projectName, tags, variables });
await sdk.projects.create({ projectName, tags, variables: requestedProjectVariables });
console.log(`Project: "${projectName}" created`);
},
});
Expand Down
Loading

0 comments on commit acbce01

Please sign in to comment.