CloudBuild jobs not executed in parallel - google-cloud-build

I am learning CloudBuild and understand that I can use waitFor to influence the order in which my build runs. job1 includes some sleep time to simulate a long running job. job2 just echos something. done waits for job1 & job2. So I created a test build like this: I have a package.json
{
"scripts": {
"job1": "echo \"[job1] Starting\" && sleep 5 && echo \"[job1] ...\" && sleep 2 && echo \"[job1] Done\" && exit 0",
"job2": "echo \"[job2] Hello from NPM\" && exit 0",
"done": "echo \"DONE DONE DONE!\" && exit 0"
},
}
Job 1 simulates a long running job, where I was hopping job 2 will execute in parallel. But seems like the output shows its not. Does CloudBuild run 1 step at a time only?
cloudbuild.yaml
steps:
- name: 'gcr.io/cloud-builders/npm'
args: ['run', 'job1']
id: 'job1'
- name: 'gcr.io/cloud-builders/npm'
args: ['run', 'job2']
id: 'job2'
- name: 'gcr.io/cloud-builders/npm'
args: ['run', 'done']
waitFor: ['job1', 'job2']
Output
Operation completed over 1 objects/634.0 B.
BUILD
Starting Step #0 - "job1"
Step #0 - "job1": Already have image (with digest): gcr.io/cloud-builders/npm
Step #0 - "job1":
Step #0 - "job1": > learn-gcp#1.0.0 job1 /workspace
Step #0 - "job1": > echo "[job1] Starting" && sleep 5 && echo "[job1] ..." && sleep 2 && echo "[job1] Done" && exit 0
Step #0 - "job1":
Step #0 - "job1": [job1] Starting
Step #0 - "job1": [job1] ...
Step #0 - "job1": [job1] Done
Finished Step #0 - "job1"
Starting Step #1 - "job2"
Step #1 - "job2": Already have image (with digest): gcr.io/cloud-builders/npm
Step #1 - "job2":
Step #1 - "job2": > learn-gcp#1.0.0 job2 /workspace
Step #1 - "job2": > echo "[job2] Hello from NPM" && exit 0
Step #1 - "job2":
Step #1 - "job2": [job2] Hello from NPM
Finished Step #1 - "job2"
Starting Step #2
Step #2: Already have image (with digest): gcr.io/cloud-builders/npm
Step #2:
Step #2: > learn-gcp#1.0.0 done /workspace
Step #2: > echo "DONE DONE DONE!" && exit 0
Step #2:
Step #2: DONE DONE DONE!
Finished Step #2
PUSH
DONE

If you wanted the job2 to be executed concurrently with job1 you should have added the line
waitFor: ['-'] in your cloudbuild.yaml, immediatly after job2. As it is stated in the official documentation:
If no values are provided for waitFor, the build step waits for all prior build steps in the build request to complete successfully before running.
To run a build step immediately at build time, use - in the waitFor
field.
The order of the build steps in the steps field relates to the order
in which the steps are executed. Steps will run serially or
concurrently based on the dependencies defined in their waitFor
fields.
In the documentation is, also an example on how to run two jobs in parallel.
In case you want job2 to run allong with job1 you should have something like this:
steps:
- name: 'gcr.io/cloud-builders/npm'
args: ['run', 'job1']
id: 'job1'
- name: 'gcr.io/cloud-builders/npm'
args: ['run', 'job2']
id: 'job2'
waitFor: ['-'] # The '-' indicates that this step begins immediately.
- name: 'gcr.io/cloud-builders/npm'
args: ['run', 'done']
waitFor: ['job1', 'job2']
Also note that the maximum number of concurent builds you can use is ten.

Related

Bash: How to execute paths

I have job in my gitlab-cicd.yml file:
unit_test:
stage: test
image: $MAVEN_IMAGE
script:
- *tests_variables_export
- mvn ${MAVEN_CLI_OPTS} clean test
- cat ${CI_PROJECT_DIR}/rest-service/target/site/jacoco/index.html
- cat ${CI_PROJECT_DIR}/soap-service/target/site/jacoco/index.html
artifacts:
expose_as: 'code coverage'
paths:
- ${CI_PROJECT_DIR}/soap-service/target/surefire-reports/
- ${CI_PROJECT_DIR}/rest-service/target/surefire-reports/
- ${CI_PROJECT_DIR}/soap-service/target/site/jacoco/index.html
- ${CI_PROJECT_DIR}/rest-service/target/site/jacoco/index.html
And I want to change it to this one:
unit_test:
stage: test
image: $MAVEN_IMAGE
script:
- *tests_variables_export
- mvn ${MAVEN_CLI_OPTS} clean test
- cat ${CI_PROJECT_DIR}/rest-service/target/site/jacoco/index.html
- cat ${CI_PROJECT_DIR}/soap-service/target/site/jacoco/index.html
artifacts:
expose_as: 'code coverage'
paths:
- *resolve_paths
I try to use this bash script:
.resolve_paths: &resolve_paths |-
if [ "${MODULE_FIRST}" != "UNKNOWN" ]; then
echo "- ${CI_PROJECT_DIR}/${MODULE_FIRST}/target/surefire-reports/"
echo "- ${CI_PROJECT_DIR}/${MODULE_FIRST}/target/site/jacoco/index.html"
fi
if [ "${MODULE_SECOND}" != "UNKNOWN" ]; then
echo "- ${CI_PROJECT_DIR}/${MODULE_SECOND}/target/surefire-reports/"
echo "- ${CI_PROJECT_DIR}/${MODULE_SECOND}/target/site/jacoco/index.html"
fi
And right now I'm getting this error in pipeline:
WARNING: if [ "rest-service" != "UNKNOWN" ]; then\n echo "- /builds/minv/common/testcommons/taf-api-support/rest-service/target/surefire-reports/"\n echo "- /builds/minv/common/testcommons/taf-api-support/rest-service/target/site/jacoco/index.html"\nfi\nif [ "soap-service" != "UNKNOWN" ]; then\n echo "- /builds/minv/common/testcommons/taf-api-support/soap-service/target/surefire-reports/"\n echo "- /builds/minv/common/testcommons/taf-api-support/soap-service/target/site/jacoco/index.html"\nfi: no matching files ERROR: No files to upload
Can I execute [sic] paths using bash script like this?
No, scripts cannot alter the current YAML, particularly not if you specify the script (which is just a string) in a place where it is interpreted as a path.
You could trigger a dynamically generated YAML:
generate:
stage: build
script:
- |
exec > generated.yml
echo ".resolve_paths: &resolve_paths"
for module in "${MODULE_FIRST}" "${MODULE_SECOND}"; do
[[ "$module" = UNKNOWN ]] && continue
echo "- ${CI_PROJECT_DIR}/${module}/target/surefire-reports/"
echo "- ${CI_PROJECT_DIR}/${module}/target/site/jacoco/index.html"
done
sed '1,/^\.\.\. *$/d' "${CI_CONFIG_PATH}"
artifacts:
paths:
- generated.yml
run:
stage: deploy
trigger:
include:
- artifact: generated.yml
job: generate
...
# Start of actual CI. When this runs, there will be an
# auto-generated job `.resolve_paths: &resolve_paths`.
# Put the rest of your CI (e.g. `unit_test:`) here.
But there are so many extensions in GitLab's YAML that you likely will find a tremendously better solution, which depends on what you plan to do with .resolve_paths. Maybe have a look at
artifacts:exclude
additional jobs with rules:

Not able to set environment variable in cloudbuild.yaml file

I am trying to set env variable in the cloudbuild.yaml file but it's not getting set. Am I missing something ? Below is the yaml file:
cloudbuild.yaml
steps:
# Install npm
- name: "node:10.16.3"
id: installing_npm
args: ["npm", "install"]
dir: "/workspace/API/ground_truth_trigger"
# Test Cloud Function
- name: 'node:10.16.3'
id: run_test_coverage
dir: '/workspace/API/ground_truth_trigger'
entrypoint: bash
env: ['BUCKET_NAME = dummycblbucket', 'AUDIT_BUCKET_NAME = dummyAuditbucket']
args:
- '-c'
- |
if [[ $BRANCH_NAME =~ ^ground_truth_trigger-[0-9]+-api$ ]]
then
npm run test
fi
# env:
# - 'BUCKET_NAME = dummycblbucket'
# - 'AUDIT_BUCKET_NAME = dummyAuditbucket'
Below are the logs:
Step #1 - "run_test_coverage": Already have image: node:10.16.3
Step #1 - "run_test_coverage":
Step #1 - "run_test_coverage": > ground_truth_trigger#1.0.0 test /workspace/API/ground_truth_trigger
Step #1 - "run_test_coverage": > nyc --reporter=lcov --reporter=text mocha test/unit/*
Step #1 - "run_test_coverage":
Step #1 - "run_test_coverage": envs { npm_config_cache_lock_stale: '60000',
Step #1 - "run_test_coverage": npm_config_ham_it_up: '',
Step #1 - "run_test_coverage": npm_config_legacy_bundling: '',
Step #1 - "run_test_coverage": npm_config_sign_git_tag: '',
Step #1 - "run_test_coverage": npm_config_user_agent: 'npm/6.9.0 node/v10.16.3 linux x64',
Step #1 - "run_test_coverage": '{"_":["mocha"],"reporter":["lcov","text"],"r":["lcov","text"],"cwd":"/workspace/API/ground_truth_trigger","temp-dir":"./.nyc_output","t":"./.nyc_output","tempDir":"./.nyc_output","exclude":["coverage/**","packages/*/test{,s}/**","**/*.d.ts","test{,s}/**","test{,-*}.{js,cjs,mjs,ts}","**/*{.,-}test.{js,cjs,mjs,ts}","**/__tests__/**","**/{ava,nyc}.config.{js,cjs,mjs}","**/jest.config.{js,cjs,mjs,ts}","**/{karma,rollup,webpack}.config.js","**/{babel.config,.eslintrc,.mocharc}.{js,cjs}"],"x":["coverage/**","packages/*/test{,s}/**","**/*.d.ts","test{,s}/**","test{,-*}.{js,cjs,mjs,ts}","**/*{.,-}test.{js,cjs,mjs,ts}","**/__tests__/**","**/{ava,nyc}.config.{js,cjs,mjs}","**/jest.config.{js,cjs,mjs,ts}","**/{karma,rollup,webpack}.config.js","**/{babel.config,.eslintrc,.mocharc}.{js,cjs}"],"exclude-node-modules":true,"excludeNodeModules":true,"include":[],"n":[],"extension":[".js",".cjs",".mjs",".ts",".tsx",".jsx"],"e":[".js",".cjs",".mjs",".ts",".tsx",".jsx"],"ignore-class-methods":[],"ignoreClassMethods":[],"auto-wrap":true,"autoWrap":true,"es-modules":true,"esModules":true,"parser-plugins":["asyncGenerators","bigInt","classProperties","classPrivateProperties","dynamicImport","importMeta","objectRestSpread","optionalCatchBinding"],"parserPlugins":["asyncGenerators","bigInt","classProperties","classPrivateProperties","dynamicImport","importMeta","objectRestSpread","optionalCatchBinding"],"compact":true,"preserve-comments":true,"preserveComments":true,"produce-source-map":true,"produceSourceMap":true,"source-map":true,"sourceMap":true,"require":[],"i":[],"instrument":true,"exclude-after-remap":true,"excludeAfterRemap":true,"branches":0,"functions":0,"lines":90,"statements":0,"per-file":false,"perFile":false,"check-coverage":false,"checkCoverage":false,"report-dir":"coverage","reportDir":"coverage","show-process-tree":false,"showProcessTree":false,"skip-empty":false,"skipEmpty":false,"skip-full":false,"skipFull":false,"silent":false,"s":false,"all":false,"a":false,"eager":false,"cache":true,"c":true,"babel-cache":false,"babelCache":false,"use-spawn-wrap":false,"useSpawnWrap":false,"hook-require":true,"hookRequire":true,"hook-run-in-context":false,"hookRunInContext":false,"hook-run-in-this-context":false,"hookRunInThisContext":false,"clean":true,"in-place":false,"inPlace":false,"exit-on-error":false,"exitOnError":false,"delete":false,"complete-copy":false,"completeCopy":false,"$0":"node_modules/.bin/nyc","instrumenter":"./lib/instrumenters/istanbul"}',
Step #1 - "run_test_coverage": NYC_CWD: '/workspace/API/ground_truth_trigger',
Step #1 - "run_test_coverage": NODE_OPTIONS:
Step #1 - "run_test_coverage": ' --require /workspace/API/ground_truth_trigger/node_modules/node-preload/preload-path/node-preload.js',
Step #1 - "run_test_coverage": NODE_PRELOAD_904597faf3dd793b123e0cc47c7e6f55e1b18fb4:
Step #1 - "run_test_coverage": '/workspace/API/ground_truth_trigger/node_modules/nyc/lib/register-env.js:/workspace/API/ground_truth_trigger/node_modules/nyc/lib/wrap.js',
Step #1 - "run_test_coverage": NYC_PROCESS_ID: '2403b1ad-d5b2-4715-b9de-abbb54f424cf' }
Step #1 - "run_test_coverage":
Step #1 - "run_test_coverage": Error: A bucket name is needed to use Cloud Storage.
Step #1 - "run_test_coverage": at Storage.bucket (/workspace/API/ground_truth_trigger/node_modules/#google-cloud/storage/build/src/storage.js:151:19)
Step #1 - "run_test_coverage": at /workspace/API/ground_truth_trigger/src/index.js:4:48
Could you please help!
You need to remove the space before and after the =
env: ['BUCKET_NAME=dummycblbucket', 'AUDIT_BUCKET_NAME=dummyAuditbucket']
You can check the value in Cloud Build by performing
An echo of the env var echo $$BUCKET_NAME. The double $ is required to indicate to Cloud Build to not replace with substituons variables.
Use the printenv command.

Gitlab CI/CD execute specific stages instead of all the stages

I have several stages in my gitlab-ci.yml file,
For example:
stages:
- one
- two
- three
Is there possibility to run specified stages? In Makefile it's called "targets". I want in different cases execute different stages. For example:
if [ <condition 1> ]; then
run all stages;
if [ <condition 2> ]; then
run stage "one";
if [ <condition 3> ]; then
run stages "two" and "three";
fi
You can do it at the job level using if rules.
Also, a stage can contain only one job. So, create 3 jobs in your .gitlab-ci.yml, one per stage and configure rules like this (check the doc for more example) ex :
stages:
- one
- two
- three
job_one:
stage: one
script: "echo Hello, stage one"
rules:
- if: '$VAR == "string value"'
job_two:
stage: two
script: "echo Hello, stage two"
rules:
- if: '$VAR == "string value"'
job_three:
stage: three
script: "echo Hello, stage three"
rules:
- if: '$VAR == "string value"'

Salt's cmd.run ignoring shell script return code

I am using a simple salt state to send (file.managed) and execute (cmd.run) a shell script on a minion/target. No matter what exit or return value the shell script sends, the salt master is interpreting the result as successful.
I tried using cmd.script, but keep getting a permission denied error on the temp version of the file under /tmp. Filesystem is not mounted with noexec so we can't figure out why it won't work.
For cmd.run, stdout in the job output shows the failed return code and message but Salt still says Success. Running the script locally on the minion reports the return/exit code as expected.
I tried adding stateful: True into the cmd.run block and formatted the key value pairs at the end of the shell script as demonstrated in the docs.
Running against 2 minion target, 1 fail 1 succeed. Both report Result as True but correctly populate Comment with my key value pair.
I've tried YES/NO, TRUE/FALSE, 0/1 - nothing works.
The end of my shell script, formatted as shown in the docs.
echo Return_Code=${STATUS}
# exit ${STATUS}
if [[ ${STATUS} -ne 0 ]]
then
echo ""
echo "changed=False comment='Failed'"
else
echo ""
echo "changed=True comment='Success'"
fi
The SLS block:
stop_oracle:
cmd.run:
- name: {{scriptDir}}/{{scriptName}}{{scriptArg}}
- stateful: True
- failhard: True
SLS output from Successful minion:
----------
ID: stop_oracle
Function: cmd.run
Name: /u01/orastage/oraclepsu/scripts/oracle_ss_wrapper.ksh stop
Result: True
Comment: Success
Started: 14:37:44.519131
Duration: 18930.344 ms
Changes:
----------
changed:
True
pid:
26195
retcode:
0
stderr:
stty: standard input: Inappropriate ioctl for device
stdout:
Script running under ROOT
Mon Jul 1 14:38:03 EDT 2019 : Successful
Return_Code=0
SLS output from Failed minion:
----------
ID: stop_oracle
Function: cmd.run
Name: /u01/orastage/oraclepsu/scripts/oracle_ss_wrapper.ksh stop
Result: True
Comment: Failed
Started: 14:07:14.153940
Duration: 38116.134 ms
Changes:
Output from shell script run locally on fail target:
[oracle#a9tvdb102]:/home/oracle:>>
/u01/orastage/oraclepsu/scripts/oracle_ss_wrapper.ksh stop
Mon Jul 1 15:29:18 EDT 2019 : There are errors in the process
Return_Code=1
changed=False comment='Failed'
Output from shell script run locally on success target:
[ /home/oracle ]
oracle#r9tvdo1004.giolab.local >
/u01/orastage/oraclepsu/scripts/oracle_ss_wrapper.ksh stop
Mon Jul 1 16:03:18 EDT 2019 : Successful
Return_Code=0
changed=True comment='Success'

How do I pass boolean Environmental Variables to a `when` step in CircleCI?

I want to do something along the lines of
commands:
send-slack:
parameters:
condition:
type: env_var_name
steps:
- when:
# only send if it's true
condition: << parameters.condition >>
steps:
- run: # do some stuff if it's true
jobs:
deploy:
steps:
- run:
name: Prepare Message
command: |
# Do Some stuff dynamically to figure out what message to send
# and save it to success_message or failure_message
echo "export success_message=true" >> $BASH_ENV
echo "export failure_message=false" >> $BASH_ENV
- send-slack:
text: "yay"
condition: success_message
- send-slack:
text: "nay"
condition: failure_message
```
Based on this documentation, you cannot use environment variables as conditions in CircleCI. This is because the when logic is done when the configuration is processed (ie, before the job actually runs and the environment variables are set). As an alternative, I would add the logic to a separate run step (or the same initial one).
jobs:
deploy:
steps:
- run:
name: Prepare Message
command: |
# Do Some stuff dynamically to figure out what message to send
# and save it to success_message or failure_message
echo "export success_message=true" >> $BASH_ENV
echo "export failure_message=false" >> $BASH_ENV
- run:
name: Send Message
command: |
if $success_message; then
# Send success message
fi
if $failure_message; then
# Send failure message
fi
Here is a relevant ticket on the CircleCI discussion board.

Resources