Skip to content

CR-17813 #800

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 21 commits into from
Apr 23, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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