CI/CD for Hardware-Heavy Companies: Why It Matters and How to Use GitLab Runners
Even if your company’s main products are physical hardware, chances are you have a lot of software behind the scenes. In fact, in today’s digital world “every company is a software business, irrespective of the industry it is in” (12 Business Benefits of CI/CD | A CI/CD Overview).
This means hardware-focused organizations also need to deliver software updates (for firmware, internal tools, user applications, etc.) quickly and reliably. That’s where CI/CD (Continuous Integration / Continuous Deployment) comes in. CI/CD is a set of practices and tools that automate the software build, test, and release process, helping teams integrate and ship code changes more frequently and reliably.
In this post, we’ll explore how CI/CD benefits even hardware-heavy companies, and how we set up a cross-platform GitLab CI/CD pipeline (with Linux, macOS, and Windows runners) to speed up development and standardize our delivery process.
What is CI/CD and Why Should Hardware Companies Care?
Continuous Integration (CI) is the practice of frequently merging code changes into a shared repository, running automated builds and tests to catch issues early.
Continuous Deployment (CD) automates releasing those validated changes to environments or end-users. Together, CI/CD forms an automated pipeline that takes code from commit to production with minimal human intervention. The key idea is automation: as code changes progress through development, CI/CD ensures that every change is built, tested, and delivered in a consistent way.
Why does this matter for a hardware-centric company? Simply put, reliable software processes improve everything. Even if you build physical devices, you likely have supporting software (device firmware, control software, manufacturing tools, customer apps) that needs constant updates. Adopting CI/CD brings the same advantages that software companies enjoy to your hardware company’s software development.
The bottom line: modern hardware products often live or die by the quality and speed of their software updates, so a robust CI/CD pipeline is a huge asset.
Benefits of CI/CD: Speed, Reliability, and Standardized Delivery
Implementing CI/CD can transform your development cycle. Some key benefits include:
-
Improved Reliability: Automation reduces the chance of human error. Every code change goes through the same tested process, which means fewer “it works on my machine” problems. Issues are caught earlier through automated tests, so by the time something is delivered, it’s far more stable. This rigorous approach leads to more reliable software releases (and by extension, more reliable hardware behavior when that software controls devices).
-
Faster Development Cycles: With CI/CD, builds and tests run automatically on each commit, giving developers quick feedback. Instead of waiting days for a manual build or a tester to verify a change, you get results in hours or minutes. Parallelization allows multiple jobs to run on different platforms simultaneously, accelerating overall build times. For example, our team saw significantly faster build times for our Python-based tools once we enabled caching in the pipeline – tasks that used to be slow (like installing dependencies or compiling parts of the code) are now much quicker (also thanks to using clever tools such as uv. Faster feedback and shorter build times mean developers can iterate rapidly and try out improvements without long delays.
-
Standardized Delivery: CI/CD enforces a repeatable process for packaging and delivering software. Whether the target is a Linux server, a Mac application, or a Windows executable (and in all flavors of x86 to ARM64…), the pipeline uses version-controlled scripts to build and package it in a consistent manner. This standardization means every release follows the same steps and quality checks. It becomes easier to support multiple platforms because you’re not crafting one-off build procedures for each; the CI/CD pipeline orchestrates all of them with the same high-level workflow. In turn, customers or end-users get a uniform experience (e.g. a consistent version numbering and quality across platforms).
Cross-Platform CI Pipeline with GitLab Runners (Linux, macOS, Windows)
One big challenge for us was ensuring our software builds and runs on multiple operating systems. We support Linux, macOS, and Windows environments. With GitLab CI/CD, we solved this by using self-hosted GitLab runners on each platform. GitLab’s architecture separates the CI/CD coordination (handled by the GitLab server) from the execution (handled by runners). GitLab uses “runners” to execute CI jobs, and you can install runners on any machine or VM you want to use for builds. Each runner registers with the GitLab CI server and is assigned a tag (or multiple tags) to identify its platform or purpose. In our setup, we configured runners for all three major OS platforms:
-
Linux runners – running inside LXC containers on a Proxmox virtualization server. We use Proxmox (an open-source hypervisor) to host lightweight LXC containers that act as isolated Linux build agents. This allows us to easily spin up clean Linux environments for CI jobs. The Linux runner is tagged
linux
in GitLab, so any job that needs a Linux environment will run in one of these containers. Using containers gives us reproducible Linux environments and easy scalability (we can launch multiple container runners if we need parallel Linux jobs). -
macOS runners – running on a dedicated Mac Mini. Since macOS requires Apple hardware, we have a Mac Mini in-house that serves as our macOS build machine. We installed the GitLab Runner agent on this Mac Mini and tagged it as
macos
. This runner picks up jobs that require Mac-specific building or testing (for example, building a .app bundle or running unit tests that use macOS frameworks). Having a macOS runner ensures our pipeline can build and verify Mac software artifacts just like it does for Linux, using the same GitLab CI definitions. (As an alternative, one could use cloud Mac runners, but an on-premise Mac Mini is cost-effective for us and keeps everything in-house.) -
Windows runners – running on a dedicated Windows machine. We also set up a Windows 11 (could also be a Windows Server) machine with the GitLab Runner installed, tagged as
windows
. This machine performs CI jobs that need a Windows environment, such as building a Windows installer or running tests that depend on Windows-only libraries. The runner uses the shell executor on Windows to run batch scripts or PowerShell commands as defined in the CI jobs. By having a dedicated Windows runner, our pipeline covers the last major platform in our support matrix, ensuring we don’t treat Windows builds as a manual afterthought.
With this infrastructure, every commit triggers a pipeline that includes jobs for Linux, macOS, and Windows. GitLab will route each job to the appropriate runner based on the tags. For instance, a job tagged with windows
will only run on our Windows runner, and so on. All three platforms run in parallel, so we get build/test results roughly at the same time. This setup has dramatically improved our confidence that a change won’t break platform-specific functionality—if something fails on Windows but passes on Linux, the pipeline will immediately flag it so we can fix the issue before merging.
Example GitLab CI Configuration for Multiple Platforms
So, how does one configure a single pipeline to build for all these platforms? GitLab CI allows you to specify multiple jobs (even in the same stage) and use tags to pin them to certain runners. Here’s a simplified example of a .gitlab-ci.yml
snippet that illustrates a cross-platform pipeline:
stages:
- build
# Job for Linux
build_linux:
stage: build
tags: [ "linux" ] # will run on runner tagged 'linux'
script:
- echo "Building on Linux..."
# Place Linux build commands here (e.g., make, docker build, etc.)
# Job for macOS
build_macos:
stage: build
tags: [ "macos" ] # will run on runner tagged 'macos'
script:
- echo "Building on macOS..."
# Place macOS build commands here (e.g., xcodebuild, pkgbuild, etc.)
# Job for Windows
build_windows:
stage: build
tags: [ "windows" ] # will run on runner tagged 'windows'
script:
- echo "Building on Windows..."
# Place Windows build commands here (e.g., MSBuild, npm install, etc.)
In this example, we define three jobs (build_linux
, build_macos
, and build_windows
), all in the build stage. Since they share the stage, GitLab will run them in parallel (assuming runners are available). Each job uses a tags
attribute to ensure it runs on the correct runner: for instance, build_macos
will only run on a runner that has the tag “macos” (which we assigned to our Mac Mini runner during registration). The script
section of each job contains the platform-specific build steps. In a real pipeline, you could add subsequent stages like testing or deployment, and similarly have jobs per platform if needed (e.g., platform-specific tests). The key takeaway is that one .gitlab-ci.yml
can orchestrate all your multi-OS builds in one go, giving you a unified pipeline for multiple environments.
Putting It All Together: CI Pipeline Architecture
Conclusion
Adopting CI/CD has been a game-changer, even in our hardware-heavy context. It enabled us to deliver software updates with greater speed and confidence across all the platforms we support. By leveraging GitLab CI/CD with self-hosted runners, we’ve achieved automated builds and tests on Linux, macOS, and Windows – all from a single unified pipeline. The benefits are clear: more reliable releases (thanks to catching issues early), faster development iterations (no more waiting on slow manual processes), and a standardized delivery process (every build follows the same steps, no matter the platform). In an era where every company is also a software company, even hardware-focused teams can reap the rewards of CI/CD. Embracing these practices leads to happier developers, more predictable schedules, and ultimately, better products for your customers. So if you haven’t already, give CI/CD a try in your organization’s workflow – your hardware and software teams will thank you!