DevOps on Android: 加速 App 从代码到上线

DevOps 是一个众所周知的开发方法,其主要目的是自动化软件交付。事实上,DevOps 的目标是不断的测试,代码质量,功能开发,更容易维护版本。因此,DevOps 的一个最终目标是为开发者进行快速,可信赖和自动化发布提供指导,理想化状态是在这个过程中不牵涉任何人工劳动。这就是所谓的持续交付。我写这篇文章来证明,我们现在能在 Android 平台上达成这样的目标,同时和大家分享一下我的想法和听取大家的反馈。

持续集成为出发点

想要达到持续交付,持续集成必须是强制的。在安卓平台上的持续集成已经有一段时间了,为了更清楚的去了解,我们先说一下它的优势。

安卓平台必须采用持续集成方法,是的我说过。确实,持续集成有一些在构建 Android App过程中无法发忽略的好处。在我看来,它的优势在于:

  • 自动化构建:不再只是在我的机器,而是在所有的环境。

  • 早失败:一旦代码提交之后就马上构建,这样就保证错误能被及早的发现。

  • 构建测试:保证每一个测试用例都能正常运行。

  • 不断打包:防止打包过程中的人为错误。

  • 快速发布:既然我们对于每一次构建都有信心,那么发布就变得简单了

  • 增加信心:最后,我们相信我们的代码,我们的过程,我们减少不良的惊喜。

一个典型的持续集成过程

首先,我们需要一个集成服务器像Jenkins 或 Travis 。下面的工作是我的标准配置:

  • 启动一个监视代码推送到我们的代码仓库(Jenkins or Travis)完成事件的任务。该任务监视代码的 dev 分支去自动的编译、单元测试、打包或者 debug APK .

  • 当上面的任务完成之后,另外一个任务就要被启动了。这个任务主要用来跑集成测试(通过 Espresso 或者 Robotium)。在这个过程中,通过模拟用户场景和检查渲染的图形内容的方式来保证最终的用户体验。

  • 另外一个任务就是一个每天晚上都会运行的执行代码质量扫描(例如 Sonarqube )的任务。

  • 最后还有一个任务用来检测一旦代码仓库的 master/release 分支有更新就去构建发布的APK包。

看看吧,正如你看见的,这个过程很简单并且保证能达成我开始所说的优势。

测试是关键

我曾经写过一篇关于测试的文章(testing on Android)。测试是如此的重要因为它是能够保证App按照我们所设定的那样去工作的唯一工具。写单元测试有很多工具和方法,请明智的去选择。
此外,确认一下你要在你的应用程序集成的库。事实上,当你使用的库有一个良好的单元测试覆盖率的时候,就更容易测试您的App。一些被认为恰当测试的并且用测试驱动他们的开发的类库(例如 IMO, OkHttp and Retrofit )。很可能,你将能够在使用它的时候来测试它。
最后,像 Dagger 库可以帮助你提高可测试性。事实上,它会迫使你遵循单一职责原则和正确分开你的代码,从而更容易测试。
一旦你有一个强大的持续集成,让我们来看看如何提高水平。

持续交付: Level++

举例来说,在 Captain Train。我们发布每6周一次,我们都非常小心了。 目前每次发布都要做:

  • 我们有一个测试阶段
  • 我们支持 4 个区域设置。
  • 我们支持 3 种类型的设备(phone, 7 and 9 inches tablets)。
  • 我们经常检查我们的的 Play Store。
  • 我们写发行说明。
  • 我们使用部署功能。
  • 我们上传了 72 截图(6 screenshots * 4 locales * 3 types)

整个过程非常消耗时间,最近我们想,是时候去把这个过程给自动化了。即使我们的最终目标是减少发布时间。这种感觉非常好,去防止人为的犯错误以及经常的发布发布。我们能掌握整个过程,这样让我们更加有责任心。

但是,坦白的说,安卓开发者不能控制所有的事情,只有 Google 能做到。
例如,它暴露了一个 HTTP API,使开发人员能够使用 Play 商店控制台轻松互动。他们也提供了很多语言实现的语言包,例如Java ,Ruby 等。

在这篇文章,我讲专注于 Java 语言,因为对于安卓开发者来说,这是最容易的。

编写你自己的 App 发布工具

让我们看看如何编写自己的 App 发布工具来把 APP 发布到 Play Store 。大概有两个步骤:首先,我们将配置我们的控制台,使我们的客户端能够进行操作,进而我们就会发现其中的 API。最困难的事情经常用谷歌去配置。文档()可以在这里找到。请注意,这是一个有点过时。
配置
首先,如果没有做,你必须在谷歌控制台创建一个新的项目。然后,我们需要启用 Google Play Android Developer API。

一旦完成,我们必须创建服务帐户关键的凭证:

最后填写表格,并下载一个 json 格式的凭证。你需要保存三个值:private_key_id, private_key 、 client_email. 把 private_key 的值保存在 secret.pem 中.
我们正在与开发者控制台交互......现在让我们去到第二个控制台! \ O /
连接到您的控制台。你必须进入 Settings > API access:



然后,你必须简单地链接您的项目。最后,在 Service accounts,授予权限给你下的 JSON 文件中的的客户端邮件的client_email。

到现在为止,一切都准备好了。
API发现
现在,让我们深入到 Java 客户端 API。我们创建了一个单独的 Java 项目为我们的发布工具,我们添加下面的依赖(Maven的中央仓库有):

compile 'com.google.apis:google-api-services-androidpublisher:
         v2-rev20-1.21.0'

下一个步骤是创建一个 AndroidPublisher。首先我们通过提供 transport client, JSON factory,和 private_key_id 对应的 private key ID,和 client_email 对应的账户 ID 来实例化一个 GoogleCredential。ANDROIDPUBLISHER 是一个包含了私钥的关键文件。

http = GoogleNetHttpTransport.newTrustedTransport();
json = JacksonFactory.getDefaultInstance();

Set<String> scopes =
      Collections.singleton(AndroidPublisherScopes.ANDROIDPUBLISHER);

GoogleCredential credential = new GoogleCredential.Builder().
                setTransport(http).
                setJsonFactory(json).
                setServiceAccountPrivateKeyId(KEY_ID).
                setServiceAccountId(SERVICE_ACCOUNT_EMAIL).
                setServiceAccountScopes(scopes).
                setServiceAccountPrivateKeyFromPemFile(secretFile).
                build();

publisher = new AndroidPublisher.Builder(http, json, credential).
                setApplicationName(PACKAGE).
                build();

AndroidPublisher 对象是Google控制台的主入口,他有一个 Edit 方法,允许我们编辑控制台的数据。
要开始一个新的版本,你必须以发起插入请求,并存储它的返回值,你会在每一个后续调用中使用这个返回的 ID。

AndroidPublisher.Edits edits = publisher.edits();

AppEdit edit = edits.insert(PACKAGE, null).execute();
String id = edit.getId();

现在我们将改变我们的控制台数据,举例来说改变 listings:

Listings listings = edits.listings();

Listing listing = new Listing().
                        setFullDescription(description).
                        setShortDescription(shortDescription).
                        setTitle(title);

listings.update(PACKAGE, id, "en_US", listing).execute();

你也可以上传截图

Images images = edits.images();

FileContent content = new FileContent(PNG_MIME_TYPE, file);

images.upload(PACKAGE, id, "en_US", "phone5", content).execute();

最后一个例子,让我们上传一个 APK

// APK upload
Apks apks = edits.apks();
FileContent apkContent = new FileContent(APK_MIME_TYPE, apkFile);
Apk apk = apks.upload(PACKAGE, id, apkContent).execute();
int version = apk.getVersionCode();

// Assign APK to Track
Tracks tracks = edits.tracks();
List<Integer> versions = Collections.singletonList(version)
Track track = new Track().setVersionCodes(versions);
tracks.update(PACKAGE, id, "production", track).execute();

// Update APK listing
Apklistings apklistings = edits.apklistings();
ApkListing whatsnew = new ApkListing().setRecentChanges(changes);
apklistings.update(PACKAGE, id, version, "en_US", whatsnew).execute();

我推荐大家使用 API,因为它很完美并且很强大。
最后一步,你必须提交你的版本。事实上,到目前为止,谷歌记录您所请求的每一个变化,但是它只会保存您提交的变化。我也建议你尝试提交之前验证您的更改。

edits.validate(PACKAGE, id).execute();
edits.commit(PACKAGE, id).execute();

正如你看见的那样,开始所获取的 ID,就像是一个事务ID 一样。你开始事务之后,通过 insert, update/upload 来处理变化,并且通过 validate 方法验证 ,通过commit 方法提交。一切都如此简单。

讨论

现在我们可以遵循 devOps 原则,甚至对于安卓开发来说有了比较强大的持续交付能力。在 Captain Train 我们选择去写我们自己的发布工具以此来控制重要的每一个步骤。一旦 release 任务执行成功,我们就执行发布工具来发布 App。当然了Jenkin 和 Gradle 也有一些类似的工具可用。

诸如此类的工具能让你简单的通过向 master 或者 release 分支推送代码的方式来发布你的App。这个过程简单、可信赖、节省时间!
很明显,这个过程不一定适用于每个团队/公司/应用程序~ ,这取决于你所在团队的具体情况。但是,我要强调的是持续交付应该是每一个团队/公司的目标。一旦达成,它将驱动您走向成功。

原文:http://jeremie-martinez.com/2016/01/14/devops-on-android/

OneAPM Mobile Insight ,监控网络请求及网络错误,提升用户留存。访问 OneAPM 官方网站感受更多应用性能优化体验,想阅读更多技术文章,请访问 OneAPM 官方技术博客
本文转自 OneAPM 官方博客

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,732评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,496评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,264评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,807评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,806评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,675评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,029评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,683评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 41,704评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,666评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,773评论 1 332
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,413评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,016评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,978评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,204评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,083评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,503评论 2 343

推荐阅读更多精彩内容