CircleCI Orb Example

With this CircleCI orb example…

You’ll see how to make your configs faster and simpler.

With common snippets for Node.js and PHP.

What are orbs?

Orbs are like NPM packages for CircleCI®.

They’re pre-packaged YAML that can run CircleCI commands and jobs.

CircleCI has many official orbs that you can use.

So you don’t have to worry about security the same way you do with 3rd party NPM packages.

In this example, we’ll use orbs for Node.js and PHP.

For comparison, here’s the example .circleci/config.yml file without orbs:

We’ll edit it to use orbs, and it’ll go from 70 lines to 34.

It’ll also be faster, as it’ll cache the packages.

Node Orb

We’ll start with the Node orb.

You’ll see a ‘Certified’ badge, meaning it’s “Written and tested by the CircleCI team”:

CircleCI orb example certified orb

In .circleci/config.yml, we’ll add an orbs stanza and add the Node orb.

Orbs should end with a version number, which is 5.0.0 here.

Then, we’ll use node/install-packages instead of npm ci:

--- a/.circleci/config.yml
+++ b/.circleci/config.yml
@@ -6,7 +6,7 @@ jobs:
       - image: cimg/node:14.18
     steps:
       - checkout
-      - run: npm ci
+      - node/install-packages
       - run:
           name: Running JS linting and unit test
           command: |
@@ -20,7 +20,7 @@ jobs:
       - image: cimg/node:<< parameters.node-version >>
     steps:
       - checkout
-      - run: npm ci
+      - node/install-packages
       - run:
           name: Running JS linting and unit test
           command: |Code language: Diff (diff)

In node/install-packages, node is the name of the orb.

And install-packages is the command name.

Simply replacing npm ci seems trivial, but it will cache the NPM packages:

So it can save minutes each build if there are a lot of NPM dependencies.

Next, we’ll replace the entire js-lint job with a prepackaged job in the Node orb:

--- a/.circleci/config.yml
+++ b/.circleci/config.yml
@@ -3,18 +3,6 @@ version: 2.1
 orbs:
   node: circleci/node@5.0.0
 
jobs:
-  js-lint:
-    docker:
-      - image: cimg/node:14.18
-    steps:
-      - checkout
-      - node/install-packages
-      - run:
-          name: Running JS linting and unit test
-          command: |
-            npm run lint:js
-
   js-test:
     parameters:
       node-version:
@@ -58,7 +46,8 @@ jobs:
 workflows:
   test-lint:
     jobs:
-      - js-lint
+      - node/run:
+          npm-run: lint:js
       - js-test:
           requires:
             - js-lintCode language: Diff (diff)

This node/run job does npm ci and runs whatever NPM command you pass as npm-run.

We passed an npm-run parameter of lint:js, meaning it will do:

npm run lint:jsCode language: Bash (bash)

It’s essentially the same as our custom lint:js job, but 9 lines shorter.

It also caches NPM dependencies.

Now, we’ll replace another job with an orb job:

--- a/.circleci/config.yml
+++ b/.circleci/config.yml
@@ -3,21 +3,7 @@ version: 2.1
 orbs:
   node: circleci/node@5.0.0
 
-  js-test:
-    parameters:
-      node-version:
-        type: string
-    docker:
-      - image: cimg/node:<< parameters.node-version >>
-    steps:
-      - checkout
-      - node/install-packages
-      - run:
-          name: Running JS unit test
-          command: |
-            npm run test:js
-
jobs:
   php-lint:
     docker:
       - image: cimg/php:8.1
@@ -48,12 +34,13 @@ workflows:
     jobs:
       - node/run:
           npm-run: lint:js
-      - js-test:
+      - node/test:
           requires:
             - node/run
           matrix:
             parameters:
-              node-version: [ '14.18', '15.0', '16.14', '17.4' ]
+              version: [ '14.18', '15.0', '16.14', '17.4' ]
+          run-command: test:js
       - php-lint
       - php-test:
           requires:Code language: Diff (diff)

We passed node/test in place of the previous job name.

And we deleted the js-test list from the jobs list, we don’t need a definition of the job there.

Then, we passed a run-command parameter of test:js.

If your test command in package.json is simply test, you won’t need that parameter.

PHP Orb

We can also simplify the PHP jobs with the CircleCI PHP orb.

First, we’ll add the orb to this CircleCI orb example:

--- a/.circleci/config.yml
+++ b/.circleci/config.yml
@@ -2,6 +2,7 @@ version: 2.1
 
 orbs:
   node: circleci/node@5.0.0
+  php: circleci/php@1.1.0
 Code language: Diff (diff)

Now, we’ll use that orb in place of composer i:

--- a/.circleci/config.yml
+++ b/.circleci/config.yml
@@ -12,7 +13,7 @@ jobs:
       - run:
           name: Linting PHP
           command: |
-            composer i
+            php/install-packages
             composer lintCode language: Diff (diff)

That will do composer install, but it will also cache the packages.

Next, we can replace another full job with an orb:

--- a/.circleci/config.yml
+++ b/.circleci/config.yml
@@ -9,25 +10,8 @@ jobs:
-
-  php-test:
-    parameters:
-      php-version:
-        type: string
-    docker:
-      - image: cimg/php:<< parameters.php-version >>
-    steps:
-      - checkout
-      - run:
-          name: Testing PHP
-          command: |
-            composer i
-            composer test
 
 workflows:
   test-lint:
@@ -42,9 +26,9 @@ workflows:
               version: [ '14.18', '15.0', '16.14', '17.4' ]
           run-command: test:js
       - php-lint
-      - php-test:
+      - php/test:
           requires:
             - php-lint
           matrix:
             parameters:
-              php-version: [ '7.3', '7.4', '8.0', '8.1' ]
+              version: [ '7.3', '7.4', '8.0', '8.1' ]Code language: Diff (diff)

Like before, it will do composer test in 4 versions of PHP.

Those PHP versions are in the parameter version.

CircleCI Orb Example

With these changes, we’ve decreased the file from 70 to 34 lines:

Now that you’ve seen a way to make the config faster and more concise…

Here’s another way to make your builds faster.

Be the first to get CI/CD tips like this

You'll get these tips before they're on the blog page. See most up-to-date ways to use CircleCI®. No spam.