<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Kyle TechSquidTV</title>
    <description>The latest articles on DEV Community by Kyle TechSquidTV (@techsquidtv).</description>
    <link>https://dev.to/techsquidtv</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F459906%2F6add1888-a727-4cb2-9491-ba80bfa7a610.png</url>
      <title>DEV Community: Kyle TechSquidTV</title>
      <link>https://dev.to/techsquidtv</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/techsquidtv"/>
    <language>en</language>
    <item>
      <title>Introducing the CircleCI Config SDK</title>
      <dc:creator>Kyle TechSquidTV</dc:creator>
      <pubDate>Mon, 19 Sep 2022 18:00:00 +0000</pubDate>
      <link>https://dev.to/circleci/introducing-the-circleci-config-sdk-43kc</link>
      <guid>https://dev.to/circleci/introducing-the-circleci-config-sdk-43kc</guid>
      <description>&lt;p&gt;We are excited to announce the new CircleCI Config SDK is now available as an open-source TypeScript library. Developers can now write and manage their CircleCI &lt;code&gt;config.yml&lt;/code&gt; files using TypeScript and JavaScript.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.npmjs.com/package/@circleci/circleci-config-sdk"&gt;NPM Package&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/CircleCI-Public/circleci-config-sdk-ts"&gt;GitHub Repository&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/CircleCI-Public/circleci-config-sdk-ts/wiki"&gt;Docs&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For developers used to the ecosystem and flexibility of a full-fledged programming language, sometimes YAML can feel limiting or intimidating. With the Config SDK you can define and generate your YAML config from type-safe and annotated JavaScript. You can even take advantage of package management to modularize any portion of your config code for reuse.&lt;/p&gt;

&lt;p&gt;When paired with CircleCI’s &lt;a href="https://circleci.com/docs/dynamic-config"&gt;dynamic configuration&lt;/a&gt;, the Config SDK makes it possible to dynamically build your CI configuration at run-time, allowing you to choose what you want to execute based on any number of factors, such as the status of your Git repo, an external API, or just the day of the week.&lt;/p&gt;

&lt;h2&gt;
  
  
  Getting started
&lt;/h2&gt;

&lt;p&gt;For our example, let’s imagine we manage several Node.js projects that are all built using the same framework and generally require the same CI configuration. So we decided that we want to build a config “template” that all of our projects will use, and which can be centrally managed and updated. We’ll create and publish an NPM package that will generate the perfect config file for all of our Node projects.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Oql4pp_X--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://circleci.com/blog/media/2022-09-19-config-sdk.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Oql4pp_X--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://circleci.com/blog/media/2022-09-19-config-sdk.gif" alt="Generating a config" width="" height=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let’s build the config template package, and then build the pipelines that will use it.&lt;/p&gt;

&lt;h3&gt;
  
  
  Setup
&lt;/h3&gt;

&lt;p&gt;We’re going to start by creating a standard NPM package. You can use TypeScript or JavaScript, but we’ll use JavaScript in this example for the sake of speed. The example shown here is based on&lt;a href="https://github.com/CircleCI-Public/circleci-config-sdk-ts/wiki/Write-Package"&gt;this page from the repo’s wiki&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Begin by initializing a JavaScript project in a new directory.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mkdir &amp;lt;your-package-name&amp;gt;

cd &amp;lt;your-package-name&amp;gt;

npm init -y

npm i --save @circleci/circleci-config-sdk

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;@circleci/circleci-config-sdk&lt;/code&gt; package will allow us to define a CircleCI config file with JavaScript. While we could simply define a config and export it, we can also take advantage of dynamic config and export a function instead. In our example, we’ll keep it simple and create a config generation function that will take a &lt;code&gt;tag&lt;/code&gt; parameter for our deployments, and a &lt;code&gt;path&lt;/code&gt; parameter to choose where the config file will be exported to.&lt;/p&gt;

&lt;h2&gt;
  
  
  Create the app
&lt;/h2&gt;

&lt;p&gt;Create an &lt;code&gt;index.js&lt;/code&gt; file and import the CircleCI Config SDK package and Node’s &lt;code&gt;fs&lt;/code&gt; package so we can write the config to a file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const CircleCI = require("@circleci/circleci-config-sdk");
const fs = require('fs');

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next we’ll start building up the components of our config file using the Config SDK. You’ll notice because we are working with a TypeScript-based library, we are able to receive code hints, type definitions, documentation and auto-completion.&lt;/p&gt;

&lt;h3&gt;
  
  
  Create executor
&lt;/h3&gt;

&lt;p&gt;Given we are building a config for our Node.js projects, we’ll begin by defining the &lt;a href="https://circleci.com/docs/using-docker"&gt;Docker executor&lt;/a&gt; our jobs will use. You can pass in the Docker image, resource class, and any other parameters you may want to configure.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Node executor
const dockerNode = new CircleCI.executors.DockerExecutor(
  "cimg/node:lts"
);

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Create jobs
&lt;/h3&gt;

&lt;p&gt;We are building up to a workflow that will test our application on every commit, and deploy it when we provide a certain tag. Like our executor, we’ll define these two jobs, both using the executor we just defined and each with a unique set of steps for their respective purposes.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Test Job
const testJob = new CircleCI.Job("test", dockerNode);
testJob.addStep(new CircleCI.commands.Checkout());
testJob.addStep(new CircleCI.commands.Run({ command: "npm install &amp;amp;&amp;amp; npm run test" }));

//Deploy Job
const deployJob = new CircleCI.Job("deploy", dockerNode);
deployJob.addStep(new CircleCI.commands.Checkout());
deployJob.addStep(new CircleCI.commands.Run({ command: "npm run deploy" }));

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Jobs can be instantiated with steps or dynamically added to an existing job like shown above. In this overly simplified example, we lack a &lt;a href="https://circleci.com/docs/caching"&gt;caching&lt;/a&gt; step, but you can see how we build up elements of our configuration.&lt;/p&gt;

&lt;h2&gt;
  
  
  Create a workflow
&lt;/h2&gt;

&lt;p&gt;With our jobs defined, it’s time to implement them in a workflow and define how they should run. We mentioned earlier that we want the &lt;code&gt;test&lt;/code&gt; job to run on all commits, and the &lt;code&gt;deploy&lt;/code&gt; job to only run on the given tag.&lt;/p&gt;

&lt;p&gt;Now that we are working with top-level components of our config file, let’s finally define a new CircleCI config object, and name the workflow that we will add our jobs to.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;//Instantiate Config and Workflow
const nodeConfig = new CircleCI.Config();
const nodeWorkflow = new CircleCI.Workflow("node-test-deploy");
nodeConfig.addWorkflow(nodeWorkflow);

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We are not adding any parameters to our testing job because we want to run it on all commits, so we can directly add it to our config object.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;nodeWorkflow.addJob(testJob);

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For the deploy job, we need to first define the workflow job so that we can add filters to it. We are going to add one filter now which tells CircleCI to ignore this job for all branches, so it doesn’t execute on every commit. We’ll deal with enabling it for a tag in a moment.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const wfDeployJob = new CircleCI.workflow.WorkflowJob(deployJob, {requires: ["test"], filters: {branches: {ignore: ".*"}}});
nodeWorkflow.jobs.push(wfDeployJob);

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Export the config generator function
&lt;/h2&gt;

&lt;p&gt;Now that we have everything defined we are ready to create and export the final piece. We are going to create a function which takes in the tag and path parameters we mentioned earlier and will write what we have defined to a new file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/**
* Exports a CircleCI config for a node project
*/
export default function writeNodeConfig(deployTag, configPath) {
 // next step
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the newly created &lt;code&gt;writeNodeConfig&lt;/code&gt; function, we’ll add the tag filter being passed in here to the deploy job in our workflow and finally write the config to the file supplied by the &lt;code&gt;path&lt;/code&gt; parameter using the &lt;code&gt;generate&lt;/code&gt; function on the config object.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/**
* Exports a CircleCI config for a node project
*/
export default function writeNodeConfig(deployTag, configPath) {
  wfDeployJob.parameters.filters.tags = {only: deployTag}
  fs.writeFile(configPath, nodeConfig.generate(), (err) =&amp;gt; {
    if (err) {
      console.error(err);
      return
    }
  })
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here is the full source code, which you can also find &lt;a href="https://github.com/CircleCI-Public/circleci-config-sdk-ts/wiki/Write-Package"&gt;in the wiki&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const CircleCI = require("@circleci/circleci-config-sdk");
const fs = require('fs');

// Node executor
const dockerNode = new CircleCI.executors.DockerExecutor(
  "cimg/node:lts"
);

// Test Job
const testJob = new CircleCI.Job("test", dockerNode);
testJob.addStep(new CircleCI.commands.Checkout());
testJob.addStep(new CircleCI.commands.Run({ command: "npm install &amp;amp;&amp;amp; npm run test" }));

//Deploy Job
const deployJob = new CircleCI.Job("deploy", dockerNode);
deployJob.addStep(new CircleCI.commands.Checkout());
deployJob.addStep(new CircleCI.commands.Run({ command: "npm run deploy" }));

//Instantiate Config and Workflow
const nodeConfig = new CircleCI.Config();
const nodeWorkflow = new CircleCI.Workflow("node-test-deploy");
nodeConfig.addWorkflow(nodeWorkflow);

//Add Jobs. Add filters to deploy job
nodeWorkflow.addJob(testJob);
const wfDeployJob = new CircleCI.workflow.WorkflowJob(deployJob, {requires: ["test"], filters: {branches: {ignore: ".*"}}});
nodeWorkflow.jobs.push(wfDeployJob);

/**
* Exports a CircleCI config for a node project
*/
export default function writeNodeConfig(deployTag, configPath) {
  wfDeployJob.parameters.filters.tags = {only: deployTag};
  fs.writeFile(configPath, nodeConfig.generate(), (err) =&amp;gt; {
    if (err) {
      console.error(err);
      return
    }
  });
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Publish the package
&lt;/h2&gt;

&lt;p&gt;With your &lt;code&gt;index.js&lt;/code&gt; file completed with the &lt;code&gt;writeNodeConfig&lt;/code&gt; function exported, it’s time to &lt;a href="https://docs.npmjs.com/creating-and-publishing-unscoped-public-packages"&gt;publish the package&lt;/a&gt; to your package repository of choice, such as NPM or GitHub.&lt;/p&gt;

&lt;p&gt;When complete, you should be able to import your package in other projects, just like we imported &lt;code&gt;@circleci/circleci-config-sdk&lt;/code&gt; earlier.&lt;/p&gt;

&lt;h2&gt;
  
  
  Create a CI pipeline
&lt;/h2&gt;

&lt;p&gt;You now have a published NPM package that can generate a CircleCI config file. We can use CircleCI’s dynamic configuration to pull in this package at run-time and dynamically run our generated config file. We can replicate this basic template across our many similar NodeJS projects, and when we want to update or change our config, we will be able to simply update the package we created.&lt;/p&gt;

&lt;h3&gt;
  
  
  Create config.yml
&lt;/h3&gt;

&lt;p&gt;As usual, our CircleCI project will require a &lt;code&gt;.circleci&lt;/code&gt; directory and a &lt;code&gt;config.yml&lt;/code&gt; file inside. The config file in this case will be a basic template used in all of our projects which simply tells CircleCI to enable the dynamic configuration feature for the current pipeline, generate the new config file, and run it. We will also create a &lt;code&gt;dynamic&lt;/code&gt; directory that we will use later.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;└── .circleci/
    ├── dynamic/
    └── config.yml` \

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Use the following &lt;a href="https://github.com/CircleCI-Public/circleci-config-sdk-ts/blob/main/sample/01-dynamic-workflow-javascript/.circleci/config.yml"&gt;example configuration file&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;version: 2.1
orbs:
  continuation: circleci/continuation@0.3.1
  node: circleci/node@5.0.2
setup: true
jobs:
  generate-config:
    executor: node/default
    steps:
      - checkout
      - node/install-packages:
          app-dir: .circleci/dynamic
      - run:
          name: Generate config
          command: node .circleci/dynamic/index.js
      - continuation/continue:
          configuration_path: ./dynamicConfig.yml
workflows:
  dynamic-workflow:
    jobs:
      - generate-config

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can find this config file and other examples in the &lt;a href="https://github.com/CircleCI-Public/circleci-config-sdk-ts/wiki/Write-Dynamic-Config-App"&gt;Wiki&lt;/a&gt; on GitHub.&lt;/p&gt;

&lt;p&gt;This config is a boilerplate responsible for executing our package which contains the “real” logic we want to execute.&lt;/p&gt;

&lt;p&gt;Notice the &lt;code&gt;setup&lt;/code&gt; key is set to &lt;code&gt;true&lt;/code&gt;, enabling dynamic config for the pipeline. Using the Node orb, we install a Node app located in &lt;code&gt;.circleci/dynamic&lt;/code&gt; (we’ll come back to this), and run the &lt;code&gt;.circleci/dynamic/index.js&lt;/code&gt; in Node. This is what will use the package we wrote earlier and create a new config file at &lt;code&gt;./dynamicConfig.yml&lt;/code&gt;, which will finally be executed by the &lt;code&gt;continuation&lt;/code&gt; orb.&lt;/p&gt;

&lt;p&gt;We will use a config like this one in all of our Node projects, and it is unlikely to need to be updated or changed often. Rather than modifying this config, we update the package we created earlier.&lt;/p&gt;

&lt;h3&gt;
  
  
  Create the config app
&lt;/h3&gt;

&lt;p&gt;The last thing to do is build our “Config application”. This is the app responsible for implementing our package and acts as the source of our “real” config we plan on executing. Because in this example we have outsourced the majority of the logic of our config to an external package, in this example, our config app is mostly boilerplate as well.&lt;/p&gt;

&lt;p&gt;Change directory into &lt;code&gt;.circleci/dynamic&lt;/code&gt; where we will set up our application. Initialize a new repository and install the package you published previously.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm init -y

npm i &amp;lt;your-package-name&amp;gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After running these two commands, you should have a &lt;code&gt;package.json&lt;/code&gt; file with a dependency showing your package.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"dependencies": {
  "my-circleci-node-config": "^1.0.0",
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can &lt;a href="https://docs.npmjs.com/about-semantic-versioning#using-semantic-versioning-to-specify-update-types-your-package-can-accept"&gt;modify the semantic version string&lt;/a&gt; to dictate what version of your package should be pulled at run time. This means, you could update your &lt;code&gt;my-circleci-node-config&lt;/code&gt; package and, if you choose, have all of your CircleCI projects that utilize this package immediately pick up these changes the next time your CI pipeline is triggered.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Not Recommended:&lt;/strong&gt; Say you always wanted to pull the latest version of the custom dependency you have created, you could use:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"dependencies": {
  "my-circleci-node-config": "x",
},

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To be safer, pull in only minor and patch updates, not major releases.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"dependencies": {
  "my-circleci-node-config": "1.x",
},

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Finally, utilize your custom package in the &lt;code&gt;.circleci/dynamic.index.js.&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Our package exports a function named &lt;code&gt;writeNodeConfig&lt;/code&gt; which takes in the value of the &lt;code&gt;tag&lt;/code&gt; we want for triggering deployments, and the &lt;code&gt;path&lt;/code&gt; we want to export the config to. We know the path from earlier in our config.yml, we set to be &lt;code&gt;./dynamicConfig.yml&lt;/code&gt;, because we are in the &lt;code&gt;dynamic&lt;/code&gt; directory, we will prepend &lt;code&gt;..&lt;/code&gt;. For the tag, we’ll use a generic regex string &lt;code&gt;v.*&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import writeNodeConfig from '&amp;lt;your/package&amp;gt;';

writeNodeConfig("v.*", "../dynamicConfig.yml")

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That is our entire application. We simply need to pull whichever version of our package we desire and invoke it to generate our config file from the template we created in the package.&lt;/p&gt;

&lt;h2&gt;
  
  
  Running the pipeline
&lt;/h2&gt;

&lt;p&gt;To recap, we have a boilerplate &lt;code&gt;config.yml&lt;/code&gt; file which instructs CircleCI to enable dynamic configuration, and uses Node.js to build a new config file at run-time. The Node app responsible for building our new config uses a package dependency which contains the “template” of our desired config. We can now use this package in many different projects and update it centrally. Our projects can either pull in the latest version of this package by specifying an &lt;code&gt;x&lt;/code&gt; in the package.json, or we can use tools like dependabot to open a pull request automatically to all of our projects that use this package when it is updated.&lt;/p&gt;

&lt;p&gt;With dynamic configuration and the Config SDK together, the possibilities are endless. The tutorial above was based on &lt;a href="https://github.com/CircleCI-Public/circleci-config-sdk-ts/wiki/Write-Package"&gt;this page from the wiki&lt;/a&gt; on GitHub. Check out the rest of our &lt;a href="https://github.com/CircleCI-Public/circleci-config-sdk-ts/wiki"&gt;wiki&lt;/a&gt; and &lt;a href="https://circleci-public.github.io/circleci-config-sdk-ts/"&gt;documentation&lt;/a&gt; for even more examples of interesting things you can do with the Config SDK.&lt;/p&gt;

&lt;p&gt;We’d love to hear from you and see how you utilize the Config SDK in your own pipelines. Connect with us on &lt;a href="https://twitter.com/CircleCI"&gt;Twitter&lt;/a&gt;, say hello in our &lt;a href="https://discuss.circleci.com/t/circleci-config-sdk-now-g-a/45457"&gt;discussion forum&lt;/a&gt;, or chat with us on &lt;a href="https://discord.gg/5dUX4FstW2"&gt;Discord&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>circleci</category>
      <category>cicd</category>
      <category>sdk</category>
      <category>pipelines</category>
    </item>
    <item>
      <title>Trigger your CircleCI pipelines from a GitHub Actions workflow</title>
      <dc:creator>Kyle TechSquidTV</dc:creator>
      <pubDate>Fri, 17 Dec 2021 17:30:00 +0000</pubDate>
      <link>https://dev.to/circleci/trigger-your-circleci-pipelines-from-a-github-actions-workflow-1l7j</link>
      <guid>https://dev.to/circleci/trigger-your-circleci-pipelines-from-a-github-actions-workflow-1l7j</guid>
      <description>&lt;p&gt;If you are already a GitHub user, you may know that GitHub Actions provides you with powerful tools to increase efficiencies in your software delivery life cycle. Actions can be impactful for team collaborations and process simplification. For example, you can automate things like building a container, welcoming new users to your open source projects, managing branches, or triaging issues.&lt;/p&gt;

&lt;p&gt;It’s important to use the right tool for the right job. Using GitHub Actions along with CircleCI allows you to automate aspects of your version control system while also benefiting from features that are only available in your CircleCI pipelines. Imagine extending your VCS workflow to include advanced features like &lt;a href="https://dev.to/blog/debugging-ci-cd-pipelines-with-ssh-access/"&gt;SSH debugging&lt;/a&gt;, &lt;a href="https://dev.to/blog/a-guide-to-test-splitting/"&gt;test splitting&lt;/a&gt;, robust &lt;a href="https://circleci.com/docs/2.0/configuration-reference/#resourceclass"&gt;CPU and RAM options&lt;/a&gt; and GPU and &lt;a href="https://dev.to/blog/managing-ci-cd-pipelines-with-arm-compute-resource-classes/"&gt;Arm support&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;For example, you can use Actions for team collaboration and process simplification while accelerating your build, test, and deploy stages with CircleCI.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--NVj-QIiy--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://production-cci-com.imgix.net/blog/media/2021-12-17-github-actions-with-circleci.png%3Fixlib%3Drb-3.2.1%26w%3D2000%26auto%3Dformat%26fit%3Dmax%26q%3D60%26ch%3DDPR%252CWidth%252CViewport-Width%252CSave-Data" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--NVj-QIiy--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://production-cci-com.imgix.net/blog/media/2021-12-17-github-actions-with-circleci.png%3Fixlib%3Drb-3.2.1%26w%3D2000%26auto%3Dformat%26fit%3Dmax%26q%3D60%26ch%3DDPR%252CWidth%252CViewport-Width%252CSave-Data" alt="A Workflow using both GitHub Actions and CircleCI" width="880" height="286"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To make it even easier to kick off your CircleCI pipelines from any event on GitHub, our team built the Trigger CircleCI Pipeline action, which is now &lt;a href="https://github.com/marketplace/actions/trigger-circleci-pipeline"&gt;available in the GitHub Marketplace&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--rsJz5vKi--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://production-cci-com.imgix.net/blog/media/2021-12-17-trigger-circleci-pipeline-marketplace.png%3Fixlib%3Drb-3.2.1%26w%3D2000%26auto%3Dformat%26fit%3Dmax%26q%3D60%26ch%3DDPR%252CWidth%252CViewport-Width%252CSave-Data" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--rsJz5vKi--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://production-cci-com.imgix.net/blog/media/2021-12-17-trigger-circleci-pipeline-marketplace.png%3Fixlib%3Drb-3.2.1%26w%3D2000%26auto%3Dformat%26fit%3Dmax%26q%3D60%26ch%3DDPR%252CWidth%252CViewport-Width%252CSave-Data" alt="Trigger CircleCI Pipeline action listing in GitHub Marketplace" width="863" height="300"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In this article, we will describe a few ways you can incorporate the Trigger CircleCI Pipeline action into your workflow to make the most of your GitHub automation credits while benefiting from CircleCI’s world-class continuous integration capabilities.&lt;/p&gt;

&lt;h2&gt;
  
  
  Trigger CircleCI Pipeline: A GitHub Action for triggering workflows in CircleCI
&lt;/h2&gt;

&lt;p&gt;With the Trigger CircleCI Pipeline action, you can kick off a CircleCI pipeline from any event on a given branch or tag. The action passes along a set of pipeline parameters containing metadata that can be used to control the flow of your CircleCI pipelines and workflows.&lt;/p&gt;

&lt;p&gt;One potential use case for the Trigger CircleCI Pipeline action is triggering a CircleCI pipeline whenever a pull request is opened by a developer. Triggering on a pull request allows you to test changes in a PR even if the last commit was made prior to the PR being opened (or to trigger a build and test cycle any time changes are pushed to the branch a PR was opened from).&lt;/p&gt;

&lt;p&gt;Another use case for the Trigger CircleCI Pipeline action is triggering a build and deployment from CircleCI whenever a &lt;a href="https://docs.github.com/en/repositories/releasing-projects-on-github/about-releases"&gt;release&lt;/a&gt; is created, edited, or published in GitHub. Triggering on a release allows you to build and deploy an application—such as deploying a Dockerized microservice to a Kubernetes cluster or publishing a binary to an app store—when the repo owner specifies a new release version of the application.&lt;/p&gt;

&lt;p&gt;You can view complete implementations of these two use cases, including templates for both your CircleCI and GitHub Actions configuration files, in the &lt;a href="https://github.com/CircleCI-Public/trigger-circleci-pipeline-action/tree/main/examples"&gt;Examples directory of the Trigger CircleCI Pipeline repository&lt;/a&gt;. Next we’ll explore an example of using the Trigger CircleCI Pipeline Action to initiate a CircleCI workflow when a new release is published.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to use the Trigger CircleCI Pipeline Action to trigger a pipeline from a new release
&lt;/h2&gt;

&lt;p&gt;The first step in setting up GitHub Actions to work with CircleCI is to create a GitHub Actions workflow for the desired CircleCI pipeline. You can do this by adding a workflow YAML file (we’ll use &lt;code&gt;main.yml&lt;/code&gt;) to &lt;code&gt;./.github/workflows&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;In the following example, you use the &lt;code&gt;on&lt;/code&gt; and &lt;code&gt;types&lt;/code&gt; syntax to specify that the &lt;code&gt;trigger-circleci&lt;/code&gt; action triggers when a new release is published. Select a custom &lt;code&gt;name&lt;/code&gt; and &lt;code&gt;id&lt;/code&gt; for the step to provide additional contextual metadata in your CircleCI pipeline:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;on:
  release:
    types: [published]
jobs:
  trigger-circleci:
    runs-on: ubuntu-latest
    steps:
      - name: &amp;lt;customize name&amp;gt;
        id: &amp;lt;customize id&amp;gt;
        uses: circleci/trigger_circleci_pipeline@v1.0
        env:
          CCI_TOKEN: $

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, create an &lt;a href="https://docs.github.com/en/actions/security-guides/encrypted-secrets#creating-encrypted-secrets-for-a-repository"&gt;encrypted secret&lt;/a&gt; named &lt;code&gt;CCI_TOKEN&lt;/code&gt; containing the &lt;a href="https://circleci.com/docs/2.0/managing-api-tokens/"&gt;personal API token&lt;/a&gt; that will be used to trigger the pipelines. We recommend making this a &lt;a href="https://docs.github.com/en/developers/overview/managing-deploy-keys#machine-users"&gt;machine user&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Now that you have your GitHub workflow set up, you can modify your CircleCI config file to run when your GitHub Action kicks off. Start by adding the &lt;a href="https://circleci.com/docs/2.0/pipeline-variables/"&gt;pipeline parameter&lt;/a&gt; definitions to your CircleCI config. This data will be entered by the GitHub Action when triggered.&lt;/p&gt;

&lt;p&gt;Add the following to the top of your &lt;code&gt;.circleci/config.yml&lt;/code&gt; file. Make sure you specify version 2.1:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;version: 2.1
parameters:
  GHA_Event:
    type: string
    default: ""
  GHA_Actor:
    type: string
    default: ""
  GHA_Action:
    type: string
    default: ""
  GHA_Meta:
    type: string
    default: ""

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The action generates several pipeline parameters:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;GHA_Actor&lt;/code&gt; indicates which user triggered the pipeline.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;GHA_Action&lt;/code&gt; is the &lt;code&gt;id&lt;/code&gt; assigned in the workflow configuration.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;GHA_Event&lt;/code&gt; is the type of GitHub event that triggered the pipeline.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;GHA_Meta&lt;/code&gt; is an optional additional metadata parameter that allows you to specify additional metadata using &lt;a href="https://docs.github.com/en/actions/creating-actions/metadata-syntax-for-github-actions#inputs"&gt;input parameters&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can use this pipeline parameter data to &lt;a href="https://circleci.com/docs/2.0/pipeline-variables/#conditional-workflows"&gt;run workflows conditionally&lt;/a&gt;. In this example, the &lt;code&gt;GHA_Event&lt;/code&gt; parameter will be populated with the value &lt;code&gt;release&lt;/code&gt;, and you can use a &lt;a href="https://circleci.com/docs/2.0/configuration-reference/#using-when-in-workflows"&gt;&lt;code&gt;when&lt;/code&gt; clause&lt;/a&gt; in your CircleCI config to specify workflows that should run only when triggered by the GitHub workflow:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;jobs:
  release:
    docker:
      - image: cimg/node:lts
    steps:
      - run: npm install
      - run: npm build
      - run: npm publish

workflows:
  release:
    when:
      equal: ["release", &amp;lt;&amp;lt; pipeline.parameters.GHA_Event &amp;gt;&amp;gt;]
    jobs:
      - release

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This config snippet specifies a &lt;code&gt;release&lt;/code&gt; job that publishes an npm package and a &lt;code&gt;release&lt;/code&gt; workflow that invokes the &lt;code&gt;release&lt;/code&gt; job. In the &lt;code&gt;when&lt;/code&gt; clause, you specify that the &lt;code&gt;release&lt;/code&gt; workflow will run only when the GitHub workflow runs and populates the &lt;code&gt;GHA_Event&lt;/code&gt; parameter with the value &lt;code&gt;release&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Although this example demonstrates how to set up a release trigger, you can use the same techniques to kick off a CircleCI pipeline from any of the available &lt;a href="https://docs.github.com/en/actions/learn-github-actions/events-that-trigger-workflows"&gt;GitHub events for triggering workflows&lt;/a&gt;. To view the complete setup for triggering CircleCI from events on a pull request, visit the &lt;a href="https://github.com/CircleCI-Public/trigger-circleci-pipeline-action/tree/main/examples/01-Trigger-Workflow-On-Pull_Request"&gt;example GitHub repo&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to prevent double execution of jobs in GitHub and CircleCI
&lt;/h2&gt;

&lt;p&gt;It is important to emphasize that GitHub Actions runs alongside native CircleCI integration. By default, when a repository is connected to CircleCI, if a workflow within that project’s configuration does not specify any conditionals or filters that would otherwise prevent execution, then the workflow will execute on every push event by default. This means that it is possible to accidentally run a job twice, once on the push event from CircleCI and again on other events triggered by the GitHub Action.&lt;/p&gt;

&lt;p&gt;If you are relying on GitHub Actions to provide all of your API triggers, ensure that each of your CircleCI configuration’s workflows contains a conditional limiting its execution to only the GitHub Action trigger, as in the following example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;workflows:
  # This workflow is set to be triggered conditionally, only when
  # the GitHub Action is triggered.
  # With no other workflows, normal push events will be ignored.
  when: &amp;lt;&amp;lt; pipeline.parameters.GHA_Action &amp;gt;&amp;gt;
  test:
    jobs:
      - test

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Using the &lt;code&gt;when&lt;/code&gt; clause in your workflow declaration allows you to specify that CircleCI should run the workflow only when the specified &lt;code&gt;GHA_Action&lt;/code&gt; is triggered and not after normal push events.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;GitHub Actions is a useful tool for automating a variety of version control processes, from checking out a Git repository at a particular version to automatically creating or merging pull requests to updating README files based on changes to your code. With the help of the Trigger CircleCI Pipeline action, you can combine the time-saving benefits of version control automation with the powerful workflow acceleration that only the fastest, most secure, and feature-rich continuous integration platform can provide.&lt;/p&gt;

&lt;p&gt;To add the Trigger CircleCI Pipeline action to your repository, visit the &lt;a href="https://github.com/marketplace/actions/trigger-circleci-pipeline"&gt;GitHub Marketplace&lt;/a&gt; and copy the workflow syntax to your &lt;code&gt;workflow.yml&lt;/code&gt; file. If your team is not already using CircleCI to validate and ship changes to your users quickly and confidently, &lt;a href="https://circleci.com/signup/"&gt;sign up for a free account&lt;/a&gt; today.&lt;/p&gt;

</description>
      <category>githubactions</category>
      <category>circleci</category>
      <category>cicd</category>
    </item>
    <item>
      <title>Combine Objects In TypeScript</title>
      <dc:creator>Kyle TechSquidTV</dc:creator>
      <pubDate>Sun, 11 Apr 2021 20:41:32 +0000</pubDate>
      <link>https://dev.to/techsquidtv/combine-objects-in-typescript-3f64</link>
      <guid>https://dev.to/techsquidtv/combine-objects-in-typescript-3f64</guid>
      <description>&lt;p&gt;&lt;iframe class="tweet-embed" id="tweet-1381343242130690055-554" src="https://platform.twitter.com/embed/Tweet.html?id=1381343242130690055"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-1381343242130690055-554');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=1381343242130690055&amp;amp;theme=dark"
  }



&lt;/p&gt;

&lt;p&gt;If you Google how to combine multiple objects into a single object with shared properties, you will get some information back on using the &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax" rel="noopener noreferrer"&gt;spread operator&lt;/a&gt;. Let's look at a basic example of the spread operator with TypeScript.&lt;/p&gt;

&lt;p&gt;In this example, we will be creating Super Heros by combining our regular Heros with SuperPowers to result in a single Super Hero.&lt;/p&gt;

&lt;p&gt;Begin by creating an Interface for each of the two objects. One object should ideally contain all of the required properties, and our secondary object should contain only optional properties.&lt;/p&gt;

&lt;p&gt;Our Hero will be the base object which we will later combine with Super Powers.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;Hero&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;class&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;human&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;elf&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;orc&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;baseHealth&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Our secondary object Interface, SuperPowers will contain only optional properties describing our possible superpowers.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;SuperPowers&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;flying&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="nx"&gt;boolean&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;superSpeed&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="nx"&gt;boolean&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;strengthMultiplier&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, if our human Hero were to fall into a vat of nuclear waste we can only assume they would potentially gain Super Powers. Let's describe an object with the properties of both.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;SuperHero&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nx"&gt;Hero&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;SuperPowers&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Our SuperHero interface simply extends both of our prior definitions, effectively adding them together into this new Interface.&lt;/p&gt;

&lt;p&gt;Now we have our definitions, let's create our new &lt;em&gt;human &lt;strong&gt;Hero&lt;/strong&gt;&lt;/em&gt; and an object containing the &lt;em&gt;&lt;strong&gt;SuperPowers&lt;/strong&gt;&lt;/em&gt; we plan to add to our &lt;em&gt;human &lt;strong&gt;Hero&lt;/strong&gt;&lt;/em&gt; later.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;human&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Hero&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;human&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;baseHealth&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;powers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;SuperPowers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;flying&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Time to combine. Our Hero has fallen into a vat of nuclear waste, what emerges will no longer be a Hero, but a &lt;em&gt;&lt;strong&gt;SuperHero&lt;/strong&gt;&lt;/em&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;superMan&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;SuperHero&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{...&lt;/span&gt;&lt;span class="nx"&gt;human&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;powers&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;superMan&lt;/strong&gt; will have the following types:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;baseHealth&lt;/li&gt;
&lt;li&gt;class&lt;/li&gt;
&lt;li&gt;flying?&lt;/li&gt;
&lt;li&gt;strengthMultiplier?&lt;/li&gt;
&lt;li&gt;superSpeed?&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Full example
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;Hero&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;class&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;human&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;elf&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;orc&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;baseHealth&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;SuperPowers&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;flying&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="nx"&gt;boolean&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;superSpeed&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="nx"&gt;boolean&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;strengthMultiplier&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;SuperHero&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nx"&gt;Hero&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;SuperPowers&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;human&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Hero&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;human&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;baseHealth&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;powers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;SuperPowers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;flying&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;superMan&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;SuperHero&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{...&lt;/span&gt;&lt;span class="nx"&gt;human&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;powers&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;TypeScript Playground: &lt;a href="https://www.typescriptlang.org/play?#code/JYOwLgpgTgZghgYwgAgBLQPbIN4ChnIIA2cAzqQFzIBEAFgK4C2cI1yAPjRETG59RigJqAGnzIARmQjo4RMLSogmE6LgC+uXKEixEKAMr0ADtAAKGAO7RSOcTCIBPUAHMA-FQkYMRCCzEEpCbQBqYQACYekt6+-uKkYFAQIC4KALL08sDGRMDQUcqMqlAaWjrQ8EjIRqZQ6FBYEAAekCDhtvUYItXBUBbWULbYmrgIGCAJyAzMIFSdyAC8OMRklDTTLKKS0rLyisgAjAAMR5pjE2DIxlY2VDXmN4OLOA7OKVSJ9BAj55NBtWkWHdevMltgAHSQjYgbqQ8HXAakTQAemRAAEACoQBC0AwAR3owHCGIAakA" rel="noopener noreferrer"&gt;TS Playground&lt;/a&gt;&lt;br&gt;
Spread Syntax: &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax" rel="noopener noreferrer"&gt;MDN Spread Syntax&lt;/a&gt;&lt;/p&gt;

</description>
      <category>typescript</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Kubernetes overview in 10 minutes</title>
      <dc:creator>Kyle TechSquidTV</dc:creator>
      <pubDate>Sun, 06 Sep 2020 20:15:29 +0000</pubDate>
      <link>https://dev.to/techsquidtv/kubernetes-overview-in-10-minutes-28l0</link>
      <guid>https://dev.to/techsquidtv/kubernetes-overview-in-10-minutes-28l0</guid>
      <description>&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/RaM1DFqQOm4"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;So you’ve used Docker, deployed a service or two, maybe even ran some production application using Docker-Compose. Now your audience has grown and you need to support an increasing demand on your server.&lt;/p&gt;

&lt;p&gt;Or like me, you just work in #devops. One of the most critical tools of DevOps today is the Kubernetes platform, a way to manage and scale our containerized deployments to “the cloud”.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is “the cloud”?
&lt;/h2&gt;

&lt;p&gt;“The cloud” is an abstract colloquialism to describe a range of different services, platforms, and ideologies with the goals of storing and serving data on the internet. That could mean your cloud backup provider who is storing your data with Amazon’s AWS S3 or Google’s GCP Cloud storage, or how Netflix serves and delivers its vast content library.&lt;/p&gt;

&lt;p&gt;A cloud is a representation of some number of machines (servers, virtual machines, ect) which are communicating together over the internet in cooperation of some task. A slightly more technical term we’ll use from now on is “cluster”.  A cluster, in particular, refers to some group of machines.&lt;/p&gt;

&lt;h2&gt;
  
  
  What does Kubernetes do?
&lt;/h2&gt;

&lt;p&gt;Well, a lot.&lt;/p&gt;

&lt;p&gt;But, one of the main things Kubernetes does is maintain clusters for us. Kubernetes is a platform for managing the lifecycle of a group of machines, virtual or not. When you compare that capability with a cloud provider that can give you “unlimited” compute at any time, that gives us a way to scale up our apps or services when they are in high demand, but then turn off and remove those extra servers when they are no longer needed, saving a lot of headaches and of course, money 💰.&lt;/p&gt;

&lt;p&gt;There’s also a bunch of other great features such as rolling deployments, and rolling back deployments.&lt;/p&gt;

&lt;h2&gt;
  
  
  How does Kubernetes work?
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Kubernetes Cluster
&lt;/h3&gt;

&lt;p&gt;Kubernetes is a platform made of many micro-services that work together to create and manage the cluster of machines that will soon run our application.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--BHrPa2UB--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/6wsuoakqz7438rawk55j.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--BHrPa2UB--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/6wsuoakqz7438rawk55j.jpg" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Master Node and the API service
&lt;/h3&gt;

&lt;p&gt;The main service of the platform is the Kubernetes API, with which each node in the cluster will communicate with.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The node(s) in the cluster running the API service are typically referred to as “master” nodes, while any other node is referred to as a “worker” node.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This API is also how we as administrators will interact with the cluster and issue command and deployments, etc. However, we don’t usually deal with the API directly (but we could), we usually use a CLI tool called “kubectl”.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--B7LQ-rGD--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/psjzffny6qz7lmlyh20b.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--B7LQ-rGD--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/psjzffny6qz7lmlyh20b.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you are familiar with Docker, this should be familiar. Docker also operates in a Client-Server relationship using APIs.&lt;/p&gt;

&lt;h3&gt;
  
  
  Worker Nodes
&lt;/h3&gt;

&lt;p&gt;The other nodes in the cluster, “worker” nodes are responsible for reacting to events from the API service and reporting back their status, and ultimately will run our containerized applications.&lt;/p&gt;

&lt;p&gt;Typically, you do not self-manage the hardware for a Kubernetes cluster, instead you work with a cloud provider. Working with a cloud provider who can supply a large number of machines means we can request and pay for only as many of these worker nodes as we need, and remove them from the cluster when demand goes down.&lt;/p&gt;

&lt;p&gt;On each node in a cluster, you will find an agent installed called “kublet”. The “kublet” agent will self-register with the API server and become a part of the cluster as soon as it is online. This two-way communication between the Node and the API service allows the API to maintain state, so if a node were to go offline it can be detected and replaced.&lt;/p&gt;

&lt;p&gt;While the API service manages and maintains the worker nodes, the worker nodes are maintaining their own components called pods and if any pod were to fail, the worker node would “self-heal” by replacing the pod.&lt;/p&gt;

&lt;h3&gt;
  
  
  Pods
&lt;/h3&gt;

&lt;p&gt;We mentioned above that worker nodes ultimately run our containerized applications, they do so by creating and maintaining “pods”. Pods are the smallest deployable unit in Kubernetes and their lifecycle is handled by the node on which it is running.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--kEv76FJW--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/o6sltjdmzgpyy6i445v3.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--kEv76FJW--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/o6sltjdmzgpyy6i445v3.jpg" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In Kubernetes we don’t interact with Docker directly, everything we deal with is purely Kubernetes API and the Docker stuff happens behind the scenes. Pods also manage their own networking and any attached volumes individually.&lt;/p&gt;

&lt;p&gt;If the pod, or container within, crashes or fails, the node should automatically attempt to rebuild the pod.&lt;/p&gt;

&lt;h2&gt;
  
  
  Deploy a sample app to the cloud with Kubernetes
&lt;/h2&gt;

&lt;p&gt;In the video above we go a little deeper in-depth on Kubernetes and write our own configuration file which we use to deploy a sample application to our Kubernetes cluster.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Sample deploy.yaml config file:&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;apps/v1&lt;/span&gt; &lt;span class="c1"&gt;# for versions before 1.9.0 use apps/v1beta2&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Deployment&lt;/span&gt;
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;echoserver-deploy&lt;/span&gt;
&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;selector&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;matchLabels&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;app&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;echoserver&lt;/span&gt;
  &lt;span class="na"&gt;replicas&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;3&lt;/span&gt; &lt;span class="c1"&gt;# tells deployment to run 3 pods matching the template&lt;/span&gt;
  &lt;span class="na"&gt;template&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;labels&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;app&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;echoserver&lt;/span&gt;
    &lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;containers&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;echoserver&lt;/span&gt;
        &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;gcr.io/google-samples/node-hello:1.0&lt;/span&gt;
        &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;containerPort&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;80&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The instructions for configuring your cluster will vary slightly depending on the cloud provider you choose.&lt;/p&gt;

&lt;p&gt;Once we have a cluster configured and are authenticated with kubectl, we apply our configuration file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;kubectl apply -f ./deploy.yaml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The Kubernetes API service will now work to mirror the state of this config file by issuing commands to worker nodes to stand up 3 pods containing the container specified.&lt;/p&gt;

&lt;p&gt;Run “get deployments” to watch the status of the deployment. Once 3/3 have completed (in this case), we are nearly done.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;kubectl get deployments
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To expose our internally deployed service to the outside internet, we must forward the port from our containerized service to the outside port on the node.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;kubectl expose deployment/echoserver-deploy --type="NodePort" --port 80
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If at this point you run the get services command, you should see both the Kubernetes API service and the service we have just deployed.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;kubectl get services
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, if you visit the IP address of any of your nodes at the port specified you should see your live service.&lt;/p&gt;

&lt;p&gt;🎉&lt;/p&gt;

&lt;p&gt;With your service now live on each node, it’s time to place these services behind a load balancer. But, that will be a tutorial for part2!&lt;/p&gt;

</description>
      <category>kubernetes</category>
      <category>devops</category>
      <category>tutorial</category>
      <category>beginners</category>
    </item>
  </channel>
</rss>
