Merge Conflict - 177: DevOps, DevOps, DevOps 封面

177: DevOps, DevOps, DevOps

177: DevOps, DevOps, DevOps

本集简介

It is all things DevOps for mobile apps this week. We try to get Frank inline with figuring out continuous delivery with several different products including App Center, Azure DevOps, Bitrise, and more. Follow Us Frank: Twitter, Blog, GitHub James: Twitter, Blog, GitHub Merge Conflict: Twitter, Facebook, Website, Chat on Discord Music : Amethyst Seer - Citrine by Adventureface ⭐⭐ Review Us ⭐⭐ Machine transcription available on http://mergeconflict.fm Support Merge Conflict Links: jonathanpeppers/boots: boots is a .NET global tool for "bootstrapping" vsix & pkg files. Just "boots https://url/to/your/package"! Mobile DevOps Video Series Azure DevOps Services | Microsoft Azure Visual Studio App Center | iOS, Android, Xamarin & React Native Bitrise - Mobile Continuous Integration and Delivery

双语字幕

仅展示文本字幕,不包含中文音频;想边听边看,请使用 Bayt 播客 App。

Speaker 0

弗兰克,你现在和我做的其实是同一件事。

Frank, both you and I are literally trying to do the same thing right now.

Speaker 0

把应用送到用户手里,可我们在这方面的努力全都失败了,弗兰克。

Get apps into our users' hands, and we're failing in every regard of life, Frank.

Speaker 0

现在就正在发生。

It's happening right now.

Speaker 1

是啊。

Yeah.

Speaker 1

我的知识早就过时了。

My knowledge is so out of date.

Speaker 1

我得来问你,因为我看到推特上有人传,说应用上传工具……

I had to ask you because I saw rumors on Twitter that application loader yeah.

Speaker 1

好像叫这个名字。

That's what it was called.

Speaker 1

这工具我用了好多年了。

That's the tool that I've used for years.

Speaker 1

上传个应用,感觉都像等了十年似的。

It almost feels like a decade to upload apps.

Speaker 1

结果苹果突然决定停掉它,不再支持了。

And Apple's decided to, stop shipping it, stop supporting it.

Speaker 1

人家明明说别再用这个工具了。

You're supposed to stop using it.

Speaker 1

我就跟詹姆斯说:我到底该咋办啊?

And I'm like, James, what am I supposed to do?

Speaker 1

我只好来问你。

I had to ask you.

Speaker 1

我挺过意不去的。

I feel bad.

Speaker 1

我真该多关注点 iOS 的新动向。

I should be more on top of iOS stuff.

Speaker 0

我觉得你这事儿挺逗的——居然跑去问个搞 Android 的,怎么发 iOS 应用。

I like that you had to ask the Android guy how to distribute your iOS app.

Speaker 1

我就想,我这儿有好几个可执行文件呢。

I'm like, I got I got these executables.

Speaker 1

得赶紧发出去给用户,但说实话,这事儿我一直搁在心里没管。

I need to get them out to people, but turns out, I just it's been in the back of my mind.

Speaker 1

我跟你说过,我在推特上看到过这事儿。

Like I said, I've seen it on Twitter.

Speaker 1

对啊。

Mhmm.

Speaker 1

好多人都在说这事正在发生。

People are mentioning that this is happening.

Speaker 1

可我上个月根本没发过任何应用,所以一直没碰上这问题。

I just haven't actually released any apps in the last month, so I haven't had to deal with it.

Speaker 1

现在可好,终于轮到我来处理了。

So now I'm dealing with it.

Speaker 1

然后你跟我说了件特别糟心的事。

And then you said something terrible to me.

Speaker 1

你意思是,要是你的应用上了CI就好了。

You're like, well, if your apps were in CI.

Speaker 1

我就说,詹姆斯,我的应用当然在CI里啊,但我猜你是想说还得有CD吧。

And I was like, James, of course my apps are in CI, but I think you were implying some sort of CD thing also.

Speaker 0

对。

Yes.

Speaker 0

我忘了说,是持续集成和持续交付。

I forgot to say continuous integration and continuous delivery.

Speaker 0

弗兰克,要是你有套CI/CD流水线,那就万事大吉了。

If you had a CICD pipeline, Frank, then you'd be good to go.

Speaker 1

所以我回你的是,詹姆斯,这事儿我们在《Merge Conflict》里聊过无数次了。

So my reply was, James, we've talked about this on Merge Conflict constantly.

Speaker 1

我的CI做得挺好的。

I have good CI.

Speaker 1

我甚至还专门做了一个小展示屏。

I even have, a little marquee display that I made.

Speaker 1

你还记得吧,我之前说过那个显示构建状态的物联网设备?

Remember, was talking about my IoT device that displays build status?

Speaker 1

CI 我搞得挺溜的。

I am good at CI.

Speaker 1

CD?我压根没管过。

CD, I've completely ignored.

Speaker 1

根本没做那事儿。

Not doing that.

Speaker 0

对。

Yeah.

Speaker 0

那咱们先说说,你平时怎么搞构建的?

So, okay, let's talk first here about how you get your builds.

Speaker 0

就拿开发者本地构建来说吧。

So do for developer builds.

Speaker 0

你 CI 是搭好了,但你有拿构建产物做点啥吗?还是说就光看个‘构建成功’就完事了?

Okay, so you have continuous integration set up like, do you ever do anything with the artifacts in your continuous integration or is it just a, hey, this thing built successfully.

Speaker 0

点赞。

Thumbs up.

Speaker 0

我特别期待这个。

I'm very excited about it.

Speaker 1

对。

Yeah.

Speaker 1

我这边有点乱七八糟的。

I'm a little bit all over the map.

Speaker 1

我说啊,我一半以上的应用,其实大部分都只是点个赞而已。

So I would say for half of my apps, probably more than that, the majority of my apps, it is just a thumbs up.

Speaker 1

能跑起来就行,跑跑测试,差不多就完了。

Build or no build, run some tests, that kind of thing.

Speaker 1

连设备测试都基本不做。

Usually not even, device tests, almost always not even device tests.

Speaker 1

不过呢,我确实有几个应用用的是微软的移动应用中心——2019年那会儿叫这名字,不是HockeyApp那个老工具,那个还挺不错的。

That said, I do have a few apps in, Microsoft's mobile app center, whatever it's called in 2019, not hockey app tool thing, which, is quite nice.

Speaker 1

我觉得,对于免费账号来说,他们能帮你自动构建,甚至确保应用能在真机上跑起来。

I think for a free account out there, they'll do builds for you and even make sure that the app starts up on a device.

Speaker 1

所以我那些大点的项目都会用这个,就图个万无一失。

So I have that for, my bigger apps, just so I I can be absolutely sure.

Speaker 1

另外,不好意思老占着话筒,这还跟我怎么管测试人员有关。

Plus, sorry to keep hogging, but, it comes down to how I deal with beta testers also.

Speaker 1

有些人用 App Center 做内测分发。

So some people have beta testing through App Center.

Speaker 1

有些人则用苹果自己的那一套。

Some people have beta testing through Apple's thing.

Speaker 1

所以针对这些,我的发布流程完全不一样。

And for that, my deployment is all different.

Speaker 1

天哪,詹姆斯,我刚意识到,我说这事儿简直乱成一锅粥。

Oh my god, James, I'm just realizing how scattered I am about all of this stuff.

Speaker 0

这也很正常吧,你都干了十年了,说不定还在维护十年前的老项目?

Well, it's hard when you've been doing it for what, ten years and probably still supporting apps that are ten years old?

Speaker 1

是的。

Yeah.

Speaker 1

没错。

Exactly.

Speaker 1

但就连这个,也只是懒得把所有东西都迁移到一个系统上罢了。

But even that, it's just a laziness not to move everything over to one system.

Speaker 1

尤其是最近,GitHub Actions 加入了,我简直爱死了它。

Even now, lately, GitHub actions has been added, and I am absolutely in love with it.

Speaker 1

但那纯粹是 CI,持续集成、持续构建,就是通过或不通过。

But that is most definitely just CI, continuous integration, continuous builds, thumbs up, thumbs down.

Speaker 1

我是不是把代码搞崩了?

Did I break the code or not?

Speaker 0

我觉得这还挺搞笑的,因为我们聊过 CI 和 CD,也扯过一堆库的事儿。

I I feel like this is funny too because we've talked about CI and CD and we bullshit a lot of libraries.

Speaker 0

我觉得搞 DevOps 的人,说到库这一块,我们其实心里有数。

I feel like for DevOps, we're talking DevOps people, for libraries, I feel like we have that under control.

Speaker 0

我这边全都用 Azure DevOps,特别顺手。

For me, I build everything in Azure DevOps easily.

Speaker 0

直接去构建这个库,然后自动发布到 NuGet 就行了。

Just go build this library and then ship it to new get right.

Speaker 0

就像 NuGet 一搞定,完事。

Just like and new get done.

Speaker 0

整个流程特别流畅。

It's like very seamless.

Speaker 0

要是打了 beta 标签,那就是 beta 包。

And if I have it with a beta tag, then it's a beta package.

Speaker 0

要是没打 beta 标签,那就不是 beta 包。

If I don't have it with a beta tag, then it's not a beta package.

Speaker 0

对啊。

Right.

Speaker 0

我就希望现实真是这样,大家都能一眼看懂这逻辑。

It's like it's like that's the world that I wish we lived in and everybody just gets it.

Speaker 0

但我们现实里不是这样的,因为你刚才说的,测试人员的设备可能还得注册。

But we're not in that world because what you just said, you have testers where maybe their devices have to be registered.

Speaker 0

他们可能是通过TestFlight获取应用,也可能通过邮件接收,或者干脆手动安装到设备上。

Maybe they're getting it through test flight, maybe they're getting it via an email, maybe they're sideloading it onto their device.

Speaker 0

一堆证书、配置,乱七八糟的事情全堆在这儿了。

And there's all these certificates provisioning and all this shenanigans going on.

Speaker 0

我们真正想要的,就是别人下载完就能直接测试。

And what we really want to have happen is someone downloads it and then to test it.

Speaker 0

对。

Right.

Speaker 0

首要目标就是:我想能随时下载并测试我自己的版本。

This is like the first goal is like the first goal is that I want to be able to download and test my own build.

Speaker 0

这可是我最想做到的,哪怕我本地编译成功了,也不代表我发到App Store的版本就一定没问题。

Like, that's the first thing I want to do, because even if I build it locally, it doesn't necessarily mean that what I'm shipping to the app store is correct.

Speaker 0

这就是持续交付最根本的出发点:我怎么才能持续地把应用交付到自己手上?

And that's that's the first like framing of continuous delivery is how can I continuously deliver an app to me?

Speaker 0

这样说得通吧?

Does that make sense?

Speaker 1

是的,完全明白。

Yeah, absolutely.

Speaker 1

我得澄清一下,我到底该怎么发布一个应用呢?

And I should say and clear the air here, how do I actually ship an app?

Speaker 1

我从不会直接把CI服务器上的构建包上传上去。

I never take a build off of a CI server and upload that.

Speaker 1

我对任何自动化的东西都不放心。

I just don't trust anything.

Speaker 1

所以每次真正要发布应用时,我都会在自己的电脑上亲手构建。

So whenever I really, really release an app, I build it myself on my own machine.

Speaker 1

我会去把bin和obj文件夹彻底清空。

I go to the bin and OBJ folders, I wipe them out.

Speaker 1

然后自己重新构建应用。

I build the app.

Speaker 1

我把它归档。

I archive it.

Speaker 1

然后我会部署到设备上,做最后一次手动测试,再上传到苹果。

Then I start deploying it to devices and do one last test manual test pass, and then I upload to Apple.

Speaker 1

我该怎么在流水线里自动化这一切啊?

How in the world do I automate all of that in a pipeline?

Speaker 0

什么?

What?

Speaker 0

像动物一样?

Like an animal?

Speaker 0

天哪。

Oh my gosh.

Speaker 0

我的天

Oh my

Speaker 1

我的天啊。

goodness.

Speaker 1

不是。

No.

Speaker 1

好吧。

Okay.

Speaker 1

你给我讲清楚。

Set me straight.

Speaker 1

你给我讲清楚。

Set me straight.

Speaker 0

行。

Okay.

Speaker 0

这也不是什么大不了的事。

So that's not the worst thing in the world.

Speaker 0

我可是干了这么多年了。

You know, I did this for for many years.

Speaker 0

说实话,弗兰克,我跟你透露个小秘密。

And and to be honest, Frank, let me let me tell you a little secret.

Speaker 1

我到现在偶尔还会这么做。

I still do this today sometimes.

Speaker 1

当然了,这方法经得起时间考验。

Of course, it's a it's a tried and true method.

Speaker 1

可能会有点疼。

It may be painful.

Speaker 1

可能慢点,但管用。

It may be slow, but it works.

Speaker 1

我喜欢这个。

I like that

Speaker 0

Visual Studio、Visual Studio for Mac 和 Xcode 都自带归档功能。

Visual Studio and Visual Studio for Max and Xcode.

Speaker 0

它们内置了归档功能。

They have the archiving built in.

Speaker 0

我特别喜欢这个归档工具,哪怕你不用持续集成,它也相当于持续交付了。

I like I love this feature, the archiving tool, because even if you're not using CI, it's sort of like in CD, I should say.

Speaker 0

这就像你自己的版本管理一样。

It's kind of like your own versioning.

Speaker 0

至少你知道,嘿,这个版本特别靠谱,我把它发出去了,因为有存档记录。

You at least know like, hey, this is this magical build and I shipped it to somewhere because it's archived.

Speaker 0

以前我存版本就靠一个Dropbox文件夹,里面分安卓、版本号,再把APK放进去。

Previously, my archive was a Dropbox folder that had Android and then the version number and then like the APK inside of it.

Speaker 0

我就靠这个记住自己发到App Store的是哪个版本。

Like, that's how I remember what build I shipped to the App Store.

Speaker 0

那做法真是够烂的。

That was that was bad news.

Speaker 0

那是八年前的事了。

That was like eight years ago.

Speaker 0

我现在肯定进步多了。

I've definitely come further.

Speaker 0

你说得对。

You're right.

Speaker 0

至少要把应用提交到谷歌或苹果时,最棒的是Visual Studio和Xcode都会一步步带你完成。

At least to get it to Google or to Apple, the cool part is that Visual Studio and Xcode will walk you through it.

Speaker 0

安卓这边,你直接从Visual Studio就能把应用推送到Google Play。

Android, you can ship to Google Play directly from Visual Studio.

Speaker 0

这简直太神奇了。

That's magical.

Speaker 0

这个应用到底是什么?

The app, what is it?

Speaker 0

以前叫Application Loader。

It used to be Application Loader.

Speaker 0

现在那个工具没了,换成了Transporter。

It's gone and now it's transported.

Speaker 0

你下载Transporter了吗?

Did you download Transporter?

Speaker 0

这名字起得真不错。

It's a cool name.

Speaker 0

他们肯定是看太多杰森·斯坦森的电影了。

They're watching too many Jason Statham movies, I think.

Speaker 1

明白,先生。

Yes, sir.

Speaker 1

我刚登录上去,想把那些开发账号的密码全想起来。

And I'm just logging into it, trying to remember all my dev passwords.

Speaker 1

界面一片空白,乱七八糟的,跟以前的Application Loader一模一样。

And the UI is blank and confusing, just like the old app loader.

Speaker 1

我真迫不及待想搞明白这玩意儿怎么用了。

So I can't wait to figure out how to use this puppy.

Speaker 0

谢谢啦,App Loader。

Thanks, App Loader.

Speaker 0

是的。

Yeah.

Speaker 0

谢谢,Transporter。

Thanks, Transporter.

Speaker 0

谢谢,苹果。

Thanks, Apple.

Speaker 0

对。

Yeah.

Speaker 0

我觉得他们这么做是因为现在人们分发的不只是应用,还有别的东西。

And then that's I think they they they did this because people are distributing more than just apps.

Speaker 0

他们还在分发媒体内容。

They're distributing media too.

Speaker 0

所以这就像一个一站式平台,方便把所有东西都传给苹果。

So it's like one stop shop, I think, for getting everything to Apple.

Speaker 1

没错。

Yeah.

Speaker 1

咱们再回来说说归档的事吧。

So let's go back to the archiving.

Speaker 1

这么做其实有个特别好的理由。

There's one really good reason, for doing it.

Speaker 1

但也有不少坏处。

There's a few bad reasons.

Speaker 1

占地方,尤其是十年后,简直堆成山。

They take up a lot of space, especially after ten years.

Speaker 1

我其实没保存完整的归档记录。

I I've I don't have a a complete archive history.

Speaker 1

换设备的时候就全丢了,毕竟文件太大了。

I've lost it between machines and all that because they're huge.

Speaker 1

不过最近几年的记录我倒是保存得挺全的。

But I have a pretty good, decent recent history.

Speaker 1

归档工具的好处是,当你拿到苹果发来的崩溃日志时,里面有符号信息,能清楚看出到底是哪里崩溃了。

The good thing about the archive tool is that when you get crash logs from Apple, you have symbol information, and you can make sense of what actually crashed.

Speaker 1

我觉得随着我们发布应用的方式变了,这点也在慢慢改。

I think that this is changing a little bit with how we deploy apps.

Speaker 1

应用。

Apps.

Speaker 1

不过我敢打赌,我们部署应用的时候还是没上传符号表。

I'm pretty sure we still don't upload symbols when we're deploying apps, though.

Speaker 1

所以我们还是得把那些符号表存起来。

So we still need to keep those symbols somewhere.

Speaker 1

如果你有这种归档文件,苹果会用它计算出一堆复杂的哈希值,用来匹配崩溃日志和对应的二进制文件。

And if you have, one of these archives, Apple calculates all the crazy hash codes it uses to determine which crash log is associated with which binary.

Speaker 1

如果你干这行久了,就知道这系统有多乱了。

And if you've done this for a while, you know it's a very hairy system.

Speaker 1

你只要在包里改了一个字节,符号表立马就全找不到了——就因为哈希值对不上了。

You change one byte in your package, and all of sudden, you don't get symbols anywhere, like a byte anywhere, just because the hashes don't match anymore.

Speaker 1

所以这个归档工具确实能帮我们把这些东西管得井井有条。

So the archiving tool is great for keeping all that stuff in line.

Speaker 1

不过话说回来,我觉得在CI系统里其实也能自动生成这些归档文件。

That said, I'm pretty sure even in a CI system, you could generate these archives.

Speaker 1

你试过这么干吗?

Have you tried doing that?

Speaker 0

是的。

Yeah.

Speaker 0

当你编译 iOS 或 Android 应用的时候,我觉得编译器里有一些参数可以传,比如 iOS 的 DSYM,就是调试符号那一块。

So when you generate and compile up your iOS or Android app, I think there's certain flags that you can pass to the compiler to create your for iOS, it's the DSIM, the debug symbols part of it.

Speaker 0

在我的持续集成流程里,你其实就是生成一个归档文件,对吧?

And during my continuous integration cycle, you can you're just creating an archive for all intents, right?

Speaker 0

对,就是这个意思。

That's the that's the idea there.

Speaker 0

对我来说,持续集成分两步:第一步是构建调试用的开发包,第二步是构建或签名发布包。

So for me, when I think of my continuous integration, there's two steps to it, which is how do I first build my debug developer package and then how do I build or sign my release package?

Speaker 0

这两种情况,我都需要保留调试符号。

And for both of those, I want to have those debug symbols.

Speaker 0

所以这里就有点意思了——如果你像说,嘿,我完全不想用任何云服务,所有东西都跑在本地机器上。

So I think this is where it becomes interesting because for you, if you're like, Hey, I don't want to use any services, everything's on a machine.

Speaker 0

那太好了,因为你完全可以在本地搞定这一切,东西也都在自己手上。

That's great because you have the ability to do this all on your machine and it's there.

Speaker 0

但问题是,这很耗时,对吧?

The problem, though, is it's time, right?

Speaker 0

占时间、耗电量、还占硬盘空间。

It's like it's time, it's energy, it's hard drive space.

Speaker 0

我自己的目标就是,写完代码后,想直接推到设备上,不用搞什么额外操作。

And I think the goal that at least I had was I want to commit code and I want to get it onto my device without having to do anything special.

Speaker 0

真的不想搞什么特殊步骤。

Like, don't want to have to do anything special.

Speaker 0

然后从那儿,我想立刻把包上传到 App Store。

And then from there, I want to immediately ship that package to the App Store.

Speaker 0

就是这个。

That.

Speaker 0

这基本上就是我的终极目标。

That's my goal in general.

Speaker 0

所以你问我,比如那个应用加载器去哪儿了,我现在用的是 Transporter 这个工具。

So when you ask me like, oh, like where the application loader go and I got it on this transporter thing.

Speaker 0

对我来说,这种事太常见了,顺便说一句,不光是我,整个互联网都炸了,Objective-C、Swift、Xamarin的开发者都在问:这玩意儿去哪儿了?

Like for me, I saw this all the time, by the way, weren't the only one like literally the Internet blew up from both Objective C and Swift and Xamarin developers like, Where did it go?

Speaker 0

我当时就想,天啊,我三年都没打开过这东西了。

And I was like, Man, I haven't opened that thing in three years.

Speaker 0

这挺有意思的,因为我觉得大家还是在走这条路。

I was like, That's kind of interesting because I feel like everybody is still going down this route.

Speaker 0

从归档到完整的DevOps,中间肯定有什么特别难搞的地方。

There must be something hard about taking it from archive to full DevOps.

Speaker 0

肯定不容易。

That must be difficult.

Speaker 0

你那儿卡在哪儿了?

Like, what's your roadblock there?

Speaker 0

这个我才真想知道。

That's what I'm really curious about.

Speaker 1

行,那咱们可以好好聊聊这个。

Okay, so we can definitely get into that.

Speaker 1

不过在那之前,我再问你个宏观点的问题。

But first, let me ask one more high level question of you.

Speaker 1

你们在做测试包和发布包的时候,是怎么区分的?

When you're doing, how are you differentiating between test builds for beta testers and distribution builds?

Speaker 1

就是说,你们具体是怎么操作,来生成这两种不同的包的?

Like, what is your physical different action for creating those two different things?

Speaker 1

还是说你们一直都是自动处理,两个一起搞?

Or is it still always automatic like you do both always?

Speaker 0

嗯,是这样。

Okay.

Speaker 0

在咱们聊为什么你们做不到之前,我先说说我当初是怎么做的,然后你再告诉我,为啥你们没法走我这条路。

So here's let's let's before we talk about why you can't get there, let me tell you what I did, and then you can tell me why you can't get to what the thing that I did.

Speaker 1

你是不是该按我说的顺序来?

Does that Should make I go in your order?

Speaker 1

我先说说我的情况。

Let me tell you my No.

Speaker 1

不行。

No.

Speaker 1

不行。

No.

Speaker 0

我觉得这值得说,因为你刚才描述的问题真的很难,对吧?

Think it's worth I think because the problem you just described is really hard, right?

Speaker 0

因为测试员和非测试员不一样。

Because testers versus non testers.

Speaker 0

这是我的理想流程,弗兰克。

So here's my optimal flow, Frank.

Speaker 0

我觉得每个开发者今天都该这么干。

Here's what I think is what every developer should be doing today.

Speaker 0

我特别喜欢两个产品。

There are two products that I like.

Speaker 0

它们恰好都是微软的。

They both happen to be from Microsoft.

Speaker 0

第一个其实无所谓。

The first one actually doesn't matter.

Speaker 0

就是持续集成。

It's continuous integration.

Speaker 0

你用哪个持续集成服务都行。

You can use any continuous integration service you want.

Speaker 0

就是把你的包、源码、应用编译构建一下。

This is just building your package, building your source code, compiling your app.

Speaker 0

然后把这些产物通过持续交付的发布流水线传到别的地方去。

And then those things take artifacts and then you ship them to something else through a continuous delivery release pipeline.

Speaker 0

所以这里的第一步就是持续集成。

So the first part here is the continuous integration.

Speaker 0

我用的是 Azure DevOps,iOS 和 Android 都用免费的托管 Mac 构建代理。

And I use Azure DevOps and I use the free hosted Mac build agents for iOS and Android.

Speaker 0

它们预装了所有 Xamarin 的组件,我还装了一个叫 Boots 的插件,是 Jonathan Peppers 做的,能让你在这台机器上安装指定版本的 Mono 和 Xamarin iOS、Android。

They have all the Xamarin bits installed, but I also use a plug in from Jonathan peppers called boots, which allows you to install specific versions of mono and specific versions of Xamarin iOS and Android on that machine.

Speaker 0

每次大概就一分钟,挺快的,毕竟这是托管服务,软件不是你管,是微软在管。

It takes like a minute each, so it's pretty slim because these are hosted, The software is not managed by you, it's managed by Microsoft.

Speaker 0

不过他们确实提供托管的 Mac,这点挺棒的。

But there are hosted Macs, so that's cool.

Speaker 0

我就这么干。

I do that.

Speaker 0

至于 Android,我现在是在同一个阶段里构建两次我的应用。

Now for Android, what I've done is I build my application twice in the same phase.

Speaker 0

每次启动构建,都会分两个阶段:Android 和 iOS,它们是并行运行的。

When I kick off a build, there's two phases, Android and then iOS, and these run-in parallel.

Speaker 0

Android 阶段会搞定我需要的所有东西。

Android will get everything I need.

Speaker 0

它会生成我的 APK,就是我们一直用的那种 Android 安装包。

It builds my APK, so my Android package like we've always used.

Speaker 0

最近我把整个持续集成流程都升级了,改用 App Bundle,这是种新格式,只要加几个编译参数,就能生成 AAB 文件。

And then I just recently upgraded all of my continuous integration pipelines to use app bundles and app bundles are a new format and you just pass it some compiler flags that give you an AAB, an Android app bundle.

Speaker 0

这样做的好处是,Google Play 可以按需把你的应用拆分打包。

What that does is allows Google Play to split your application up on demand.

Speaker 0

能让你的安卓应用体积减少高达一半,挺棒的,而且完全不用改代码。

It reduces your app size on Android up to 50%, which is cool, and you don't have to change any code.

Speaker 0

到头来,我会得到两个安装包。

I get two packages at the end of the day.

Speaker 0

在安卓这边,有个特别方便的地方:我签个名,这个包就能直接传给 Google Play、发给测试人员,或者装到自己手机上。

Now in Android, we live in this beautiful world where I sign my application and that's the same exact package that I can give to Google Play or send to a tester or put on my device.

Speaker 0

说白了,就是同一个东西,对吧?

It's the same thing, right?

Speaker 0

一切都挺顺的。

It's all good.

Speaker 0

至于 iOS,我就得再走一个流程。

Now in iOS, I have another phase.

Speaker 0

它会在 Mac 上做同样的事,装上我需要的 Xamarin iOS 版本。

It does the same thing on a Mac and installs a version of Xamarin iOS that I want.

Speaker 0

然后在我的持续集成服务里,我会先用我的开发者证书签名。

And then I on my continuous integration service, I sign with my developer certs first.

Speaker 0

好了,现在。

Okay, now.

Speaker 0

这事儿有好几种做法。

There's a few ways of doing this.

Speaker 0

有些人喜欢把 iOS 应用打包两次,一次用开发证书,一次用发布证书。

Some people like to build their iOS app twice and they'll say, Here's the iOS developer cert, and then here's one with my distribution cert.

Speaker 0

这其实要看你用不用不同的后端,对吧?

It really depends if you're using different back ends, right?

Speaker 0

你的应用里需要编译不同的 URL 吗?

Do you need to compile different URLs into your application?

Speaker 0

那就有点头大了,因为你真得打包两次。

Then that gets tricky because you do have to compile your app twice.

Speaker 0

不过我常用的一个小技巧是,直接用我的开发者账号来构建和签名。

However, one trick that I like to do is build and sign with my developer account.

Speaker 0

但在 Azure DevOps 里有个特别方便的构建步骤,能让你用任何其他证书重新签名 IPA 文件。

But then there's a magical build step in Azure DevOps that lets you re sign your IPA file with any other cert.

Speaker 0

所以我的持续集成产物里,Android 文件直接出来,iOS 则会生成两个 IPA 文件。

So on my continuous integration drop, I get my Android bits and then iOS, I get two IPAs.

Speaker 0

一个用开发者证书签名,另一个用 App Store 证书签名。

I get one signed for developer and one signed for App Store.

Speaker 0

你可以用任意证书重新签名,因为 IPA 本质上就是个签名流程。

You could re sign it with whatever because the IPA is just a signing process.

Speaker 0

整个过程其实就是个签名步骤,特别爽。

It's just a signing step, which is really cool.

Speaker 0

这就是我的持续集成流程,目前只做到构建阶段。

And that's my continuous integration, just my build phase.

Speaker 0

Frank,这里有什么问题吗?

Any questions there, Frank?

Speaker 1

太厉害了。

Wow.

Speaker 1

咱们要聊的内容可真不少。

We have a lot to cover.

Speaker 1

咱们先说说吧,你也不用给我上课,但到底什么是 Boots 呢?

Let's start with tell me more about well, you don't have to lecture me, but what boots?

Speaker 1

Boots。

Boots.

Speaker 1

我超爱 Boots 的。

I love boots.

Speaker 1

再多给我讲讲吧。

Tell me more about it.

Speaker 1

所以它是个脚本吗?

So is it like a script?

Speaker 1

然后安装起来很快是吧?

And so it's a quick install?

Speaker 1

它是像 Linux 那样的工具?哦不对,应该是 Mac 上用的吧?

Is it like a Linux or sorry, it would be a Mac tool?

Speaker 1

那它也能在 Mac 上用吗?

Is it a Mac tool also?

Speaker 0

当然可以。

Yes.

Speaker 0

问得好。

Great question.

Speaker 0

Boots 是 John 和 Peppers 开发的,是个能在任何机器上跑的构建脚本工具。

Boots is from John and Peppers, and it is a build scripting tool that can work on any machine.

Speaker 0

Linux、Windows、Mac,哪儿都行。

Linux, Windows, Mac, anything.

Speaker 0

它就是一个命令行工具。

It's just a command line tool.

Speaker 0

厉害的是,他们还给 Azure DevOps 做了个任务插件,界面特别漂亮。

The beautiful part is that they wrote a task plug in for Azure DevOps, so it's very pretty UI.

Speaker 0

但如果你用 YAML,或者别的 CI 服务,直接写一句‘用 boots’,指定要装哪个 Mono 版本,再丢个 Mac 的安装包,它就自动下载安装了。

But if you're in YAML, basically, or if you're on your other CI service, you just say, Hey, use boots, go install this mono version and you give it the pkg for Mac and it installs it and it just downloads it.

Speaker 0

所以它会自动帮你下载、安装,全搞定。

So curls it, installs it, does everything for you automatically.

Speaker 0

Peppers之所以做这个,是因为我们在Xamarin开发者大会上聊到这个问题:我的应用跑得好好的,结果一更新Xcode,CI构建就崩了,因为我根本管不了那台服务器。

And the reason Peppers did this was because we were at the Xamarin Developer Summit and we were talking about this problem, which is I have my app running and building, and then there's a new version of Xcode and then my app stops building on CI because I'm not managing that server.

Speaker 0

于是Boots就派上用场了——它让我能自己控制Mono、Xamarin iOS和Android的版本。

So boom, that's where boots comes in because it allows me to control the mono and the Xamarin iOS and Android version.

Speaker 0

一切都在掌控之中,而且你能在任何机器上用。

And and then it's it's just in control and and you can use this on any machine.

Speaker 0

说白了就是个命令行工具,挺酷的。

So it's just a command line tool, which is cool.

Speaker 1

太棒了。

Love it.

Speaker 1

迫不及待想试试,好好折腾一下。

Can't wait to try that out and abuse it.

Speaker 1

看看能往里头塞哪些版本。

See which versions I can put in there.

Speaker 1

我觉得我们一直没法回避的一点是,Xcode 会不断更新。

I think one thing that we're always stuck with is, Xcode changes over time.

Speaker 1

平时倒没什么问题,但到了那个‘精彩’的测试版季,就肯定出岔子。

That usually doesn't cause any issues, but during, you know, the wonderful beta season, of course, it does.

Speaker 1

我通常得忍上几个月。

I usually have to accept it for a couple months.

Speaker 1

因为 CI 上的项目老是构建失败,都是因为用了什么测试版之类的。

My apps just don't build in CI because they're using, like, beta versions and all that.

Speaker 1

不过嘛,这几个月咱们可以先不管,这点还挺有意思的。

But we can ignore those couple months, so that's interesting.

Speaker 1

我很喜欢这个设计。

And I like that.

Speaker 1

特别喜欢。

I like it a lot.

Speaker 1

尤其是你说它跑得很快,这点太棒了。

Especially like that you say it's fast.

Speaker 1

我真想马上试试这个。

I can't wait to try that on.

Speaker 1

我打算在 Bitrise 和 GitHub Actions 都试一遍。

I'm I'm gonna try both on Bitrise and GitHub actions.

Speaker 1

我俩都用得特别疯。

I use both kind of crazily.

Speaker 1

你刚才说的那点太到位了,我差点儿觉得自己傻——其实根本不用重新编译,直接重新签名就行。

So I think the last point you made was smart, and I felt a little bit dumb was that, of course, you can just resign the app.

Speaker 1

你没必要编两次,我以前就干过这种事:复制粘贴一遍构建脚本,然后说:‘这次咱用这套证书。’

You don't have to build it twice because I could totally see myself just copying and pasting the build script and being like, well, this time we're gonna do it with these certs.

Speaker 1

知道这个真挺让人松口气的。

So, that that was nice to know.

Speaker 1

这里有个坑,Danny Ackerman,你在听吗?

A tricky part here, Danny Ackerman, are you out there?

Speaker 1

就是当你有 WatchKit 扩展这类东西的时候。

Is when you have, extensions like watch kit extensions and things like that.

Speaker 1

重新签名挺麻烦的,因为我也不太清楚为啥。

Resigning is hard because I don't know.

Speaker 1

每次想重新签名一些复杂的东西,总是搞不定。

It just never seems to work whenever you try to resign, complex things.

Speaker 1

我真想看看那个步骤的源码,就是Azure DevOps里那个重新签名的步骤,或者你们叫它啥来着?

But I would love to see the source code to that step or what do you call it in Azure DevOps when you have like a step like that or a workflow item resigning?

Speaker 0

那是个步骤,不过我们管它叫任务。

It's a the it's a step, but we call it a a a task.

Speaker 0

所以A

So A

Speaker 1

任务。

task.

Speaker 1

对。

Yeah.

Speaker 1

那这个任务是开源的吗?

So are is that, like, open source?

Speaker 1

我能看看这个‘离职’功能是怎么实现的吗?

Could I see the code to how resigning works?

Speaker 1

我想看看他们能不能处理这种情况。

I'd be interested to see if they can handle that situation.

Speaker 0

哦,当然。

Oh, yeah.

Speaker 0

微软内置的所有 Azure DevOps 任务源代码都在 GitHub 上开源的。

All of the Azure DevOps built in tasks from Microsoft are all open source on GitHub.

Speaker 1

太棒了。

Super sweet.

Speaker 1

不错。

Cool.

Speaker 1

是的。

Yeah.

Speaker 1

我一般都用脚本来搞定一切。

I tend to do everything with scripts.

Speaker 1

所以如果我不懂怎么弄,我就觉得这事儿根本没法做。

And so if I don't know how to do it, I assume it can't be done.

Speaker 1

多去看看别人的代码挺好的,学学他们是怎么搞定这些棘手的小问题的。

Be good to go read someone else's code and see how they accomplish these tricky little things like that.

Speaker 0

是的。

Yeah.

Speaker 0

而且说真的,你其实可以在任何 CI 服务器上做这件事。

Now the cool part too is that like for me, you could of course be doing this on any CI server.

Speaker 0

比如用 Bitrise,或者 App Center,类似的工具都行。

Like you could be using Bitrise or you could use App Center or things like that.

Speaker 0

我偏爱用 Azure DevOps,是因为我大部分应用都不只是个 App,还有别的组件。

The reason I like to do it on Azure DevOps is most of my apps have other components besides just the app.

Speaker 0

像 Handshake 和 Forms 这些,我都会连着部署一些 Azure 函数,而且我也想统一管理版本。

Even handsome and forms, I'm deploying some Azure functions along with my my my apps and I also want to control versioning.

Speaker 0

所以我还是喜欢用这儿。

So I like it there.

Speaker 0

这些功能在其他平台甚至Boot上也完全能实现。

These are totally accomplishable in other services and even boots.

Speaker 0

比如你去Boot官网,他们都有教程,教你怎么在Azure DevOps、App Center、GitHub Actions和Bitrise上搞。

Like when you go to boots, they have scripts on how to do it in Azure DevOps App Center, GitHub Actions and Bitrise.

Speaker 0

所有东西都给你准备好了,特别方便。

It's all there for you, which is really cool.

Speaker 0

他们确实会一步步带你做,但我还是更喜欢自己掌控流程,我觉得这样才爽。

They walk you through it, but I like to be in control of it a little bit more, which I think is really nice.

Speaker 0

我觉得这其实就只是构建部分,说白了就是搞清楚构建到底要做什么。

I think that's just the build part of it, it's just knowing what goes into a build.

Speaker 0

无非就是版本管理、打包、签名,就这三样。

It's versioning, it's building, it's signing and that's it.

Speaker 0

希望你的CI服务够灵活,对吧?

And hopefully your your CI service is flexible enough, right?

Speaker 0

就像你说的,它允许你写脚本,但App Center给我的控制太少了。

It's like you said, it lets you do scripting and App Center doesn't give me enough control over that.

Speaker 0

所以我从不用 App Center 做构建。

That's why I don't use App Center for my builds builds.

Speaker 0

所以我才用 Azure DevOps。

That's why I use Azure DevOps for it.

Speaker 0

但更重要的是下一步——持续交付:我会把 CI 服务(也就是 Azure DevOps)生成的产物,导入到发布流水线里。

But the important part is the next step, which is continuous delivery, which is I take those artifacts from that continuous integration service, which happens to be Azure DevOps, and then I put it into a release pipeline.

Speaker 0

这事儿也是在 Azure DevOps 里完成的。

It also in Azure DevOps.

Speaker 0

整个流程是自动流转的。

Like it automatically flows.

Speaker 0

不过在这方面,我还是会把东西推到 Azure DevOps 的发布管道里。

But, you know, in this regard, I ship it over to to the Azure DevOps release pipeline tool.

Speaker 0

我喜欢这里的一点是,发布流水线能清晰地展现流程。

And what I like here is that the release pipeline gives me a flow.

Speaker 0

发布过程里会分好几个环境或者阶段,对吧?

There's sort of these environments or stages to a release, right?

展开剩余字幕(还有 480 条)
Speaker 0

你有开发者版本、测试版本,然后才是App Store版本。

You have developer release and then you have tester release and then you have App Store release.

Speaker 0

这三块其实是连在一起的流水线,对吧?

And there are these three pipelines pieces that go into it, right?

Speaker 0

每次我一构建应用,都会收到一封邮件,说我的新版本已经准备好可以安装了。

So every single time I build an application, I literally get an email that says there's a new version of my app ready to install.

Speaker 0

这一步,其实就是Azure DevOps发布流水线的起点。

Now, that is the first step in the Azure DevOps release pipeline.

Speaker 0

但Frank,真正往外发版的不是Azure DevOps。

But Azure DevOps is not releasing that, Frank.

Speaker 0

是App Center把版本推给我的。

App Center is releasing that to me.

Speaker 0

你明白吗?

Does that make sense?

Speaker 1

这整个流程太乱了。

It's all confusing.

Speaker 1

但求你了,咱们别这样了。

But please, can we no.

Speaker 1

别这样了。

No.

Speaker 1

我开玩笑的。

I I I'm joking.

Speaker 1

我逗你玩呢。

I'm joking.

Speaker 1

不过咱们能倒回去说会儿吗?

But can we rewind for a moment?

Speaker 1

因为你刚才说的那几句话,一下戳中我了,让我突然有点难过。

Because you said a few words that kinda struck a bolt through my heart and just made me sad for a moment as I reflected.

Speaker 1

你说的是‘你的网站和你的 API’。

You said, and your website and your APIs.

Speaker 1

这话真让我震惊,你得看看我怎么部署我的网站。

And that was just a shock to me because you should see how I deploy my websites.

Speaker 1

这太让人难过了。

It's tragic.

Speaker 1

我不是那样的,我代码部署的规范做得很好,CI/CD 一条龙都很到位。

It is not I I have pretty good I have excellent library CICD hygiene.

Speaker 1

我的应用维护得也挺干净的。

I have pretty good app hygiene.

Speaker 1

唯独网页这块,烂透了。

Terrible for the web.

Speaker 1

我有好几个网站是托管在 Azure 上的。

I mean, I have a couple sites that are on Azure.

Speaker 1

只要我推送到某个分支,网站就自动更新了。

And if I release to a branch, then they update automatically.

Speaker 1

所以我觉得,这套流程跟你们这儿简直完美匹配。

So I'm sure that would fit in beautifully with your setup here.

Speaker 1

但你刚才那句话,真戳我心窝子了。

But you that was a strike, man.

Speaker 1

这简直就是一记直击下巴的重拳啊,尤其是说到部署网页内容的时候——天哪,我的网站永远都不同步。

That was a that was a that was a blow right to the chin about, deploying your web stuff too because, oh my god, mine's always out of sync.

Speaker 1

当然不同步了,谁让我写了一堆复杂得要命的部署脚本,结果自己都记不清怎么跑了。

Of course, it's out of sync because I I write terribly complicated scripts that I never remember how to run later for deploying my websites.

Speaker 1

谢谢你啊。

So thanks.

Speaker 1

谢谢你又给我添了个新烦恼,让我多操一份心。

Thanks for giving me something else to think about and worry about.

Speaker 1

不过我真喜欢这点,我以前压根没想过,但仔细一想,所有网页部分其实都能纳入这套体系里。

But I I love that I just hadn't considered it before, but of course all the web stuff could be a part of this.

Speaker 0

谢谢。

Thanks.

Speaker 0

永远要把它当成一个解决方案来看。

Always think of it as a solution.

Speaker 0

我经常和多诺万·布朗、多诺万·贝尔一起工作,我们聊的都是这个——我超爱Bitrise和App Center,但归根结底,它们就只专注在App上,你知道的。

When I often work with Donovan Brown, Donovan Bell, that's what we talk about because I love Bitrise and I love App Center, but they're really just focused on the app, you know, at the end of the day.

Speaker 0

而且没错,你可以用脚本搞定任何事,让一切神奇地自动运行。

And yes, you can script anything and make things magically happen.

Speaker 0

但我特别看重从开始到结束的整个流程,比如从提交代码到部署上线,因为我可不是脚本高手,我就是个喜欢简单操作的人。

But the pipeline from start to finish, like from commit to deployment is really important to me because I'm not a scripting guru and I and I am a gooey person.

Speaker 0

我就想要这种贴心的体验——代码一提交,事情就自动办好了。

I want that nicety in there and I want it to just commit code and things happen.

Speaker 0

对,我每次把代码推到 GitHub,Azure 函数的后端就自动部署更新了。

Yeah, when I when I commit code to handsome informs, it releases a new Azure functions back end.

Speaker 0

整个设置我只花了五秒钟。

It's literally took me five seconds to set up.

Speaker 0

我的移动应用也是同样的流程。

Then same thing for my mobile apps.

Speaker 0

一准备好就能发布。

It gets ready to release.

Speaker 0

我是这么想的。

I think of it like this.

Speaker 0

Azure DevOps里的发布流程,也就是我的持续交付部分,其实就是一个个关卡,对吧?

The Azure DevOps, my release pipeline or my continuous delivery part, it's just like gates, right?

Speaker 0

我会设一些关卡,比如:这是开发人员的入口。

I'm putting in gates like, hey, you know, this is the developer gate.

Speaker 0

我打算让开发人员拿这个包做什么?

What do I want to do with this package for developers?

Speaker 0

让他们去折腾呗。

Go do stuff, right?

Speaker 0

网站那边也是一样。

Same thing with the website.

Speaker 0

我搞定了这个应用,这个Azure函数或者这个网站。

Hey, I built this application, this this Azure function or this website.

Speaker 0

那接下来想怎么用它?

What do you want to do with it?

Speaker 0

等这部分搞完,还有个关卡,专门给测试人员的:这个包,你们打算怎么用?

And then when I'm done with that, there's another gate that says, Okay, for my testers, what do I want to do with this package?

Speaker 0

我通过一个写着‘批准’的按钮来控制这个门的开启。

And I'm in control via a button that says approve to open that gate.

Speaker 0

对。

Right.

Speaker 0

所以门有开着的,也有关着的。

So there's closed gates and there's open gates.

Speaker 0

就像电路板上的电路一样,对吧?

It's like a circuit on an iCircuit board, right?

Speaker 0

门要么开着,要么关着。

The gate is either open or it's closed.

Speaker 0

我不确定中间有没有过渡状态。

I don't know if there's an in between.

Speaker 0

也许根本就没连上。

Maybe it's not connected.

Speaker 0

我也说不准。

I don't know.

Speaker 0

但你明白我的意思吧?

But you know what I mean?

Speaker 1

是的。

Yeah.

Speaker 1

我很好奇。

I'm curious.

Speaker 1

这个比喻不完全贴切,因为我觉得,一旦你把二进制文件上传给苹果,这扇门就再也关不上了,老兄。

It's not a perfect analogy because I assume once you open the gate to uploading a binary to Apple, can't really close that gate, buddy.

Speaker 1

一旦这扇门开了,你就没回头路了。

That's that once that gate's been opened, you can't you're you're done for.

Speaker 1

你已经把二进制文件发出去了。

You've sent a binary.

Speaker 1

不过除此之外,这听起来太棒了,我本来就想问你,你具体都做些什么操作。

But otherwise, that sounds fantastic because I was gonna ask you what the I'm always interested in what are the actual actions you take.

Speaker 1

所以我猜你那儿有个开关,用来控制这扇门是开是关,我之前还以为是按钮呢。

So I'm assuming you have like a toggle box then for whether this gate is open or not, but I was thinking buttons before.

Speaker 1

你知道吗,我总是从界面的角度去想问题,这个流程在用户操作上到底是怎么样的?

You know, I I think of everything in UI terms, like how does this process work from a UI standpoint?

Speaker 1

不过听起来确实不错。

But that sounds pretty good to me.

Speaker 1

希望我们不是在给 Azure DevOps 做广告啊,不过你这推销得也太到位了。

I hope we're not doing just a commercial on Azure DevOps, but you are selling it pretty well.

Speaker 1

因为我本来可以

Because I could

Speaker 0

我在卖产品。

I'm selling the product.

Speaker 0

我在卖产品。

I'm selling the product.

Speaker 0

我想卖的其实是

I wanna I wanna be selling

Speaker 1

对。

the Yeah.

Speaker 0

是的。

Yeah.

Speaker 1

对。

Yeah.

Speaker 1

其实我也可以用类似获取分支的技巧来操作。

Well, I could do the same by, doing, like, get branch tricks.

Speaker 1

比如说,我可以设一个发布分支之类的。

So I could say that there is a release branch or something like that.

Speaker 1

只要我把新版本号推到那个发布分支上,就能自动触发一堆构建脚本。

And whenever I push a new version number or something up to that release branch, then I can have that kick off a bunch of build scripts.

Speaker 1

不过这玩意儿挺小众的,显而易见。

But that's a semi esoteric process, obviously.

Speaker 1

就连我刚说完,自己都快记不清具体怎么弄了。

Even as I just described it, I can't even remember how it works.

Speaker 1

所以说到界面,我完全同意你的看法。

So having a UI in this case, I'm there with you.

Speaker 1

我理想中的系统界面就是:顶部选一个分支,然后决定打开或关闭哪些环节。

My ideal UI for the system would then be pick a branch at the top and then pick which of these gates you want to open and close.

Speaker 1

你能做出这么简单的界面吗?

Can you get the UI that simple?

Speaker 0

对,就是这么设计的。

That's exactly how it is.

Speaker 0

简单说,你的发布流程就是:只要检测到某个分支(或者多个分支)有新版本发布,就自动执行一系列操作。

Basically, your release pipeline says, hey, whenever a release or a or artifacts from this specific branch or multiple branches happens, go do this stuff.

Speaker 0

我这儿有三个环节。

I have three gates.

Speaker 0

就在我屏幕上看着呢。

So there's on my screen.

Speaker 0

我现在正盯着它呢。

I'm looking at it right now.

Speaker 0

你看,这里有个发布记录,显示是从我当前的分支 vnext 发出来的。

Are there's a release which says this happened from vnext, which is my current branch that I'm on.

Speaker 0

就像我说的,找来自 vnext 的内容。

Like I specified, find things from vnext.

Speaker 0

然后有个大框,从这个发布开始连出一条线,通向几个阶段,一共有三个大阶段框。

And then there's a big box has a line from this release and it goes into stages and there's three big boxes of stages.

Speaker 0

所以是三个并排的大框。

So vision three boxes horizontal.

Speaker 1

这我挺喜欢的。

I'm liking it.

Speaker 1

我就喜欢这种大框。

I like big boxes.

Speaker 0

第一个写着 'dev',是绿色的,已经成功了,因为这个是自动部署的,对吧?

One says dev and it's green and it succeeded because that one auto deploys, right?

Speaker 0

它会自动部署。

It automatically deploys.

Speaker 1

当然。

Sure.

Speaker 1

为什么不呢?

Why not?

Speaker 1

你搞你的……哦,这可不是测试人员吧?

Make your make your Oh, that's not testers, is it?

Speaker 1

明白了。

Okay.

Speaker 1

你先说完。

I'll let you finish.

Speaker 0

开发环境。

Dev.

Speaker 0

对。

Yes.

Speaker 0

然后我这边的测试,是公开预览版。

Then I have testers or in my test for this app, it's public preview.

Speaker 0

所以我的测试人员是通过公开预览链接来的,但也可以是内部测试,那就是中间另一个盒子。

Okay, so my testers is a public preview link, but this could be internal testers and that's another box in the middle.

Speaker 0

现在显示的是蓝色,写着‘待审批’。

Currently it is blue and it says pending approval.

Speaker 0

明白了。

Okay.

Speaker 0

下面还有一个按钮,写着‘批准’。

And there's another button right underneath it, says approve.

Speaker 0

点那个按钮,发布就会开始推送给我的测试人员。

And if you click that button, then the release to my testers starts.

Speaker 1

听起来太棒了。

Sounds fantastic.

Speaker 1

就该是这么个样子。

Just how I want it to work.

Speaker 1

我希望这个界面真像我想的那样简洁优雅。

I'm I'm hoping this UI is as elegant and as simple as I'm imagining.

Speaker 1

咱们走着瞧吧。

We'll see.

Speaker 0

对。

Yes.

Speaker 0

现在下面还有一个框,写着‘App Store’。

Now there's a third box that says App Store.

Speaker 0

有时候你会看到好几个框,比如一个给TestFlight,一个给App Store,或者Alpha、Google之类的,看你想要怎么设。

Now, sometimes you might have multiple boxes like once to test flight, once to the apps or whatever, maybe Alpha, Google and then whatever you want.

Speaker 0

没错。

Right.

Speaker 0

所以你可以有多个框。

So you can have multiple boxes.

Speaker 0

但我这儿第三个框写的是‘App Store’,针对iOS,我一般先去TestFlight,然后总是从那儿下载。

But I have a third one that says App Store and specifically for iOS, I just go to like I go to go to TestFlight first and then I always download from TestFlight.

Speaker 0

我还设了个Google Play的Alpha版本,也会先发那个。

And then I also have a Google Play Alpha and I'll release their first.

Speaker 0

这么做的话,会再出现一个蓝色的框,但得等测试人员都通过之后才能看到,旁边还有一个‘批准’的按钮。

What that does, it has another blue box that you can't get to until you do your testers go through and there's another approved box.

Speaker 0

所以你做完这一步,它就会自动进行。

So once you do that, it goes.

Speaker 0

Frank,这些框后面其实都藏着一系列步骤。

Now, behind each of these boxes, Frank, are steps.

Speaker 0

每一步都对应着你要完成的具体任务。

There's tasks that you want to do.

Speaker 0

这个流水线呢,我每一步都会把应用推送到App Center,因为App Center其实就是以前那个HockeyApp。

So this pipeline, basically I ship my app each step to App Center because App Center is just like hockey app, the old hockey app.

Speaker 0

App Center的分发功能有好几处特别让我喜欢。

And What's cool about App Center Distribute is a few things that I really, really like.

Speaker 0

据我所知,它是唯一一个能让你自定义测试群组的服务——你可以设个注册制的测试团队,或者搞个公开预览版。

It's the only service that I know that really does this, but you can create your own groups where people have to register like your test groups or you can have a public preview.

Speaker 0

这个步骤的意思就是:把你的APK或者IPA包,推送到你已经授权过的应用,发给指定的群组或者商店。

And this task says take this APK or take this IPA and ship it to this app that I've authenticated with and to this group or to this store.

Speaker 0

发到TestFlight也好,发到别的地方也行。

Ship it to test flight or ship it to whatever.

Speaker 0

所以 App Center 就成了我的分发中心,不管用哪个 CI 服务,都能把应用推到 App Center 里。

So App Center becomes my distribution where from any CI service you can ship it into App Center.

Speaker 0

对。

Right.

Speaker 0

然后 App Center 会自动给用户发邮件通知。

And App Center will then, you know, send your users an email.

Speaker 0

它有个 SDK,只要用户装了这个应用,就会弹出提示,说有新版本可以更新给你的测试人员。

There's an SDK where if they have the app, it'll just pop up and say there's a new version of the app available for your testers.

Speaker 0

我登录 Google 账号和 Apple 账号,也全都在 App Center 里搞定。

And App Center is where I sign into my Google account and sign into my Apple account.

Speaker 0

我让 App Center 全权负责分发,因为它还帮我做数据分析、崩溃报告、推送通知这些事儿。

And I let App Center do all the distribution because App Center also does my analytics, crash reporting, push notifications and things like that.

Speaker 0

挺方便的是,我还会把调试符号一并上传上去。

What's nice is that I also send them my debug symbols.

Speaker 0

回到最开始,我的发布流程不只是发应用,还得把调试符号一起传到 App Center。

To go back to the very beginning, part of my release pipeline is not to just release my app, but also to release my my debug symbols up into App Center.

Speaker 0

所以一旦出现崩溃,App Center 会根据调试符号生成更清晰的崩溃日志给我看。

So if I get a crash, App Center is aware of the debug symbols and I can see the better crash logs in it.

Speaker 0

Azure DevOps 只负责控制各个步骤的触发时机。

Azure DevOps is just managing when things happen.

Speaker 0

至于这个环节,我就是让系统把应用推送到 App Center,比如开发者组、测试组,或者——抱歉,是 TestFlight 组。

And for this thing, am saying distribute this app to App Center, you know, developer group, tester group or the App Center group or sorry, the test flight group.

Speaker 0

同时,我还会直接从同一个流水线把 Azure 函数后端部署到 Azure 上。

At the same time, I'm also releasing my Azure function back end directly into Azure, all from the same pipeline.

Speaker 0

我设置了几个检查点,确保等所有人都准备好了,再一起发布后端服务。

Like I have those gates in place to say, when I finally go through this, then publish my back end when everybody needs to hit it at the same time.

Speaker 0

所以我的应用和后端服务都能完美同步,整个流程特别顺溜,你懂吧。

So my apps and my back end are all in sync in a beautiful little flow there, if that makes sense.

Speaker 1

是的,明白。

Yes, sir.

Speaker 1

天哪。

Wow.

Speaker 1

好的。

Okay.

Speaker 1

听起来不错。

I like what I hear.

Speaker 1

不过我想再聊聊那些按钮。

I wanna go back to the buttons again, though.

Speaker 1

好的。

Okay.

Speaker 1

按钮。

Buttons.

Speaker 1

对。

Yep.

Speaker 1

你们的是连在一起的吗?

Are yours chained?

Speaker 1

就是好奇,纯属个人兴趣。

I'm just curious, personal preference here.

Speaker 1

你们的流程是串在一起的吗?

Are yours chained together?

Speaker 1

比如必须先走开发,然后才能进测试,再接着部署?

Like you have to go through dev, and then you have to go through test and then you have to go through deployment?

Speaker 1

我刚才听你讲的时候就在想,我可不会这么搭,我肯定直接跳过测试环节。

Because I was thinking while you were talking, I'm like, that's not how I'd wire it up because I would definitely want to skip the testers.

Speaker 1

我老是跳过测试,所以我猜我肯定会这么设计我的流程,不过就是好奇你那边是怎么安排的。

I skip testers way too often, and so I'm pretty sure that's how I would set up my graph, but I was just curious how you set up yours.

Speaker 0

对。

Yeah.

Speaker 0

其实这个你可以完全自己掌控,怎么设都行。

So what you can do is you're really in control of this, you can have it.

Speaker 0

比如每次发布的时候,你可以设三个独立的阶段,每个阶段都有个确认按钮。

So literally when a release happens, you can have three stages that aren't linked together and like all three of them would have an approve button.

Speaker 0

你可以直接说,算了,这次我就只发到 App Store。

You can say, Oh no, this one I actually want to release just to the App Store go.

Speaker 0

还有另一种操作方式,你随时都能手动发起发布流程,直接跳过前面这些步骤,直接进入第三个阶段。

Or another thing you can do, too, is at any time you can just say create release and then you can say skip over skip over these steps and go to the third one.

Speaker 0

就是说你可以

Like, can

Speaker 1

手动发起

do a

Speaker 0

发起手动发布,就说‘就这样,跳过这些步骤,直接把产品推出去’就行。

you can do a manual release and say, you know what, skip over these and then just ship that other thing out.

Speaker 1

好的

Okay.

Speaker 1

这说得通

That's fair.

Speaker 1

我就想一直这么点按钮操作就行

I just want to stay in button world.

Speaker 1

不过你还没回答我刚才的问题呢

But you didn't answer the question, sir.

Speaker 1

你个人觉得,它们是绑在一起的,还是彼此独立的?

You personally, are they, chained together or are they, independent of each other?

Speaker 0

它们一直都是绑在一起的。

They're always chained together.

Speaker 0

对。

Yeah.

Speaker 1

是的。

Yeah.

Speaker 1

明白了。

Okay.

Speaker 1

我刚才有点被一个小细节搞糊涂了。

So I did get lost in one little thing.

Speaker 1

我特别喜欢你刚才说的那句,DevOps 就是用来协调这一切的工具。

So I love, some line you said about DevOps is just what you're using to orchestrate all this thing.

Speaker 1

它就是处理事件、触发操作,你用 App Center 举例,讲得特别清楚。

It's just handling the events and kicking things off, And he made that really clear with the App Center thing.

Speaker 1

我从来没想过能这么用 App Center。

I had never considered using App Center in that way.

Speaker 1

感觉有点儿滥用,毕竟他们界面做得挺漂亮的。

It seems a little bit abusive because they they have a nice UI.

Speaker 1

我挺喜欢 App Center 的界面,但真没想过用脚本往里硬塞数据。

I like the App Center UI, but I never considered just having scripts just shoving data into it.

Speaker 1

这招真够聪明的。

So that's very clever.

Speaker 1

我压根儿没这么想过。

Never considered that.

Speaker 1

不过回到 DevOps,那构建也能在里头做吗?

But, going back to the DevOps, can you do builds in that too?

Speaker 1

你能直接让 DevOps 在 Xamarin 机器上跑脚本,还是说你用的是别的 CI 系统?

So you can say DevOps run this script on Xamarin machine, or are you or do you have a different CI system from DevOps?

Speaker 0

你是说发布这部分吗?

From the CD, the the release part, I mean?

Speaker 1

是的

Yeah.

Speaker 1

他们是两个不同的系统,还是全都用一个?

Are they two different ones or are you all in one?

Speaker 0

这个问题问得好。

So great question.

Speaker 0

不管是构建还是发布,每个阶段都是在全新的机器上进行的。

So every stage in the in the build and in the release is on a fresh machine.

Speaker 0

明白了。

Okay.

Speaker 0

不过,如果你愿意的话,也可以让某个发布阶段使用固定的机器。

However, if you want to, you can have one of your release stages.

Speaker 0

你可以指定它构建或发布时使用的机器。

Can you can pick the machine that it's building or shipping it from.

Speaker 0

所以它得先启动一台机器。

So it needs to spin up a machine.

Speaker 0

所以,比如我在开发阶段加了个任务,写的是‘发布到 App Center’,那它就会在 Windows、Linux 或 Mac 机器上下载好产物,再用 curl 把它传上去。

So like if I just have a task, a step here on my dev that says release to App Center, then it will just download the artifacts on a Windows or a Linux or a Mac machine and then ship it via curl.

Speaker 0

对。

Right.

Speaker 0

就相当于把东西扔到那边去。

It's like, put it over there.

Speaker 0

然后通过它们提供的 RESTful API 把东西发过去。

And then via the the, you know, there's a restful API for them to send it over there.

Speaker 0

不过你也可以这么做,比如某个阶段可以包含多个步骤。

But what you could do, for instance, is like one of those stages can have multiple steps.

Speaker 0

你可以说:在这台 Mac 上下载产物,安装配置文件,重新签名应用,再发到你想发的地方。

You could say, hey, download this artifact on this Mac machine, install my provisioning profiles, resign this application and then ship it wherever you want.

Speaker 0

其实你想的话,发布流程里能做的,跟持续集成里能做的完全一样。

Or you can you can do anything that you did in the in the continuous integration you could do in the release pipeline if you really wanted to.

Speaker 0

比如你可能想在开发和上架 App Store 之间加个环节——跑一遍 UI 测试。

So maybe you want to run tests or UI tests or something that's like, hey, there's an in between step between dev and and, you know, App Store, which is run UI tests.

Speaker 0

我不关心开发那部分。

I don't care about the dev part.

Speaker 0

我只想确保能多跑一套测试,比如你可以把这当成中间环节,把应用拿过来跑一遍 UI 测试之类的。

I want to make sure that, you know, I run an additional suite of tests like you could put that as a middle tier and totally take your app and then run UI tests on it or something like that, too.

Speaker 0

你问的是这个意思吗?

Is that the question you're asking?

Speaker 1

是的。

Yeah.

Speaker 1

但你老说‘可以’。

But you keep saying you could.

Speaker 1

所以你是觉得不该这么做吗?

So are you saying you shouldn't?

Speaker 1

那推荐的做法是什么?

What is the recommended place?

Speaker 1

官方入门文档里到底建议我在哪儿做构建啊?

Like, where do the getting started docs say I should do my builds?

Speaker 0

嗯,这么说吧,我一向这么想。

Well, see all of your here's what I like to think.

Speaker 0

我觉得每个人都有自己最顺手的方式。

I like to think that that everybody has their own way that works best for them.

Speaker 0

你按你的来就行。

You do your own thing.

Speaker 0

但我希望我的构建就是最终的构建,懂吧?

But I like my build to be the build, right?

Speaker 0

我是想用这些产物来做点事儿的。

Like this is the artifacts that I want to do stuff with.

Speaker 0

这些产物其实就是发布环节的一部分。

And those artifacts are are the distribution part of it.

Speaker 0

不过我觉得,发布前还该加点别的,比如跑跑额外的测试、压测一下网站啥的,确保开发环境没问题、测试人员也满意,但还得再过一道关——在上架App Store或上线网站前,确认这一套额外的检查都过了。

But I do think that part of the distribution should be additional tests or load testing of a website or something else to make sure that, hey, you know, everything works great in dev and, you know, my testers are Okay, but I want to have this additional checklist that says before I release to the App Store, before I put this website on the Internet, make sure that there's an additional suite there.

Speaker 0

我觉得这样挺好的。

And I think that's Okay.

Speaker 0

我觉得你的构建可以跑测试,但我更喜欢我的构建速度快一点。

I think that your your build can do tests, but I like my builds to happen fast.

Speaker 0

我宁愿构建很快通过,但发布时因为测试失败或者别的原因挂掉。

And I would rather that my build went green fast and then my release failed because my tests, you know, failed or whatever.

Speaker 0

比如压测没通过之类的。

My load testing failed or something like that.

Speaker 0

你得想清楚,你希望你的系统在哪个环节出问题?

And I think you just need to be aware of like, where would you like your things to fail?

Speaker 0

在哪个阶段?

At what point?

Speaker 0

对。

Right.

Speaker 0

有时候我就希望单元测试先挂掉,对吧?

And sometimes it's I want my my unit test to fail, right?

Speaker 0

因为单元测试跑得特别快。

Because unit tests are really fast to run.

Speaker 0

所以,如果我在开发一个库或者网站,那就在我打包应用的时候直接跑单元测试。

So if I'm building a library or a website, like run my unit tests when I'm building my app.

Speaker 0

要是单元测试挂了,那就等于我的构建没通过。

So if those fail, then it's as if my build failed.

Speaker 0

但如果是做压力测试,就别在打包的时候搞,等后面再做,因为压力测试只该在发布流程的某个特定阶段才跑。

But if I'm load testing my website, like, don't do that when I'm building, do that later on because I only want to load test at a certain point of distribution.

Speaker 0

我觉得关键是要搞清楚:哪些检查应该在进入下一阶段之前做,这得根据你自己的情况来定。

I think that's sort of you need to make that distinguishing point of like, when are the checks before it gets to go to the next thing and decide where that makes sense for you.

Speaker 1

明白了。

Okay.

Speaker 1

咱们举个具体例子吧,我还有一个疑问:构建是触发DevOps流程的起点,还是说提交到GitHub才触发?或者Azure其实一直在轮询各种东西?

Let's, clarify with a concrete example because one thing one question I still have is whether builds kick off the DevOps process or commits to GitHub or is it a polling system and Azure is just always querying different things.

Speaker 1

比如说,我在Bitrise上设了一个构建任务。

So let's say I have a build on Bitrise.

Speaker 1

假设一下,詹姆斯,我是不是在构建结束时跑个脚本,去通知DevOps说:嘿,文件都准备好了。

Hypothetically, James, would I run a script at the end of my build that pokes DevOps and says, hey, hey, here's a bunch of files.

Speaker 1

现在就开始这个流程,还是别的什么方式?

Begin this process now or something else?

Speaker 1

还是说其实是 Git 触发了 DevOps?

Or is it Git that triggers DevOps?

Speaker 0

对。

Yeah.

Speaker 0

这是个非常好的问题。

So this is a great question.

Speaker 0

首先,不管是 Bitrise、Azure DevOps 还是 App Center,其他类似的服务也一样,对吧?

So the first part, which is the for both Bitrise and Azure DevOps and App Center, anything else like that, right?

Speaker 0

就是构建阶段。

The build phase.

Speaker 0

你用来构建产物的构建流水线,是由提交代码触发的。

So the the build pipeline where you're going to build your artifacts that is kicked off via a commit.

Speaker 0

明白了。

Okay.

Speaker 1

对,这个我早就做过。

Yeah, that I have done.

Speaker 1

我所有库这些东西的CI流程都是这么搞的。

That's the CI part that I do for all my libraries and all that.

Speaker 1

这块我可太熟了。

That part I'm solid.

Speaker 0

没错。

Yes.

Speaker 0

现在说说持续交付的部分。

Now the continuous delivery part.

Speaker 0

就是那个由制品上传触发的发布流程。

So the release pipeline that is triggered by an artifact drop.

Speaker 0

相当于把制品推到网上某个地方。

So it's like a commit of artifacts somewhere on the Internet.

Speaker 0

这样说得通吧?

Does that make sense?

Speaker 1

好的。

Okay.

Speaker 1

对,这完全说得通,因为CI流程结束后,你总得决定把哪些产物导出来。

Yeah, that makes absolute sense because at the end of a CI process, you always have to decide which artifacts you wanna export from your, process.

Speaker 1

对我而言,通常是开发版的签名应用之类的。

So for me, that's usually, dev signed built apps, things like that.

Speaker 1

但你所有的库都是打包好的组件。

But for all your My Libraries, it's a bunch of packages.

Speaker 1

这对我来说完全合理。

So that makes absolute sense to me.

Speaker 1

我特别喜欢这一点,因为我之前还担心得用什么奇怪的API来搞。

And I love that because I was worried that it was gonna be like some API that you had to encode in a funny way.

Speaker 1

可能还是得用API,但本质上就是把一堆文件扔到服务器上,事情就自动开始了。

I'm sure it still is, but some way you just have to take a bunch of files and dump them on a server somewhere, and that kicks things off.

Speaker 0

没错。

That's correct.

Speaker 0

你在 Azure DevOps 里做这个特别简单,因为构建一完成,产物就会自动生成,发布流水线立马就能察觉:嘿,有新东西了。

You're doing it inside of Azure DevOps, it's really easy because when your build completes, the artifact is dropped and then the release pipeline says, Hey, there's a new thing.

Speaker 0

去启动那个已经准备好的发布流水线吧。

Go start up this release pipeline, which is there.

Speaker 0

这个 Azure DevOps 里的发布流水线,Frank,其实有九种触发方式。

That release pipeline in Azure DevOps can be triggered in one of nine ways, Frank.

Speaker 0

准备好了吗?

Are you ready?

Speaker 0

好。

Okay.

Speaker 0

它可以通过 Azure DevOps 里的构建来触发。

So it can be triggered via a build in Azure DevOps.

Speaker 0

这很合理。

That makes sense.

Speaker 0

也可以通过源代码仓库来触发,我记得是这样。

It can be triggered via, I think, source code repository.

Speaker 0

所以我这边用的是 GitHub TFCC。

So a get a GitHub TFCC.

Speaker 0

我觉得如果你在那儿提交代码,也能触发流水线运行。

I think that like if you commit something there, it can also trigger the pipeline to occur.

Speaker 0

没错。

Sure.

Speaker 0

你也可以把东西发布到 Azure 工件里。

You can ship items to Azure artifacts.

Speaker 0

最理想的情况是通过 GitHub 的发布版本来触发。

You can do it ideally off of GitHub releases.

Speaker 0

如果你有发布版本,就可以监控 GitHub 上有没有新的发布。

So if you had a release, you could be listening for new releases to GitHub.

Speaker 0

还有呢。

There's also

Speaker 1

这招对库文件挺合适,但我估计自己不会把应用发到 GitHub 发布里,反正我是不会。

That's nice for libraries, but I won't I'm not ever gonna put my app on GitHub releases, I don't think.

Speaker 1

哦,你知道吗?

Oh, I you know what?

Speaker 1

我收回刚才的话。

I take that back.

Speaker 1

你说到发布的时候,我还以为非得把二进制文件传上去,现在才知道其实就只是一个标签而已。

When you were saying releases, I was thinking that you're forced to put the binaries up there, but now it's more of just a tag.

Speaker 1

不错。

Cool.

Speaker 1

所以,是这样。

So, yeah.

Speaker 0

然后我觉得你还可以把它们打包进 Docker 容器,或者推到 Docker Hub,甚至 Jenkins 里也行。

And then I think you can also put them in like Docker containers or Docker hubs or even like Jenkins.

Speaker 0

比如可以直接关联到一个 Jenkins 任务。

Like you can like link it to a Jenkins job.

Speaker 0

不过我现在还不确定,如果你用 Bitrise 来构建应用,最好的方式该是什么。

Now, I'm not sure what the best way to do it is if you're going to use Bitrise to build your app.

Speaker 0

我猜你可能会在 Git 发布里打个标签,或者 somehow 上传到 Azure Artifacts,反正就是往里丢个包之类的?

My assumption is you'd either tag it in a git release or upload it to Azure artifacts somehow and like basically drop something in there, like drop a package or something like that?

Speaker 0

说实话,我也不太确定。

I'm not a 100% sure, to be honest with you.

Speaker 1

对我而言,这可能是最简单、最理想的方案了。

That would be the simplest, most ideal solution for me.

Speaker 1

如果真是这样就太棒了,那样你直接用 curl 之类的命令就能上传一堆文件。

That would be wonderful if that's how it works because you could always just use curl or something to upload a bunch of files.

Speaker 1

对。

Mhmm.

Speaker 1

但了解互联网的尿性,我猜肯定是个复杂的 JSON API,得花时间学怎么用。

But knowing the Internet, I'm sure it's complicated JSON API that I'm gonna have to learn to use.

Speaker 0

大概吧。

Probably.

Speaker 0

八成是。

Probably.

Speaker 0

但我用的是 Ruby。

But I Ruby.

Speaker 0

我是说 Ruby。

Mean Ruby.

Speaker 0

对。

Yeah.

Speaker 0

我的意思是,就像我说的,你大概也能做到这一点。

I mean and like I said, you could most likely accomplish this.

Speaker 0

我以前在 Bitrise 时,会根据分支设置多个工作流,每个分支做不同的事。

What I used to do in Bitrise is I would have multiple workflows based off the branch and then each branch would do something.

Speaker 0

但我不喜欢那样,因为那样我就得重新构建一遍应用,对吧?

But the reason I didn't like that was because then I'm building my app again, right?

Speaker 0

比如我在 master 分支上已经构建好了,还得神奇地把代码拉到发布分支,再重新构建一遍,然后走另一套流程。

Like I'm I built my app in master and then I have to magically pull the code up into this release branch and then I have to build again and then it goes through a different flow.

Speaker 0

与其搞一堆不同的构建和发布方式,不如就一种构建方式、一种发布方式,直接走通就行。

Instead of having multiple ways of building and managing your app, like, there's one way to build it and there's one way to release it and here it goes.

Speaker 0

这差不多就是我的想法。

That's kind of my idea.

Speaker 1

对。

Yep.

Speaker 1

好的。

Okay.

Speaker 1

我挺喜欢这一切的。

So I like all of this.

Speaker 1

我都喜欢。

I like it all.

Speaker 1

你都说服我了。

You you you have me sold.

Speaker 1

好的。

Okay.

Speaker 1

但我有个顾虑。

But I have a concern.

Speaker 1

詹姆斯,我有个顾虑。

James, I have a concern.

Speaker 1

我们现在要管的配置和各种服务太多了。

We are managing a lot of configurations and services and things like that.

Speaker 1

我反而在想,这到底能不能真给我省事,毕竟我还得维护这些流程。

I wonder if it's truly saving me any work, because I have to maintain these processes.

Speaker 1

让我重新说一遍。

Let me actually start over.

Speaker 1

我把这个顾虑改成个问题吧。

I'm going to turn this into a question instead of a concern.

Speaker 1

假设我为iCircuit投入了这么多精力,结果特别完美。

Let's say I put all this effort into this for iCircuit, and it's glorious.

Speaker 1

我搞出了有史以来最漂亮的图谱。

I have the most beautiful graph ever.

Speaker 1

门电路、构建流程,样样都做得特别到位。

It does the best things with gates and builds and all that.

Speaker 1

版本控制,不错。

Versioning, great.

Speaker 1

那Kalka怎么办?

What do I do for Kalka?

Speaker 1

我能不能直接拿个JSON或者YAML文件,直接应用到Kalka上?

Can I just take like some JSON file or YAML file and apply it to Kalka?

Speaker 1

还是说,我得为另一个应用重新搞一遍这些工作?

Or do I have to rebuild all that work and effort again for another app?

Speaker 0

是啊,这问题问得好。

Yeah, it's a good question.

Speaker 0

构建流水线,也就是你的CI部分,完全可以写在YAML文件里,把它当成代码的一部分来管理发布流程。

The build pipelines, your CI part of it, that's you can just do that all in a YAML file and make your make that part of your code for the release pipeline.

Speaker 0

现在里面还没有YAML文件。

There is no YAML today in there.

Speaker 0

不过你可以进发布流程里,点导出,把这套配置导出来,再导入到另一个项目里。

However, you can go into a release and then say export, like export this and then reimport it into another one.

Speaker 0

你懂我意思吧?

You know what I mean?

Speaker 1

太酷了。

Oh, so cool.

Speaker 1

我很好奇,你点导出的时候它具体给你啥东西?

What does it just out of curiosity, what does it give you when you hit export?

Speaker 0

我现在就在弄。

I'm doing it right now.

Speaker 0

它会给你一个

So it gives you a

Speaker 1

是JSON吗?

JSON curious.

Speaker 1

对。

Yeah.

Speaker 1

JSON。

JSON.

Speaker 1

明白了。

Okay.

Speaker 1

所以最后生成的还真是个 JSON 文件。

So it really is a JSON file at the end.

Speaker 1

这挺棒的。

That's cool.

Speaker 1

所以如果你真用得上,理论上可以把这文件提交进代码库。

So you could ostensibly check that in if you ever are.

Speaker 1

像我这种懒人,老记不住怎么操作,就喜欢复制粘贴,我特别依赖图形界面。

If you're like me and are lazy slash can never remember how to do things and like to copy and paste things, you know, I need, I like UIs.

Speaker 1

我超爱这个。

I love them.

Speaker 1

但一旦配好了,我就想把它固定下来,把选好的配置套用到好几个应用上——我得维护五六个应用呢,每次都弄挺费劲的。

But once I have everything configured, I just want to lock it down and say these are the options that I've picked and apply it to many apps because I maintain five, six apps, and it's a bit of effort.

Speaker 1

对。

So Mhmm.

Speaker 1

我搞的任何流程,都要乘以五倍。

Any process I come up with gets multiplied by five.

Speaker 1

这正是我担心的。

That's kind of my concern.

Speaker 1

所以一点小开销都会被放大,我得小心,别以为自动化真能省时间。

So any little overhead just gets multiplied, and I have to be wary of that when I'm building automated processes, whether they're actually saving me time or not.

Speaker 0

是的。

Yeah.

Speaker 0

我刚开始做插件时也头疼,得不停往 NuGet 发十几个库。

I struggle with that early on with my plugins because I have 10 or so, 15 or so libraries that I'm shipping all the time to NuGet.

Speaker 0

在 Azure DevOps 里,我把这些都叫插件。

Inside of my Azure DevOps project, it's called my plugins.

Speaker 0

我这儿有十五个构建流水线。

And my plugins has 15 build pipelines.

Speaker 0

每加个新库,我就右键复制,然后直接克隆一份。

Whenever I add a new library, I just right click copy and then duplicate basically.

Speaker 0

发布也是这么搞的。

Same thing with release.

Speaker 0

我直接右键复制,然后粘贴一份就行。

I just right click and I say duplicate this and then it duplicates it there.

Speaker 0

要是得一个个去更新,确实挺烦的。

It is a little bit tedious if I have to go through and update all of them.

Speaker 0

但说实话,每当我得改点啥,比如要加个新步骤,想干点啥新事儿,我就得把所有这些都改一遍。

But I will say like that's like if I have to change something, I'm like, Oh, I need to add this new step because I want to do this thing.

Speaker 0

得把所有流程都更新一遍。

I have to update all of them.

Speaker 0

但转念一想,就算用YAML也差不多,不还是得去改15个YAML文件吗?

But then I think, well, there'd be no difference if that was YAML because I would have to go update 15 YAML's, right?

Speaker 0

每个文件的配置还不一样。

All with different properties.

Speaker 0

所以其实也没啥区别。

So it's similar.

Speaker 0

我觉得这属于风险和回报的权衡,尤其是像你我这样的独立开发者,真值得花这么多时间和精力去搞这个吗?

And I think it is one of those risk versus rewards where especially if you're a solo developer like you and me, is it really worth my time and energy to go through this this experience?

Speaker 0

这确实得花点时间,对吧?

And it takes some time, right?

Speaker 0

你得先投入一点时间进去。

I think you have to invest a little bit of time in it.

Speaker 0

但一旦做成了,每次加新东西都跟抹黄油一样顺滑。

However, once you've done it, I mean, every time I add something new, it's like butter.

Speaker 0

第二次做起来就轻松多了。

It's just like it takes the second time I do it.

Speaker 0

第一次要是花了八小时,第二次就四小时,第三次半小时,再下次两分钟就搞定。

Like if the first time took me eight hours, the next time takes me four hours, the next time takes me thirty minutes, and then the next time takes me two minutes.

Speaker 0

对吧?

Right?

Speaker 0

现在我直接心里有数,知道该怎么做了。

And now I'm just like, Oh, I just I know exactly what I'm doing.

Speaker 0

但理想情况下,什么都别出问题。

But, but, but, but, and and ideally nothing breaks.

Speaker 0

我觉得我的发布流程从来没出过岔子,不管是发到 GitHub 还是 App Center,甚至发到 TestFlight,从 CI 的角度看,根本没变过。

Would say that my releases, my release pipelines have like never broken because releasing something to new get or releasing something to App Center has not changed and even releasing to test flight has not really changed from a CI point.

Speaker 0

发布流程倒是总在变,因为你刚才说的那些原因,对吧?

The pipelines always change because the for building because of what you said, right?

Speaker 0

Visual Studio 在更新,Xcode 在更新,这一堆东西都在变。

Visual Studio is updating X codes, updating all this stuff is updating.

Speaker 0

最难搞的其实是确保这些环境别乱动。

And that's the trickier part sometimes is is is making sure that that those environments don't change.

Speaker 0

发布这部分倒没问题,因为你早就把最难的活儿干完了,对吧?

The release part is fine because it's you already you already did all the hard work, right?

Speaker 0

该做的你都做完了。

You already did the thing.

Speaker 0

所以哪怕你直接拿你本地编译好的包,跑个命令上传上去就行,对吧?

So even if you were to take your thing that you built, even on your machine and then run a command to upload that, right?

Speaker 0

所以你的发布管理其实可以很简单,直接把归档文件扔出来,再写几个脚本,分别发到开发版、测试版和其他版本就行。

So even your release management could literally be frank, like here's the archive and then you have scripts that run to say, here's my dev one and here's my tester one and here's my other one.

Speaker 0

然后它就自动跑到对应的地方了。

And like, it just goes into the right places.

Speaker 0

这种做法完全可行。

Like, that could totally be a thing.

Speaker 0

你甚至可以用 bash 脚本搞个简易的发布流水线。

Like your ad hoc, a little release pipelines via you know, bash scripts.

Speaker 0

我觉得这就是 Frank 以后会走的路。

That's what I see Frank doing in the future.

Speaker 1

不用了。

No.

Speaker 1

我其实挺喜欢 App Center 的,因为我最担心 CD 部分的就是跟苹果那边的对接问题。

I'm I kinda like the App Center part because one of my biggest concerns with the CD part was that interface with Apple.

Speaker 1

往苹果那边传东西,自动化起来太麻烦了。

Uploading stuff to them is notoriously difficult to automate.

Speaker 1

所以我特别希望别人在解决这个问题,我就不用操心了。

So I'd love that other people are working on that problem, and I don't have to deal with it.

Speaker 1

这听起来真不错。

That sounds really good.

Speaker 1

没错。

Yeah.

Speaker 1

对啊。

Yeah.

Speaker 1

你刚才说插件的事让我想到,我自己的项目其实也需要支持多平台。

So I like what you said about, the plugins because it actually got me thinking about, multi platform for myself.

Speaker 1

我们一直聊的都是安卓和iOS,但像iCircuit这样的应用,现在其实已经在三个平台上发布了。

So this whole time we've been talking, Android and iOS, But, apps like iCircuit are is on, three shipping three different platforms right now.

Speaker 1

以前甚至还在五个平台上推过。

Used to be on, like, five different platforms.

Speaker 1

所以分开构建每个平台的版本对我来说特别重要,还得把整个流程管好。

And so having those separate builds is really important to me and orchestrating the whole thing.

Speaker 1

我根本没做好,每次加了个小功能或者修了个bug,就只改了一个版本。

I'm definitely not good at I added a little feature or I did some bug fixing to one version.

Speaker 1

然后我有没有把更新推到所有三四个发布渠道去?

And have I released it to all three or four distribution channels?

Speaker 1

答案呢,詹姆斯,通常都是没有。

And the answer, James, is usually no.

Speaker 1

所以我现在意识到,要是当初花点功夫搭好这套自动化流程,我就能同步发布,稳定多了。

So I'm realizing that if I had put in the effort to building one of these pipelines, I would have much more consistent simultaneous releases.

Speaker 1

这让我开始想,也许我真的该去搞一搞这个了。

That's, it's making me think a bit that maybe I should, look into this.

Speaker 0

是啊。

Yeah.

Speaker 0

你知道吗,我觉得一旦你真投入进去,回报其实会超乎想象。

You know, I think that what happens is once you invest in it, the payoff maybe it's a none, right?

Speaker 0

说白了,你懂的。

Maybe like, you know what?

Speaker 0

我弄了这么个东西。

I set up this thing.

Speaker 0

花的时间跟手动做一模一样。

It's taking me the same amount of time if I had just done it manually.

Speaker 0

但长远来看,这样就能更快地把新功能推给测试人员,反馈也来得更快。

But then over time, ideally, it means that you can ship new features to your testers faster so you get that feedback faster.

Speaker 0

理想情况下,你甚至不用坐在电脑前就能发布更新——改完代码就行。

Ideally, you can ship an update without having to be at your computer because you could change some code.

Speaker 0

这事儿其实挺酷的。

Was at This was actually kind of cool.

Speaker 0

我在保加利亚的DevReach大会上遇到一个叫兰斯·麦卡锡的人,他在Telerik Progress工作。

I was at Lance, I think McCarthy is his last name, that works at Telerik Progress.

Speaker 0

他讲了怎么用安卓手机给大会App发更新。

I was at the DevReach conference in Bulgaria, and he talked about how he shipped an update to the conference app from his Android phone.

Speaker 0

他那时候根本没带电脑。

He had no computer.

Speaker 0

他当时在飞机上。

He was on a flight.

Speaker 0

他在天上飞着呢,弗兰克。

He was on a flight in the air, Frank.

Speaker 0

因为苹果拒了他的应用,他就写了个补丁。

He made a code because Apple had rejected his app.

Speaker 0

他直接在 GitHub 上在线改了代码,触发了 Azure DevOps 的构建流程,接着自动进入持续交付环节。

He made a a code change in GitHub, like online, which kicked off of a DevOps, build in Azure DevOps and then kicked off his continuous delivery part.

Speaker 0

等他下飞机,就能下载更新后的应用,马上测试验证。

And when he got off the plane, he could download the updated app, validate it.

Speaker 0

然后他直接在手机上点了一下‘发布给苹果’,系统就自动提交上去了。

And then from his phone, he said release to Apple and it like released to Apple automatically.

Speaker 0

这简直太酷了。

Like, that's kind of freaking cool.

Speaker 0

对吧?

Right?

Speaker 1

好吧。

Okay.

Speaker 1

那我问个简单的问题。

So one quick yes.

Speaker 1

这确实挺厉害的。

It is obviously very cool.

Speaker 1

我希望永远别遇到这种情况。

I hope to never be in that situation.

Speaker 1

我绝对不想这么发布应用,不过嘛,确实挺牛的。

I hope to absolutely never ever release an app that way, but sure.

Speaker 1

太酷了。

Absolutely cool.

Speaker 1

说吧。

Shoot.

Speaker 1

我刚想问啥来着,哦对不起,我忘了。

I just totally forgot my question, but I had a oh, I'm sorry.

Speaker 1

所以你说的‘发布到苹果’,如果是手动操作,其实是两个步骤。

So when you say, release to Apple, when you do it manually, it's a two step process.

Speaker 1

你先上传二进制文件,然后要么批准给测试人员,要么提交为更新——如果是更新,就得填更新说明和其他相关信息。

So you upload your binary, and then you either, approve it for testing and distribute it to testers, or you submit it as an update, and in which case you should get give update text and other details like that.

Speaker 1

你提到上传到苹果,是包括填写发布说明这一步,还是说你只是传了二进制文件,之后还得再登录 iTunes Connect 手动填新版本信息?

So when you say upload it to Apple, are you taking that final step of giving release notes, Or are you just saying that you're uploading the binary and then you have to log into iTunes Connect later and say, new new version?

Speaker 0

不是。

No.

Speaker 0

其实你完全可以直接在应用或更新里填写发布说明。

I mean, you can totally specify release note information directly for the apps or update.

Speaker 0

那詹姆斯是怎么做的?

Now, what does James do?

Speaker 0

詹姆斯从来不会亲自把应用提交上线。

James does not ever directly I never directly submit my application to the release.

Speaker 0

我总是觉得,这一步得由我亲自来完成,不管是哪种情况。

I always like this is my my final step for both.

Speaker 0

你完全可以这么做,对吧?

You could do this, right?

Speaker 0

但对我来说,从我的发布流程来看,最后一步就是……

But my final thing like from my my distribution pipeline, my final step.

Speaker 0

最终我会把应用分发到 TestFlight 和 Google Play 的 Alpha 渠道。

Where it ends is a distribution to test flight and a distribution to Google Play Alpha.

Speaker 0

之后我完全可以点一下,说‘把这个版本推到正式发布’,带上这些更新说明,推给苹果和谷歌。

After that, I could say, Hey, promote this build to the release and promote this build with these release notes to release for Google and for Apple.

Speaker 0

不过我本人就是不喜欢这么干,不知道为啥。

For me, though, I don't like that for some reason.

Speaker 0

我总是习惯先从 TestFlight 下载测试版,亲自验证一遍。

Like I like to always download a test via test flight, validate it.

Speaker 0

我知道这个版本没问题了,然后就去 App Center Connect,手动点一下‘用这个版本提交审核’,确认所有信息都对得上。

Like I know that like this is the build and then I just go into the App Center Connect and I and I and I flip that switch where I say, use this build, submit for review, make sure everything's valid.

Speaker 0

我喜欢这种最后的人工确认环节——亲自给苹果和谷歌提交应用,这样我心里才踏实。

I like sort of that final like human scan that like I'm I'm doing this thing right now for Apple and for Google to like submit my app just so I have a peace of mind.

Speaker 0

没错。

Right.

Speaker 0

如果你不想走这些流程,完全可以让你的DevOps管道全自动化处理。

And if you if you want to skip all that, you can totally have your DevOps pipeline do all that stuff.

Speaker 0

但我就是喜欢最后这个确认环节。

But for me, I like that final little validation phase.

Speaker 0

这算是我自己的一个把关步骤。

That's kind of like my my my own personal gate.

Speaker 0

对吧?

Right?

Speaker 0

我就喜欢这样操作。

I like to have that.

Speaker 1

对。

Mhmm.

Speaker 1

这么说来,我有点震惊——你从不登录iTunes Connect?

So to be clear, and I'm a little bit in shock here, you never log into iTunes Connect?

Speaker 0

没有。

No.

Speaker 0

没有。

No.

Speaker 0

没有。

No.

Speaker 0

我是说,我每次都登录 iTunes Connect。

I I'm saying that I always log in to iTunes Connect.

Speaker 1

明白了。

Okay.

Speaker 1

原来如此。

Okay.

Speaker 1

所以你在 iTunes Connect 里有个 TestFlight 构建版本。

So you have a test flight build in iTunes Connect.

Speaker 1

你进去后点新建发布,填上新版本号,写好更新说明,然后点提交。

You go in there and you say new release, type in a new version, type in release notes, hit submit.

Speaker 1

但你是说,这其实也能通过 DevOps 自动化吧?

But you're saying that could also technically be automated via DevOps?

Speaker 0

是的。

Yeah.

Speaker 0

没错。

Correct.

Speaker 0

你完全可以把这整个流程都自动化掉。

You could totally just, yeah, automate that.

Speaker 1

明白了。

Okay.

Speaker 1

不是通过 App Center。

Not through App Center.

Speaker 1

我刚才就是有点好奇这一点。

That's what I was a little curious.

Speaker 1

到底是 App Center 还是 DevOps 能实现这个自动化?

Is it App Center or DevOps that can automate that?

Speaker 1

两个都可以吧。

Both, I guess.

Speaker 0

我觉得两个都能行。

I think both can.

Speaker 0

我觉得两个都能行。

I think both can.

Speaker 1

嗯,其中一个 probably 是在用另一个。

Well, yeah, one's probably using the other.

Speaker 1

挺有意思的东西。

Very interesting stuff.

Speaker 1

我现在才意识到,我真是个胆小鬼。

I realized now that I'm a wimp.

Speaker 1

我一直都不敢去搞复杂的流程。

And I've always just been afraid of setting setting up a complex process.

Speaker 1

但我真不该这么胆小,我特别想让我的应用能同时发布。

But I should, I should not be a wimp because I would love to have simultaneous releases of my app.

Speaker 1

你能想象詹姆斯同一天在所有平台发布吗?

Could you imagine James releasing on all platforms on the same day?

Speaker 1

我反正做不到。

I I can't personally.

Speaker 0

你完全可以的。

You, it's all possible.

Speaker 0

对吧?

Right?

Speaker 0

我觉得问题在于,对苹果来说,你只是提交了审核,还没上架。

I think then the problem with that is then for, like, for Apple, you're you're just submitting it for App Store review.

Speaker 0

对吧?

Right?

Speaker 0

你只是提交了,还没真正上架。

You're not actually getting it into into the App Store.

Speaker 0

所以你得让它先挂着,等时候到了再一键发布。

So you really you want it to be held for release and then toggle back somehow.

Speaker 1

没错。

So Yeah.

Speaker 1

这事儿还挺麻烦的。

It gets a tricky.

Speaker 1

就像DevOps里的一个审批闸门,我只要点一下‘通过’,它就会自动把其他版本提交到Android平台。

Like a gate in DevOps, and I'll just have when I when I click that button approved, then it'll actually submit the other ones to Android.

Speaker 1

我还以为Android那边也有点延迟呢,还是说其实很快?

So I thought Android had a little delay too, or is that pretty instant?

Speaker 1

通常要两个小时。

It's two hours usually.

Speaker 1

两小时。

Two hours.

Speaker 1

明白了。

Okay.

Speaker 0

对。

Yeah.

关于 Bayt 播客

Bayt 提供中文+原文双语音频和字幕,帮助你打破语言障碍,轻松听懂全球优质播客。

继续浏览更多播客