标签 开发 下的文章

要在三天内打造一个可玩的游戏,你需要一些快速而稳定的好工具。

在十月初,我们的俱乐部马歇尔大学的 Geeks and Gadgets 参加了首次 Open Jam,这是一个庆祝最佳开源工具的游戏 Jam。游戏 Jam 是一种活动,参与者以团队协作的方式来开发有趣的计算机游戏。Jam 一般都很短,仅有三天,并且非常累。Opensource.com 在八月下旬发布了 Open Jam 活动,足有 45 支游戏 进入到了竞赛中。

我们的俱乐部希望在我们的项目中创建和使用开放源码软件,所以 Open Jam 自然是我们想要参与的 Jam 了。我们提交的游戏是一个实验性的游戏,名为 Mark My Words。我们使用了多种自由和开放源码 (FOSS) 工具来开发它;在这篇文章中,我们将讨论一些我们使用的工具和我们注意到可能有潜在阻碍的地方。

音频工具

MilkyTracker

MilkyTracker 是一个可用于编曲老式视频游戏中的音乐的软件包。它是一种 音乐声道器 music tracker ,是一个强大的 MOD 和 XM 文件创建器,带有基于特征网格的模式编辑器。在我们的游戏中,我们使用它来编曲大多数的音乐片段。这个程序最好的地方是,它比我们其它的大多数工具消耗更少的硬盘空间和内存。虽然如此,MilkyTracker 仍然非常强大。

其用户界面需要一会来习惯,这里有对一些想试用 MilkyTracker 的音乐家的一些提示:

  • 转到 “Config > Misc.” ,设置编辑模式的控制风格为 “MilkyTracker”,这将给你提供几乎全部现代键盘快捷方式。
  • Ctrl+Z 撤销
  • Ctrl+Y 重做
  • 用空格键切换模式编辑方式
  • 用退格键删除先前的音符
  • 用插入键来插入一行
  • 默认情况下,一个音符将持续作用,直到它在该频道上被替换。你可以明确地结束一个音符,通过使用一个反引号(`)键来插入一个 KeyOff 音符
  • 在你开始谱写乐曲前,你需要创建或查找采样。我们建议在诸如 FreesoundccMixter 这样的网站上查找采用 Creative Commons 协议的采样,

另外,把 MilkyTracker 文档页面 放在手边。它含有数不清的教程和手册的链接。一个好的起点是在该项目 wiki 上的 MilkyTracker 指南

LMMS

我们的两个音乐家使用多用途的现代音乐创建工具 LMMS。它带有一个绝妙的采样和效果库,以及多种多样的灵活的插件来生成独特的声音。LMMS 的学习曲线令人吃惊的低,在某种程度上是因为其好用的节拍/低音线编辑器。

我们对于想试试 LMMS 的音乐家有一个建议:使用插件。对于 chiptune式音乐,我们推荐 sfxrBitInvaderFreeBoy。对于其它风格,ZynAddSubFX 是一个好的选择。它配备了各种合成仪器,可以根据您的需要进行更改。

图形工具

Tiled

在开放源码游戏开发中,Tiled 是一个流行的贴片地图编辑器。我们使用它为来为我们在游戏场景中组合连续的、复古式的背景。

Tiled 可以导出地图为 XML、JSON 或普通的图片。它是稳定的、跨平台的。

Tiled 的功能之一允许你在地图上定义和放置随意的游戏对象,例如硬币和提升道具,但在 jam 期间我们没有使用它。你需要做的全部是以贴片集的方式加载对象的图像,然后使用“插入平铺”来放置它们。

一般来说,对于需要一个地图编辑器的项目,Tiled 是我们所推荐的软件中一个不可或缺的部分。

Piskel

Piskel 是一个像素艺术编辑器,它的源文件代码以 Apache 2.0 协议 发布。在这次 Jam 期间,们的大多数的图像资源都使用 Piskel 来处理,我们当然也将在未来的工程中使用它。

在这个 Jam 期间,Piskel 极大地帮助我们的两个功能是 洋葱皮 Onion skin 精灵序列图 spritesheet 导出。

洋葱皮

洋葱皮功能将使 Piskel 以虚影显示你编辑的动画的前一帧和后一帧的,像这样:

洋葱皮是很方便的,因为它适合作为一个绘制指引和帮助你在整个动画进程中保持角色的一致形状和体积。 要启用它,只需单击屏幕右上角预览窗口下方的洋葱形图标即可。

精灵序列图导出

Piskel 将动画导出为精灵序列图的能力也非常有用。精灵序列图是一个包含动画所有帧的光栅图像。例如,这是我们从 Piskel 导出的精灵序列图:

该精灵序列图包含两帧。一帧位于图像的上半部分,另一帧位于图像的下半部分。精灵序列图通过从单个文件加载整个动画,大大简化了游戏的代码。这是上面精灵序列图的动画版本:

Unpiskel.py

在 Jam 期间,我们很多次想批量转换 Piskel 文件到 PNG 文件。由于 Piskel 文件格式基于 JSON,我们写一个基于 GPLv3 协议的名为 unpiskel.py 的 Python 小脚本来做转换。

它像这样被调用的:

python unpiskel.py input.piskel

这个脚本将从一个 Piskel 文件(这里是 input.piskel)中提取 PNG 数据帧和图层,并将它们各自存储。这些文件采用模式 NAME_XX_YY.png 命名,在这里 NAME 是 Piskel 文件的缩减名称,XX 是帧的编号,YY 是层的编号。

因为脚本可以从一个 shell 中调用,它可以用在整个文件列表中。

for f in *.piskel; do python unpiskel.py "$f"; done

Python、Pygame 和 cx\_Freeze

Python 和 Pygame

我们使用 Python 语言来制作我们的游戏。它是一个脚本语言,通常被用于文本处理和桌面应用程序开发。它也可以用于游戏开发,例如像 Angry Drunken DwarvesRen'Py 这样的项目所展示的。这两个项目都使用一个称为 Pygame 的 Python 库来显示图形和产生声音,所以我们也决定在 Open Jam 中使用这个库。

Pygame 被证明是既稳定又富有特色,并且它对我们创建的街机式游戏来说是很棒的。在低分辨率时,库的速度足够快的,但是在高分辨率时,它只用 CPU 的渲染开始变慢。这是因为 Pygame 不使用硬件加速渲染。然而,开发者可以充分利用 OpenGL 基础设施的优势。

如果你正在寻找一个好的 2D 游戏编程库,Pygame 是值得密切注意的一个。它的网站有 一个好的教程 可以作为起步。务必看看它!

cx\_Freeze

准备发行我们的游戏是有趣的。我们知道,Windows 用户不喜欢装一套 Python,并且要求他们来安装它可能很过分。除此之外,他们也可能必须安装 Pygame,在 Windows 上,这不是一个简单的工作。

很显然:我们必须放置我们的游戏到一个更方便的格式中。很多其他的 Open Jam 参与者使用专有的游戏引擎 Unity,它能够使他们的游戏在网页浏览器中来玩。这使得它们非常方便地来玩。便利性是一个我们的游戏中根本不存在的东西。但是,感谢生机勃勃的 Python 生态系统,我们有选择。已有的工具可以帮助 Python 程序员将他们的游戏做成 Windows 上的发布版本。我们考虑过的两个工具是 cx\_FreezePygame2exe(它使用 py2exe)。我们最终决定用 cx\_Freeze,因为它是跨平台的。

在 cx\_Freeze 中,你可以把一个单脚本游戏打包成发布版本,只要在 shell 中运行一个命令,像这样:

cxfreeze main.py --target-dir dist

cxfreeze 的这个调用将把你的脚本(这里是 main.py)和在你系统上的 Python 解释器捆绑到到 dist 目录。一旦完成,你需要做的是手动复制你的游戏的数据文件到 dist 目录。你将看到,dist 目录包含一个可以运行来开始你的游戏的可执行文件。

这里有使用 cx\_Freeze 的更复杂的方法,允许你自动地复制数据文件,但是我们发现简单的调用 cxfreeze 足够满足我们的需要。感谢这个工具,我们使我们的游戏玩起来更便利一些。

庆祝开源

Open Jam 是庆祝开源模式的软件开发的重要活动。这是一个分析开源工具的当前状态和我们在未来工作中需求的一个机会。对于游戏开发者探求其工具的使用极限,学习未来游戏开发所必须改进的地方,游戏 Jam 或许是最好的时机。

开源工具使人们能够在不损害自由的情况下探索自己的创造力,而无需预先投入资金。虽然我们可能不会成为专业的游戏开发者,但我们仍然能够通过我们的简短的实验性游戏 Mark My Words 获得一点点体验。它是一个以语言学为主题的游戏,描绘了虚构的书写系统在其历史中的演变。还有很多其他不错的作品提交给了 Open Jam,它们都值得一试。 真的,去看看

在本文结束前,我们想要感谢所有的 参加俱乐部的成员,使得这次经历真正的有价值。我们也想要感谢 Michael ClaytonJared SpragueOpensource.com 主办 Open Jam。简直酷毙了。

现在,我们对读者提出了一些问题。你是一个 FOSS 游戏开发者吗?你选择的工具是什么?务必在下面留下一个评论!


via: https://opensource.com/article/18/1/graphics-music-tools-game-dev

作者:Charlie Murphy 译者:robsean 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

为什么在工程中混合角色对用户更好的三个原因。

大多数开源社区没有很多正式的角色。当然,也有一些固定人员帮助处理系统管理员任务、测试、编写文档以及翻译或开发代码。但开源社区的人员通常在不同的角色之间流动,往往同时履行几个角色的职责。

相反,大多数传统公司的团队成员都定义了角色,例如,负责文档、技术支持、质量检验和其他领域。

为什么开源社区采取共享角色的方法,更重要的是,这种协作方式如何影响产品和客户?

Nextcloud 采用了这种社区式的混合角色的做法,我们看到了我们的客户和用户受益颇多。

1、更好的产品测试

每个测试人员都会说测试是一项困难的工作。你需要了解工程师开发的产品,并且需要设计测试案例、执行测试案例并将结果返回给开发人员。完成该过程后,开发人员将进行更改,然后重复该过程,根据需要来回进行多次,直到任务完成。

在社区中,贡献者通常会对他们开发的项目负责,因此他们会对这些项目进行广泛的测试和记录,然后再将其交给用户。贴近项目的用户通常会与开发人员协作,帮助测试、翻译和编写文档。这将创建一个更紧密、更快的反馈循环,从而加快开发速度并提高质量。

当开发人员不断面对他们的工作结果时,会鼓励他们以最大限度地减少测试和调试的方式去书写。自动化测试是开发中的一个重要元素,反馈循环可以确保正确地完成操作:开发人员主观能动的来实现自动化 —— 而不过于简化也不过于复杂。当然,他们可能希望别人做更多的测试或自动化的测试,但当测试是正确的选择时,他们就会这样做。此外,他们还审查对方的代码,因为他们知道问题往往会在以后让他们付出代价。

因此,虽然我不认为放弃专用测试人员更好,但在没有社区志愿者进行测试的项目中,测试人员应该是开发人员,并密切嵌入到开发团队中。结果如何?客户得到的产品是由 100% 有动机的人测试和开发的,以确保它是稳定和可靠的。

2、开发和客户需求之间的密切协作

要使产品开发与客户需求保持一致是非常困难的。每个客户都有自己独特的需求,有长期和短期的因素需要考虑 —— 当然,作为一家公司,你对你的发展方向有想法。你如何整合所有这些想法和愿景?

公司通常会创建与工程和产品开发分开的角色,如产品管理、支持、质量检测等。这背后的想法是,人们在专攻的时候做得最好,工程师不应该为测试或支持等 “简单” 的任务而烦恼。

实际上,这种角色分离是一项削减成本的措施。它使管理层能够进行微观管理,并更能掌握全局,因为他们可以简单地进行产品管理,例如,确定路线图项目的优先次序。(它还创建了更多的会议!)

另一方面,在社区,“决定权在工作者手上”。开发人员通常也是用户(或由用户支付报酬),因此他们自然地与用户的需求保持一致。当用户帮助进行测试时(如上所述),开发人员会不断地与他们合作,因此双方都完全了解什么是可行的,什么是需要的。

这种开放的合作方式使用户和项目紧密协作。在没有管理层干涉和指手画脚的情况下,用户最迫切的需求可以迅速得到满足,因为工程师已经非常了解这些需求。

在 nextcloud 中,客户永远不需要解释两次,也不需要依靠初级支持团队成员将问题准确地传达给工程师。我们的工程师根据客户的实际需求不断调整他们的优先级。同时,基于对客户的深入了解,合作制定长期目标。

3、最佳支持

与专有的或 开放源核心 open core 的供应商不同,开源供应商有强大的动力提供尽可能最好的支持:这是与其他公司在其生态系统中的关键区别。

为什么项目背后的推动者(比如 CollaboraLibreOffice 背后,The Qt CompanyQt 背后,或者 Red HatRHEL 背后)是客户支持的最佳来源呢?

当然是直接接触工程师。这些公司并不阻断来自工程团队的支持,而是为客户提供了获得工程师专业知识的机会。这有助于确保客户始终尽快获得最佳答案。虽然一些工程师可能比其他人在支持上花费更多的时间,但整个工程团队在客户成功方面发挥着作用。专有供应商可能会为客户提供一个专门的现场工程师,费用相当高,但一个开源公司,如 OpenNMS 可以在您的支持合同中提供相同级别的服务,即使您不是财富 500 强客户也是如此。

还有一个好处,那就是与测试和客户协作有关:共享角色可确保工程师每天处理客户问题和愿望,从而促使他们快速解决最常见的问题。他们还倾向于构建额外的工具和功能,以满足客户预期。

简单地说,将质量检测、支持、产品管理和其他工程角色合并为一个团队,可确保优秀开发人员的三大优点 —— 从简、精益求精、高度自我要求 laziness,impatience,and hubris —— 与客户紧密保持一致。


via: https://opensource.com/article/18/8/mixing-roles-engineering

作者:Jos Poortvliet 选题:lujun9972 译者:lixinyuxx 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

应用 Align 中,用户主页的控制面板

从构思到部署应用程序的简单分步指南

我在 Grace Hopper Program 为期三个月的编码训练营即将结束,实际上这篇文章的标题有些纰漏 —— 现在我已经构建了 三个 全栈应用:从零开始的电子商店、我个人的 私人黑客马拉松项目,还有这个“三周的结业项目”。这个项目是迄今为止强度最大的 —— 我和另外两名队友共同花费三周的时光 —— 而它也是我在训练营中最引以为豪的成就。这是我目前所构建和涉及的第一款稳定且复杂的应用。

如大多数开发者所知,即使你“知道怎么编写代码”,但真正要制作第一款全栈的应用却是非常困难的。JavaScript 生态系统出奇的大:有包管理器、模块、构建工具、转译器、数据库、库文件,还要对上述所有东西进行选择,难怪如此多的编程新手除了 Codecademy 的教程外,做不了任何东西。这就是为什么我想让你体验这个决策的分布教程,跟着我们队伍的脚印,构建可用的应用。


首先,简单的说两句。Align 是一个 web 应用,它使用直观的时间线界面帮助用户管理时间、设定长期目标。我们的技术栈有:用于后端服务的 Firebase 和用于前端的 React。我和我的队友在这个短视频中解释的更详细。

从第 1 天(我们组建团队的那天)开始,直到最终应用的完成,我们是如何做的?这里是我们采取的步骤纲要:


第 1 步:构思

第一步是弄清楚我们到底要构建什么东西。过去我在 IBM 中当咨询师的时候,我和合作组长一同带领着构思工作组。从那之后,我一直建议小组使用经典的头脑风暴策略,在会议中我们能够提出尽可能多的想法 —— 即使是 “愚蠢的想法” —— 这样每个人的大脑都在思考,没有人因顾虑而不敢发表意见。

在产生了好几个关于应用的想法时,我们把这些想法分类记录下来,以便更好的理解我们大家都感兴趣的主题。在我们这个小组中,我们看到实现想法的清晰趋势,需要自我改进、设定目标、情怀,还有个人发展。我们最后从中决定了具体的想法:做一个用于设置和管理长期目标的控制面板,有保存记忆的元素,可以根据时间将数据可视化。

从此,我们创作出了一系列用户故事(从一个终端用户的视角,对我们想要拥有的功能进行描述),阐明我们到底想要应用实现什么功能。

第 2 步:UX/UI 示意图

接下来,在一块白板上,我们画出了想象中应用的基本视图。结合了用户故事,以便理解在应用基本框架中这些视图将会如何工作。

这些骨架确保我们意见统一,提供了可预见的蓝图,让我们向着计划的方向努力。

第 3 步:选好数据结构和数据库类型

到了设计数据结构的时候。基于我们的示意图和用户故事,我们在 Google doc 中制作了一个清单,它包含我们将会需要的模型和每个模型应该包含的属性。我们知道需要 “目标(goal)” 模型、“用户(user)”模型、“里程碑(milestone)”模型、“记录(checkin)”模型还有最后的“资源(resource)”模型和“上传(upload)”模型,

最初的数据模型结构

在正式确定好这些模型后,我们需要选择某种 类型 的数据库:“关系型的”还是“非关系型的”(也就是“SQL”还是“NoSQL”)。由于基于表的 SQL 数据库需要预定义的格式,而基于文档的 NoSQL 数据库却可以用动态格式描述非结构化数据。

对于我们这个情况,用 SQL 型还是 No-SQL 型的数据库没多大影响,由于下列原因,我们最终选择了 Google 的 NoSQL 云数据库 Firebase:

  1. 它能够把用户上传的图片保存在云端并存储起来
  2. 它包含 WebSocket 功能,能够实时更新
  3. 它能够处理用户验证,并且提供简单的 OAuth 功能。

我们确定了数据库后,就要理解数据模型之间的关系了。由于 Firebase 是 NoSQL 类型,我们无法创建联合表或者设置像 “记录 (Checkins)属于目标(Goals)” 的从属关系。因此我们需要弄清楚 JSON 树是什么样的,对象是怎样嵌套的(或者不是嵌套的关系)。最终,我们构建了像这样的模型:

我们最终为目标(Goal)对象确定的 Firebase 数据格式。注意里程碑(Milestones)和记录(Checkins)对象嵌套在 Goals 中。

(注意: 出于性能考虑,Firebase 更倾向于简单、常规的数据结构, 但对于我们这种情况,需要在数据中进行嵌套,因为我们不会从数据库中获取目标(Goal)却不获取相应的子对象里程碑(Milestones)和记录(Checkins)。)

第 4 步:设置好 Github 和敏捷开发工作流

我们知道,从一开始就保持井然有序、执行敏捷开发对我们有极大好处。我们设置好 Github 上的仓库,我们无法直接将代码合并到主(master)分支,这迫使我们互相审阅代码。

我们还在 Waffle.io 网站上创建了敏捷开发的面板,它是免费的,很容易集成到 Github。我们在 Waffle 面板上罗列出所有用户故事以及需要我们去修复的 bug。之后当我们开始编码时,我们每个人会为自己正在研究的每一个用户故事创建一个 git 分支,在完成工作后合并这一条条的分支。

我们还开始保持晨会的习惯,讨论前一天的工作和每一个人遇到的阻碍。会议常常决定了当天的流程 —— 哪些人要结对编程,哪些人要独自处理问题。

我认为这种类型的工作流程非常好,因为它让我们能够清楚地找到自己的定位,不用顾虑人际矛盾地高效执行工作。

第 5 步: 选择、下载样板文件

由于 JavaScript 的生态系统过于复杂,我们不打算从最底层开始构建应用。把宝贵的时间花在连通 Webpack 构建脚本和加载器,把符号链接指向项目工程这些事情上感觉很没必要。我的团队选择了 Firebones 框架,因为它恰好适用于我们这个情况,当然还有很多可供选择的开源框架。

第 6 步:编写后端 API 路由(或者 Firebase 监听器)

如果我们没有用基于云的数据库,这时就应该开始编写执行数据库查询的后端高速路由了。但是由于我们用的是 Firebase,它本身就是云端的,可以用不同的方式进行代码交互,因此我们只需要设置好一个可用的数据库监听器。

为了确保监听器在工作,我们用代码做出了用于创建目标(Goal)的基本用户表格,实际上当我们完成表格时,就看到数据库执行可更新。数据库就成功连接了!

第 7 步:构建 “概念证明”

接下来是为应用创建 “概念证明”,也可以说是实现起来最复杂的基本功能的原型,证明我们的应用 可以 实现。对我们而言,这意味着要找个前端库来实现时间线的渲染,成功连接到 Firebase,显示数据库中的一些种子数据。

Victory.JS 绘制的简单时间线

我们找到了基于 D3 构建的响应式库 Victory.JS,花了一天时间阅读文档,用 VictoryLine 和 VictoryScatter 组件实现了非常基础的示例,能够可视化地显示数据库中的数据。实际上,这很有用!我们可以开始构建了。

第 8 步:用代码实现功能

最后,是时候构建出应用中那些令人期待的功能了。取决于你要构建的应用,这一重要步骤会有些明显差异。我们根据所用的框架,编码出不同的用户故事并保存在 Waffle 上。常常需要同时接触前端和后端代码(比如,创建一个前端表格同时要连接到数据库)。我们实现了包含以下这些大大小小的功能:

  • 能够创建新目标、里程碑和记录
  • 能够删除目标,里程碑和记录
  • 能够更改时间线的名称,颜色和详细内容
  • 能够缩放时间线
  • 能够为资源添加链接
  • 能够上传视频
  • 在达到相关目标的里程碑和记录时弹出资源和视频
  • 集成富文本编辑器
  • 用户注册、验证、OAuth 验证
  • 弹出查看时间线选项
  • 加载画面

有各种原因,这一步花了我们很多时间 —— 这一阶段是产生最多优质代码的阶段,每当我们实现了一个功能,就会有更多的事情要完善。

第 9 步: 选择并实现设计方案

当我们使用 MVP 架构实现了想要的功能,就可以开始清理,对它进行美化了。像表单,菜单和登陆栏等组件,我的团队用的是 Material-UI,不需要很多深层次的设计知识,它也能确保每个组件看上去都很圆润光滑。

这是我制作的最喜爱功能之一了。它美得令人心旷神怡。

我们花了一点时间来选择颜色方案和编写 CSS ,这让我们在编程中休息了一段美妙的时间。期间我们还设计了 logo 图标,还上传了网站图标。

第 10 步: 找出并减少 bug

我们一开始就应该使用测试驱动开发的模式,但时间有限,我们那点时间只够用来实现功能。这意味着最后的两天时间我们花在了模拟我们能够想到的每一种用户流,并从应用中找出 bug。

这一步是最不具系统性的,但是我们发现了一堆够我们忙乎的 bug,其中一个是在某些情况下加载动画不会结束的 bug,还有一个是资源组件会完全停止运行的 bug。修复 bug 是件令人恼火的事情,但当软件可以运行时,又特别令人满足。

第 11 步:应用上线

最后一步是上线应用,这样才可以让用户使用它!由于我们使用 Firebase 存储数据,因此我们使用了 Firebase Hosting,它很直观也很简单。如果你要选择其它的数据库,你可以使用 Heroku 或者 DigitalOcean。一般来讲,可以在主机网站中查看使用说明。

我们还在 Namecheap.com 上购买了一个便宜的域名,这让我们的应用更加完善,很容易被找到。


好了,这就是全部的过程 —— 我们都是这款实用的全栈应用的合作开发者。如果要继续讲,那么第 12 步将会是对用户进行 A/B 测试,这样我们才能更好地理解:实际用户与这款应用交互的方式和他们想在 V2 版本中看到的新功能。

但是,现在我们感到非常开心,不仅是因为成品,还因为我们从这个过程中获得了难以估量的知识和理解。点击 这里 查看 Align 应用!

Align 团队:Sara Kladky(左),Melanie Mohn(中),还有我自己。


via: https://medium.com/ladies-storm-hackathons/how-we-built-our-first-full-stack-javascript-web-app-in-three-weeks-8a4668dbd67c?imm_mid=0f581a&cmp=em-web-na-na-newsltr_20170816

作者:Sophia Ciocca 译者:BriFuture 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

在软件开发中经常会提到 持续集成 Continuous Integration (CI)和 持续交付 Continuous Delivery (CD)这几个术语。但它们真正的意思是什么呢?

在谈论软件开发时,经常会提到 持续集成 Continuous Integration (CI)和 持续交付 Continuous Delivery (CD)这几个术语。但它们真正的意思是什么呢?在本文中,我将解释这些和相关术语背后的含义和意义,例如 持续测试 Continuous Testing 持续部署 Continuous Deployment

概览

工厂里的装配线以快速、自动化、可重复的方式从原材料生产出消费品。同样,软件交付管道以快速、自动化和可重复的方式从源代码生成发布版本。如何完成这项工作的总体设计称为“持续交付”(CD)。启动装配线的过程称为“持续集成”(CI)。确保质量的过程称为“持续测试”,将最终产品提供给用户的过程称为“持续部署”。一些专家让这一切简单、顺畅、高效地运行,这些人被称为 运维开发 DevOps 践行者。

“持续”是什么意思?

“持续”用于描述遵循我在此提到的许多不同流程实践。这并不意味着“一直在运行”,而是“随时可运行”。在软件开发领域,它还包括几个核心概念/最佳实践。这些是:

  • 频繁发布:持续实践背后的目标是能够频繁地交付高质量的软件。此处的交付频率是可变的,可由开发团队或公司定义。对于某些产品,一季度、一个月、一周或一天交付一次可能已经足够频繁了。对于另一些来说,一天可能需要多次交付也是可行的。所谓持续也有“偶尔、按需”的方面。最终目标是相同的:在可重复、可靠的过程中为最终用户提供高质量的软件更新。通常,这可以通过很少甚至无需用户的交互或掌握的知识来完成(想想设备更新)。
  • 自动化流程:实现此频率的关键是用自动化流程来处理软件生产中的方方面面。这包括构建、测试、分析、版本控制,以及在某些情况下的部署。
  • 可重复:如果我们使用的自动化流程在给定相同输入的情况下始终具有相同的行为,则这个过程应该是可重复的。也就是说,如果我们把某个历史版本的代码作为输入,我们应该得到对应相同的可交付产出。这也假设我们有相同版本的外部依赖项(即我们不创建该版本代码使用的其它交付物)。理想情况下,这也意味着可以对管道中的流程进行版本控制和重建(请参阅稍后的 DevOps 讨论)。
  • 快速迭代:“快速”在这里是个相对术语,但无论软件更新/发布的频率如何,预期的持续过程都会以高效的方式将源代码转换为交付物。自动化负责大部分工作,但自动化处理的过程可能仍然很慢。例如,对于每天需要多次发布候选版更新的产品来说,一轮 集成测试 integrated testing 下来耗时就要大半天可能就太慢了。

什么是“持续交付管道”?

将源代码转换为可发布产品的多个不同的 任务 task 作业 job 通常串联成一个软件“管道”,一个自动流程成功完成后会启动管道中的下一个流程。这些管道有许多不同的叫法,例如持续交付管道、部署管道和软件开发管道。大体上讲,程序管理者在管道执行时管理管道各部分的定义、运行、监控和报告。

持续交付管道是如何工作的?

软件交付管道的实际实现可以有很大不同。有许多程序可用在管道中,用于源代码跟踪、构建、测试、指标采集,版本管理等各个方面。但整体工作流程通常是相同的。单个业务流程/工作流应用程序管理整个管道,每个流程作为独立的作业运行或由该应用程序进行阶段管理。通常,在业务流程中,这些独立作业是以应用程序可理解并可作为工作流程管理的语法和结构定义的。

这些作业被用于一个或多个功能(构建、测试、部署等)。每个作业可能使用不同的技术或多种技术。关键是作业是自动化的、高效的,并且可重复的。如果作业成功,则工作流管理器将触发管道中的下一个作业。如果作业失败,工作流管理器会向开发人员、测试人员和其他人发出警报,以便他们尽快纠正问题。这个过程是自动化的,所以比手动运行一组过程可更快地找到错误。这种快速排错称为 快速失败 fail fast ,并且在抵达管道端点方面同样有价值。

“快速失败”是什么意思?

管道的工作之一就是快速处理变更。另一个是监视创建发布的不同任务/作业。由于编译失败或测试未通过的代码可以阻止管道继续运行,因此快速通知用户此类情况非常重要。快速失败指的是在管道流程中尽快发现问题并快速通知用户的方式,这样可以及时修正问题并重新提交代码以便使管道再次运行。通常在管道流程中可通过查看历史记录来确定是谁做了那次修改并通知此人及其团队。

所有持续交付管道都应该被自动化吗?

管道的几乎所有部分都是应该自动化的。对于某些部分,有一些人为干预/互动的地方可能是有意义的。一个例子可能是 用户验收测试 user-acceptance testing (让最终用户试用软件并确保它能达到他们想要/期望的水平)。另一种情况可能是部署到生产环境时用户希望拥有更多的人为控制。当然,如果代码不正确或不能运行,则需要人工干预。

有了对“持续”含义理解的背景,让我们看看不同类型的持续流程以及它们在软件管道上下文中的含义。

什么是“持续集成”?

持续集成(CI)是在源代码变更后自动检测、拉取、构建和(在大多数情况下)进行单元测试的过程。持续集成是启动管道的环节(尽管某些预验证 —— 通常称为 上线前检查 pre-flight checks —— 有时会被归在持续集成之前)。

持续集成的目标是快速确保开发人员新提交的变更是好的,并且适合在代码库中进一步使用。

持续集成是如何工作的?

持续集成的基本思想是让一个自动化过程监测一个或多个源代码仓库是否有变更。当变更被推送到仓库时,它会监测到更改、下载副本、构建并运行任何相关的单元测试。

持续集成如何监测变更?

目前,监测程序通常是像 Jenkins 这样的应用程序,它还协调管道中运行的所有(或大多数)进程,监视变更是其功能之一。监测程序可以以几种不同方式监测变更。这些包括:

  • 轮询:监测程序反复询问代码管理系统,“代码仓库里有什么我感兴趣的新东西吗?”当代码管理系统有新的变更时,监测程序会“唤醒”并完成其工作以获取新代码并构建/测试它。
  • 定期:监测程序配置为定期启动构建,无论源码是否有变更。理想情况下,如果没有变更,则不会构建任何新内容,因此这不会增加额外的成本。
  • 推送:这与用于代码管理系统检查的监测程序相反。在这种情况下,代码管理系统被配置为提交变更到仓库时将“推送”一个通知到监测程序。最常见的是,这可以以 webhook 的形式完成 —— 在新代码被推送时一个 挂勾 hook 的程序通过互联网向监测程序发送通知。为此,监测程序必须具有可以通过网络接收 webhook 信息的开放端口。

什么是“预检查”(又称“上线前检查”)?

在将代码引入仓库并触发持续集成之前,可以进行其它验证。这遵循了最佳实践,例如 测试构建 test build 代码审查 code review 。它们通常在代码引入管道之前构建到开发过程中。但是一些管道也可能将它们作为其监控流程或工作流的一部分。

例如,一个名为 Gerrit 的工具允许在开发人员推送代码之后但在允许进入(Git 远程)仓库之前进行正式的代码审查、验证和测试构建。Gerrit 位于开发人员的工作区和 Git 远程仓库之间。它会“接收”来自开发人员的推送,并且可以执行通过/失败验证以确保它们在被允许进入仓库之前的检查是通过的。这可以包括检测新变更并启动构建测试(CI 的一种形式)。它还允许开发者在那时进行正式的代码审查。这种方式有一种额外的可信度评估机制,即当变更的代码被合并到代码库中时不会破坏任何内容。

什么是“单元测试”?

单元测试(也称为“提交测试”),是由开发人员编写的小型的专项测试,以确保新代码独立工作。“独立”这里意味着不依赖或调用其它不可直接访问的代码,也不依赖外部数据源或其它模块。如果运行代码需要这样的依赖关系,那么这些资源可以用 模拟 mock 来表示。模拟是指使用看起来像资源的 代码存根 code stub ,可以返回值,但不实现任何功能。

在大多数组织中,开发人员负责创建单元测试以证明其代码正确。事实上,一种称为 测试驱动开发 test-driven develop (TDD)的模型要求将首先设计单元测试作为清楚地验证代码功能的基础。因为这样的代码可以更改速度快且改动量大,所以它们也必须执行很快。

由于这与持续集成工作流有关,因此开发人员在本地工作环境中编写或更新代码,并通单元测试来确保新开发的功能或方法正确。通常,这些测试采用断言形式,即函数或方法的给定输入集产生给定的输出集。它们通常进行测试以确保正确标记和处理出错条件。有很多单元测试框架都很有用,例如用于 Java 开发的 JUnit

什么是“持续测试”?

持续测试是指在代码通过持续交付管道时运行扩展范围的自动化测试的实践。单元测试通常与构建过程集成,作为持续集成阶段的一部分,并专注于和其它与之交互的代码隔离的测试。

除此之外,可以有或者应该有各种形式的测试。这些可包括:

  • 集成测试 验证组件和服务组合在一起是否正常。
  • 功能测试 验证产品中执行功能的结果是否符合预期。
  • 验收测试 根据可接受的标准验证产品的某些特征。如性能、可伸缩性、抗压能力和容量。

所有这些可能不存在于自动化的管道中,并且一些不同类型的测试分类界限也不是很清晰。但是,在交付管道中持续测试的目标始终是相同的:通过持续的测试级别证明代码的质量可以在正在进行的发布中使用。在持续集成快速的原则基础上,第二个目标是快速发现问题并提醒开发团队。这通常被称为快速失败。

除了测试之外,还可以对管道中的代码进行哪些其它类型的验证?

除了测试是否通过之外,还有一些应用程序可以告诉我们测试用例执行(覆盖)的源代码行数。这是一个可以衡量代码量指标的例子。这个指标称为 代码覆盖率 code-coverage ,可以通过工具(例如用于 Java 的 JaCoCo)进行统计。

还有很多其它类型的指标统计,例如代码行数、复杂度以及代码结构对比分析等。诸如 SonarQube 之类的工具可以检查源代码并计算这些指标。此外,用户还可以为他们可接受的“合格”范围的指标设置阈值。然后可以在管道中针对这些阈值设置一个检查,如果结果不在可接受范围内,则流程终端上。SonarQube 等应用程序具有很高的可配置性,可以设置仅检查团队感兴趣的内容。

什么是“持续交付”?

持续交付(CD)通常是指整个流程链(管道),它自动监测源代码变更并通过构建、测试、打包和相关操作运行它们以生成可部署的版本,基本上没有任何人为干预。

持续交付在软件开发过程中的目标是自动化、效率、可靠性、可重复性和质量保障(通过持续测试)。

持续交付包含持续集成(自动检测源代码变更、执行构建过程、运行单元测试以验证变更),持续测试(对代码运行各种测试以保障代码质量),和(可选)持续部署(通过管道发布版本自动提供给用户)。

如何在管道中识别/跟踪多个版本?

版本控制是持续交付和管道的关键概念。持续意味着能够经常集成新代码并提供更新版本。但这并不意味着每个人都想要“最新、最好的”。对于想要开发或测试已知的稳定版本的内部团队来说尤其如此。因此,管道创建并轻松存储和访问的这些版本化对象非常重要。

在管道中从源代码创建的对象通常可以称为 工件 artifact 。工件在构建时应该有应用于它们的版本。将版本号分配给工件的推荐策略称为 语义化版本控制 semantic versioning 。(这也适用于从外部源引入的依赖工件的版本。)

语义版本号有三个部分: 主要版本 major 次要版本 minor 补丁版本 patch 。(例如,1.4.3 反映了主要版本 1,次要版本 4 和补丁版本 3。)这个想法是,其中一个部分的更改表示工件中的更新级别。主要版本仅针对不兼容的 API 更改而递增。当以 向后兼容 backward-compatible 的方式添加功能时,次要版本会增加。当进行向后兼容的版本 bug 修复时,补丁版本会增加。这些是建议的指导方针,但只要团队在整个组织内以一致且易于理解的方式这样做,团队就可以自由地改变这种方法。例如,每次为发布完成构建时增加的数字可以放在补丁字段中。

如何“分销”工件?

团队可以为工件分配 分销 promotion 级别以指示适用于测试、生产等环境或用途。有很多方法。可以用 Jenkins 或 Artifactory 等应用程序进行分销。或者一个简单的方案可以在版本号字符串的末尾添加标签。例如,-snapshot 可以指示用于构建工件的代码的最新版本(快照)。可以使用各种分销策略或工具将工件“提升”到其它级别,例如 -milestone-production,作为工件稳定性和完备性版本的标记。

如何存储和访问多个工件版本?

从源代码构建的版本化工件可以通过管理 工件仓库 artifact repository 的应用程序进行存储。工件仓库就像构建工件的版本控制工具一样。像 Artifactory 或 Nexus 这类应用可以接受版本化工件,存储和跟踪它们,并提供检索的方法。

管道用户可以指定他们想要使用的版本,并在这些版本中使用管道。

什么是“持续部署”?

持续部署(CD)是指能够自动提供持续交付管道中发布版本给最终用户使用的想法。根据用户的安装方式,可能是在云环境中自动部署、app 升级(如手机上的应用程序)、更新网站或只更新可用版本列表。

这里的一个重点是,仅仅因为可以进行持续部署并不意味着始终部署来自管道的每组可交付成果。它实际上指,通过管道每套可交付成果都被证明是“可部署的”。这在很大程度上是由持续测试的连续级别完成的(参见本文中的持续测试部分)。

管道构建的发布成果是否被部署可以通过人工决策,或利用在完全部署之前“试用”发布的各种方法来进行控制。

在完全部署到所有用户之前,有哪些方法可以测试部署?

由于必须回滚/撤消对所有用户的部署可能是一种代价高昂的情况(无论是技术上还是用户的感知),已经有许多技术允许“尝试”部署新功能并在发现问题时轻松“撤消”它们。这些包括:

蓝/绿测试/部署

在这种部署软件的方法中,维护了两个相同的主机环境 —— 一个“蓝色” 和一个“绿色”。(颜色并不重要,仅作为标识。)对应来说,其中一个是“生产环境”,另一个是“预发布环境”。

在这些实例的前面是调度系统,它们充当产品或应用程序的客户“网关”。通过将调度系统指向蓝色或绿色实例,可以将客户流量引流到期望的部署环境。通过这种方式,切换指向哪个部署实例(蓝色或绿色)对用户来说是快速,简单和透明的。

当新版本准备好进行测试时,可以将其部署到非生产环境中。在经过测试和批准后,可以更改调度系统设置以将传入的线上流量指向它(因此它将成为新的生产站点)。现在,曾作为生产环境实例可供下一次候选发布使用。

同理,如果在最新部署中发现问题并且之前的生产实例仍然可用,则简单的更改可以将客户流量引流回到之前的生产实例 —— 有效地将问题实例“下线”并且回滚到以前的版本。然后有问题的新实例可以在其它区域中修复。

金丝雀测试/部署

在某些情况下,通过蓝/绿发布切换整个部署可能不可行或不是期望的那样。另一种方法是为 金丝雀 canary 测试/部署。在这种模型中,一部分客户流量被重新引流到新的版本部署中。例如,新版本的搜索服务可以与当前服务的生产版本一起部署。然后,可以将 10% 的搜索查询引流到新版本,以在生产环境中对其进行测试。

如果服务那些流量的新版本没问题,那么可能会有更多的流量会被逐渐引流过去。如果仍然没有问题出现,那么随着时间的推移,可以对新版本增量部署,直到 100% 的流量都调度到新版本。这有效地“更替”了以前版本的服务,并让新版本对所有客户生效。

功能开关

对于可能需要轻松关掉的新功能(如果发现问题),开发人员可以添加 功能开关 feature toggles 。这是代码中的 if-then 软件功能开关,仅在设置数据值时才激活新代码。此数据值可以是全局可访问的位置,部署的应用程序将检查该位置是否应执行新代码。如果设置了数据值,则执行代码;如果没有,则不执行。

这为开发人员提供了一个远程“终止开关”,以便在部署到生产环境后发现问题时关闭新功能。

暗箱发布

暗箱发布 dark launch 中,代码被逐步测试/部署到生产环境中,但是用户不会看到更改(因此名称中有 暗箱 dark 一词)。例如,在生产版本中,网页查询的某些部分可能会重定向到查询新数据源的服务。开发人员可收集此信息进行分析,而不会将有关接口,事务或结果的任何信息暴露给用户。

这个想法是想获取候选版本在生产环境负载下如何执行的真实信息,而不会影响用户或改变他们的经验。随着时间的推移,可以调度更多负载,直到遇到问题或认为新功能已准备好供所有人使用。实际上功能开关标志可用于这种暗箱发布机制。

什么是“运维开发”?

运维开发 DevOps 是关于如何使开发和运维团队更容易合作开发和发布软件的一系列想法和推荐的实践。从历史上看,开发团队研发了产品,但没有像客户那样以常规、可重复的方式安装/部署它们。在整个周期中,这组安装/部署任务(以及其它支持任务)留给运维团队负责。这经常导致很多混乱和问题,因为运维团队在后期才开始介入,并且必须在短时间内完成他们的工作。同样,开发团队经常处于不利地位 —— 因为他们没有充分测试产品的安装/部署功能,他们可能会对该过程中出现的问题感到惊讶。

这往往导致开发和运维团队之间严重脱节和缺乏合作。DevOps 理念主张是贯穿整个开发周期的开发和运维综合协作的工作方式,就像持续交付那样。

持续交付如何与运维开发相交?

持续交付管道是几个 DevOps 理念的实现。产品开发的后期阶段(如打包和部署)始终可以在管道的每次运行中完成,而不是等待产品开发周期中的特定时间。同样,从开发到部署过程中,开发和运维都可以清楚地看到事情何时起作用,何时不起作用。要使持续交付管道循环成功,不仅要通过与开发相关的流程,还要通过与运维相关的流程。

说得更远一些,DevOps 建议实现管道的基础架构也会被视为代码。也就是说,它应该自动配置、可跟踪、易于修改,并在管道发生变化时触发新一轮运行。这可以通过将管道实现为代码来完成。

什么是“管道即代码”?

管道即代码 pipeline-as-code 是通过编写代码创建管道作业/任务的通用术语,就像开发人员编写代码一样。它的目标是将管道实现表示为代码,以便它可以与代码一起存储、评审、跟踪,如果出现问题并且必须终止管道,则可以轻松地重建。有几个工具允许这样做,如 Jenkins 2

DevOps 如何影响生产软件的基础设施?

传统意义上,管道中使用的各个硬件系统都有配套的软件(操作系统、应用程序、开发工具等)。在极端情况下,每个系统都是手工设置来定制的。这意味着当系统出现问题或需要更新时,这通常也是一项自定义任务。这种方法违背了持续交付的基本理念,即具有易于重现和可跟踪的环境。

多年来,很多应用被开发用于标准化交付(安装和配置)系统。同样, 虚拟机 virtual machine 被开发为模拟在其它计算机之上运行的计算机程序。这些 VM 要有管理程序才能在底层主机系统上运行,并且它们需要自己的操作系统副本才能运行。

后来有了 容器 container 。容器虽然在概念上与 VM 类似,但工作方式不同。它们只需使用一些现有的操作系统结构来划分隔离空间,而不需要运行单独的程序和操作系统的副本。因此,它们的行为类似于 VM 以提供隔离但不需要过多的开销。

VM 和容器是根据配置定义创建的,因此可以轻易地销毁和重建,而不会影响运行它们的主机系统。这允许运行管道的系统也可重建。此外,对于容器,我们可以跟踪其构建定义文件的更改 —— 就像对源代码一样。

因此,如果遇到 VM 或容器中的问题,我们可以更容易、更快速地销毁和重建它们,而不是在当前环境尝试调试和修复。

这也意味着对管道代码的任何更改都可以触发管道新一轮运行(通过 CI),就像对代码的更改一样。这是 DevOps 关于基础架构的核心理念之一。


via: https://opensource.com/article/18/8/what-cicd

作者:Brent Laster 选题:lujun9972 译者:pityonline 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

扩展给予 GNOME3 桌面环境以非常大的灵活性,这种灵活性赋予了用户在定制化桌面上的优势,从而使他们的工作流程变得更加舒适和有效率。Fedora Magazine 已经介绍了一些很棒的桌面扩展,例如 EasyScreenCastgTileOpenWeather ,本文接下来会重点报道这些为开发者而改变的扩展。

如果你需要帮助来安装 GNOME 扩展,那么可以参考《如何安装一个 GNOME Shell 扩展》这篇文章。

Docker 集成(Docker Integration)

Docker Integration extension icon

Docker Integration extension status menu

对于为自己的应用使用 Docker 的开发者而言,这个 Docker 集成 扩展是必不可少的。这个状态菜单提供了一个带着启动、停止、暂停、甚至删除它们的选项的 Docker 容器列表,这个列表会在新容器加入到这个系统时自动更新。

在安装完这个扩展后,Fedora 用户可能会收到这么一条消息:“Error occurred when fetching containers.(获取容器时发生错误)”。这是因为 Docker 命令默认需要 sudo 或 root 权限。要设置你的用户权限来运行 Docker,可以参考 Fedora 开发者门户网站上的 Docker 安装这一页

你可以在该扩展的站点上找到更多的信息。

Jenkins CI 服务器指示器(Jenkins CI Server Indicator)

Jenkins CI Server Indicator icon

Jenkins CI Server Indicator extension status menu

Jenkins CI 服务器指示器这个扩展可以使开发者在 Jenkins CI 服务器建立应用很简单,它展示了一个菜单,包含有任务列表及那些任务的状态。它也包括了一些如轻松访问 Jenkins 网页前端、任务完成提示、以及触发和过滤任务等特性。

如果想要更多的信息,请去浏览开发者站点

安卓工具(android-tool)

android-tool extension icon

android-tool extension status menu

安卓工具对于 Android 开发者来说会是一个非常有价值的扩展,它的特性包括捕获错误报告、设备截屏和屏幕录像。它可以通过 usb 和 tcp 连接两种方式来连接 Android 设备。

这个扩展需要 adb 的包,从 Fedora 官方仓库安装 adb 只需要运行这条命令

sudo dnf install android-tools

你可以在这个扩展的 GitHub 网页里找到更多信息。

GnomeHub

GnomeHub extension icon

GnomeHub extension status menu

对于自己的项目使用 GitHub 的 GNOME 用户来说,GnomeHub 是一个非常好的扩展,它可以显示 GitHub 上的仓库,还可以通知用户有新提交的拉取请求。除此之外,用户可以把他们最喜欢的仓库加在这个扩展的设置里。

如果想要更多信息,可以参考一下这个项目的 GitHub 页面

gistnotes

gistnotes extension icon

简单地说,gistnotes 为 gist 用户提供了一种创建、存储和管理注释和代码片段的简单方式。如果想要更多的信息,可以参考这个项目的网站

gistnotes window

Arduino 控制器(Arduino Control)

Arduino Control extension icon

这个 Arduino 控制器扩展允许用户去连接或者控制他们自己的 Arduino 电路板,它同样允许用户在状态菜单里增加滑块或者开关。除此之外,开发者放在扩展目录里的脚本可以通过以太网或者 usb 来连接 Arduino 电路板。

最重要的是,这个扩展可以被定制化来适合你的项目,在器 README 文件里的提供例子是,它能够“通过网络上任意的电脑来控制你房间里的灯”。

你可以从这个项目的 GitHub 页面上得到更多的产品信息并安装这个扩展。

Hotel Manager

Hotel Manager extension icon

Hotel Manager extension status menu

使用 Hotel 进程管理器开发网站的开发人员,应该尝试一下 Hotel Manager 这个扩展。它展示了一个增加到 Hotel 里的网页应用的列表,并给与了用户开始、停止和重启这些应用的能力。此外,还可以通过右边的电脑图标快速打开、浏览这些网页应用。这个扩展同样可以启动、停止或重启 Hotel 的后台程序。

本文发布时,GNOME 3.26 版本的 Hotel Manager 版本 4 没有在该扩展的下拉式菜单里列出网页应用。版本 4 还会在 Fedora 28 (GNOME 3.28) 上安装时报错。然而,版本 3 工作在 Fedora 27 和 Fedora 28。

如果想要更多细节,可以去看这个项目在 GitHub 上的网页

VSCode 搜索插件(VSCode Search Provider)

VSCode 搜索插件是一个简单的扩展,它能够在 GNOME 综合搜索结果里展示 Visual Studio Code 项目。对于重度 VSCode 用户来说,这个扩展可以让用户快速连接到他们的项目,从而节省时间。你可以从这个项目在 GitHub 上的页面来得到更多的信息。

GNOME Overview search results showing VSCode projects.

在开发环境方面,你有没有一个最喜欢的扩展呢?发在评论区里,一起来讨论下吧。


via: https://fedoramagazine.org/awesome-gnome-extensions-developers/

作者:Shaun Assam 选题:lujun9972 译者:hopefully2333 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

我最近买了新 MacBook Pro 作为我的主要的安卓开发机,我的老式的 MacBookPro(13 寸,2011 年后期发布,16GB 内存, 500G 的固态硬盘,内核是 i5,主频 2.4GHz,64 位),我也没卖,我清理了它,并把他变成了一个 MacOS 和Ubuntu 双引导的持续集成(CI)服务器。

写这篇文章我主要想总结一下安装步骤,好给自己以后作参考,当然,这篇文章也是给同行看的,只要他们感兴趣。好了,现在开始:

  1. 配置一个新的 Ubuntu ,以便运行 Android SDK。
  2. 安装 Jenkins CI 服务来拉取、编译、运行测试托管在 Github 的多模块 Android 项目。
  3. 安装 Docker 并在容器中运行 MySQL 服务器和 SonarQube。来运行由 Jenkins 触发的静态代码分析。
  4. Android app 配置需求。

第一步-安装 Ubuntu:

我将使用 Ubuntu 作为持续集成的 SO,因为 Ubuntu 有一个强大的社区,它可以解决你遇到的任何问题,而且我个人推荐总是使用 LTS 版本,当前是 16.04 LTS。已经有很多教程教大家在各种硬件上怎么安装了,我就不废话了,贴个下载链接就行了。

有人可能很奇怪:用什么桌面版,服务器版多好。额,这个嘛,萝卜青菜,各有所爱。我倒不在乎 UI 占用的那点运算资源。相反,用那一点资源换来生产力的提升我觉得挺值的。

第二步-远程管理:

SSH 服务器

Ubuntu 桌面版默认安装并没有 ssh 服务器,所以你想远程通过命令行管理的话就只好自己安装。

$ sudo apt-get install openssh-server

NoMachine 远程桌面

可能你的持续集成服务器没有挨着你,而是在你的路由器后面,或者其它屋子,甚至还可能远离你数里。我试过各种远程桌面方案,不得不说,IMHO NoMachine 在这方面表现的最好,它只需要你的 ssh 证书就可以工作了(显然你要先把它安装在 CI 和你的机器中)。

第三步-配置环境:

这里我打算安装 Java8,Git,和 Android SDK,Jenkins 需要它们来拉取、编译和运行 android 项目。

SDKMAN!

这个超级厉害的命令行工具让你可以安装各种流行的 SDK(比如说,Gradle、Groovy、Grails、Kotlin、 Scala……),并可以以容易方便的方式列出它们和在各个并行版本中切换。

它们最近又增加了对 JAVA8 的支持,所以我使用它来安装 Java,而是用流行的 webupd8 仓库。所以在你安装开始前,务必要想清你要不要安装 SDKMAN,话说回来,最好还是装上,因为我们以后应该会用到。

安装 SDKMAN! 很容易,执行以下命令即可:

$ curl -s "https://get.sdkman.io" | bash

Oracle JAVA8

因为我们已经安装了 SDKMAN! ,所以安装 JAVA8 就相当简单了:

$ sdk install java

或者使用 webupd8 这个仓库:

Git:

安装git的命令也非常直观,就不废话了。

$ sudo apt install git

Android SDK

这下面这篇文章的底部

你可以找到 “Get just the command line tools” 等字样,复制这个链接。比如:

https://dl.google.com/android/repository/tools_r25.2.3-linux.zip

下载,然后解压到 /opt/android-sdk-linux 下:

$ cd /opt
$ sudo wget https://dl.google.com/android/repository/tools_r25.2.3-linux.zip
$ sudo unzip tools_r25.2.3-linux.zip -d android-sdk-linux

我们使用 root 用户创建了该目录,所以我们需要重新授权来使我们的主要用户对它可读可写。

$ sudo chown -R YOUR_USERNAME:YOUR_USERNAME android-sdk-linux/

然后,在 ~/.bashrc 文件下设置 SDK 的环境变量

$ cd
$ nano .bashrc

在文件底部写入这些行(注意,但要在 SDKMAN! 配置文件前):

export ANDROID_HOME="/opt/android-sdk-linux"
export PATH="$ANDROID_HOME/tools:$ANDROID_HOME/platform-tools:$PATH"

关闭此终端,再打开一个新的终端看看环境变量是否正确生效:

$ echo $ANDROID_HOME
/opt/android-sdk-linux

然后我们启动图形界面的 Android SDK 管理器,并安装你所需的平台和依赖:

$ android

运行 Android SDK Manager 的图形交互界面

第四步-Jenkins 服务器

这里,我要讲讲怎么安装、配置该服务器,并创建 Jenkin 任务来拉取、构建和测试 Android 项目,并怎样获取控制台输出。

安装 Jenkins

你可以在下面的链接找到 Jenkins 服务器相关信息:

我们有许多办法运行 Jenkins,比如说运行 .war 文件,作为 Linux 服务,作为 Docker 容器等等。

我起初是想把它当做 Docker 容器运行,但是后来我意识到正确地配置代码文件夹、android-sdk 文件夹的可见性,和插到运行的 Android 测试机上的物理设备的 USB 可见性简直是一场噩梦。

少操点心,我最终决定以服务的方式,增加 Stable 仓库的 key 来通过 apt 安装和更新。

$ wget -q -O - https://pkg.jenkins.io/debian-stable/jenkins.io.key | sudo apt-key add -

编辑 source.list,写入这一行:

$ sudo nano /etc/apt/sources.list
#Jenkin Stable
deb https://pkg.jenkins.io/debian-stable binary/

然后安装:

sudo apt-get update
sudo apt-get install jenkins

在你的用户组里面增加 jenkins ,允许其读写 Android SDK 文件夹。

$ sudo usermod -a -G 你的用户组 jenkins

Jenkins 服务在开机引导时就会被启动,并可通过 http://localhost:8080 访问:

安装完毕会有一些安全预警信息,跟着引导程序走,你的 Jenkins 就会运行了。

启用安装成功的 Jenkins 服务器。

Jenkins 配置

启用成功后,会有提示程序提示你安装插件,单击 “Select plugins to Install” 就可以开始浏览所有插件,然后选择你要安装的插件就 OK 了 。

安装 Jenkins 插件

创建管理员用户,并完成安装。

要完成安全需要配置环境变量 ANDROID_HOMEJAVA_HOME

点击 Manage Jenkins,接着 Configure System。

滚动文件至底部,在全局属性模块中找到环境变量,并增加 ANDROID_HOMOE,和 JAVA_HOME 变量。

给所有 Jenkins 任务增加全局变量

创建 Jenkins 任务

一个 Jenkins 任务定义了一系列不间断的操作。如果你跟随本篇引导的话,那么你可以使用我已经在 GitHub 上为你准备了一个 Android 练习项目,你可以使用这个来试试手。它只是一个多模块的 app,带有单元测试、Android 测试,包括 JaCoCo、SonarQube 插件。

首先创建一个新的 Freestyle 任务项目,取名为 Hello_Android。不要在名字中使用空格,这样可以避免与 SonarQube 不兼容的问题。

创建一个 Freestyle Jenkins 任务

接下来就是配置了,我给每一部分都做了截屏。

概况

这部分比较繁琐,你可以在这里变更任务的名字、增加简介。如果你使用 GitHub 项目,你还可以写下项目的 URL(不要 *.git,这是 url 的部分,不是仓库的)。

项目 Url 配置

源代码管理

这时候我们就要选择我们的 CVS 作为 Git,并且增加仓库的 url(这次就要包括 *.git)然后选择分支拉取。因为这是一个公开的 GitHub 仓库,我们就不需要提交证书了,否则的话就要设置账号和密码。

相比于使用你的带有完全权限的公开仓库,我更倾向于为你的私有库创建一个新的只读用户来专门配给 Jenkins 任务使用。

另外,如果你已经使用了双因子认证,Jenkins 就无法拉取代码,所以为 Jenkins 专门创建一个用户可以直接从私有库中拉取代码。

配置仓库

构建触发器

你可以手动开始构建,也可以远程地、周期性地、或者在另一个任务构建完成之后开始构建,只要这些改变可以被检测到。

最好的情况肯定是一旦你更改了某些地方,就会立刻触发构建事件,Github 为此提供了一个名叫 webhooks 的系统。

这样,我们就可以配置来发送这些事件到 CI 服务器,然后触发构建。显然,我们的 CI 服务器必须要联网,并且可以与 GitHub 服务器通信。

你的 CI 服务器也许为了安全只限于内网使用,那么解决办法就只有集中周期性的提交。我就是只有工作时才打开 CI,我把它设置为每十五分钟轮询一次。轮询时间可以通过 CRON 语法设置,如果你不熟悉,请点击右侧的帮助按钮获取带有例子的丰富文档。

仓库轮询配置

构建环境

这里我推荐设置构建超时来避免 Jenkings 占用内存和 CPU ,毕竟有时候有意外发生。当然,你还可以插入环境变量和密码等等。

构建超时

构建

现在是见证魔法的时刻了,增加一个 Build 步骤,引入 Gradle 脚本,选择 Gradle Wrapper (默认情况下,Android 项目带有 Gradle Wrapper,不要忘记把它检入到 Git ),然后定义你要执行哪些任务:

  1. clean:清除之前构建的所有历史输出,这样可以确保没有东西缓存,从头构建。
  2. asseembleDebug: 生成调试 .apk 文件。
  3. test:在所有模块上执行 JUnit 测试。
  4. connectedDebugAndroidTest:在连接到 CI 的实体机上执行安卓测试单元(也可以使用安装了安卓模拟器的 Jenkins 插件,但是它不支持所有型号,而且相当麻烦)。

配置 Gradle

构建后操作

我们将要增加“发布 JUnit 测试报告”,这一步由 JUnit 插件提供,其搜集由 JUnit 测试结果生成的 XML 文件,它会生成漂亮的图表来按时间展示测试结果。

我们 app 模块中,测试运行结果的路径是: app/build/test-results/debug/*.xml

在多模块项目中,其它的“纯” Java 模块中测试结果在这里:*/build/test-results/*.xml

还要增加“记录 JaCoCo 覆盖率报告”,它要创建一张显示代码覆盖率的图表。

运行 Jenkins 任务

只要有任何改变提交到仓库,我们的测试任务将每十五分钟执行一次,但是如果你不想等的话,或者你只是想验证一下配置的改变,你也可以手动运行。单击“现在构建”按钮,当前的构建将出现在构建历史中,点击它可以查看细节。

手动执行任务

最有趣的部分是控制台输出,你可以看到 Jenkins 是如何拉取代码并执行我们之前定义的 Gradle 项目,例如 clean。

控制台输出的开始部分

如果一切都正常的话,控制台将会有如下输出 (任何仓库连接问题,单元测试或 Android 测试的失败都将导致构建失败)。

哈哈哈哈,构建成功,测试结果符合预期

第五步-SonarQube

这部分我会讲讲如何安装、配置 SonarQube ,并配以使用 Docker 作为容器的 MySQL 数据库。

SonarQube 是个代码静态分析工具,它可以帮助开发者写出干净的代码、检测错误和学习最佳体验。它还可以跟踪代码覆盖、测试结果、功能需求等等。SonarQube 检测到的问题可以使用插件十分容易的导入到 Android Studion/IntelliJ 中去。

安装 Docker

安装 Docker 十分容易,按照下面的教程即可:

生成容器

MySQL

我们先搭建一个 MySQL5.7.17 服务器容器,命名为 mysqlserver,它将在开机引导时启动,带有一个在你的家目录下的本地卷,带有密码,服务暴露在 localhost:3306 上(把命令中的 YOUR_USERYOUR_MYSQL_PASSWORD 替换为你自己账号密码)。

$ docker run --name mysqlserver --restart=always -v /home/YOUR_USER/mysqlVolume:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=YOUR_MYSQL_PASSWORD -p 3306:3306 -d mysql:5.7.17

phpMyAdmin

想要优雅简单地管理 MySQL服务器,我强烈推荐 phpMyAdmin。你只要建立个容器,命名为 phpmyadmin,然后链接到我们的 mysqlserver 容器,它会在开机引导时启动,它暴露在 localhost:9090。使用最新的版本。

$ docker run --name phpmyadmin --restart=always --link mysqlserver:db -p 9090:80 -d phpmyadmin/phpmyadmin

你可以用你的 mysql 密码 YOUR_MYSQL_PASSWORD ,以 root 身份登录 localhost:9090 的 phpMyAdmin 界面,并创建一个数据库 sonar,使用uft8_general_ci 字符集。此外,也创建一个 sonar 的新用户,密码 YOUR_SONAR_PASSWORD,并给它 sonar 数据库的权限。

SonarQube

现在我们已经创建好了我们的 SonarQube 容器,就叫 sonarqube,它会在机器引导时启动,自动链接搭配我们的数据库,服务暴露在 localhost:9090,使用 5.6.4 版本。

$ docker run --name sonarqube --restart=always --link mysqlserver:db -p 9000:9000 -p 9092:9092 -e "SONARQUBE_JDBC_URL=jdbc:mysql://db:3306/sonar?useUnicode=true&characterEncoding=utf8&rewriteBatchedStatements=true&useConfigs=maxPerformance" -e "SONARQUBE_JDBC_USER=sonar" -e "SONARQUBE_JDBC_PASSWORD=YOUR_SONAR_PASSWORD" -d sonarqube:5.6.4

配置 SonarQube

如果一起都正常,你将在 localhost:9000 看到如下页面:

好了,让我们来配置必要的插件和基本的配置文件:

  1. 在页面的右上角可以登录(默认的管理员账号和密码是 admin/admin)。
  2. 进入到 Administration,然后点击 System,接下来是 Updata Center,最后是 Updates Only。

    • 如果需要的话,更新 Java 插件。
  3. 现在启用,并安装以下插件

    • Android (提供 Android lint 规则)
    • Checkstyle
    • Findbugs
    • XML
  4. 返回顶部,点击重启按钮完成整个安装。

SonarQube 配置文件

我们刚刚安装的插件可以定义配置文件,可以用一套规则去衡量项目的代码质量。

同一时间一个项目只能使用一个配置文件。但是我们可以定义父配置文件并继承规则,所以要对我们的项目执行所有的规则,我们可以创建定制的配置文件并链状串联所有配置文件。

就这么干,点击 Quality Profiles ,跳转到 Create ,然后命名,比如 CustomAndroidProfile。

将 Android Lint 作为父级,然后选择 Android Lint 配置,增加 FindBugs Security Minial 作为上一级,继续此步骤,直到你完成父级继承方案,并且设置 CustomAndroidProfile 作为默认。

继承链

运行 Sonarqube 分析器

现在我们的 SonarQube 已经正式配置完毕,我们需要添加一个 Gradle 任务 sonarqube 到我们的 Jenkins 任务。我们在最后执行。

再次运行 Jenkins 任务,一旦运行完毕,我们可以在 localhost:9090 中看到我们的 sonarQube 控制面板。

分析结果的显示

点击项目名称我们可以进入到不同的显示界面,最重要的可能就是问题界面了。

在下一屏,我将展示一个主要问题,它是一个空构造器方法。就我个人而言,使用 SonarQube 最大的好处就是当我点击“...”时可以在屏幕底部显示解释。这是一个学习编程十分有用的技能。

第六步 附加:配置其他 Android 应用

想要配置 Android 应用得到覆盖率和 sonarqube 的结果,只要安装 JaCoCo 和 Sonarqube 插件就可以了。你也可以在我的示例中得到更多信息

你也可以看看我在云上测试的文章:

最后

啊,你终于走到头了,希望你觉得本文有点用处。你要是发现了任何错误,有任何疑问,别迟疑,赶紧评论。我拼了老命也要帮你。哦,忘了提醒,好东西要和朋友分享。


作者简介:

Entrepreneur & CEO at GreenLionSoft · Android Lead @MadridMBC & @Shoptimix · Android, OpenSource and OpenData promoter · Runner · Traveller


via: https://medium.com/@pamartineza/how-to-set-up-a-continuous-integration-server-for-android-development-ubuntu-jenkins-sonarqube-43c1ed6b08d3#.x6jhcpg98

作者:Pablo A. Martínez 译者:Taylor1024 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出