<?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: Anthony Nwaizuzu</title>
    <description>The latest articles on DEV Community by Anthony Nwaizuzu (@cuddi).</description>
    <link>https://dev.to/cuddi</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%2F56000%2Fb350a7ef-da2f-4e6a-8e2e-951ba85e5670.PNG</url>
      <title>DEV Community: Anthony Nwaizuzu</title>
      <link>https://dev.to/cuddi</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/cuddi"/>
    <language>en</language>
    <item>
      <title>🚀 Cube: The Automation Platform That Actually Gets Developers</title>
      <dc:creator>Anthony Nwaizuzu</dc:creator>
      <pubDate>Mon, 23 Mar 2026 10:12:23 +0000</pubDate>
      <link>https://dev.to/cuddi/cube-the-automation-platform-that-actually-gets-developers-200</link>
      <guid>https://dev.to/cuddi/cube-the-automation-platform-that-actually-gets-developers-200</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgtcpzp03fw4i4lt2jdnz.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgtcpzp03fw4i4lt2jdnz.gif" alt="Wow" width="480" height="347"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The Automation Nightmare We All Live Through 🌙
&lt;/h2&gt;

&lt;p&gt;It's 2 AM. Sarah, your lead developer, is staring at her laptop for the third night this week. The customer onboarding script she wrote 6 months ago just broke because Stripe updated their API. Again.&lt;/p&gt;

&lt;p&gt;Meanwhile, in the marketing department, Tom is trying to set up a simple "welcome email sequence" in Zapier. He hits a wall - he needs to check if the user's subscription tier matches their company size. Zapier can't handle that logic. He opens a ticket to engineering. The backlog is now 3 weeks long.&lt;/p&gt;

&lt;p&gt;Sound familiar? This is the automation trap that every team falls into:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Developer Trap:&lt;/strong&gt; You write custom scripts. They work great. Until they don't. APIs change, dependencies break, the original developer leaves, and suddenly your business-critical automation becomes a ticking time bomb.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The No-Code Trap:&lt;/strong&gt; You start with Zapier/Make.com because it's "easy." But the moment you need real logic, custom integrations, or proper error handling, you're back to begging developers for help.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Enterprise Trap:&lt;/strong&gt; You spend $50,000+ on an "enterprise solution" that requires a dedicated team, 6-month implementation cycles, and more meetings than actual automation.&lt;/p&gt;

&lt;p&gt;We've all been there. The frustration is real. The wasted hours are real. The broken business processes are very, very real.&lt;/p&gt;

&lt;h2&gt;
  
  
  Let's Be Honest About Automation Tools 😅
&lt;/h2&gt;

&lt;p&gt;You know the drill. You try to automate something and end up with:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Option A: Zapier/Make.com&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;"Great! I can connect Gmail to Slack!"&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;5 minutes later:&lt;/em&gt; "Wait, I need custom logic. Time to beg a developer for help..."&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Result:&lt;/em&gt; Back to square one, but with a subscription bill&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Option B: Write Custom Code&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;em&gt;Developer spends 3 days building a Python script&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;Works perfectly for 6 months&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;API changes, script breaks, developer left the company&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Result:&lt;/em&gt; Business-critical automation is dead&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Option C: Enterprise "Solution"&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;em&gt;6-month implementation cycle&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;Dedicated team required&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;Costs more than your entire marketing budget&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Result:&lt;/em&gt; Nobody wants to use it&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What If Automation Was Actually... Nice? ✨
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F86dwshpsj8d54pmqx2b5.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F86dwshpsj8d54pmqx2b5.PNG" alt="Cube Workflow" width="800" height="424"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://usecube.co" rel="noopener noreferrer"&gt;Cube&lt;/a&gt; is different. We built it for developers who are tired of the automation BS.&lt;/p&gt;

&lt;h3&gt;
  
  
  🎯 For Developers, By Developers
&lt;/h3&gt;

&lt;p&gt;Instead of fighting with limited UI builders or writing endless boilerplate code, &lt;a href="https://usecube.co" rel="noopener noreferrer"&gt;Cube&lt;/a&gt; gives you visual workflows that just work. No more 200-line error handling functions or retry logic nightmares.&lt;/p&gt;

&lt;h3&gt;
  
  
  🔧 The Developer Dream Stack
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://usecube.co" rel="noopener noreferrer"&gt;Cube&lt;/a&gt; gives you what you actually want:&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;HTTP Requests That Don't Suck&lt;/strong&gt;
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;✅ Built-in retry logic (no more &lt;code&gt;try/catch&lt;/code&gt; hell)&lt;/li&gt;
&lt;li&gt;✅ SSRF protection (security team will love you)&lt;/li&gt;
&lt;li&gt;✅ Template variables (use data from previous steps)&lt;/li&gt;
&lt;li&gt;✅ Multiple auth methods (Bearer, Basic, custom headers)&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Webhooks That Actually Work&lt;/strong&gt;
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;✅ HMAC signature validation (enterprise-grade security)&lt;/li&gt;
&lt;li&gt;✅ Rate limiting built-in&lt;/li&gt;
&lt;li&gt;✅ Automatic logging and monitoring&lt;/li&gt;
&lt;li&gt;✅ No more "why isn't this firing?" debugging sessions&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Flow Control That Makes Sense&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;Remember those nested if/else statements that gave you headaches? &lt;a href="https://usecube.co" rel="noopener noreferrer"&gt;Cube&lt;/a&gt; turns complex logic into simple visual nodes that anyone can understand.&lt;/p&gt;

&lt;h3&gt;
  
  
  🚀 Real Power, Zero Boilerplate
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://usecube.co" rel="noopener noreferrer"&gt;Cube&lt;/a&gt; handles all the stuff you hate writing:&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Error Handling &amp;amp; Retries&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;Remember spending hours writing retry logic with exponential backoff? &lt;a href="https://usecube.co" rel="noopener noreferrer"&gt;Cube&lt;/a&gt; handles all of that automatically. Just set the retry count and walk away.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Scheduled Tasks Without Cron Headaches&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;Tired of managing crontabs and hoping they don't conflict? &lt;a href="https://usecube.co" rel="noopener noreferrer"&gt;Cube&lt;/a&gt; gives you visual scheduling that just works.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Monitoring That Actually Helps&lt;/strong&gt;
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;✅ See exactly which step failed&lt;/li&gt;
&lt;li&gt;✅ Input/output data for each node&lt;/li&gt;
&lt;li&gt;✅ Execution time tracking&lt;/li&gt;
&lt;li&gt;✅ One-click replay of failed executions&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The Cube Difference: Developer-Focused vs. App-Focused 🎭
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;Zapier/Make&lt;/th&gt;
&lt;th&gt;Custom Scripts&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Cube&lt;/strong&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Custom Logic&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;❌ Very limited&lt;/td&gt;
&lt;td&gt;❌ Manual work&lt;/td&gt;
&lt;td&gt;✅ Visual + Code&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;API Integration&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;❌ Pre-built only&lt;/td&gt;
&lt;td&gt;✅ Everything&lt;/td&gt;
&lt;td&gt;✅ Everything + Easy&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Error Handling&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;❌ Basic&lt;/td&gt;
&lt;td&gt;❌ Manual work&lt;/td&gt;
&lt;td&gt;✅ Built-in&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Monitoring&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;❌ Basic logs&lt;/td&gt;
&lt;td&gt;✅ DIY only&lt;/td&gt;
&lt;td&gt;✅ Built-in&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Setup Time&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;✅ Minutes&lt;/td&gt;
&lt;td&gt;❌ Days/Weeks&lt;/td&gt;
&lt;td&gt;✅ Seconds&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Real Scenarios Where Cube Shines 🌟
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Scenario 1: E-commerce Order Processing
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Before Cube:&lt;/strong&gt;&lt;br&gt;
300+ lines of Python code, error handling for 5 different APIs, database connections, email templates, Slack notifications, retry logic, logging, monitoring setup, deployment scripts... you get the idea.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;With Cube:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Add webhook trigger (Shopify)&lt;/li&gt;
&lt;li&gt;Add HTTP request (inventory API)&lt;/li&gt;
&lt;li&gt;Add email node (customer confirmation)&lt;/li&gt;
&lt;li&gt;Add Slack node (team notification)&lt;/li&gt;
&lt;li&gt;Add condition node (if order &amp;gt; $100, tag as VIP)&lt;/li&gt;
&lt;li&gt;Deploy&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Time saved:&lt;/strong&gt; 2 weeks → 30 minutes&lt;/p&gt;

&lt;h3&gt;
  
  
  Scenario 2: User Onboarding Pipeline
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Before Cube:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Multiple Lambda functions&lt;/li&gt;
&lt;li&gt;Step Functions for orchestration&lt;/li&gt;
&lt;li&gt;CloudWatch for logging&lt;/li&gt;
&lt;li&gt;SNS for notifications&lt;/li&gt;
&lt;li&gt;$200+ monthly AWS bill&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;With Cube:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Visual workflow&lt;/li&gt;
&lt;li&gt;Built-in monitoring&lt;/li&gt;
&lt;li&gt;Self-hosted (your infrastructure)&lt;/li&gt;
&lt;li&gt;$0 additional cost&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Scenario 3: API Integration Hell
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Before Cube:&lt;/strong&gt;&lt;br&gt;
"Just need to call this API..." 3 hours later you've implemented OAuth 2.0 flow, token refresh logic, rate limiting, error parsing, retry logic, logging, tests, and documentation.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;With Cube:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Add HTTP Request node&lt;/li&gt;
&lt;li&gt;Set auth type to "Bearer Token"&lt;/li&gt;
&lt;li&gt;Paste token&lt;/li&gt;
&lt;li&gt;Done&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The Bottom Line: Stop Wasting Time on Boilerplate ⏰
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpqkxff3rxx9tsl2utxqe.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpqkxff3rxx9tsl2utxqe.gif" alt="Visual Workflow" width="360" height="378"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Every hour you spend writing:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Error handling code&lt;/li&gt;
&lt;li&gt;Retry logic&lt;/li&gt;
&lt;li&gt;Logging infrastructure&lt;/li&gt;
&lt;li&gt;Monitoring dashboards&lt;/li&gt;
&lt;li&gt;Authentication wrappers&lt;/li&gt;
&lt;li&gt;API integration boilerplate&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Is an hour you're NOT spending on:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Features your users actually want&lt;/li&gt;
&lt;li&gt;Performance improvements&lt;/li&gt;
&lt;li&gt;Security enhancements&lt;/li&gt;
&lt;li&gt;Code that makes your product better&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://usecube.co" rel="noopener noreferrer"&gt;Cube&lt;/a&gt; eliminates the boring stuff so you can focus on the important stuff.&lt;/p&gt;

&lt;h2&gt;
  
  
  Ready to Actually Enjoy Automation Again? 🚀
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Get started in 5 minutes:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;🎯 Sign In/Sign Up and Build your first workflow with &lt;a href="https://usecube.co" rel="noopener noreferrer"&gt;Cube&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;🎉 Wonder why you ever did it any other way&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;The result:&lt;/strong&gt; You'll build automations 10x faster, with better error handling, monitoring, and security than you'd ever implement yourself.&lt;/p&gt;




&lt;h2&gt;
  
  
  🎯 TL;DR
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Problem:&lt;/strong&gt; Most automation tools are either too limited (Zapier) or too much work (custom code)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://usecube.co" rel="noopener noreferrer"&gt;Cube&lt;/a&gt; solution:&lt;/strong&gt; Visual workflow builder + developer power + built-in best practices&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Result:&lt;/strong&gt; Build complex automations in minutes, not weeks&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Bonus:&lt;/strong&gt; You get all the enterprise features without the enterprise price tag&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Stop fighting with automation tools. Start building things that matter.&lt;/strong&gt; 🎉&lt;/p&gt;




&lt;p&gt;&lt;em&gt;P.S. &lt;a href="https://usecube.co" rel="noopener noreferrer"&gt;Cube&lt;/a&gt; is currently in MVP and we'd love your feedback! What features would you like to see? Let us know and help shape the future of automation.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>automation</category>
      <category>startup</category>
      <category>showdev</category>
      <category>softwareengineering</category>
    </item>
    <item>
      <title>How i spent my Christmas break!!</title>
      <dc:creator>Anthony Nwaizuzu</dc:creator>
      <pubDate>Thu, 08 Jan 2026 02:14:50 +0000</pubDate>
      <link>https://dev.to/cuddi/how-i-spent-my-christmas-break-5g0o</link>
      <guid>https://dev.to/cuddi/how-i-spent-my-christmas-break-5g0o</guid>
      <description>&lt;div class="ltag__link--embedded"&gt;
  &lt;div class="crayons-story "&gt;
  &lt;a href="https://dev.to/cuddi/if-swagger-works-but-your-sdk-fails-your-sdk-is-lying-4pjo" class="crayons-story__hidden-navigation-link"&gt;If Swagger Works but Your SDK Fails, Your SDK Is Lying&lt;/a&gt;


  &lt;div class="crayons-story__body crayons-story__body-full_post"&gt;
    &lt;div class="crayons-story__top"&gt;
      &lt;div class="crayons-story__meta"&gt;
        &lt;div class="crayons-story__author-pic"&gt;

          &lt;a href="/cuddi" class="crayons-avatar  crayons-avatar--l  "&gt;
            &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F56000%2Fb350a7ef-da2f-4e6a-8e2e-951ba85e5670.PNG" alt="cuddi profile" class="crayons-avatar__image" width="800" height="1732"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
        &lt;div&gt;
          &lt;div&gt;
            &lt;a href="/cuddi" class="crayons-story__secondary fw-medium m:hidden"&gt;
              Anthony Nwaizuzu
            &lt;/a&gt;
            &lt;div class="profile-preview-card relative mb-4 s:mb-0 fw-medium hidden m:inline-block"&gt;
              
                Anthony Nwaizuzu
                
              
              &lt;div id="story-author-preview-content-3156750" class="profile-preview-card__content crayons-dropdown branded-7 p-4 pt-0"&gt;
                &lt;div class="gap-4 grid"&gt;
                  &lt;div class="-mt-4"&gt;
                    &lt;a href="/cuddi" class="flex"&gt;
                      &lt;span class="crayons-avatar crayons-avatar--xl mr-2 shrink-0"&gt;
                        &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F56000%2Fb350a7ef-da2f-4e6a-8e2e-951ba85e5670.PNG" class="crayons-avatar__image" alt="" width="800" height="1732"&gt;
                      &lt;/span&gt;
                      &lt;span class="crayons-link crayons-subtitle-2 mt-5"&gt;Anthony Nwaizuzu&lt;/span&gt;
                    &lt;/a&gt;
                  &lt;/div&gt;
                  &lt;div class="print-hidden"&gt;
                    
                      Follow
                    
                  &lt;/div&gt;
                  &lt;div class="author-preview-metadata-container"&gt;&lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
            &lt;/div&gt;

          &lt;/div&gt;
          &lt;a href="https://dev.to/cuddi/if-swagger-works-but-your-sdk-fails-your-sdk-is-lying-4pjo" class="crayons-story__tertiary fs-xs"&gt;&lt;time&gt;Jan 8&lt;/time&gt;&lt;span class="time-ago-indicator-initial-placeholder"&gt;&lt;/span&gt;&lt;/a&gt;
        &lt;/div&gt;
      &lt;/div&gt;

    &lt;/div&gt;

    &lt;div class="crayons-story__indention"&gt;
      &lt;h2 class="crayons-story__title crayons-story__title-full_post"&gt;
        &lt;a href="https://dev.to/cuddi/if-swagger-works-but-your-sdk-fails-your-sdk-is-lying-4pjo" id="article-link-3156750"&gt;
          If Swagger Works but Your SDK Fails, Your SDK Is Lying
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;div class="crayons-story__tags"&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/fastapi"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;fastapi&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/python"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;python&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/sdk"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;sdk&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/database"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;database&lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="crayons-story__bottom"&gt;
        &lt;div class="crayons-story__details"&gt;
          &lt;a href="https://dev.to/cuddi/if-swagger-works-but-your-sdk-fails-your-sdk-is-lying-4pjo" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left"&gt;
            &lt;div class="multiple_reactions_aggregate"&gt;
              &lt;span class="multiple_reactions_icons_container"&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/raised-hands-74b2099fd66a39f2d7eed9305ee0f4553df0eb7b4f11b01b6b1b499973048fe5.svg" width="24" height="24"&gt;
                  &lt;/span&gt;
              &lt;/span&gt;
              &lt;span class="aggregate_reactions_counter"&gt;1&lt;span class="hidden s:inline"&gt; reaction&lt;/span&gt;&lt;/span&gt;
            &lt;/div&gt;
          &lt;/a&gt;
            &lt;a href="https://dev.to/cuddi/if-swagger-works-but-your-sdk-fails-your-sdk-is-lying-4pjo#comments" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left flex items-center"&gt;
              Comments


              2&lt;span class="hidden s:inline"&gt; comments&lt;/span&gt;
            &lt;/a&gt;
        &lt;/div&gt;
        &lt;div class="crayons-story__save"&gt;
          &lt;small class="crayons-story__tertiary fs-xs mr-2"&gt;
            2 min read
          &lt;/small&gt;
            
              &lt;span class="bm-initial"&gt;
                

              &lt;/span&gt;
              &lt;span class="bm-success"&gt;
                

              &lt;/span&gt;
            
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;


</description>
      <category>fastapi</category>
      <category>python</category>
      <category>sdk</category>
      <category>database</category>
    </item>
    <item>
      <title>If Swagger Works but Your SDK Fails, Your SDK Is Lying</title>
      <dc:creator>Anthony Nwaizuzu</dc:creator>
      <pubDate>Thu, 08 Jan 2026 02:11:38 +0000</pubDate>
      <link>https://dev.to/cuddi/if-swagger-works-but-your-sdk-fails-your-sdk-is-lying-4pjo</link>
      <guid>https://dev.to/cuddi/if-swagger-works-but-your-sdk-fails-your-sdk-is-lying-4pjo</guid>
      <description>&lt;h4&gt;
  
  
  I spent hours debugging my backend, my database, and my auth logic — only to discover none of them were broken.
&lt;/h4&gt;

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

&lt;p&gt;&lt;code&gt;I was building a feature flag / runtime config service.(just a fun thing to do during the holidays)&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;The idea was simple:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Backend exposes config values per environment&lt;/li&gt;
&lt;li&gt;SDK fetches them at runtime&lt;/li&gt;
&lt;li&gt;Same token, same environment, same key&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Swagger UI worked perfectly.&lt;/p&gt;

&lt;p&gt;The SDK?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ConfigNotFoundError: config not found in environment 'development'
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Step 1: Trust Swagger First
&lt;/h4&gt;

&lt;p&gt;&lt;code&gt;Swagger wasn’t lying.&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;It showed:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The request&lt;/li&gt;
&lt;li&gt;The headers&lt;/li&gt;
&lt;li&gt;The resolved environment&lt;/li&gt;
&lt;li&gt;The correct response&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Mistake #1: The SDK Route Didn’t Match the API
&lt;/h4&gt;

&lt;p&gt;&lt;code&gt;If you're not careful you can literally spend days trying to figure out what the issue is and meanwhile all you had to do is make sure both routes are the same&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;The backend exposed this route:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;GET /api/v1/sdk/configs/{key}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But my SDK was building URLs like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/api/v1/config/{key}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The annoying part is when it happens, it comes with No expection, No warning, just a clean 404&lt;/p&gt;

&lt;p&gt;Lesson&lt;br&gt;
&lt;code&gt;Your SDK must match your backend routes character for character.&lt;/code&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Mistake #2: Key Normalization Was Inconsistent
&lt;/h4&gt;

&lt;p&gt;&lt;code&gt;This part sounds ordinary, right?......just make sure you don't forget about it. If it requires you setting a reminder to do it, please do because i don't think you will want to shed invisible tears...lol&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Configs were stored as:&lt;br&gt;
&lt;code&gt;FEATURE_CHECKOUT_ENABLED&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;But SDK users could pass:&lt;br&gt;
&lt;code&gt;"feature_checkout_enabled"&lt;br&gt;
"Feature_Checkout_Enabled "&lt;br&gt;
&lt;/code&gt;&lt;br&gt;
That caused:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Cache misses&lt;/li&gt;
&lt;li&gt;False “not found” errors&lt;/li&gt;
&lt;li&gt;Inconsistent results&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Used:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Before API calls&lt;/li&gt;
&lt;li&gt;Before caching&lt;/li&gt;
&lt;li&gt;Before comparisons
&lt;code&gt;Normalize input once — and enforce it everywhere.&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  What This Experience Taught Me
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Swagger is your contract&lt;/li&gt;
&lt;li&gt;SDKs lie by omission&lt;/li&gt;
&lt;li&gt;Route mismatches are silent killers&lt;/li&gt;
&lt;li&gt;Normalization prevents phantom bugs&lt;/li&gt;
&lt;li&gt;If Swagger works, your backend is innocent&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  The Rule I Follow Now
&lt;/h4&gt;

&lt;p&gt;Swagger first. SDK second. Database last.&lt;/p&gt;

&lt;p&gt;Every time!!!&lt;/p&gt;

</description>
      <category>fastapi</category>
      <category>python</category>
      <category>sdk</category>
      <category>database</category>
    </item>
    <item>
      <title>Hello Guys, Check out my latest article after a long time away</title>
      <dc:creator>Anthony Nwaizuzu</dc:creator>
      <pubDate>Sun, 28 Dec 2025 16:41:12 +0000</pubDate>
      <link>https://dev.to/cuddi/hello-guys-check-mout-my-latest-article-after-a-long-time-away-4e5k</link>
      <guid>https://dev.to/cuddi/hello-guys-check-mout-my-latest-article-after-a-long-time-away-4e5k</guid>
      <description>&lt;p&gt;

&lt;/p&gt;
&lt;div class="ltag__link--embedded"&gt;
  &lt;div class="crayons-story "&gt;
  &lt;a href="https://dev.to/cuddi/that-dreaded-alembic-notnullviolation-error-and-how-to-survive-it-33a1" class="crayons-story__hidden-navigation-link"&gt;That Dreaded Alembic NotNullViolation Error (and How to Survive It)&lt;/a&gt;


  &lt;div class="crayons-story__body crayons-story__body-full_post"&gt;
    &lt;div class="crayons-story__top"&gt;
      &lt;div class="crayons-story__meta"&gt;
        &lt;div class="crayons-story__author-pic"&gt;

          &lt;a href="/cuddi" class="crayons-avatar  crayons-avatar--l  "&gt;
            &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F56000%2Fb350a7ef-da2f-4e6a-8e2e-951ba85e5670.PNG" alt="cuddi profile" class="crayons-avatar__image"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
        &lt;div&gt;
          &lt;div&gt;
            &lt;a href="/cuddi" class="crayons-story__secondary fw-medium m:hidden"&gt;
              Anthony Nwaizuzu
            &lt;/a&gt;
            &lt;div class="profile-preview-card relative mb-4 s:mb-0 fw-medium hidden m:inline-block"&gt;
              
                Anthony Nwaizuzu
                
              
              &lt;div id="story-author-preview-content-3131705" class="profile-preview-card__content crayons-dropdown branded-7 p-4 pt-0"&gt;
                &lt;div class="gap-4 grid"&gt;
                  &lt;div class="-mt-4"&gt;
                    &lt;a href="/cuddi" class="flex"&gt;
                      &lt;span class="crayons-avatar crayons-avatar--xl mr-2 shrink-0"&gt;
                        &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F56000%2Fb350a7ef-da2f-4e6a-8e2e-951ba85e5670.PNG" class="crayons-avatar__image" alt=""&gt;
                      &lt;/span&gt;
                      &lt;span class="crayons-link crayons-subtitle-2 mt-5"&gt;Anthony Nwaizuzu&lt;/span&gt;
                    &lt;/a&gt;
                  &lt;/div&gt;
                  &lt;div class="print-hidden"&gt;
                    
                      Follow
                    
                  &lt;/div&gt;
                  &lt;div class="author-preview-metadata-container"&gt;&lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
            &lt;/div&gt;

          &lt;/div&gt;
          &lt;a href="https://dev.to/cuddi/that-dreaded-alembic-notnullviolation-error-and-how-to-survive-it-33a1" class="crayons-story__tertiary fs-xs"&gt;&lt;time&gt;Dec 28 '25&lt;/time&gt;&lt;span class="time-ago-indicator-initial-placeholder"&gt;&lt;/span&gt;&lt;/a&gt;
        &lt;/div&gt;
      &lt;/div&gt;

    &lt;/div&gt;

    &lt;div class="crayons-story__indention"&gt;
      &lt;h2 class="crayons-story__title crayons-story__title-full_post"&gt;
        &lt;a href="https://dev.to/cuddi/that-dreaded-alembic-notnullviolation-error-and-how-to-survive-it-33a1" id="article-link-3131705"&gt;
          That Dreaded Alembic NotNullViolation Error (and How to Survive It)
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;div class="crayons-story__tags"&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/psqlalchemy"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;psqlalchemy&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/alembic"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;alembic&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/postgres"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;postgres&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/database"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;database&lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="crayons-story__bottom"&gt;
        &lt;div class="crayons-story__details"&gt;
          &lt;a href="https://dev.to/cuddi/that-dreaded-alembic-notnullviolation-error-and-how-to-survive-it-33a1" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left"&gt;
            &lt;div class="multiple_reactions_aggregate"&gt;
              &lt;span class="multiple_reactions_icons_container"&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/sparkle-heart-5f9bee3767e18deb1bb725290cb151c25234768a0e9a2bd39370c382d02920cf.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
              &lt;/span&gt;
              &lt;span class="aggregate_reactions_counter"&gt;3&lt;span class="hidden s:inline"&gt; reactions&lt;/span&gt;&lt;/span&gt;
            &lt;/div&gt;
          &lt;/a&gt;
            &lt;a href="https://dev.to/cuddi/that-dreaded-alembic-notnullviolation-error-and-how-to-survive-it-33a1#comments" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left flex items-center"&gt;
              Comments


              1&lt;span class="hidden s:inline"&gt; comment&lt;/span&gt;
            &lt;/a&gt;
        &lt;/div&gt;
        &lt;div class="crayons-story__save"&gt;
          &lt;small class="crayons-story__tertiary fs-xs mr-2"&gt;
            2 min read
          &lt;/small&gt;
            
              &lt;span class="bm-initial"&gt;
                

              &lt;/span&gt;
              &lt;span class="bm-success"&gt;
                

              &lt;/span&gt;
            
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;




</description>
      <category>psqlalchemy</category>
      <category>alembic</category>
      <category>postgres</category>
      <category>database</category>
    </item>
    <item>
      <title>That Dreaded Alembic NotNullViolation Error (and How to Survive It)</title>
      <dc:creator>Anthony Nwaizuzu</dc:creator>
      <pubDate>Sun, 28 Dec 2025 16:40:16 +0000</pubDate>
      <link>https://dev.to/cuddi/that-dreaded-alembic-notnullviolation-error-and-how-to-survive-it-33a1</link>
      <guid>https://dev.to/cuddi/that-dreaded-alembic-notnullviolation-error-and-how-to-survive-it-33a1</guid>
      <description>&lt;h4&gt;
  
  
  What Happened?
&lt;/h4&gt;

&lt;p&gt;Imagine you have a table called organizations full of precious data. You decide:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Hey, let’s add a new column called plan!&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Sounds harmless, right? Wrong. You add it as &lt;code&gt;NOT NULL&lt;/code&gt;, meaning every row must have a value. But wait… your table is already filled with rows. PostgreSQL looks at them and says:&lt;/p&gt;

&lt;h4&gt;
  
  
  Why It’s Not Your Fault
&lt;/h4&gt;

&lt;p&gt;This isn’t a bug in Alembic or SQLAlchemy. It’s PostgreSQL protecting your precious data. Adding a NOT NULL column to existing data without a default is basically like asking someone to fill out a survey you didn’t give them in advance. They don’t know what to answer, so they freak out.&lt;/p&gt;

&lt;h4&gt;
  
  
  How to Fix It
&lt;/h4&gt;

&lt;p&gt;You’ve got a few ways to make PostgreSQL happy again:&lt;/p&gt;

&lt;h5&gt;
  
  
  Option 1: Give it a Default
&lt;/h5&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;op.add_column(
    'organizations', 
    sa.Column('plan', sa.String(), nullable=False, server_default='free')
)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Existing rows get a value ('free') automatically.&lt;/li&gt;
&lt;li&gt;After the migration, you can remove the default if you like.&lt;/li&gt;
&lt;li&gt;Quick, painless, and everyone’s happy.&lt;/li&gt;
&lt;/ul&gt;

&lt;h5&gt;
  
  
  Option 2: Three-Step Dance
&lt;/h5&gt;

&lt;p&gt;&lt;code&gt;Add the column as nullable:&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;op.add_column(
    'organizations', 
    sa.Column('plan', sa.String(), nullable=True)
)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;Update existing rows:&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;UPDATE organizations SET plan = 'free' WHERE plan IS NULL;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h5&gt;
  
  
  Make it NOT NULL:
&lt;/h5&gt;

&lt;p&gt;&lt;code&gt;op.alter_column('organizations', 'plan', nullable=False)&lt;/code&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;More steps, but more control.&lt;/li&gt;
&lt;li&gt;Good if you need custom logic per row.&lt;/li&gt;
&lt;/ul&gt;

&lt;h5&gt;
  
  
  Option 3: Pre-Migration Prep
&lt;/h5&gt;

&lt;p&gt;&lt;code&gt;Before Alembic touches anything, manually update the table:&lt;/code&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Then run your migration.&lt;/li&gt;
&lt;li&gt;Old rows are ready, and PostgreSQL doesn’t throw a tantrum.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Moral of the Story
&lt;/h4&gt;

&lt;p&gt;Adding a &lt;code&gt;NOT NULL&lt;/code&gt; column to a table with existing rows is like adding a new rule to a crowded party: someone will get upset if you don’t provide a plan. Always think about existing data. Give PostgreSQL a default, update the old rows, or do both.&lt;/p&gt;

&lt;p&gt;And remember: Alembic errors might look scary, but they’re really just your database’s way of saying:&lt;br&gt;
&lt;code&gt;“Hey, I love your data too much to let it break. Let’s do this right.”&lt;/code&gt;&lt;/p&gt;

</description>
      <category>psqlalchemy</category>
      <category>alembic</category>
      <category>postgres</category>
      <category>database</category>
    </item>
    <item>
      <title>How to set-up a CI/CD environment on Gitlab using NodeJs</title>
      <dc:creator>Anthony Nwaizuzu</dc:creator>
      <pubDate>Wed, 06 Feb 2019 01:16:18 +0000</pubDate>
      <link>https://dev.to/cuddi/how-to-set-up-a-cicd-environment-on-gitlab-using-nodejs-jh3</link>
      <guid>https://dev.to/cuddi/how-to-set-up-a-cicd-environment-on-gitlab-using-nodejs-jh3</guid>
      <description>&lt;p&gt;So I decided to start my first article on dev.to by discussing how to set-up Continuous Integration (CI) and Continuous Delivery (CD), feedback is welcome it helps!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F866hyeljqrx49q63hnqy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F866hyeljqrx49q63hnqy.gif" width="480" height="270"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Continuous Integration (CI) is a practice that requires developers to integrate code into a shared repository several times. Each check-in is then verified by an automated build, allowing teams to detect problems to fix early.&lt;/p&gt;

&lt;p&gt;Continuous Delivery (CD) is a software engineering approach in which continuous integration, automated testing, and automated deployment capabilities allow software to be developed and deployed with minimal human intervention.&lt;/p&gt;

&lt;p&gt;Having a proper CI/CD environment will enable bugs to be caught earlier and developers can review code faster and fix it.&lt;/p&gt;

&lt;p&gt;By the end of this article, you will have the basic understanding on how to set up a CI/CD environment on Gitlab.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 1: Create a Project on Gitlab
&lt;/h3&gt;

&lt;p&gt;Gitlab is a web-based Git-repository manager, where code can be hosted. Sign up for an account if you do not have one, or log into your existing account if you already have an account. Create a repository, you can name it anything you like, you can also choose to either make the repository public or private. A public repository is accessible to the public through search or direct access using the project’s URL, conversely, a private repository is only accessible to members invited to the repository by the Owner or Maintainer. &lt;/p&gt;

&lt;h3&gt;
  
  
  Step 2: Setting up your CI environment
&lt;/h3&gt;

&lt;p&gt;To setup a CI environment, you will need to create a file named &lt;code&gt;.gitlab-ci.yml&lt;/code&gt;  and it should be in the root of your repository.&lt;/p&gt;

&lt;p&gt;This file contains a steps by step description on how your project will be built. The Gitlab runner will search for this file in your repository and execute it. GitLab CI looks for this particular file within your repository to determine how it should test the code.&lt;/p&gt;

&lt;p&gt;You can create this file through your already created Gitlab project or via your terminal. I will be using terminal in this tutorial. I love my bash commands😏😏&lt;/p&gt;

&lt;p&gt;Open your terminal and move to the directory where the project file is located then create a file named  &lt;code&gt;.gitlab-ci.yml&lt;/code&gt; by doing this:-&lt;/p&gt;

&lt;p&gt;&lt;code&gt;$ touch .gitlab-ci.yml&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Next we have to edit the &lt;code&gt;.gitlab-ci.yml&lt;/code&gt; file so we can create our CI configuration by doing this:-&lt;/p&gt;

&lt;p&gt;&lt;code&gt;$ nano .gitlab-ci.yml&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;The CI configuration will look like this and should be inside your &lt;code&gt;.gitlab-ci.yml&lt;/code&gt; file:-&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;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;node:latest&lt;/span&gt;

    &lt;span class="na"&gt;stages&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;build&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;test&lt;/span&gt;

    &lt;span class="na"&gt;cache&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;paths&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;node_modules/&lt;/span&gt;

    &lt;span class="na"&gt;install_dependencies&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;stage&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;build&lt;/span&gt;
      &lt;span class="na"&gt;script&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;npm install&lt;/span&gt;
      &lt;span class="na"&gt;artifacts&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;paths&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;node_modules/&lt;/span&gt;

    &lt;span class="na"&gt;testing_testing&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;stage&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;test&lt;/span&gt;
      &lt;span class="na"&gt;script&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;npm test&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let’s understand what the above snippet is all about&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fec9ru9rl39blzvcrste5.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fec9ru9rl39blzvcrste5.gif" width="450" height="253"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The configuration file starts by declaring a docker image that allows you to specify a certain version of NodeJS you want to use during build time.&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;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;node:latest&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, we define the different continuous integration process it will run.&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;stages&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;build&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;test&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we’ve defined the stages, the configuration includes a &lt;code&gt;cache&lt;/code&gt;  that specifies files that should be saved for later to be used between runs or stages.&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;cache&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;paths&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;node_modules/&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next is &lt;code&gt;install_dependencies&lt;/code&gt;,  in the process of  demonstrating the interaction between stages, we are extracting this step to run its own stage. Typically, running  &lt;code&gt;npm install&lt;/code&gt; can be combined with the next testing stages.&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;install_dependencies&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;stage&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;build&lt;/span&gt;
      &lt;span class="na"&gt;script&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;npm install&lt;/span&gt;
      &lt;span class="na"&gt;artifacts&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;paths&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;node_modules/&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Lastly,  &lt;code&gt;testing_testing&lt;/code&gt; declares the command that will run the test suit, Since this is the last stage, it will access what is been produced by the &lt;code&gt;build&lt;/code&gt; stage, which are the project dependencies in our case.&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;testing_testing&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;stage&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;test&lt;/span&gt;
      &lt;span class="na"&gt;script&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;npm test&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Oh yea, &lt;code&gt;testing_testing&lt;/code&gt; is just a name I used, you can name it anything you want.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 3: Installing Gitlab Runner
&lt;/h3&gt;

&lt;p&gt;Since our repository includes a &lt;code&gt;.gitlab-ci.yml&lt;/code&gt; file, any new commits will trigger a new CI run. If no runners are available, the CI run will be set to "pending".&lt;/p&gt;

&lt;p&gt;As mentioned, in GitLab, Runners run the jobs that you define in &lt;code&gt;.gitlab-ci.yml&lt;/code&gt;. I will be following the instructions &lt;a href="https://docs.gitlab.com/runner/install/osx.html" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 4: Register the Gitlab Runner
&lt;/h3&gt;

&lt;p&gt;Next, register the Gitlab Runner by following instructions &lt;a href="https://docs.gitlab.com/runner/register/index.html" rel="noopener noreferrer"&gt;here&lt;/a&gt;. &lt;br&gt;
Running the runner executor on shell is the easiest to setup, so after registration, install and start the service with this commands:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;$ gitlab-runner install&lt;br&gt;
 $ gitlab-runner start&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;To be sure your runner is running run this command:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;$ gitlab-runner status&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;If you see this:  &lt;code&gt;gitlab-runner: Service is running!&lt;/code&gt; and the green tick on the project you created on gitlab&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fc67echrg9t3pg34r6zni.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fc67echrg9t3pg34r6zni.png" alt="Alt gitlab screenshot" width="800" height="50"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;Hopefully this article has widen the borders of Gitlab CI/CD and enriched your understanding and like I said earlier feedback is welcome and just in case I missed something kindly notify me.&lt;/p&gt;

</description>
      <category>gitlab</category>
      <category>node</category>
      <category>ci</category>
      <category>intro</category>
    </item>
  </channel>
</rss>
