<?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: Pete Miloravac</title>
    <description>The latest articles on DEV Community by Pete Miloravac (@pete_miloravac).</description>
    <link>https://dev.to/pete_miloravac</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%2F3890709%2F8969b6a9-ab0d-4a1b-8333-635214a96324.png</url>
      <title>DEV Community: Pete Miloravac</title>
      <link>https://dev.to/pete_miloravac</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/pete_miloravac"/>
    <language>en</language>
    <item>
      <title>What CI/CD strategies work for embedded or IoT projects that require hardware testing?</title>
      <dc:creator>Pete Miloravac</dc:creator>
      <pubDate>Thu, 30 Apr 2026 10:48:53 +0000</pubDate>
      <link>https://dev.to/semaphore/what-cicd-strategies-work-for-embedded-or-iot-projects-that-require-hardware-testing-39p2</link>
      <guid>https://dev.to/semaphore/what-cicd-strategies-work-for-embedded-or-iot-projects-that-require-hardware-testing-39p2</guid>
      <description>&lt;p&gt;Embedded and IoT teams face a very different CI/CD reality than traditional SaaS teams. While most continuous integration and continuous delivery pipelines assume everything can run in the cloud, embedded systems depend on physical hardware, constrained environments, and real world signals.&lt;/p&gt;

&lt;p&gt;If you search forums like Reddit (r/embedded, r/devops), Stack Overflow, or vendor communities, the same questions keep appearing:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;How do I run CI tests when I need actual hardware?&lt;/li&gt;
&lt;li&gt;How do I scale hardware testing across teams?&lt;/li&gt;
&lt;li&gt;How do I avoid flaky tests caused by devices?&lt;/li&gt;
&lt;li&gt;Can I still use modern CI/CD tools or do I need something custom?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This guide walks through practical CI/CD strategies used by engineering teams building firmware, IoT platforms, and hardware dependent systems. It focuses on approaches that scale, reduce cost, and maintain reliability.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why CI/CD is harder for embedded and IoT projects
&lt;/h2&gt;

&lt;p&gt;Unlike pure software systems, embedded pipelines must deal with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Physical device availability&lt;/li&gt;
&lt;li&gt;Hardware state and reset issues&lt;/li&gt;
&lt;li&gt;Long flashing and boot cycles&lt;/li&gt;
&lt;li&gt;Non deterministic behavior (timing, sensors, connectivity)&lt;/li&gt;
&lt;li&gt;Limited parallelization&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This creates a mismatch with traditional CI/CD platforms that expect fast, stateless, fully virtualized execution.&lt;/p&gt;

&lt;p&gt;For engineering leaders, this often results in slower pipelines, higher costs, and fragile automation. The goal is not to force cloud native assumptions onto hardware, but to design a hybrid pipeline.&lt;/p&gt;

&lt;h2&gt;
  
  
  The core strategy: split your pipeline by test layers
&lt;/h2&gt;

&lt;p&gt;The most effective approach seen across teams is to separate tests into layers, minimizing hardware usage to only what is necessary.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Fast feedback layer (no hardware)
&lt;/h3&gt;

&lt;p&gt;Run as much as possible without devices:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Unit tests for firmware logic&lt;/li&gt;
&lt;li&gt;Static analysis (clang tidy, cppcheck)&lt;/li&gt;
&lt;li&gt;Build validation&lt;/li&gt;
&lt;li&gt;Simulation or emulation (QEMU, Renode)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Example Semaphore pipeline block:&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;version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;v1.0&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;Firmware CI&lt;/span&gt;

&lt;span class="na"&gt;blocks&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;Build and unit tests&lt;/span&gt;
    &lt;span class="na"&gt;task&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;jobs&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;Build&lt;/span&gt;
          &lt;span class="na"&gt;commands&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;checkout&lt;/span&gt;
            &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;make build&lt;/span&gt;
            &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;make test&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This layer should cover 70 to 90 percent of your test surface. It keeps pipelines fast and cost effective.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Hardware in the loop testing (HIL)
&lt;/h3&gt;

&lt;p&gt;Only after passing fast checks should jobs use real devices.&lt;/p&gt;

&lt;p&gt;Typical setup discussed in forums:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;USB connected device farms&lt;/li&gt;
&lt;li&gt;Network controlled power switches&lt;/li&gt;
&lt;li&gt;Raspberry Pi or similar acting as device controllers&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Example structure:&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="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;Hardware tests&lt;/span&gt;
    &lt;span class="na"&gt;task&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;prologue&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;commands&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;checkout&lt;/span&gt;
      &lt;span class="na"&gt;jobs&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;Run on device farm&lt;/span&gt;
          &lt;span class="na"&gt;commands&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;./scripts/flash_device.sh&lt;/span&gt;
            &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;./scripts/run_integration_tests.sh&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With Semaphore, you can integrate self hosted agents that have direct access to hardware, allowing your pipeline to orchestrate physical tests while keeping control centralized.&lt;/p&gt;

&lt;p&gt;This hybrid model is critical for teams that have outgrown default CI tools that cannot reliably interface with hardware.&lt;/p&gt;

&lt;h2&gt;
  
  
  Designing a reliable device farm
&lt;/h2&gt;

&lt;p&gt;A common pain point across discussions is flaky hardware tests. The root cause is usually poor device management.&lt;/p&gt;

&lt;p&gt;Best practices:&lt;/p&gt;

&lt;h3&gt;
  
  
  Isolate devices per job
&lt;/h3&gt;

&lt;p&gt;Avoid shared hardware when possible. If sharing is required, implement locking mechanisms.&lt;/p&gt;

&lt;h3&gt;
  
  
  Automate reset and recovery
&lt;/h3&gt;

&lt;p&gt;Use:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Smart power switches&lt;/li&gt;
&lt;li&gt;USB relay boards&lt;/li&gt;
&lt;li&gt;Watchdog scripts&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Example reset script:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#!/bin/bash&lt;/span&gt;
&lt;span class="c"&gt;# Power cycle device&lt;/span&gt;
curl http://power-switch.local/off
&lt;span class="nb"&gt;sleep &lt;/span&gt;2
curl http://power-switch.local/on
&lt;span class="nb"&gt;sleep &lt;/span&gt;5
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Make tests idempotent
&lt;/h3&gt;

&lt;p&gt;Each test run should not depend on previous device state.&lt;/p&gt;

&lt;h3&gt;
  
  
  Collect logs externally
&lt;/h3&gt;

&lt;p&gt;Stream logs via serial or network so failures can be diagnosed post run.&lt;/p&gt;

&lt;h2&gt;
  
  
  Orchestrating hardware with CI/CD
&lt;/h2&gt;

&lt;p&gt;One of the biggest questions teams ask is: how do I connect CI/CD pipelines to real devices?&lt;/p&gt;

&lt;p&gt;The most robust approach is:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Use cloud CI/CD for orchestration&lt;/li&gt;
&lt;li&gt;Use self hosted runners or agents for hardware interaction&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;With Semaphore, this means:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Running standard pipeline steps in the cloud&lt;/li&gt;
&lt;li&gt;Routing hardware jobs to agents inside your lab&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This keeps pipelines fast while maintaining control over physical infrastructure.&lt;/p&gt;

&lt;h2&gt;
  
  
  Handling test flakiness and timing issues
&lt;/h2&gt;

&lt;p&gt;Forum discussions consistently highlight flaky tests as a major blocker.&lt;/p&gt;

&lt;p&gt;Strategies that work:&lt;/p&gt;

&lt;h3&gt;
  
  
  Add retry logic at the pipeline level
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;retry&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;limit&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Add health checks before tests
&lt;/h3&gt;

&lt;p&gt;Ensure device is reachable and responsive before running tests.&lt;/p&gt;

&lt;h3&gt;
  
  
  Use time budgets instead of strict timing
&lt;/h3&gt;

&lt;p&gt;Avoid asserting exact timing unless necessary.&lt;/p&gt;

&lt;h3&gt;
  
  
  Tag and isolate flaky tests
&lt;/h3&gt;

&lt;p&gt;Run them separately to avoid blocking the main pipeline.&lt;/p&gt;

&lt;h2&gt;
  
  
  Parallelizing hardware testing
&lt;/h2&gt;

&lt;p&gt;Scaling is a key concern for engineering managers.&lt;/p&gt;

&lt;p&gt;Options include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Expanding device farms&lt;/li&gt;
&lt;li&gt;Sharding tests across devices&lt;/li&gt;
&lt;li&gt;Prioritizing critical test subsets&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Example:&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;jobs&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;Device &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;
    &lt;span class="na"&gt;commands&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;./run_tests.sh --group=1&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;Device &lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;
    &lt;span class="na"&gt;commands&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;./run_tests.sh --group=2&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Semaphore allows parallel job execution, which is especially valuable when coordinating multiple hardware nodes.&lt;/p&gt;

&lt;h2&gt;
  
  
  Cost optimization strategies
&lt;/h2&gt;

&lt;p&gt;Hardware pipelines can become expensive quickly.&lt;/p&gt;

&lt;p&gt;Key tactics:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Maximize non hardware test coverage&lt;/li&gt;
&lt;li&gt;Use on demand hardware instead of always on&lt;/li&gt;
&lt;li&gt;Optimize pipeline duration&lt;/li&gt;
&lt;li&gt;Avoid rerunning full hardware suites unnecessarily&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Engineering teams often switch CI/CD platforms when costs become unpredictable or tied to inefficient pipelines. A system that allows fine grained control over execution and resource usage is critical.&lt;/p&gt;

&lt;h2&gt;
  
  
  When to consider custom tooling vs CI/CD platforms
&lt;/h2&gt;

&lt;p&gt;Many teams ask whether they should build their own system.&lt;/p&gt;

&lt;p&gt;Build custom only if:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Your workflow is highly specialized&lt;/li&gt;
&lt;li&gt;You require deep hardware orchestration beyond standard pipelines&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Otherwise, modern CI/CD platforms like Semaphore can handle orchestration while letting you customize the hardware layer.&lt;/p&gt;

&lt;p&gt;This balance avoids reinventing core CI/CD capabilities while still supporting embedded workflows.&lt;/p&gt;

&lt;h2&gt;
  
  
  Putting it all together
&lt;/h2&gt;

&lt;p&gt;A production ready embedded CI/CD pipeline typically looks like:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Code commit triggers pipeline&lt;/li&gt;
&lt;li&gt;Build and unit tests run in parallel&lt;/li&gt;
&lt;li&gt;Simulation tests validate behavior&lt;/li&gt;
&lt;li&gt;Hardware tests run on device farm via self hosted agents&lt;/li&gt;
&lt;li&gt;Results aggregated and reported&lt;/li&gt;
&lt;li&gt;Deployment triggered if all checks pass&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This structure aligns with how high performing engineering teams reduce risk while maintaining delivery speed.&lt;/p&gt;

&lt;h2&gt;
  
  
  FAQs
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;How do I run CI tests on real hardware?&lt;/strong&gt; &lt;/p&gt;

&lt;p&gt;Use a device farm connected to self hosted CI agents. The pipeline triggers scripts that flash firmware and execute tests on physical devices.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What tools are commonly used for hardware testing in CI?&lt;/strong&gt; &lt;/p&gt;

&lt;p&gt;Teams commonly use QEMU or Renode for simulation, and custom scripts combined with device controllers for real hardware testing.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How do I reduce flaky tests in IoT CI/CD?&lt;/strong&gt; &lt;/p&gt;

&lt;p&gt;Focus on device reset automation, idempotent tests, retries, and proper health checks before execution.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Can CI/CD pipelines scale with hardware constraints?&lt;/strong&gt; &lt;/p&gt;

&lt;p&gt;Yes, by parallelizing across device farms and minimizing reliance on hardware through simulation and unit testing.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Is CI/CD worth it for embedded systems?&lt;/strong&gt; &lt;/p&gt;

&lt;p&gt;Yes. Teams that invest in CI/CD for embedded systems see improvements in reliability, faster debugging, and more predictable releases.&lt;/p&gt;

&lt;p&gt;The post &lt;a href="https://semaphore.io/what-ci-cd-strategies-work-for-embedded-or-iot-projects-that-require-hardware-testing" rel="noopener noreferrer"&gt;What CI/CD strategies work for embedded or IoT projects that require hardware testing?&lt;/a&gt; appeared first on &lt;a href="https://semaphore.io" rel="noopener noreferrer"&gt;Semaphore&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>cicd</category>
    </item>
    <item>
      <title>How to Manage CI/CD for Game Development (Unity, Unreal, Large Binaries)</title>
      <dc:creator>Pete Miloravac</dc:creator>
      <pubDate>Fri, 27 Mar 2026 10:43:02 +0000</pubDate>
      <link>https://dev.to/pete_miloravac/how-to-manage-cicd-for-game-development-unity-unreal-large-binaries-4hd4</link>
      <guid>https://dev.to/pete_miloravac/how-to-manage-cicd-for-game-development-unity-unreal-large-binaries-4hd4</guid>
      <description>&lt;p&gt;Game development teams face a very different CI/CD reality than traditional SaaS engineering teams. Instead of small, stateless builds, you’re dealing with gigabytes of assets, long build times, platform-specific toolchains, and fragile pipelines that often break under scale.&lt;/p&gt;

&lt;p&gt;If you’ve ever searched for this topic on forums like Reddit, Stack Overflow, or Unreal/Unity communities, the same patterns emerge:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;“Our builds take hours—how do we speed this up?”&lt;/li&gt;
&lt;li&gt;“How do we version large assets in CI?”&lt;/li&gt;
&lt;li&gt;“Why does Unity/Unreal behave differently in CI than locally?”&lt;/li&gt;
&lt;li&gt;“How do we cache dependencies and avoid re-importing everything?”&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This guide walks through how to design a CI/CD pipeline for game development that is fast, reliable, and cost-efficient—without relying on brittle workarounds.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why CI/CD is Harder for Game Development
&lt;/h2&gt;

&lt;p&gt;Unlike typical web services, game pipelines introduce three unique challenges:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Large Binary Assets
&lt;/h3&gt;

&lt;p&gt;Game projects include textures, audio, models, and compiled assets that don’t behave well with traditional Git workflows.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Heavy Build Steps
&lt;/h3&gt;

&lt;p&gt;Unity and Unreal builds involve asset import, shader compilation, and platform packaging—often taking 30–120 minutes.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Environment Sensitivity
&lt;/h3&gt;

&lt;p&gt;Builds depend on specific engine versions, OS configurations, GPU drivers, and SDKs.&lt;/p&gt;

&lt;p&gt;This means your CI/CD pipeline must optimize for caching, reproducibility, and parallelization—not just correctness.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 1: Structure Your Repository for CI/CD
&lt;/h2&gt;

&lt;p&gt;The biggest mistake teams make is treating game repos like standard application repos.&lt;/p&gt;

&lt;h3&gt;
  
  
  Use Git LFS for Large Files
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git lfs track &lt;span class="s2"&gt;"*.psd"&lt;/span&gt;
git lfs track &lt;span class="s2"&gt;"*.fbx"&lt;/span&gt;
git lfs track &lt;span class="s2"&gt;"*.wav"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Without LFS, your CI pipeline will choke on clone times and storage.&lt;/p&gt;

&lt;h3&gt;
  
  
  Separate Code and Assets (When Possible)
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Core game logic → standard Git repo&lt;/li&gt;
&lt;li&gt;Large assets → LFS or external storage (S3, artifact storage)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This reduces pipeline overhead and improves caching efficiency.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 2: Use Deterministic Build Environments
&lt;/h2&gt;

&lt;p&gt;Forum discussions frequently highlight “works locally but not in CI” issues for Unity/Unreal.&lt;/p&gt;

&lt;p&gt;The root cause is almost always environment drift.&lt;/p&gt;

&lt;h3&gt;
  
  
  Solution: Containerized or Prebuilt Environments
&lt;/h3&gt;

&lt;p&gt;For example, using a Docker-based Unity build:&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;version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;v1.0&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;Unity Build Pipeline&lt;/span&gt;

&lt;span class="na"&gt;agent&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;machine&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;e1-standard-4&lt;/span&gt;
    &lt;span class="na"&gt;os_image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu2004&lt;/span&gt;

&lt;span class="na"&gt;blocks&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;Build&lt;/span&gt;
    &lt;span class="na"&gt;task&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;jobs&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;Unity Build&lt;/span&gt;
          &lt;span class="na"&gt;commands&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;checkout&lt;/span&gt;
            &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;./ci/install-unity.sh&lt;/span&gt;
            &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;./ci/build.sh&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Key idea: lock Unity/Unreal versions and dependencies.&lt;/p&gt;

&lt;p&gt;For Unreal, you might pre-bake images with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Unreal Engine installed&lt;/li&gt;
&lt;li&gt;Required SDKs (Android, iOS, etc.)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Step 3: Cache Aggressively (This Is Non-Negotiable)
&lt;/h2&gt;

&lt;p&gt;The #1 complaint across forums: “CI rebuilds everything every time.”&lt;/p&gt;

&lt;h3&gt;
  
  
  Cache Unity Library Folder
&lt;/h3&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;Library&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This avoids re-importing assets on every build.&lt;/p&gt;

&lt;h3&gt;
  
  
  Cache Unreal Derived Data Cache (DDC)
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;export &lt;/span&gt;UE-SharedDataCachePath&lt;span class="o"&gt;=&lt;/span&gt;/cache/ue-ddc
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This dramatically reduces shader compilation time.&lt;/p&gt;

&lt;h3&gt;
  
  
  Use Remote Caching
&lt;/h3&gt;

&lt;p&gt;For distributed teams, store caches in shared storage (S3 or CI-native cache).&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 4: Parallelize Builds Across Platforms
&lt;/h2&gt;

&lt;p&gt;Game teams often target multiple platforms:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Windows&lt;/li&gt;
&lt;li&gt;macOS&lt;/li&gt;
&lt;li&gt;iOS&lt;/li&gt;
&lt;li&gt;Android&lt;/li&gt;
&lt;li&gt;Consoles&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Running these sequentially kills productivity.&lt;/p&gt;

&lt;h3&gt;
  
  
  Example Parallel Pipeline
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;blocks&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;Build Matrix&lt;/span&gt;
    &lt;span class="na"&gt;task&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;jobs&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;Windows Build&lt;/span&gt;
          &lt;span class="na"&gt;commands&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-windows.sh&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;Android Build&lt;/span&gt;
          &lt;span class="na"&gt;commands&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-android.sh&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;iOS Build&lt;/span&gt;
          &lt;span class="na"&gt;commands&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-ios.sh&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Parallelization is one of the fastest ways to reduce total pipeline time.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 5: Manage Artifacts Efficiently
&lt;/h2&gt;

&lt;p&gt;Game builds produce large outputs (often multiple GBs).&lt;/p&gt;

&lt;h3&gt;
  
  
  Best Practices
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Store artifacts outside the CI workspace&lt;/li&gt;
&lt;li&gt;Use artifact versioning&lt;/li&gt;
&lt;li&gt;Expire old builds automatically&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Example:&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;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;build/&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For large studios, push builds to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;S3&lt;/li&gt;
&lt;li&gt;CDN&lt;/li&gt;
&lt;li&gt;Internal distribution systems&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Step 6: Automate Testing (Even for Games)
&lt;/h2&gt;

&lt;p&gt;A common misconception: “Games are hard to test in CI.”&lt;/p&gt;

&lt;p&gt;But modern pipelines support:&lt;/p&gt;

&lt;h3&gt;
  
  
  Unity Test Runner
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;/Applications/Unity/Hub/Editor/Unity &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-runTests&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-testPlatform&lt;/span&gt; PlayMode &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-projectPath&lt;/span&gt; &lt;span class="nb"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Unreal Automation Framework
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;RunUAT BuildCookRun &lt;span class="nt"&gt;-RunAutomationTests&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Even partial test coverage dramatically improves confidence.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 7: Control Costs and Scale Intelligently
&lt;/h2&gt;

&lt;p&gt;Game CI/CD pipelines are expensive by default.&lt;/p&gt;

&lt;p&gt;Common issues raised by engineering leaders:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;“We’re paying too much for idle build agents”&lt;/li&gt;
&lt;li&gt;“Scaling builds is unpredictable”&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Strategies
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Use autoscaling runners&lt;/li&gt;
&lt;li&gt;Avoid over-provisioning&lt;/li&gt;
&lt;li&gt;Cache to reduce compute time&lt;/li&gt;
&lt;li&gt;Use pay-per-use CI/CD platforms&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is where teams outgrow default tools like Jenkins or basic GitHub Actions setups.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 8: Handle Long Build Times with Pipeline Design
&lt;/h2&gt;

&lt;p&gt;Instead of one monolithic pipeline, split workflows:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Fast checks (lint, unit tests) → run on every commit&lt;/li&gt;
&lt;li&gt;Full builds → run on merge or nightly&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Example:&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;pipeline&lt;/span&gt;&lt;span class="pi"&gt;:&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;quick-checks&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;full-build&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This keeps feedback loops tight while still validating full builds.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 9: Debugging CI Failures in Game Pipelines
&lt;/h2&gt;

&lt;p&gt;From forum discussions, common failure causes include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Missing licenses (Unity)&lt;/li&gt;
&lt;li&gt;Incorrect SDK versions&lt;/li&gt;
&lt;li&gt;Asset import failures&lt;/li&gt;
&lt;li&gt;Path length issues (Windows)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Add Debug Visibility
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;set&lt;/span&gt; &lt;span class="nt"&gt;-x&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And always log:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Engine version&lt;/li&gt;
&lt;li&gt;Build parameters&lt;/li&gt;
&lt;li&gt;Environment variables&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Step 10: Choosing the Right CI/CD Platform
&lt;/h2&gt;

&lt;p&gt;Game development pushes CI/CD tools to their limits.&lt;/p&gt;

&lt;p&gt;Engineering leaders should evaluate:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Performance with large repositories&lt;/li&gt;
&lt;li&gt;Caching capabilities&lt;/li&gt;
&lt;li&gt;Parallel execution&lt;/li&gt;
&lt;li&gt;Cost predictability&lt;/li&gt;
&lt;li&gt;Ease of environment setup&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Modern platforms like Semaphore are designed for teams that have outgrown default tools, offering:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Fast pipelines&lt;/li&gt;
&lt;li&gt;Flexible caching&lt;/li&gt;
&lt;li&gt;Pay-per-use pricing&lt;/li&gt;
&lt;li&gt;Strong support for custom workflows&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Putting It All Together
&lt;/h2&gt;

&lt;p&gt;A production-ready game CI/CD pipeline should:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Use Git LFS or external storage for assets&lt;/li&gt;
&lt;li&gt;Cache aggressively (Unity Library, Unreal DDC)&lt;/li&gt;
&lt;li&gt;Run builds in parallel&lt;/li&gt;
&lt;li&gt;Use deterministic environments&lt;/li&gt;
&lt;li&gt;Split pipelines for faster feedback&lt;/li&gt;
&lt;li&gt;Optimize for cost and scale&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This isn’t just about automation—it’s about enabling your team to ship faster without increasing infrastructure complexity.&lt;/p&gt;

&lt;h2&gt;
  
  
  FAQs
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Why are Unity builds so slow in CI?&lt;/strong&gt; &lt;/p&gt;

&lt;p&gt;Because asset import and shader compilation are expensive. Without caching (Library folder), CI rebuilds everything from scratch.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How do I reduce Unreal build times?&lt;/strong&gt; &lt;/p&gt;

&lt;p&gt;Use a shared Derived Data Cache (DDC), prebuilt engine images, and parallel builds.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Should I store game assets in Git?&lt;/strong&gt; &lt;/p&gt;

&lt;p&gt;Yes, but use Git LFS or external storage. Standard Git is not optimized for large binaries.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How do I debug CI-only failures?&lt;/strong&gt; &lt;/p&gt;

&lt;p&gt;Ensure environment parity, log all build parameters, and verify engine and SDK versions match local setups.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What’s the biggest mistake teams make?&lt;/strong&gt; &lt;/p&gt;

&lt;p&gt;Treating game CI/CD like web CI/CD. Game pipelines require different optimization strategies—especially around caching and artifacts.&lt;/p&gt;

&lt;p&gt;The post &lt;a href="https://semaphore.io/how-to-manage-ci-cd-for-game-development-unity,-unreal,-large-binaries" rel="noopener noreferrer"&gt;How to Manage CI/CD for Game Development (Unity, Unreal, Large Binaries)&lt;/a&gt; appeared first on &lt;a href="https://semaphore.io" rel="noopener noreferrer"&gt;Semaphore&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>cicd</category>
    </item>
  </channel>
</rss>
