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.