<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Usersnap engineering]]></title><description><![CDATA[Usersnap engineering]]></description><link>https://engineering.usersnap.com</link><image><url>https://cdn.hashnode.com/res/hashnode/image/upload/v1676558933195/-5DvrP2P-.png</url><title>Usersnap engineering</title><link>https://engineering.usersnap.com</link></image><generator>RSS for Node</generator><lastBuildDate>Tue, 05 May 2026 19:53:58 GMT</lastBuildDate><atom:link href="https://engineering.usersnap.com/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[CI/CD on AWS basics]]></title><description><![CDATA[Introduction
It's 2023, so explaining CI/CD is probably not that necessary, but let's spend one sentence on the topic, so everybody's on the same page: your CI/CD (Continous Integration/ Continous Deployment) tool is connected to your source code rep...]]></description><link>https://engineering.usersnap.com/aws-ci-cd-basics</link><guid isPermaLink="true">https://engineering.usersnap.com/aws-ci-cd-basics</guid><category><![CDATA[AWS]]></category><category><![CDATA[ci-cd]]></category><category><![CDATA[codebuild]]></category><category><![CDATA[CodePipeline]]></category><dc:creator><![CDATA[martin sereinig]]></dc:creator><pubDate>Thu, 16 Feb 2023 15:24:25 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1676559547746/f998c455-452c-42fe-94d8-d1b9655207e0.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h1 id="heading-introduction">Introduction</h1>
<p>It's 2023, so explaining CI/CD is probably not <em>that</em> necessary, but let's spend one sentence on the topic, so everybody's on the same page: your CI/CD (Continous Integration/ Continous Deployment) tool is connected to your source code repository and performs certain actions when something is committed, e.g.: tests and linting, creating a build, deploying to staging, integration tests, etc.</p>
<p>Many repository providers nowadays have CI/CD solutions included (Github, Gitlab) and there are of course many, many SaaS products that focus on CI/CD (e.g. Codeship, Travis, CircleCI, ... ). Here at Usersnap, we're big AWS users, so we usually try to use services offered by AWS.</p>
<p>So how does the CI/CD situation in AWS look? There are multiple services that all seem to be related to this topic:</p>
<ul>
<li><p><a target="_blank" href="https://aws.amazon.com/codedeploy/">CodeDeploy</a></p>
</li>
<li><p><a target="_blank" href="https://aws.amazon.com/codebuild/">CodeBuild</a></p>
</li>
<li><p><a target="_blank" href="https://aws.amazon.com/codecommit/">CodeCommit</a></p>
</li>
<li><p><a target="_blank" href="https://aws.amazon.com/codestar/">CodeStar</a></p>
</li>
<li><p><a target="_blank" href="https://aws.amazon.com/codecatalyst/">CodeCatalyst</a></p>
</li>
<li><p><a target="_blank" href="https://aws.amazon.com/codepipeline/">CodePipeline</a></p>
</li>
</ul>
<p>So are you confused already? For the scope of this article, we'll focus on the services that we use, namely: CodePipeline and CodeBuild.</p>
<h1 id="heading-codepipeline">CodePipeline</h1>
<blockquote>
<p>AWS CodePipeline is a fully managed continuous delivery service that helps you automate your release pipelines for fast and reliable application and infrastructure updates.</p>
<p><a target="_blank" href="https://aws.amazon.com/codepipeline/">https://aws.amazon.com/codepipeline/</a></p>
</blockquote>
<p>Well, it's a pipeline. You connect it to your source code, and then it starts to run through various stages (or actions) until it's done. The first stage is always a source stage, which kicks the whole thing off. Every stage has input and output artifacts, and if anything goes wrong during one of the stages, the pipeline stops.</p>
<h1 id="heading-codebuild">CodeBuild</h1>
<blockquote>
<p>AWS CodeBuild is a fully managed continuous integration service that compiles source code, runs tests, and produces ready-to-deploy software packages.</p>
<p><a target="_blank" href="https://aws.amazon.com/codebuild/">https://aws.amazon.com/codebuild/</a></p>
</blockquote>
<p>CodeBuild is, generally speaking, like most other CI/CD services. You connect it to a source and then you get an environment in which you can run code to test, lint, build, deploy or whatever else you can think of. CodeBuild can be part of a CodePipeline, but doesn't have to – it can also run on its own.</p>
<h1 id="heading-putting-it-together">Putting it together</h1>
<h2 id="heading-cicd-strategy">CI/CD Strategy</h2>
<p>Let's say we have a container-based web application and want to implement the following branching + CI/CD strategy.</p>
<ul>
<li><p>A development branch that is always deployed to our staging environment. All development happens based on this branch.</p>
</li>
<li><p>A release branch that represents the current state of production. The development branch is merged into this branch to create a new production build, and release tags are used, to release the previously created build.</p>
</li>
</ul>
<p>This allows us to automate deploys to both staging and production environments, while still having a manual step to release. This means, for our CI/CD process, we have the following requirements:</p>
<ul>
<li><p>Any push to our repository always triggers linting + tests (except the commit starts with <code>[skip]</code>)</p>
</li>
<li><p>Pull requests cannot be merged unless the tests + linting didn't fail</p>
</li>
<li><p>If a commit is tagged with a special tag (or on a special branch), we want to build a version of the current state on this branch and deploy this to our staging environment</p>
</li>
<li><p>If a commit is on a specific branch ("the release branch"), we want to trigger a release build</p>
</li>
<li><p>If a commit on the release branch contains a special tag, we want to trigger a release</p>
</li>
</ul>
<h2 id="heading-implementing-the-strategy">Implementing the strategy</h2>
<p>This totally sounds like a pipeline that does different things, depending on the branch and/or tag. So let's use CodePipeline! Since we always use CDK to setup our infrastructure, let's take a look at the CDK Api for the <code>GitHubSourceAction</code>:</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">const</span> sourceAction = <span class="hljs-keyword">new</span> codepipeline_actions.GitHubSourceAction({
  actionName: <span class="hljs-string">'GitHub_Source'</span>,
  owner: <span class="hljs-string">'awslabs'</span>,
  repo: <span class="hljs-string">'aws-cdk'</span>,
  oauthToken: SecretValue.secretsManager(<span class="hljs-string">'my-github-token'</span>),
  output: sourceOutput,
  branch: <span class="hljs-string">'develop'</span>, <span class="hljs-comment">// default: 'master'</span>
});typ
</code></pre>
<p>Hmmm. We want to trigger our pipeline, at least for linting and tests, for every branch – why do we need to give a branch name here? Turns out: <strong>Codepipeline's</strong> <code>GitHubSourceAction</code> <strong>only runs for a single tag/branch</strong>. Which means we can't use it to run tests for every new feature branch.</p>
<p>One solution to get out of this problem is to dynamically create a new pipeline for every branch that is created and delete it once the branch is deleted: <a target="_blank" href="https://aws.amazon.com/blogs/devops/multi-branch-codepipeline-strategy-with-event-driven-architecture/">https://aws.amazon.com/blogs/devops/multi-branch-codepipeline-strategy-with-event-driven-architecture/</a>. But this sounds awfully complicated.</p>
<p>What we ended up doing, is <strong>utilizing CodeBuild like any other CI/CD provider</strong>:</p>
<ul>
<li><p>Connect CodeBuild to our repository</p>
</li>
<li><p>Always run tests + linting (except the <code>[skip]</code> is present in the commit)</p>
</li>
<li><p>Depending on the branch/tag, build + push to the container registry, meaning the deployment has been created at this point</p>
</li>
<li><p>Depending on the branch/tag, deploy</p>
</li>
</ul>
<p>And, <strong>in addition, have a CodePipeline for every environment</strong> (staging and production), which doesn't have <code>GitHubSourceAction</code>, but a <code>EcrSourceAction</code>, that listens for a specific container tag (e.g. <code>release</code> or <code>staging</code>) and starts the release to the corresponding environment.</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">const</span> sourceAction = <span class="hljs-keyword">new</span> codepipeline_actions.EcrSourceAction({
  actionName: <span class="hljs-string">'ECR'</span>,
  repository: ecrRepository,
  imageTag: <span class="hljs-string">'staging'</span>,
  output: sourceOutput,
});
</code></pre>
<p>In conclusion, this means we use 1 CodePipeline for every environment we're deploying to, and 1 CodeBuild project per project to do all testing + building.</p>
<h1 id="heading-further-reading">Further reading</h1>
<p>Not a lot of people seem to be doing the same as we do. The following sources pointed us into the right direction for our setup:</p>
<ul>
<li><p><a target="_blank" href="https://repost.aws/questions/QU6QMD3w21QS2i1_lnZ-yqBw/how-to-deploy-every-branch-i-push-to-my-code-commit-repo">https://repost.aws/questions/QU6QMD3w21QS2i1_lnZ-yqBw/how-to-deploy-every-branch-i-push-to-my-code-commit-repo</a></p>
</li>
<li><p><a target="_blank" href="https://stackoverflow.com/questions/46696036/can-aws-codepipeline-track-multiple-feature-branches-and-run-tests-on-each">https://stackoverflow.com/questions/46696036/can-aws-codepipeline-track-multiple-feature-branches-and-run-tests-on-each</a></p>
</li>
</ul>
]]></content:encoded></item></channel></rss>