1. circleci/orb-tools@12.3.0

circleci/orb-tools@12.3.0

Certified
Sections
An orb for creating orbs. This orb is automatically implemented as a part of the generated config produced by the Orb Development Kit. To get started writing your own orb, see the docs linked in the "Homepage" url below.
Created: September 24, 2018Version Published: December 16, 2024Releases: 97
Org Usage:
487

Orb Quick Start Guide

Use CircleCI version 2.1 at the top of your .circleci/config.yml file.

1 version: 2.1

Add the orbs stanza below your version, invoking the orb:

1 2 orbs: orb-tools: circleci/orb-tools@12.3.0

Use orb-tools elements in your existing workflows and jobs.

Usage Examples

step1_lint-pack

The Orb-Tools orb is typically configured automatically by the Orb Development Kit. After initializing a new orb, this is the configuration file that will be automatically loaded. This configuration uses "Dynamic Config" with two different configuration files. In this example, we will see only the first `config.yml` file. This config breaks our orb's CI pipeline into two workflows, "test-pack", and "test-deploy". "test-pack" will lint, shellcheck, and review our orb, before triggering the "test-deploy" workflow with the orb injected for e2e testing. See the list of jobs for a detailed description of each job. "test-deploy" is found in the `./circleci/test-deploy.yml` file. See step 2 for more information.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 version: '2.1' setup: true orbs: orb-tools: circleci/orb-tools@12.0 shellcheck: circleci/shellcheck@3.1 workflows: lint-pack: jobs: - orb-tools/lint: filters: tags: only: /.*/ - orb-tools/pack: filters: tags: only: /.*/ - orb-tools/review: filters: tags: only: /.*/ orb_name: <orb name> - shellcheck/check: exclude: SC2148,SC2038,SC2086,SC2002,SC2016 filters: tags: only: /.*/ - orb-tools/continue: filters: tags: only: /.*/ orb_name: <orb name> pipeline_number: << pipeline.number >> requires: - orb-tools/lint - orb-tools/review - orb-tools/pack - shellcheck/check vcs_type: << pipeline.project.type >>

step2_test-deploy

After linting and shellchecking the orb is injected into this config dynamically by the "continue" job and triggered. The orb is purposefully not imported here, though it is referenced in the config, it will be dynamically injected. With the orb loaded, we can run "integration tests" by executing our orbs commands and jobs and validating their output. Finally, if the commit has been tagged (ex v1.0.0), we can publish the orb to a production version. For advanced usage, see the full docs linked in the "Homepage" url above.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 version: '2.1' orbs: orb-tools: circleci/orb-tools@12.0 jobs: command-tests: docker: - image: cimg/base:current steps: - checkout - <my-orb>/my_command - <my-orb>/my_command_2 workflows: test-deploy: jobs: - command-tests: filters: tags: only: /.*/ - <my-orb>/my-job: filters: tags: only: /.*/ - orb-tools/pack: filters: tags: only: /.*/ - orb-tools/publish: context: - orb-publishing-context filters: branches: ignore: /.*/ tags: only: /^v[0-9]+\.[0-9]+\.[0-9]+$/ orb_name: <namespace>/<my-orb> pub_type: production requires: - orb-tools/pack - command-tests - <my-orb>/my_job vcs_type: <<pipeline.project.type>>

Jobs

continue

Continue the pipeline for testing. This job will inject your orb source code into the provided config file prior to continuing the pipeline. With the orb injected, it will be possible to test your orbs features as if it were published.

Show job Source
PARAMETER
DESCRIPTION
REQUIRED
DEFAULT
TYPE
attach_workspace
By default, the workspace will be attached to the job at the orb_dir path. If you are implementing a custom workflow, you may want to disable this behavior.
No
true
boolean
checkout
If you do not wish to checkout the source code, you may disable this behavior. Replace the checkout and add your own command or steps via the 'pre-steps' parameter in your workflow.
No
true
boolean
circleci_api_host
Host URL of CircleCI API. If you are using CircleCI server, this value should be set.
No
https://circleci.com
string
circleci_app_host
Host URL of CircleCI Web UI. If you are using CircleCI server, this value should be set.
No
https://app.circleci.com
string
circleci_ip_ranges
Enables jobs to go through a set of well-defined IP address ranges.
No
false
boolean
config_path
Path to the next config file to execute. By default, this will execute the "test_deploy" workflow.
No
.circleci/test-deploy.yml
string
executor
The executor to use for this job. By default, this will use the "default" executor provided by this orb.
No
default
executor
inject_orb
If true, the orb will be injected into the provided config file.
No
true
boolean
orb_dir
Directory containing packed orb source. Path must be absolute or relative to the working directory. Should match the "orb_dir" of the "pack" job.
No
dist
string
orb_file_name
The orb output file name. The orb will be named this value in the output directory. Path must be absolute or relative to the working directory.
No
orb.yml
string
orb_name
The reference name of the orb to be injected in the config, no namespace or version number. e.g. "orb-tools"
Yes
-
string
pipeline_number
The CircleCI pipeline number. Required to be passed in as a parameter for compatibility.
Yes
-
integer
vcs_type
The VCS type. Required to be passed in as a parameter for compatibility. Should be configured automatically by the Orb Development Kit.
Yes
-
enum

lint

Lint all YAML files in the project. A ".yamllint" file will be generated for you automatically by the Orb Development Kit.

Show job Source
PARAMETER
DESCRIPTION
REQUIRED
DEFAULT
TYPE
checkout
If you do not wish to checkout the source code, you may disable this behavior. Replace the checkout and add your own command or steps via the 'pre-steps' parameter in your workflow.
No
true
boolean
circleci_ip_ranges
Enables jobs to go through a set of well-defined IP address ranges.
No
false
boolean
executor
The executor to use for this job. By default, this will use the "python" executor provided by this orb.
No
python
executor
source_dir
Path to the orb source. Path must be absolute or relative to the working directory.
No
src
string

pack

Packs the orb source into a single YAML file and validates for orb config errors. For CircleCI server servers, please ensure you set the `circleci-api-host` job parameter and CIRCLE_TOKEN environment variable.

Show job Source
PARAMETER
DESCRIPTION
REQUIRED
DEFAULT
TYPE
checkout
If you do not wish to checkout the source code, you may disable this behavior. Replace the checkout and add your own command or steps via the 'pre-steps' parameter in your workflow.
No
true
boolean
circleci_api_host
Host URL of CircleCI API. If you are using self_hosted CircleCI, this value should be set.
No
https://circleci.com
string
circleci_ip_ranges
Enables jobs to go through a set of well-defined IP address ranges.
No
false
boolean
executor
The executor to use for this job. By default, this will use the "default" executor provided by this orb.
No
default
executor
orb_dir
The orb output directory. The orb will be named "orb.yml" by default in this directory and persisted to the workspace. Path must be absolute or relative to the working directory.
No
dist
string
orb_file_name
The orb output file name. The orb will be named this value in the output directory. Path must be absolute or relative to the working directory.
No
orb.yml
string
org_id
The organization ID. Only necessary if your orb depends on private orbs in the same namespace. You can use "orb_slug" instead if you prefer.
No
''
string
org_slug
The organization slug (e.g., gh/MyOrg). Only necessary if your orb depends on private orbs in the same namespace. You can use "org_id" instead if you prefer.
No
''
string
persist_to_workspace
By default, the orb_dir will be persisted to a workspace so that it may be used by the "continue" job. If you are implementing a custom workflow, you may want to disable this behavior.
No
true
boolean
source_dir
Path to the orb source. Path must be absolute or relative to the working directory.
No
src
string

publish

Publish a new version of your orb. This job will produce a development version of an orb by default or will produce a new production version if the $CIRCLE_TAG environment variable is set, and the "pub_type" parameter is set to "production".

Show job Source
PARAMETER
DESCRIPTION
REQUIRED
DEFAULT
TYPE
attach_workspace
If you do not wish to attach the workspace, you may disable this behavior and add your own command or steps via the 'pre-steps' parameter in your workflow. This will attempt to attach the workspace at the path specified by the "orb_dir" parameter. It is expected that the workspace will contain 'orb_source.tar.gz' which should contain one or more orb source files. The tar file will be extracted to the "orb_dir" path.
No
true
boolean
checkout
If you do not wish to checkout the source code, you may disable this behavior. Replace the checkout and add your own command or steps via the 'pre-steps' parameter in your workflow.
No
true
boolean
circleci_api_host
Host URL of CircleCI API. If you are using CircleCI server, this value should be set.
No
https://circleci.com
string
circleci_ip_ranges
Enables jobs to go through a set of well-defined IP address ranges.
No
false
boolean
circleci_token
Enter the name of the environment variable containing your CircleCI API Token. This token must have production publishing scope (organization owner). Never directly enter the value of any secret tokens in your config.
No
CIRCLE_TOKEN
env_var_name
dev_tags
A comma separated list of development version tags to create. These tags are created by default, unless a production version is being published.
No
dev:${CIRCLE_SHA1},dev:alpha
string
enable_pr_comment
If true, a comment will be added to the PR when the orb is published for both development and production orbs. For GitHub users, a $GITHUB_TOKEN environment variable must be set.
No
true
boolean
executor
The executor to use for this job. By default, this will use the "default" executor provided by this orb.
No
default
executor
github_token
For GitHub users with "enable_pr_comment" enabled, the GitHub API token must be set. Use this parameter in the event you need to set a custom environment variable name other than the default.
No
GITHUB_TOKEN
env_var_name
orb_dir
Directory containing packed orb source. Path must be absolute or relative to the working directory. Should match the "output_dir" of the "pack" job.
No
dist
string
orb_file_name
The orb output file name. The orb will be named this value in the output directory. Should match the "orb_file_name" of the "pack" job.
No
orb.yml
string
orb_name
The version-less orb slug, e.g. "circleci/orb-tools"
Yes
-
string
pr_comment_graphql_url
The url used for GitHub graphql queries when adding comments to pull requests.
No
https://api.github.com/graphql?=
string
pub_type
Select the publishing type. Available options are "dev" and "production". If "production" is selected, the orb will be published to the orb registry only if the $CIRCLE_TAG environment variable is set. Publishing will be skipped otherwise. If "dev" is selected, two tags will be created: "dev:alpha" and "dev:<SHA1>".
No
dev
enum
release_environment
Enables tracking of the orb release in a defined CircleCI Release's environment. Passing in no environment name will disable tracking.
No
''
string
tag_pattern
A Regular Expression to compare against `$CIRCLE_TAG` when publishing a production version of an orb. Your tag must include a full semantic version number, which will be used to automatically version the published orb. Ensure you CircleCI config is also properly configured to trigger for this tag pattern. It is recommended to prefix or suffix around this pattern: '[0-9]+\.[0-9]+\.[0-9]+'.
No
^v[0-9]+\.[0-9]+\.[0-9]+$
string
vcs_type
The VCS type. Required to be passed in as a parameter for compatibility. Should be configured automatically by the Orb Development Kit.
Yes
-
enum

review

Automatically reviews your orb for best practices and produces JUnit test reports which are natively displayed in the CircleCI UI. The "Review" job checks against a suite of "RC" review checks, and if an opportunity for improvement is found, a suggestion with links to the relevant documentation is made.

Show job Source
PARAMETER
DESCRIPTION
REQUIRED
DEFAULT
TYPE
checkout
If you do not wish to checkout the source code, you may disable this behavior. Replace the checkout and add your own command or steps via the 'pre-steps' parameter in your workflow.
No
true
boolean
circleci_ip_ranges
Enables jobs to go through a set of well-defined IP address ranges.
No
false
boolean
exclude
A comma separated list of "RC" review check codes to explicitly ignore. Each review check has an associated "RC" code that can be identified to skip in future tests. If a review check fails, the "RC" code will be included in the output. Example: "RC001,RC002"
No
''
string
executor
The executor to use for this job. By default, this will use the "python" executor provided by this orb.
No
python
executor
max_command_length
The maximum length of a command (RC009). This is used to check for commands that are too long. Commands longer than this will fail the review.
No
64
integer
orb_name
The reference name of the orb to be injected in the config, no namespace or version number. e.g. "orb-tools". This is required for RC011. RC011 will be skipped if this is not set.
No
''
string
source_dir
Path to the orb source. Path must be absolute or relative to the working directory.
No
src
string

Executors

default

The circleci-cli Docker image, which includes the CircleCI CLI executable.

Show executor Source
PARAMETER
DESCRIPTION
REQUIRED
DEFAULT
TYPE
resource_class
Configure the executor resource class
No
medium
enum
tag
What version of the CircleCI CLI Docker image? For full list, see https://hub.docker.com/r/circleci/circleci-cli/tags
No
0.1.26646
string

python

An Ubuntu based image built by CircleCI with CI/CD in mind. This image contains basic tools and the Python runtime.

Show executor Source
PARAMETER
DESCRIPTION
REQUIRED
DEFAULT
TYPE
resource_class
Configure the executor resource class
No
medium
enum
tag
What version of the cimg/python image? For full list, see https://circleci.com/developer/images/image/cimg/python
No
'3.11'
string

Orb Source

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 # This code is licensed from CircleCI to the user under the MIT license. # See here for details: https://circleci.com/developer/orbs/licensing version: 2.1 description: | An orb for creating orbs. This orb is automatically implemented as a part of the generated config produced by the Orb Development Kit. To get started writing your own orb, see the docs linked in the "Homepage" url below. display: home_url: https://circleci.com/docs/2.0/orb-author/ source_url: https://github.com/CircleCI-Public/orb-tools-orb/ orbs: bats: circleci/bats@1.1.0 cli: circleci/circleci-cli@0.1.9 executors: default: description: | The circleci-cli Docker image, which includes the CircleCI CLI executable. docker: - image: circleci/circleci-cli:<< parameters.tag >> parameters: resource_class: default: medium description: Configure the executor resource class enum: - small - medium - medium+ - large - xlarge - 2xlarge - 2xlarge+ type: enum tag: default: 0.1.26646 description: | What version of the CircleCI CLI Docker image? For full list, see https://hub.docker.com/r/circleci/circleci-cli/tags type: string resource_class: << parameters.resource_class >> python: description: | An Ubuntu based image built by CircleCI with CI/CD in mind. This image contains basic tools and the Python runtime. docker: - image: cimg/python:<< parameters.tag >> parameters: resource_class: default: medium description: Configure the executor resource class enum: - small - medium - medium+ - large - xlarge - 2xlarge - 2xlarge+ type: enum tag: default: "3.11" description: | What version of the cimg/python image? For full list, see https://circleci.com/developer/images/image/cimg/python type: string resource_class: << parameters.resource_class >> jobs: continue: circleci_ip_ranges: << parameters.circleci_ip_ranges >> description: | Continue the pipeline for testing. This job will inject your orb source code into the provided config file prior to continuing the pipeline. With the orb injected, it will be possible to test your orbs features as if it were published. executor: << parameters.executor >> parameters: attach_workspace: default: true description: | By default, the workspace will be attached to the job at the orb_dir path. If you are implementing a custom workflow, you may want to disable this behavior. type: boolean checkout: default: true description: | If you do not wish to checkout the source code, you may disable this behavior. Replace the checkout and add your own command or steps via the 'pre-steps' parameter in your workflow. type: boolean circleci_api_host: default: https://circleci.com description: Host URL of CircleCI API. If you are using CircleCI server, this value should be set. type: string circleci_app_host: default: https://app.circleci.com description: Host URL of CircleCI Web UI. If you are using CircleCI server, this value should be set. type: string circleci_ip_ranges: default: false description: Enables jobs to go through a set of well-defined IP address ranges. type: boolean config_path: default: .circleci/test-deploy.yml description: Path to the next config file to execute. By default, this will execute the "test_deploy" workflow. type: string executor: default: default description: The executor to use for this job. By default, this will use the "default" executor provided by this orb. type: executor inject_orb: default: true description: If true, the orb will be injected into the provided config file. type: boolean orb_dir: default: dist description: Directory containing packed orb source. Path must be absolute or relative to the working directory. Should match the "orb_dir" of the "pack" job. type: string orb_file_name: default: orb.yml description: The orb output file name. The orb will be named this value in the output directory. Path must be absolute or relative to the working directory. type: string orb_name: description: | The reference name of the orb to be injected in the config, no namespace or version number. e.g. "orb-tools" type: string pipeline_number: description: The CircleCI pipeline number. Required to be passed in as a parameter for compatibility. type: integer vcs_type: description: The VCS type. Required to be passed in as a parameter for compatibility. Should be configured automatically by the Orb Development Kit. enum: - gh - github - bb - bitbucket type: enum steps: - when: condition: <<parameters.checkout>> steps: - checkout - when: condition: <<parameters.attach_workspace>> steps: - attach_workspace: at: <<parameters.orb_dir>> - run: command: | #!/bin/bash ORB_DIR=${ORB_VAL_ORB_DIR%/} # In order to support the possibility of multiple orbs, but with the limitation of requiring a single path to persist to a workspace # we will first tar the orb source to a single binary file, then untar it to the workspace. tar_source() { TMP_SRC_DIR=$(mktemp -d) tar -czf "${TMP_SRC_DIR}/orb_source.tar.gz" -C "${ORB_DIR}" . rm -rf "${ORB_DIR}" mkdir -p "${ORB_DIR}" mv "${TMP_SRC_DIR}/orb_source.tar.gz" "${ORB_DIR}/orb_source.tar.gz" rm -rf "${TMP_SRC_DIR}" } untar_source() { TMP_SRC_DIR=$(mktemp -d) tar -xzf "${ORB_DIR}/orb_source.tar.gz" -C "${TMP_SRC_DIR}" rm -rf "${ORB_DIR}" mkdir -p "${ORB_DIR}" mv "${TMP_SRC_DIR}/"* "${ORB_DIR}/" rm -rf "${TMP_SRC_DIR}" } if [[ $ORB_VAL_TAR == '1' ]]; then printf "Creating tarball of orb source.\n" tar_source pwd ls -la "${ORB_DIR}" fi if [[ $ORB_VAL_UNTAR == '1' ]]; then printf "Extracting tarball of orb source.\n" untar_source pwd ls -la "${ORB_DIR}" fi environment: ORB_VAL_ORB_DIR: << parameters.orb_dir >> ORB_VAL_UNTAR: true name: Prep Workspace - run: command: | #!/bin/bash ORB_DIR=${ORB_VAL_ORB_DIR%/} ORB_FILE=${ORB_VAL_ORB_FILE_NAME#/} # Create temporary directories and files setup() { mkdir -p /tmp/circleci/modified rm -rf /tmp/circleci/continue_post.json } # Check for required environment variables and commands checkRequirements() { if [ -z "${CIRCLE_CONTINUATION_KEY}" ]; then printf "CIRCLE_CONTINUATION_KEY is required. Make sure setup workflows are enabled.\n" printf "This Job is designed to be used with the Orb Development Kit.\n" exit 1 fi if [ -z "${ORB_VAL_CIRCLECI_API_HOST}" ]; then printf "ORB_VAL_CIRCLECI_API_HOST is required.\n" printf "If you are using CircleCI Cloud, use default value or set https://circleci.com.\n" exit 1 fi if ! command -v curl >/dev/null; then printf "curl is required to use this command\n" exit 1 fi if ! command -v jq >/dev/null; then printf "jq is required to use this command\n" exit 1 fi if ! command -v yq >/dev/null; then printf "yq is required to use this command\n" exit 1 fi if [ "$ORB_VAL_INJECT_ORB" == 1 ] && [ ! -f "${ORB_DIR}/${ORB_FILE}" ]; then printf "Inject orb is enabled, but %s is not found in %s.\n" "${ORB_FILE}" "${ORB_DIR}" fi } # Inject orb source into the configuration injectOrb() { printf "Injecting orb source into configuration.\n" ORB_SOURCE="${ORB_DIR}/${ORB_FILE}" export ORB_SOURCE # NOTE: load function from yq is only available from v4.x MODIFIED_CONFIG="$(yq '.orbs.[env(ORB_VAL_ORB_NAME)] = load(env(ORB_SOURCE))' "${ORB_VAL_CONTINUE_CONFIG_PATH}")" printf "Modified config:\n\n" printf "%s" "${MODIFIED_CONFIG}" printf "%s" "${MODIFIED_CONFIG}" >"/tmp/circleci/modified/${ORB_FILE}" export MODIFIED_CONFIG_PATH="/tmp/circleci/modified/${ORB_FILE}" printf "\n\n" } # Continue the pipeline using the modified configuration continuePipeline() { # Escape the config as a JSON string. jq -Rs '.' "${MODIFIED_CONFIG_PATH:-$ORB_VAL_CONTINUE_CONFIG_PATH}" >/tmp/circleci/config-string.json jq -n \ --arg continuation "$CIRCLE_CONTINUATION_KEY" \ --slurpfile config /tmp/circleci/config-string.json \ '{"continuation-key": $continuation, "configuration": $config|join("\n")}' >/tmp/circleci/continue_post.json # Continue the pipeline printf "Continuing pipeline...\n" RESPONSE=$( curl \ -s \ -o /dev/stderr \ -w '%{http_code}' \ -XPOST \ -H "Content-Type: application/json" \ -H "Accept: application/json" \ --data @/tmp/circleci/continue_post.json \ "${ORB_VAL_CIRCLECI_API_HOST}/api/v2/pipeline/continue" ) # Check if the pipeline was successfully continued if [[ "$RESPONSE" -eq 200 ]]; then printf "Pipeline successfully continued.\n" else printf "ERROR: Response code %s\n" "$RESPONSE" printf "Failed to continue pipeline. Attempt to retry the pipeline, if the problem persists please open an issue on the Orb-Tools Orb repository: https://github.com/CircleCI-Public/orb-tools-orb\n" exit 1 fi # [[ $(curl \ # -s \ # -o /dev/stderr \ # -w '%{http_code}' \ # -XPOST \ # -H "Content-Type: application/json" \ # -H "Accept: application/json" \ # --data @/tmp/circleci/continue_post.json \ # "${ORB_VAL_CIRCLECI_API_HOST}/api/v2/pipeline/continue") -eq 200 ]] || printf "Failed to continue pipeline. Attempt to retry the pipeline, if the problem persists please open an issue on the Orb-Tools Orb repository: https://github.com/CircleCI-Public/orb-tools-orb\n" >&2 && exit 1 } # Print completion message printComplete() { printf "Continuation successful!\n" printf "Your orb will now be tested in the next workflow.\n" # shellcheck disable=SC2153 printf "View the full pipeline progress: %s/pipelines/%s/%s/%s/%s\n" "${ORB_VAL_CIRCLECI_APP_HOST}" "${ORB_VAL_PIPELINE_VCS_TYPE}" "${CIRCLE_PROJECT_USERNAME}" "${CIRCLE_PROJECT_REPONAME}" "${ORB_VAL_PIPELINE_NUMBER}" } # ======================== setup checkRequirements if [ "$ORB_VAL_INJECT_ORB" == 1 ]; then injectOrb fi continuePipeline printComplete environment: ORB_VAL_CIRCLECI_API_HOST: <<parameters.circleci_api_host>> ORB_VAL_CIRCLECI_APP_HOST: <<parameters.circleci_app_host>> ORB_VAL_CONTINUE_CONFIG_PATH: <<parameters.config_path>> ORB_VAL_INJECT_ORB: <<parameters.inject_orb>> ORB_VAL_ORB_DIR: <<parameters.orb_dir>> ORB_VAL_ORB_FILE_NAME: <<parameters.orb_file_name>> ORB_VAL_ORB_NAME: <<parameters.orb_name>> ORB_VAL_PIPELINE_NUMBER: <<parameters.pipeline_number>> ORB_VAL_PIPELINE_VCS_TYPE: <<parameters.vcs_type>> name: Continuing To Orb Testing And Deployment lint: circleci_ip_ranges: << parameters.circleci_ip_ranges >> description: | Lint all YAML files in the project. A ".yamllint" file will be generated for you automatically by the Orb Development Kit. executor: << parameters.executor >> parameters: checkout: default: true description: | If you do not wish to checkout the source code, you may disable this behavior. Replace the checkout and add your own command or steps via the 'pre-steps' parameter in your workflow. type: boolean circleci_ip_ranges: default: false description: Enables jobs to go through a set of well-defined IP address ranges. type: boolean executor: default: python description: The executor to use for this job. By default, this will use the "python" executor provided by this orb. type: executor source_dir: default: src description: Path to the orb source. Path must be absolute or relative to the working directory. type: string steps: - when: condition: <<parameters.checkout>> steps: - checkout - run: command: | #!/bin/bash if [ ! -d "$ORB_VAL_SOURCE_DIR" ]; then printf "No source directory located at %s\n" "$ORB_VAL_SOURCE_DIR" printf "This orb assumes you have built your orb using the Orb Development Kit\n" printf "https://circleci.com/docs/2.0/orb-author/#orb-development-kit\n" exit 1 fi pip install --user yamllint yamllint "$ORB_VAL_SOURCE_DIR" environment: ORB_VAL_SOURCE_DIR: << parameters.source_dir >> name: Linting all YAML files pack: circleci_ip_ranges: << parameters.circleci_ip_ranges >> description: | Packs the orb source into a single YAML file and validates for orb config errors. For CircleCI server servers, please ensure you set the `circleci-api-host` job parameter and CIRCLE_TOKEN environment variable. executor: << parameters.executor >> parameters: checkout: default: true description: | If you do not wish to checkout the source code, you may disable this behavior. Replace the checkout and add your own command or steps via the 'pre-steps' parameter in your workflow. type: boolean circleci_api_host: default: https://circleci.com description: Host URL of CircleCI API. If you are using self_hosted CircleCI, this value should be set. type: string circleci_ip_ranges: default: false description: Enables jobs to go through a set of well-defined IP address ranges. type: boolean executor: default: default description: The executor to use for this job. By default, this will use the "default" executor provided by this orb. type: executor orb_dir: default: dist description: The orb output directory. The orb will be named "orb.yml" by default in this directory and persisted to the workspace. Path must be absolute or relative to the working directory. type: string orb_file_name: default: orb.yml description: The orb output file name. The orb will be named this value in the output directory. Path must be absolute or relative to the working directory. type: string org_id: default: "" description: | The organization ID. Only necessary if your orb depends on private orbs in the same namespace. You can use "orb_slug" instead if you prefer. type: string org_slug: default: "" description: | The organization slug (e.g., gh/MyOrg). Only necessary if your orb depends on private orbs in the same namespace. You can use "org_id" instead if you prefer. type: string persist_to_workspace: default: true description: | By default, the orb_dir will be persisted to a workspace so that it may be used by the "continue" job. If you are implementing a custom workflow, you may want to disable this behavior. type: boolean source_dir: default: src description: Path to the orb source. Path must be absolute or relative to the working directory. type: string steps: - when: condition: <<parameters.checkout>> steps: - checkout - run: command: | #!/bin/bash ORB_DIR=${ORB_VAL_ORB_DIR%/} ORB_FILE=${ORB_VAL_ORB_FILE_NAME#/} mkdir -p "$ORB_VAL_ORB_DIR" && circleci orb pack --skip-update-check "$ORB_VAL_SOURCE_DIR" >"${ORB_DIR}/${ORB_FILE}" environment: ORB_VAL_ORB_DIR: << parameters.orb_dir >> ORB_VAL_ORB_FILE_NAME: <<parameters.orb_file_name>> ORB_VAL_SOURCE_DIR: << parameters.source_dir >> name: Packing orb source - run: command: | #!/bin/bash # NOTE: an explicit API token is required for orb validation, for self-hosted CircleCI. # In the case of CircleCI cloud (https://circleci.com), an API token is not needed. ORB_DIR=${ORB_VAL_ORB_DIR%/} ORB_FILE=${ORB_VAL_ORB_FILE_NAME#/} if [ "https://circleci.com" != "${ORB_VAL_CIRCLECI_API_HOST}" ] && [ -z "${CIRCLE_TOKEN}" ]; then echo "Please set a valid CIRCLE_TOKEN token from your self-hosted CircleCI." exit 1 fi circleci orb validate --host "${ORB_VAL_CIRCLECI_API_HOST:-https://circleci.com}" --token "${CIRCLE_TOKEN:-dummy}" ${ORB_VAL_ORG_ID:+--org-id "$ORB_VAL_ORG_ID"} ${ORB_VAL_ORG_SLUG:+--org-slug "$ORB_VAL_ORG_SLUG"} --skip-update-check "${ORB_DIR}/${ORB_FILE}" environment: ORB_VAL_CIRCLECI_API_HOST: <<parameters.circleci_api_host>> ORB_VAL_ORB_DIR: << parameters.orb_dir >> ORB_VAL_ORB_FILE_NAME: <<parameters.orb_file_name>> ORB_VAL_ORG_ID: << parameters.org_id >> ORB_VAL_ORG_SLUG: << parameters.org_slug >> name: Validating orb - when: condition: <<parameters.persist_to_workspace>> steps: - run: command: | #!/bin/bash ORB_DIR=${ORB_VAL_ORB_DIR%/} # In order to support the possibility of multiple orbs, but with the limitation of requiring a single path to persist to a workspace # we will first tar the orb source to a single binary file, then untar it to the workspace. tar_source() { TMP_SRC_DIR=$(mktemp -d) tar -czf "${TMP_SRC_DIR}/orb_source.tar.gz" -C "${ORB_DIR}" . rm -rf "${ORB_DIR}" mkdir -p "${ORB_DIR}" mv "${TMP_SRC_DIR}/orb_source.tar.gz" "${ORB_DIR}/orb_source.tar.gz" rm -rf "${TMP_SRC_DIR}" } untar_source() { TMP_SRC_DIR=$(mktemp -d) tar -xzf "${ORB_DIR}/orb_source.tar.gz" -C "${TMP_SRC_DIR}" rm -rf "${ORB_DIR}" mkdir -p "${ORB_DIR}" mv "${TMP_SRC_DIR}/"* "${ORB_DIR}/" rm -rf "${TMP_SRC_DIR}" } if [[ $ORB_VAL_TAR == '1' ]]; then printf "Creating tarball of orb source.\n" tar_source pwd ls -la "${ORB_DIR}" fi if [[ $ORB_VAL_UNTAR == '1' ]]; then printf "Extracting tarball of orb source.\n" untar_source pwd ls -la "${ORB_DIR}" fi environment: ORB_VAL_ORB_DIR: << parameters.orb_dir >> ORB_VAL_TAR: true name: Prep Workspace - persist_to_workspace: paths: - orb_source.tar.gz root: <<parameters.orb_dir>> publish: circleci_ip_ranges: << parameters.circleci_ip_ranges >> description: | Publish a new version of your orb. This job will produce a development version of an orb by default or will produce a new production version if the $CIRCLE_TAG environment variable is set, and the "pub_type" parameter is set to "production". executor: << parameters.executor >> parameters: attach_workspace: default: true description: | If you do not wish to attach the workspace, you may disable this behavior and add your own command or steps via the 'pre-steps' parameter in your workflow. This will attempt to attach the workspace at the path specified by the "orb_dir" parameter. It is expected that the workspace will contain 'orb_source.tar.gz' which should contain one or more orb source files. The tar file will be extracted to the "orb_dir" path. type: boolean checkout: default: true description: | If you do not wish to checkout the source code, you may disable this behavior. Replace the checkout and add your own command or steps via the 'pre-steps' parameter in your workflow. type: boolean circleci_api_host: default: https://circleci.com description: Host URL of CircleCI API. If you are using CircleCI server, this value should be set. type: string circleci_ip_ranges: default: false description: Enables jobs to go through a set of well-defined IP address ranges. type: boolean circleci_token: default: CIRCLE_TOKEN description: | Enter the name of the environment variable containing your CircleCI API Token. This token must have production publishing scope (organization owner). Never directly enter the value of any secret tokens in your config. type: env_var_name dev_tags: default: dev:${CIRCLE_SHA1},dev:alpha description: | A comma separated list of development version tags to create. These tags are created by default, unless a production version is being published. type: string enable_pr_comment: default: true description: | If true, a comment will be added to the PR when the orb is published for both development and production orbs. For GitHub users, a $GITHUB_TOKEN environment variable must be set. type: boolean executor: default: default description: The executor to use for this job. By default, this will use the "default" executor provided by this orb. type: executor github_token: default: GITHUB_TOKEN description: | For GitHub users with "enable_pr_comment" enabled, the GitHub API token must be set. Use this parameter in the event you need to set a custom environment variable name other than the default. type: env_var_name orb_dir: default: dist description: Directory containing packed orb source. Path must be absolute or relative to the working directory. Should match the "output_dir" of the "pack" job. type: string orb_file_name: default: orb.yml description: The orb output file name. The orb will be named this value in the output directory. Should match the "orb_file_name" of the "pack" job. type: string orb_name: description: | The version-less orb slug, e.g. "circleci/orb-tools" type: string pr_comment_graphql_url: default: https://api.github.com/graphql?= description: | The url used for GitHub graphql queries when adding comments to pull requests. type: string pub_type: default: dev description: | Select the publishing type. Available options are "dev" and "production". If "production" is selected, the orb will be published to the orb registry only if the $CIRCLE_TAG environment variable is set. Publishing will be skipped otherwise. If "dev" is selected, two tags will be created: "dev:alpha" and "dev:<SHA1>". enum: - dev - production type: enum release_environment: default: "" description: Enables tracking of the orb release in a defined CircleCI Release's environment. Passing in no environment name will disable tracking. type: string tag_pattern: default: ^v[0-9]+\.[0-9]+\.[0-9]+$ description: | A Regular Expression to compare against `$CIRCLE_TAG` when publishing a production version of an orb. Your tag must include a full semantic version number, which will be used to automatically version the published orb. Ensure you CircleCI config is also properly configured to trigger for this tag pattern. It is recommended to prefix or suffix around this pattern: '[0-9]+\.[0-9]+\.[0-9]+'. type: string vcs_type: description: The VCS type. Required to be passed in as a parameter for compatibility. Should be configured automatically by the Orb Development Kit. enum: - gh - github - bb - bitbucket type: enum steps: - when: condition: <<parameters.attach_workspace>> steps: - attach_workspace: at: <<parameters.orb_dir>> - run: command: | #!/bin/bash ORB_DIR=${ORB_VAL_ORB_DIR%/} # In order to support the possibility of multiple orbs, but with the limitation of requiring a single path to persist to a workspace # we will first tar the orb source to a single binary file, then untar it to the workspace. tar_source() { TMP_SRC_DIR=$(mktemp -d) tar -czf "${TMP_SRC_DIR}/orb_source.tar.gz" -C "${ORB_DIR}" . rm -rf "${ORB_DIR}" mkdir -p "${ORB_DIR}" mv "${TMP_SRC_DIR}/orb_source.tar.gz" "${ORB_DIR}/orb_source.tar.gz" rm -rf "${TMP_SRC_DIR}" } untar_source() { TMP_SRC_DIR=$(mktemp -d) tar -xzf "${ORB_DIR}/orb_source.tar.gz" -C "${TMP_SRC_DIR}" rm -rf "${ORB_DIR}" mkdir -p "${ORB_DIR}" mv "${TMP_SRC_DIR}/"* "${ORB_DIR}/" rm -rf "${TMP_SRC_DIR}" } if [[ $ORB_VAL_TAR == '1' ]]; then printf "Creating tarball of orb source.\n" tar_source pwd ls -la "${ORB_DIR}" fi if [[ $ORB_VAL_UNTAR == '1' ]]; then printf "Extracting tarball of orb source.\n" untar_source pwd ls -la "${ORB_DIR}" fi environment: ORB_VAL_ORB_DIR: << parameters.orb_dir >> ORB_VAL_UNTAR: true name: Prep Workspace - run: command: "#!/bin/bash\n\nORB_DIR=${ORB_VAL_ORB_DIR%/}\nORB_FILE=${ORB_VAL_ORB_FILE_NAME#/}\n\nfunction validateProdTag() {\n if [[ ! \"${CIRCLE_TAG}\" =~ $ORB_VAL_TAG_PATTERN ]]; then\n printf \"Malformed tag detected.\\n\"\n printf \"Tag: %s\\n\\n\" \"$CIRCLE_TAG\"\n printf \"A production release has attempted to occur, but the tag does not match the expected pattern.\\n\"\n printf \"Aborting deployment. Push a new tag with the compatible form.\\n\"\n printf \"Current tag pattern: %s\\n\" \"$ORB_VAL_TAG_PATTERN\"\n exit 1\n fi\n}\n\nfunction validateOrbPubToken() {\n if [[ -z \"${ORB_VAL_ORB_PUB_TOKEN}\" ]]; then\n printf \"No Orb Publishing Token detected.\\n\"\n printf \"Please set the CIRCLE_TOKEN environment variable.\\n\"\n printf \"Aborting deployment.\\n\"\n exit 1\n fi\n}\n\nfunction publishOrb() {\n #$1 = full tag\n\n circleci orb publish --host \"${ORB_VAL_CIRCLECI_API_HOST:-https://circleci.com}\" --skip-update-check \"${ORB_DIR}/${ORB_FILE}\" \"${ORB_VAL_ORB_NAME}@${1}\" --token \"$ORB_VAL_ORB_PUB_TOKEN\"\n\n # Track release if ORB_VAL_RELEASE_ENVIRONMENT is set\n if [[ -n \"${ORB_VAL_RELEASE_ENVIRONMENT}\" ]]; then\n circleci-agent run release log --environment-name=\"${ORB_VAL_RELEASE_ENVIRONMENT}\" --component-name=\"${ORB_VAL_ORB_NAME}\" --target-version=\"${1}\"\n fi\n \n printf \"\\n\"\n {\n printf \"Your orb has been published to the CircleCI Orb Registry.\\n\"\n printf \"You can view your published orb on the CircleCI Orb Registry at the following link: \\n\"\n printf \"https://circleci.com/developer/orbs/orb/%s?version=%s\\n\" \"${ORB_VAL_ORB_NAME}\" \"${1}\"\n } >/tmp/orb_dev_kit/publishing_message.txt\n}\n\nfunction publishDevOrbs() {\n printf \"Publishing development orb(s).\\n\\n\"\n ORB_REG_LINKS=()\n DEV_TAG_LIST=$(echo \"${ORB_VAL_DEV_TAGS}\" | tr -d ' ')\n IFS=',' read -ra array \\<<<\"$DEV_TAG_LIST\"\n for tag in \"${array[@]}\"; do\n # shellcheck disable=SC2005\n PROCESSED_TAG=$(circleci env subst \"$tag\")\n ORB_REG_LINKS+=(\"$(printf 'https://circleci.com/developer/orbs/orb/%s?version=%s' \"$ORB_VAL_ORB_NAME\" \"$PROCESSED_TAG\")\")\n publishOrb \"$PROCESSED_TAG\"\n done\n {\n printf \"Your development orb(s) have been published. It will expire in 90 days.\\n\"\n printf \"You can preview what this will look like on the CircleCI Orb Registry at the following link(s): \\n\"\n printf \"%s\\n\" \"${ORB_REG_LINKS[@]}\"\n } >/tmp/orb_dev_kit/publishing_message.txt\n}\n\n\n# The main function\nfunction orbPublish() {\n printf \"Preparing to publish your orb.\\n\"\n validateOrbPubToken\n\n if [ \"$ORB_VAL_PUB_TYPE\" == \"production\" ]; then\n printf \"Production release detected!\\n\"\n if [ -z \"$CIRCLE_TAG\" ]; then\n printf \"No tag detected. Exiting.\\n\"\n printf \"If you are trying to publish a production orb, you must push a semantically versioned tag.\\n\"\n exit 1\n fi\n validateProdTag\n ORB_RELEASE_VERSION=\"$(echo \"${CIRCLE_TAG}\" | grep -Eo \"[0-9]+\\.[0-9]+\\.[0-9]+\")\"\n printf \" Production version: %s\\n\\n\" \"${ORB_RELEASE_VERSION}\"\n publishOrb \"${ORB_RELEASE_VERSION}\"\n elif [ \"$ORB_VAL_PUB_TYPE\" == \"dev\" ]; then\n printf \" Development release detected!\\n\\n\"\n publishDevOrbs\n else\n printf \" No release type detected.\\n\"\n printf \" Please report this error.\\n\"\n fi\n\n printf \"\\n\\n\"\n printf \"********************************************************************************\\n\"\n cat /tmp/orb_dev_kit/publishing_message.txt\n\n}\n\nORB_RELEASE_VERSION=\"\"\nORB_VAL_ORB_PUB_TOKEN=${!ORB_VAL_ORB_PUB_TOKEN}\nmkdir -p /tmp/orb_dev_kit/\norbPublish\n" environment: ORB_VAL_CIRCLECI_API_HOST: <<parameters.circleci_api_host>> ORB_VAL_DEV_TAGS: <<parameters.dev_tags>> ORB_VAL_ORB_DIR: <<parameters.orb_dir>> ORB_VAL_ORB_FILE_NAME: <<parameters.orb_file_name>> ORB_VAL_ORB_NAME: <<parameters.orb_name>> ORB_VAL_ORB_PUB_TOKEN: <<parameters.circleci_token>> ORB_VAL_PUB_TYPE: <<parameters.pub_type>> ORB_VAL_RELEASE_ENVIRONMENT: <<parameters.release_environment>> ORB_VAL_TAG_PATTERN: <<parameters.tag_pattern>> name: Publishing Orb Release - when: condition: <<parameters.enable_pr_comment>> steps: - run: command: | #!/bin/bash # shellcheck disable=SC2016 # shellcheck disable=SC2028 function postGitHubPRComment() { # $1 - PR ID HTTP_RESPONSE_GH=$(curl --request POST \ -s \ -o /tmp/orb_dev_kit/github_comment_response.json \ -w "%{http_code}" \ --url "$ORB_VAL_GH_GRAPHQL_URL" \ --header "$GH_HEADER_DATA" \ --data '{"query":"mutation AddCommentToPR($body: String!, $sid: ID!) {\n addComment(input: {\n body: $body,\n subjectId: $sid\n }) {\n clientMutationId\n }\n}","variables":{"body":"'"$PR_COMMENT_BODY"'","sid":"'"$1"'"},"operationName":"AddCommentToPR"}') if [[ "$HTTP_RESPONSE_GH" -ne 200 || "$(jq '.errors | length' /tmp/orb_dev_kit/github_comment_response.json)" -gt 0 ]]; then echo "Failed to post comment to GitHub PR" echo "Response: $HTTP_RESPONSE_GH" echo "Response body: $(cat /tmp/orb_dev_kit/github_comment_response.json)" exit 1 else echo "Successfully posted comment to GitHub PR" fi } function getGithubPRFromCommit() { curl --request POST \ -s \ --url "$ORB_VAL_GH_GRAPHQL_URL" \ --header "$GH_HEADER_DATA" \ --data '{"query":"query SearchForPR($query: String!) {\n search(query: $query, type: ISSUE, first: 3) {\n issueCount\n edges {\n node {\n ... on PullRequest {\n \tid\n title\n number\n }\n }\n }\n }\n}","variables":{"query":"'"$CIRCLE_SHA1"' is:pr"},"operationName":"SearchForPR"}' } function isAuthenticatedGitHub() { curl --request POST \ -s \ --url "$ORB_VAL_GH_GRAPHQL_URL" \ --header "$GH_HEADER_DATA" \ --data '{"query":"query IsAuthenticated {\n viewer {\n login\n }\n}","variables":{},"operationName":"IsAuthenticated"}' } function mainGitHub() { if [ -z "${CIRCLE_PULL_REQUEST}" ]; then echo "The current job is not running as part of a Pull Request." echo "Skipping commenting..." exit 0 fi echo "Checking if authenticated to GitHub..." local authenticated_user authenticated_user="$(isAuthenticatedGitHub | jq -r '.data.viewer.login')" if [[ "$authenticated_user" != "null" && -n "$authenticated_user" ]]; then echo "Authenticated!" echo "Authenticated as: $authenticated_user" FetchedPRData="$(getGithubPRFromCommit)" # Fetch the PR ID from the commit if [ "$(echo "$FetchedPRData" | jq -e '.data.search.issueCount')" -gt 0 ]; then # PR Found PR_COUNT=$(echo "$FetchedPRData" | jq -e '.data.search.issueCount') echo "$PR_COUNT PR(s) found!" PR_TITLE=$(echo "$FetchedPRData" | jq -er '.data.search.edges[0].node.title') PR_NUMBER=$(echo "$FetchedPRData" | jq -er '.data.search.edges[0].node.number') PR_ID=$(echo "$FetchedPRData " | jq -er '.data.search.edges[0].node.id') echo "Selecting PR: $PR_TITLE (#$PR_NUMBER)" echo "Posting comment to PR..." postGitHubPRComment "$PR_ID" else echo "No PR found!" echo "It may be that the PR has not yet been created from this commit at the time of this build." echo "If you have recently created a PR, subsequent code pushes should properly identify the PR." echo "Skipping commenting..." exit 0 fi else echo "Not authenticated." echo "Please set the GITHUB_TOKEN environment variable to your GitHub personal access token." exit 1 fi } if [ ! -f /tmp/orb_dev_kit/publishing_message.txt ]; then echo "No Publishing message has been found." echo "This likely means the publishing scripts have not yet been run." echo "Please open an issue: https://github.com/CircleCI-Public/orb-tools-orb/issues" exit 1 fi PR_COMMENT_BODY=$(awk '{printf "%s\\n", $0}' /tmp/orb_dev_kit/publishing_message.txt) if [[ "$ORB_VAL_PIPELINE_VCS_TYPE" == "gh" || "$ORB_VAL_PIPELINE_VCS_TYPE" == "github" ]]; then # GitHub PR Comment Process GH_TOKEN_VALUE=${!ORB_VAL_GITHUB_TOKEN} if [ -z "$GH_TOKEN_VALUE" ]; then echo "UNABLE TO COMMENT" echo "GitHub Personal Access Token not found." echo "Please set the GITHUB_TOKEN environment variable to your GitHub personal access token." exit 0 fi GH_HEADER_DATA="Authorization: Bearer $GH_TOKEN_VALUE" mainGitHub elif [[ "$ORB_VAL_PIPELINE_VCS_TYPE" == "bb" || "$ORB_VAL_PIPELINE_VCS_TYPE" == "bitbucket" ]]; then echo "BitBucket PR Comments are not yet supported. Skipping." exit 0 else echo "Unsupported VCS type: $ORB_VAL_PIPELINE_VCS_TYPE" exit 0 fi environment: ORB_VAL_GH_GRAPHQL_URL: <<parameters.pr_comment_graphql_url>> ORB_VAL_GITHUB_TOKEN: <<parameters.github_token>> ORB_VAL_ORB_NAME: <<parameters.orb_name>> ORB_VAL_ORB_PUB_TOKEN: <<parameters.circleci_token>> ORB_VAL_PIPELINE_VCS_TYPE: <<parameters.vcs_type>> name: Adding Comment To PR review: circleci_ip_ranges: << parameters.circleci_ip_ranges >> description: | Automatically reviews your orb for best practices and produces JUnit test reports which are natively displayed in the CircleCI UI. The "Review" job checks against a suite of "RC" review checks, and if an opportunity for improvement is found, a suggestion with links to the relevant documentation is made. executor: << parameters.executor >> parameters: checkout: default: true description: | If you do not wish to checkout the source code, you may disable this behavior. Replace the checkout and add your own command or steps via the 'pre-steps' parameter in your workflow. type: boolean circleci_ip_ranges: default: false description: Enables jobs to go through a set of well-defined IP address ranges. type: boolean exclude: default: "" description: | A comma separated list of "RC" review check codes to explicitly ignore. Each review check has an associated "RC" code that can be identified to skip in future tests. If a review check fails, the "RC" code will be included in the output. Example: "RC001,RC002" type: string executor: default: python description: The executor to use for this job. By default, this will use the "python" executor provided by this orb. type: executor max_command_length: default: 64 description: | The maximum length of a command (RC009). This is used to check for commands that are too long. Commands longer than this will fail the review. type: integer orb_name: default: "" description: | The reference name of the orb to be injected in the config, no namespace or version number. e.g. "orb-tools". This is required for RC011. RC011 will be skipped if this is not set. type: string source_dir: default: src description: Path to the orb source. Path must be absolute or relative to the working directory. type: string steps: - when: condition: <<parameters.checkout>> steps: - checkout - bats/install - run: command: | #!/bin/bash if ! command -v bats >/dev/null; then echo 'The "bats-core" automation framework must be installed to execute review testing.' echo 'Install bats with the bats orb' exit 1 fi if ! command -v yq >/dev/null; then echo 'The "yq" package must be installed to execute review testing.' echo 'Installing "yq" automatically...' YQ_VERSION=v4.44.6 YQ_BIN=yq_linux_amd64 wget https://github.com/mikefarah/yq/releases/download/${YQ_VERSION}/${YQ_BIN}.tar.gz -O - | tar xz && mv ${YQ_BIN} /usr/bin/yq fi mkdir -p /tmp/orb_dev_kit/review/ echo "$ORB_VAL_REVIEW_BATS_FILE" > review.bats echo "Reviewing orb best practices" echo "If required, tests can be skipped via their \"RCXXX\" code with the \"exclude\" parameter." bats -T --pretty --report-formatter junit --output /tmp/orb_dev_kit/review ./review.bats environment: ORB_VAL_MAX_COMMAND_LENGTH: <<parameters.max_command_length>> ORB_VAL_ORB_NAME: <<parameters.orb_name>> ORB_VAL_RC_EXCLUDE: <<parameters.exclude>> ORB_VAL_REVIEW_BATS_FILE: | setup() { ORB_DEFAULT_SRC_DIR="./src/" ORB_SOURCE_DIR=${ORB_VAL_SOURCE_DIR:-$ORB_DEFAULT_SRC_DIR} ORB_SOURCE_DIR=${ORB_SOURCE_DIR%/} IFS="," read -ra SKIPPED_REVIEW_CHECKS \<<<"${ORB_VAL_RC_EXCLUDE}" } @test "RC001: Include source_url in @orb.yml" { if [[ "${SKIPPED_REVIEW_CHECKS[*]}" =~ "RC001" ]]; then skip fi result=$(yq '.display.source_url' "${ORB_SOURCE_DIR}/@orb.yml") echo 'Set a value for "source_url" under the "display" key in "@orb.yml"' [[ ! $result = null ]] } @test "RC002: All components (jobs, commands, executors, examples) must have descriptions" { if [[ "${SKIPPED_REVIEW_CHECKS[*]}" =~ "RC002" ]]; then skip fi for i in $(find "${ORB_SOURCE_DIR}/jobs" "${ORB_SOURCE_DIR}/examples" "${ORB_SOURCE_DIR}/commands" "${ORB_SOURCE_DIR}/executors" -name "*.yml" 2>/dev/null); do ORB_ELEMENT_DESCRIPTION=$(yq '.description' "$i") if [[ "$ORB_ELEMENT_DESCRIPTION" == null || "$ORB_ELEMENT_DESCRIPTION" == '""' ]]; then echo echo "Orb component ${i} is missing a description" echo "While descriptions are not required to create a valid orb, they provide a way to document the purpose of each component and will appear in the orb registry." echo "Check all orb components for descriptions." exit 1 fi done } @test "RC003: All production-ready orbs should contain at least one usage example." { if [[ "${SKIPPED_REVIEW_CHECKS[*]}" =~ "RC003" ]]; then skip fi ORB_ELEMENT_EXAMPLE_COUNT=$(find ${ORB_SOURCE_DIR}/examples/*.yml -type f 2>/dev/null | wc -l | xargs) if [ "$ORB_ELEMENT_EXAMPLE_COUNT" -lt 1 ]; then echo echo "This orb appears to be missing a usage example." echo "Add examples under $(${ORB_SOURCE_DIR}/examples) to document how to use the orb for any available use cases." exit 1 fi } @test "RC004: Usage example names should be descriptive." { if [[ "${SKIPPED_REVIEW_CHECKS[*]}" =~ "RC004" ]]; then skip fi for i in $(find "${ORB_SOURCE_DIR}examples/*.yml" -type f >/dev/null 2>&1); do if [[ $i =~ "example" ]]; then echo echo "Usage example file name ${i} contains the word 'example'." echo "Usage example file names should be descriptive and not contain the word 'example'." exit 1 fi done } @test "RC005: Write a detailed orb description." { if [[ "${SKIPPED_REVIEW_CHECKS[*]}" =~ "RC005" ]]; then skip fi ORB_ELEMENT_DESCRIPTION=$(yq '.description' "${ORB_SOURCE_DIR}/@orb.yml") if [[ "${#ORB_ELEMENT_DESCRIPTION}" -lt 64 ]]; then echo echo "Orb description appears short (under 64 characters)." echo "Update the description in ${ORB_SOURCE_DIR}/@orb.yml to provide a detailed description of the orb." echo "Use the orb description to help users find your orb via search. Try describing what use-case this orb solves for." exit 1 fi } @test "RC006: Source URL should be valid." { if [[ "${SKIPPED_REVIEW_CHECKS[*]}" =~ "RC006" ]]; then skip fi SOURCE_URL=$(yq '.display.source_url' "${ORB_SOURCE_DIR}/@orb.yml") HTTP_RESPONSE=$(curl -s -L -o /dev/null -w "%{http_code}" --retry 5 --retry-delay 5 "$SOURCE_URL") if [[ "$HTTP_RESPONSE" -ne 200 ]]; then echo echo "Source URL: \"$SOURCE_URL\" is not reachable." echo "Check the Source URL for this orb." exit 1 fi } @test "RC007: Home URL should be valid." { HOME_URL=$(yq '.display.home_url' "${ORB_SOURCE_DIR}/@orb.yml") if [[ "${SKIPPED_REVIEW_CHECKS[*]}" =~ "RC007" || "$HOME_URL" == "null" ]]; then skip fi HTTP_RESPONSE=$(curl -s -L -o /dev/null -w "%{http_code}" --retry 5 --retry-delay 5 "$HOME_URL") if [[ "$HTTP_RESPONSE" -ne 200 ]]; then echo echo "Home URL: \"$HOME_URL\" is not reachable." echo "Check the Home URL for this orb." exit 1 fi } @test "RC008: All Run steps should contain a name." { if [[ "${SKIPPED_REVIEW_CHECKS[*]}" =~ "RC008" ]]; then skip fi ERROR_COUNT=0 for i in $(find "${ORB_SOURCE_DIR}/jobs" "${ORB_SOURCE_DIR}/commands" -name "*.yml" 2>/dev/null); do ORB_COMPONENT_STEPS_COUNT=$(yq -o json '.' "$i" | jq '[. | paths ] | map(select(last=="run")) | length') RUN_ENTRIES=$(yq -o json '.' "$i" | jq -r '[paths] | map(select(last == "run") | join(".")) | .[]') for ENTRY in $(echo "$RUN_ENTRIES"); do ORB_COMPONENT_STEP=$(yq ".$ENTRY" "$i") ORB_COMPONENT_STEP_TYPE=$(echo "$ORB_COMPONENT_STEP" | yq 'type') ORB_COMPONENT_LINE_NUMBER=$(yq ".${ENTRY} | line" "$i") if [[ "$ORB_COMPONENT_STEP_TYPE" == '!!str' ]]; then echo "File: \"${i}\"" echo "Line number: ${ORB_COMPONENT_LINE_NUMBER}" echo "It appears this 'run' step is using 'string' formatting." echo "Consider converting this step into an object with a \"name\" and \"command\" property." echo --- echo "$ORB_COMPONENT_STEP" echo --- ERROR_COUNT=$((ERROR_COUNT + 1)) else ORB_COMPONENT_STEP_NAME=$(echo "${ORB_COMPONENT_STEP}" | yq '.name') ORB_COMPONENT_LINE_NUMBER=$(yq ".${ENTRY}.command | line" "$i") if [[ "$ORB_COMPONENT_STEP_NAME" == null || "$ORB_COMPONENT_STEP_NAME" == '""' ]]; then echo "File: \"${i}\"" echo "Line number: ${ORB_COMPONENT_LINE_NUMBER}" echo --- echo "$ORB_COMPONENT_STEP" echo --- ERROR_COUNT=$((ERROR_COUNT + 1)) fi fi done done if [[ "$ERROR_COUNT" -gt 0 ]]; then echo echo "Components were found to contain \"run\" steps without a name." echo "While a step does not require a name to be valid, not providing a name will produce a less readable output in the CircleCI UI." echo "Consider adding a name to the step to make the output in the UI easier to read." echo "https://circleci.com/docs/2.0/configuration-reference/#run" exit 1 fi } @test "RC009: Complex Run step's commands should be imported." { if [[ "${SKIPPED_REVIEW_CHECKS[*]}" =~ "RC009" ]]; then skip fi ERROR_COUNT=0 for i in $(find ${ORB_SOURCE_DIR}/jobs ${ORB_SOURCE_DIR}/commands -name "*.yml" 2>/dev/null); do ORB_COMPONENT_STEPS_COUNT=$(yq -o json '.' "$i" | jq '[. | paths ] | map(select(last=="run")) | length') RUN_ENTRIES=$(yq -o json '.' "$i" | jq -r '[paths] | map(select(last == "run") | join(".")) | .[]') for ENTRY in $(echo "$RUN_ENTRIES"); do ORB_COMPONENT_STEP=$(yq ".$ENTRY" "$i") ORB_COMPONENT_STEP_TYPE=$(echo "$ORB_COMPONENT_STEP" | yq 'type') ORB_COMPONENT_LINE_NUMBER=$(yq ".${ENTRY} | line" "$i") if [[ "$ORB_COMPONENT_STEP_TYPE" == '!!str' ]]; then echo "File: \"${i}\"" echo "Line number: ${ORB_COMPONENT_LINE_NUMBER}" echo "It appears this 'run' step is using 'string' formatting." echo "Consider converting this step into an object with a \"name\" and \"command\" property." echo --- echo "$ORB_COMPONENT_STEP" echo --- ERROR_COUNT=$((ERROR_COUNT + 1)) else ORB_COMPONENT_STEP_COMMAND=$(echo "${ORB_COMPONENT_STEP}" | yq '.command') ORB_COMPONENT_LINE_NUMBER=$(yq ".${ENTRY}.command | line" "$i") if [[ "${#ORB_COMPONENT_STEP_COMMAND}" -gt "${ORB_VAL_MAX_COMMAND_LENGTH}" ]]; then if [[ ! "$ORB_COMPONENT_STEP_COMMAND" =~ \<\<include\(* ]]; then echo "File: \"${i}\"" echo "Line number: ${ORB_COMPONENT_LINE_NUMBER}" echo "This command appears longer than ${ORB_VAL_MAX_COMMAND_LENGTH} characters. Consider using the 'include' syntax." echo --- echo "$ORB_COMPONENT_STEP_COMMAND" echo --- ERROR_COUNT=$((ERROR_COUNT + 1)) fi fi fi done done if [[ "$ERROR_COUNT" -gt 0 ]]; then echo echo "Components were found to contain \"run\" steps with a long command that is not imported." echo "Did you know you can write your shell scripts and other commands in external files and import them here?" echo "Writing your scripts externally will allow you to take advantage of syntax highlighting and avoid mixing code and markup." echo "https://circleci.com/docs/2.0/using-orbs/#file-include-syntax" exit 1 fi } @test "RC010: All components (jobs, commands, executors, examples) should be snake_cased." { if [[ "${SKIPPED_REVIEW_CHECKS[*]}" =~ "RC010" ]]; then skip fi for i in $(find "${ORB_SOURCE_DIR}/jobs" "${ORB_SOURCE_DIR}/commands" "${ORB_SOURCE_DIR}/executors" -name "*.yml" 2>/dev/null); do # Check file name for snake_case ORB_COMPONENT_FILE_NAME=$(basename "$i") if [[ "$ORB_COMPONENT_FILE_NAME" == *"-"* ]]; then echo "File: \"${i}\"" echo "Component names should be snake_cased. Please rename this file to use snake_case." exit 1 fi # Check if the file has parameters, if not skip counting. HAS_PARAMETERS=$(yq 'has("parameters")' "$i") if [[ "$HAS_PARAMETERS" == "false" ]]; then continue fi # Check parameter keys on component for snake_case ORB_COMPONENT_PARAMETERS_COUNT=$(yq '.parameters | keys | .[]' "$i") for j in $ORB_COMPONENT_PARAMETERS_COUNT; do if [[ "$j" == *"-"* ]]; then echo "File: \"${i}\"" echo " Parameter: \"${j}\"" echo "Parameter keys should be snake_cased. Please rename this parameter to use snake_case." exit 1 fi done done } @test "RC011: Ensure usage examples showcase current major version of the orb." { if [[ "${SKIPPED_REVIEW_CHECKS[*]}" =~ "RC011" ]]; then skip fi if [[ -z "$ORB_VAL_ORB_NAME" ]]; then echo "Orb name not set. Skipping usage example check." skip fi if [[ -z "$CIRCLE_TAG" ]]; then echo "No tag detected. Skipping usage example check." skip fi if [[ ! "$CIRCLE_TAG" =~ ^v[0-9]+\.[0-9]+\.[0-9]+$ ]]; then echo "Non-production tag detected. Skipping usage example check." skip fi CURRENT_MAJOR_VERSION=$(echo "${CIRCLE_TAG#v}" | cut -d '.' -f 1) for i in $(find "${ORB_SOURCE_DIR}/examples" -name "*.yml" -type f); do ORB_REF_STRING=$(yq ".usage.orbs[\"${ORB_VAL_ORB_NAME}\"]" "$i") ORB_REF_VERSION_STRING=$(echo "$ORB_REF_STRING" | cut -d '@' -f 2) ORB_REF_MAJOR_VERSION=$(echo "$ORB_REF_VERSION_STRING" | cut -d '.' -f 1) if [[ "$ORB_REF_MAJOR_VERSION" != "$CURRENT_MAJOR_VERSION" ]]; then echo "File: \"${i}\"" echo "Usage example Orb version: \"${ORB_REF_VERSION_STRING}\"" echo "Current major version: \"${CURRENT_MAJOR_VERSION}\"" echo "Usage examples should showcase at least the current major version of the orb." echo "" echo "Steps to resolve:" echo " 1. Delete the release and tag from your git repository which triggered this pipeline." echo " 2. Update all of the orb usage examples to ensure they match the next major version of the orb." echo " 3. Re-tag and release the orb to re-trigger the pipeline" exit 1 fi done } ORB_VAL_SOURCE_DIR: << parameters.source_dir >> name: Review Best Practices - store_test_results: path: /tmp/orb_dev_kit/review/ examples: step1_lint-pack: description: | The Orb-Tools orb is typically configured automatically by the Orb Development Kit. After initializing a new orb, this is the configuration file that will be automatically loaded. This configuration uses "Dynamic Config" with two different configuration files. In this example, we will see only the first `config.yml` file. This config breaks our orb's CI pipeline into two workflows, "test-pack", and "test-deploy". "test-pack" will lint, shellcheck, and review our orb, before triggering the "test-deploy" workflow with the orb injected for e2e testing. See the list of jobs for a detailed description of each job. "test-deploy" is found in the `./circleci/test-deploy.yml` file. See step 2 for more information. usage: version: "2.1" setup: true orbs: orb-tools: circleci/orb-tools@12.0 shellcheck: circleci/shellcheck@3.1 workflows: lint-pack: jobs: - orb-tools/lint: filters: tags: only: /.*/ - orb-tools/pack: filters: tags: only: /.*/ - orb-tools/review: filters: tags: only: /.*/ orb_name: <orb name> - shellcheck/check: exclude: SC2148,SC2038,SC2086,SC2002,SC2016 filters: tags: only: /.*/ - orb-tools/continue: filters: tags: only: /.*/ orb_name: <orb name> pipeline_number: << pipeline.number >> requires: - orb-tools/lint - orb-tools/review - orb-tools/pack - shellcheck/check vcs_type: << pipeline.project.type >> step2_test-deploy: description: | After linting and shellchecking the orb is injected into this config dynamically by the "continue" job and triggered. The orb is purposefully not imported here, though it is referenced in the config, it will be dynamically injected. With the orb loaded, we can run "integration tests" by executing our orbs commands and jobs and validating their output. Finally, if the commit has been tagged (ex v1.0.0), we can publish the orb to a production version. For advanced usage, see the full docs linked in the "Homepage" url above. usage: version: "2.1" orbs: orb-tools: circleci/orb-tools@12.0 jobs: command-tests: docker: - image: cimg/base:current steps: - checkout - <my-orb>/my_command - <my-orb>/my_command_2 workflows: test-deploy: jobs: - command-tests: filters: tags: only: /.*/ - <my-orb>/my-job: filters: tags: only: /.*/ - orb-tools/pack: filters: tags: only: /.*/ - orb-tools/publish: context: - orb-publishing-context filters: branches: ignore: /.*/ tags: only: /^v[0-9]+\.[0-9]+\.[0-9]+$/ orb_name: <namespace>/<my-orb> pub_type: production requires: - orb-tools/pack - command-tests - <my-orb>/my_job vcs_type: <<pipeline.project.type>>
Developer Updates
Get tips to optimize your builds
Or join our research panel and give feedback
By submitting this form, you are agreeing to ourTerms of UseandPrivacy Policy.