DevOps和敏捷方法论已经通过强调协作、自动化和持续改进,彻底改变了软件开发。将DevOps原则应用到我的设计和项目中,已经成为改变游戏规则的一步,提高了效率和可靠性。在这篇文章中,我们将介绍如何为一个使用ATmega328P微控制器的现有嵌入式系统项目设置持续集成(CI)工作流。通过本文,你将看到这些实践如何简化你的开发过程并交付更高质量的产品。
DevOps是一套实践,由软件界推广,它将软件开发(Dev)和IT运维(Ops)融合为一个持续的流程。在软件界,开发软件然后“扔过墙”给运维团队让他们部署给客户曾是常态。DevOps引入了一种方式,不仅拆除了这堵墙,还将整个过程自动化。在硬件界,我们发现产品开发和生产之间有相似之处,不断地将设计“扔过墙”给我们的制造工程团队,以确保一切都为生产做好了准备。
在嵌入式产品设计中,我们仍然需要将软件通过生产,但面临着比以往任何时候都要快的挑战,并且要以尽可能高的质量交付。通过DevOps原则,我们旨在解决其中的一些挑战。
通过应用DevOps原则,我们能够使用敏捷方法论在构建-测试-部署范式中快速迭代,为我们希望发布到生产的每个附加功能。
“构建、测试和部署”是你在讨论DevOps时经常会听到的一组常用词汇。在嵌入式系统中,我们做的事情也是一样的,因为我们的部署同样会进入生产环节(然后是最终客户)。在项目的仓库中,我们使用Gitlab CI来驱动我们的端到端工作流程,以实现嵌入式DevOps。我们使用所谓的“管道”来创建完成特定任务的作业,例如编译软件、在目标上运行测试或将其作为官方包发布。在Gitlab中,管道是一系列按顺序流动的作业集合,如下所示:
图1:在Gitlab中使用的ATmega328P DevOps工作流程示例管道
这里是CI脚本(.gitlab-ci.yml文件)的细节分解,以给你一个如何工作的概念。
有一些细微的细节,将这个工作流程从一个基本的DevOps实现转变为一个运行平稳、文档齐全且易于观察的系统。在CI工作流程中有一些微妙的细节是重要的。
if [ "$CI_COMMIT_REF_SLUG" == "$CI_DEFAULT_BRANCH" ]; then
export IMAGE_TAG=$CI_REGISTRY_IMAGE/$IMAGE_TYPE:latest
else
export IMAGE_TAG=$CI_REGISTRY_IMAGE/$IMAGE_TYPE:$CI_COMMIT_REF_SLUG
fi
此逻辑确保了我们的“latest”标签仅使用在主分支上构建的Docker镜像(即在合并请求成功通过后)。这确保了只有成功的合并请求才会发布最新最好的docker镜像,供每个人和每个流水线拉取。
图2:合并请求中的代码覆盖率
在这个截图中,Gitlab总结了在目标硬件上运行的测试:
图3:在目标上运行的测试摘要
最终,一旦我们的代码通过了单元测试和目标测试的验证,发布和发布阶段就会生成一个漂亮的包,生产团队可以使用:
图4:软件包发布
通过所有这些自动化步骤,我们可以以敏捷的方式迭代地发布新功能。不需要开发许多功能,将它们发送到QA部门,然后由生产团队审查包发布。这里的一切都在一个工作流中发生,并且完全自动化。
在本文中,我们探讨了如何将 DevOps 和敏捷方法应用于嵌入式系统开发,特别是使用 ATmega328P 微控制器。我们讨论了在 Gitlab 中实施 CI 工作流的好处,包括自动化、更快的构建时间和高效的测试。通过分解 CI 脚本并解释每个阶段,我们展示了如何创建一个健壮且流畅的开发过程,以提高效率和产品质量。通过遵循这个实用指南(以及仓库中的源代码),你也应该能够建立自己的嵌入式 DevOps 工作流。
项目的源代码可以在这里找到:https://gitlab.com/embedded-designs/atmega328p-serial-led-control。