James: 00:00:09 Frank, both you and I James: 00:00:10 literally trying to do the same thing right now. Get apps into our user's hands and we're failing in every regard of life. Frank. It's happening right now. Frank: 00:00:21 Yeah. Uh, my knowledge is so out of date. I had to ask you because I saw rumors on Twitter, that application loader. Yeah, that's what it was called. That's the tool that I've used for years. It almost feels like a decade to upload apps. And Apple's decided to stop shipping it. Stop supporting it. You're supposed to stop using it. And I'm like, James, what am I supposed to do? I had to ask you, I feel bad. I should be more on top of iOS stuff. James: 00:00:50 I liked that you had to ask the Android guy how to distribute your iOS app. Frank: 00:00:57 I'm like, I got, I got these executable, I need to get them out to people. But it turns out, uh, I just, it's been in the back of my mind. Uh, like I said, I've seen it on Twitter. People are mentioning that this is happening. Uh, I just haven't actually released any apps in the last month, so I haven't had to deal with it. So now I'm dealing with it. And then you said something terrible to me. You're like, well, if your apps were in CII, and I was like, James, of course my apps are NCI. But I think you were implying some sorta CD thing also. James: 00:01:31 Yes. I forgot to say continuous integration and continuous delivery. If you had a CIC pipeline, Frank, then you'd be good to go. Frank: 00:01:40 So my reply was, James, we've talked about this merge conflict constantly. I have good CII. I even have, um, a little marquee display that I made. Remember I was talking about my IOT device displays build status. I am good at CII, CD a, I've completely ignored not doing that. James: 00:02:02 Yeah. So, okay, let's talk first here about how you get your builds. So do for developer builds. 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? Thumbs up. I'm very excited about it. Frank: 00:02:24 Yeah, I'm a little bit all over the map. So I would say for half of my apps, probably more than that, the majority of my apps, it is just a thumbs up build or no build runs, some tests, that kind of thing. Usually not even a device tests, almost always not even device tests. That said, I do have a few apps in a Microsoft's mobile app center, whatever it's called in 2019 not hockey app tool thing, which is quite nice. I think for a free account out there they'll do builds for you and even make James: 00:03:00 sure that the app starts up on a device. So I have that for my bigger apps just by, I can be absolutely sure. Plus, sorry to keep hogging, but um, it comes down to how I deal with beta testers also. So some people I have beta testing through app center, some people have beta testing through Apple's thing. And for that my deployment is all different. Oh my God, James, I'm just realizing how scattered I have about all of this stuff. Well, it's hard when you've been doing it for what, 10 years? And probably still supporting apps that are 10 years old. Yeah, exactly. But even that, it's just, um, a laziness not to move everything over to one system. Even now, lately a get hub actions has been added and I am absolutely in love with it. But that is most definitely just CII, continuous integration, continuous builds, thumbs up, thumbs down that I break the code or not. James: 00:04:00 I feel like this is funny too because we've talked about CINC D and we bullshit a lot of libraries and I feel like for dev ops we're talking dev ops people, um, for libraries I feel like we have that under control. For me, I build everything in Azure dev ops. Like easily. It just go build this library and then ship it to new, get right. Just like an new get done. Right. It's like very seamless. And if I have it with a beta tag, then it's a beta package. If I don't have it with a beta tag, then it's not a beta package. Right. It's like, it's like that's the world that I wish we lived in and like everybody just gets it. But we're not in that world because what you just said, you have testers and where maybe their devices have to be registered. James: 00:04:49 Maybe they're getting it for through TestFlight, maybe they're getting it via an email, maybe they're siloading it onto their device and there's all these certificates provisioning in all this shenanigans going on. And what we really want to have happen is someone downloads it and then to test it, right. This is like the, the first goal is like the first goal is that I want to be able to download and test my own build. 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. And that that's the first like framing of continuous delivery is how can I continuously deliver an app to me. Does that make sense? Yeah, absolutely. And I should say, and clear the air here. How do I actually ship an app? I never take a build off of a CIS server and upload that. I just don't trust anything. So whenever I really, really release an app, I build it myself on my own machine. I go to the Ben and OBJ folders. I wiped Frank: 00:05:58 them out. I, uh, build the app, I archive it, then I start deploying it to devices and do one last test, manual test pass, and then I upload to Apple. How in the world do I automate all of that in a pipeline? Speaker 4: 00:06:15 What? Like an animal? Oh my gosh. Oh my goodness. Okay. Okay. Straight. Set me straight. Okay. So that's not the worst thing in the world. You know, I did this for, for many years and to be honest, Frank, let me tell you a little secret. Frank: 00:06:27 I still do this today. Sometimes chorus, it's a, it's a tried and true method. It may be painful, it may be slow, but it works. I like that. Speaker 4: 00:06:38 Um, visual studio and visual studio for max and X code, they have the archiving builtin. I like, I love this feature, the archiving tool, because even if you're not using CII, it's sort of like in CD I should say. Um, it's kinda like your own versioning so you at least know like, Hey, this is this magical Frank: 00:06:55 go build. Speaker 4: 00:06:58 And I shipped it to somewhere cause it's archives. Previously my archive was a Dropbox folder that had a Android and then the version number and then like the APK inside of it. And like that's how I remember what build I shipped to the app store. And that was, that was bad news. That was like eight years ago. And, and uh, I've definitely come further and, and you're, you're right, like at least to get it to Google or to Apple. The cool part is that visual studio and X code will walk you through it, right? Like Android, you can ship to Google play directly from visual studio. Like it's magical. And the app, what is it? It used to be application loader. It's gone and now it's transported. Did you download transporter? It's a cool name as they were watching too many Jason's teeth and movies, I think. Frank: 00:07:45 Yes sir. Uh, and I'm just logging into it, trying to remember all my dev passwords and the UI is blank and confusing. Just like the old app loader. So I can't wait to figure out how to use this puppy. Speaker 4: 00:07:58 Thanks Zach. Loader. Yeah, thanks transporter. Thanks Apple. Yeah, and then that's, I think they, they, they did this because people are distributing more than just apps. They're distributing media too. So it's like one stop shop I think for getting everything to Apple. Frank: 00:08:13 Yeah. So let's go back to the archiving. There's one really good reason for doing it. Uh, there's a few bad reasons they take up a lot of space, especially after 10 years. Um, I, I've, I don't have a complete archive history. I've lost it between machines and all that because they're huge. But I have a pretty good, uh, decent recent history. The good thing about the archive tool is that when you get crash logs from Apple, you have simple information and you can make sense of what actually crashed. Um, I think that this is changing a little bit with how we deploy apps. I'm pretty, we still don't upload symbols when we're deploying apps though. So we still need to keep those simple somewhere. 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. And if you've done this for a while, you know it's a very hairy system. You change one bite in your package and all of a sudden you don't get symbols anywhere like a bite anywhere just because the hashes don't match anymore. So the archiving tool is great for keeping all that stuff in line. That said, I'm pretty sure even in a CII system, you can generate these archives. Have you tried doing that? James: 00:09:38 Yeah. 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, um, for iOS is the DSM, the debug symbols part of it. And um, during my continuous integration cycle, you can, you're just creating an archive for all intents, right? That's that. That's the idea there. So for me, when I think of my continuous integration, there's sort of two steps to it, which is how do I first build my debug like developer package? And then how do I build or sign my release package? And for both of those I want to have those debug symbols. 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, that's great because you have the ability to do this all on your machine and it's there. James: 00:10:32 The problem though is, is time, right? It's like it's time. It's energy, it's hard drive space. 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. Like I don't want to have to do anything special. And then from there I want to immediately ship that package to the app store like that. That's my goal in general. Um, so when you ask me like, Oh, like where it application loader go and Oh, I got it on this transporter thing. Like for me, I saw this all the time, by the way, you weren't the only one. Like, literally the internet blew up, um, from both objective C and Swift and Xamarin developers. Like where did it go? Um, and I was like, Oh man, I mean I haven't opened that thing in three years. Like, um, and, and I was like, that's kind of interesting cause I feel like everybody's still going down this route. So there must be something hard about taking it from archive to full dev ops. That must be difficult. And like what's your roadblock there? That's what I'm really curious about. Frank: 00:11:40 Okay. So we can definitely get into that. But first let me ask one more high level question of you. Um, when you're doing, how are you differentiating between um, tests, builds for beta James: 00:11:54 and distribution builds? Like what is your physical different action for creating those two different things? Or is it still always automatic? Like you do both? Always. Okay. 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. Does that make sense? Should I go into your order? Let me tell you no, no, no, no, no, no, no, no. I think it's worth, I think because the problem you just described is really hard, right? Because testers versus non tester. So here's my optimal flow. Frank. Here is what I think is what every developer should be doing today. Um, there are two products that I like. They both happen to be from Microsoft to the first one actually doesn't matter. It's continuous integration. James: 00:12:43 So you can use any continuous integration service you want. And this is just building your package, right? Building your source code, compiling your app, and then those things take artifacts and then you ship them to something else through a continuous delivery release pipeline. So the first part here is the continuous integration. And I use Azure dev ops and I use the free hosted Mac build agents for iOS and Android and they have all the Xamarin bits installed. But I also use a, um, a, a plugin 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. It takes like a minute each. So it's pretty Slims because these are hosted, right? They, that the software is not managed by you. It's managed by Microsoft, but there are hosted Mac. So that's cool. James: 00:13:37 So I do that now for Android, what I've done is I build my application twice in the same phase. So when I kick off a build, there's two phases, Android and then iOS. And these run in parallel. So Android will get everything I need. It builds my APK. So my Android package, like we've always used. 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, um, that give you an a be an Android app bundle. And what that does is louds Google play to split your application up on demand. So it reduces your app size on Android up to 50%, which is cool. And you have to change any code. So I get to two packages at the end of the day. Now an Android, we live in this beautiful world where I signed 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. James: 00:14:40 It's the same, same thing, right? It's all good. Now in iOS, I have another phase, does the same thing on a Mac and installs a version of Xamarin iOS that I want, and then I on my continuous integration service, I signed with my developer certs first. Okay. Now there's a few ways of doing this. 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. It really depends if you're using different backends, right? Do you need to compile different URLs into your application? And then that gets tricky because you do have to compile your app twice. However, one trick that I like to do is build and sign with my developer account, but then there's a magical build step in Azure dev ops that lets you resign your IPA file with any other cert. So on my continuous integration drop, I get my Android bits and then iOS, I get two IPS. I get one sign for developer and one signed for app store and you can resign it with whatever because the IPA is just a signing process. Right? It's just a signing a step, which is really, really cool. And that's my continuous integration. Just my build phase. Any questions there, Frank? Frank: 00:16:00 Wow, we have a lot to cover. Let's start with, tell me more about, well, you don't have the lecture me, but what boots? Boots. I love boots. Uh, tell me more about it. So is it like a script and so it's a quick install. Is a like a Linux or, sorry, it would be a Mac tool. Is it a Mac tool also? James: 00:16:23 Yes. Great questions of boots is from John and peppers and it is a build scripting tool that can work on any machine, Linux, windows, Mac, anything. It's just a command line tool. The beautiful part is that they wrote a task plugin for Azure dev ops. So it's very pretty UI. But if you're in Yammel basically, or if you're on your other CII service, you just say, Hey, use boots, go install this mono version. And you give it the PKG for, for Mac and you, it installs it and it just downloads it. So curls, it installs, it does everything for you automatically. And the reason peppers did this was because we were at the Xamarin developers summit and we were talking about this problem, which is I have my app but running and building and then there's a new version of X code and then my app stops building on CSI because I'm not managing that server. So boom, that's where boots comes in because it allows me to control the mono and the Xamarin iOS and Android version. And um, and then it's, it's just in control and you can use this on any machine. So it's just a command line tool, which is cool. Frank: 00:17:36 Love it, can't wait to try that out and abuse it. See which versions I can put in there. I think one thing that we're always stuck with is, um, X code changes over time. That usually doesn't cause any issues. But during, you know, the wonderful beta season, of course it does. I usually have to accept that for a couple of months. My apps just don't build in CII because they're using like beta versions and all that, but we can ignore those couple of months. So that's interesting. And I like that. I like it a lot. Especially like that you'd say it's fast. I can't wait to try that on. I'm going to try it both on bet rise and get hub actions. I use both kind of crazily. Um, 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. Frank: 00:18:30 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 going to do it with these certs. So, uh, that, that was nice to know. A tricky part here. Um, Danny Ackerman are you out there? Uh, is when you have, um, extensions like WatchKit extensions and things like that. Resigning is hard because I don't know, it just never seems to work whenever you try to resign, uh, complex things. But I would love to see, um, the source code to that step or what do you call it? An Azure DevOps. When you have like a step like that, our workflow item resigning, it's a, the, it's a step, but we call it a tech attack. A task. So a task. Yeah. So is that like open source? Could I see the code to how resigning works? I'd be interested to see if they can handle that situation. James: 00:19:28 Oh yeah. All of the Azure dev ops built in tasks from Microsoft are all open source on get hub. Frank: 00:19:34 Super sweet. Cool. Yeah. I tend to do everything with scripts and so if I don't know how to do it, I assume it can't be done. So be good to go read someone else's code and see how they accomplish these tricky little things like that. James: 00:19:50 Yeah. Now the cool part too is that like for me, um, you could of course be doing this on any CII server. Like you could be using bit rise or you could use app center or things like that. The reason I like to do on an Azure dev ops is most of my apps have other components besides just the app. So even Hanselman forms, I'm deploying some Azure functions along with my, my, my apps. And I also want to control versioning. So I like it there. And these are totally accomplishable in, uh, other services and even boots, like when you go to boots, they have scripts and how to do it in Azure dev ops app center get hub actions and bit rise. So it's all there for you, which is really cool. So they walk you through it. But I like to be in control of it a little bit more, which I think is really, really nice. Um, but, but I think that's just a build part of it and it's just sort of knowing like what goes into a build and it's, it's versioning, it's building, it's signing and that's it. Frank: 00:20:47 Mmm. And James: 00:20:47 hopefully your, your CII service is flexible enough, right? It's like you said, get, lets you do scripting and app center. Um, is doesn't give me enough control over that. So that's why I don't use app center for my builds, builds I, that's why I use Azure dev ops for it. 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 dev ops. And then I put it into a release pipeline. It also in Azure dev ops. So like it automatically flows. Um, but you know, in this regard I, I ship it over to, um, to the Azure dev ops or lease pipeline tool. And what I like here is that the release pipeline gives me a flow. So there's sort of these environments or stages to a release, right? You have developer release and then you have test or release and then you have app store release and there's these three pipelines, pieces that go into it, right? 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. Now that is the first step in the Azure dev ops release pipeline. But Azure dev ops is not releasing that. Frank app center is releasing that to me. Does that make sense? Yeah, Frank: 00:22:18 it's all confusing. But please can we, no, no, I, I'm joking. I'm joking. I'm joking. But can we rewind for a moment, 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 you said, and your website and your API APIs. And that was just a shock to me because you should see how I deploy my websites. It's tragic. It is not. I have pretty good, I have excellent library CIC hygiene. I have pretty good app hygiene, terrible for the web. I mean I have a couple sites that are on Azure and if I release to a branch then they update automatically. So I'm sure that would fit in beautifully with your setup here. But you, that was a strike man. That was a, that was a, that was a blow right to the chin about, uh, deploying your web stuff too because Oh my God, mine's always out of sync. Of course it's out of sync because, uh, I write terribly complicated scripts that I never remember how to run later for deploying my websites. So thanks. Thanks for giving me something else to think about and worry about. But I, I love that. Um, I just hadn't considered it before, but of course all the web stuff could be a part of this. James: 00:23:43 So then, and I always think of it a solution. And when I often work with Donovan Brown, um, had Donovan Belding, uh, that's what we talk about because I love that rise and I love app center, but they're really just focused on the app, you know, at the end of the day. And yes, you can script anything and make things magically happen, 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. So I want that nicety in there and I want it to just commit code and things happen. So, yeah, when I, when I commit code to handsome informs, it releases a new Azure functions backend. It's, it's literally took me five seconds to set up. And then, um, same thing for my mobile apps. It gets ready to release. James: 00:24:30 And I think of it like this, the Azure dev ops, my release pipeline, right? Continuous delivery part. It's just like Gates, right? I'm putting in Gates like, Hey, you know, this is the developer gate. What do I want to do with this package for developers? Go do stuff, right? Same thing with a website. Hey, I built this application, this, this Azure function or this website. What do you want to do with it? 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? And I'm in control via a button that says approve to open that gate. Right? So there's close Gates and there's open Gates. It's like a circuit on an I circuit board, right? The gate is either open or it's closed. I don't know if there's an in between, maybe it's not, I don't know. But you know what I mean? Frank: 00:25:20 Yeah. Um, I, I'm curious, 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. That's that once that gate's been opened, he can't, you're, you're done for, you'd sent a binary. Um, but otherwise that sounds fantastic because I was going to ask you what the, I'm always interested in what are the actual actions you take. 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, you know, I, I think of everything in UI terms, like how does this process work from a UI standpoint? Uh, but that sounds pretty good to me. I hope we're not doing just a commercial on Azure dev ops, but you are selling it pretty well because I could, James: 00:26:08 I'm selling the product, selling the product. I want to say I want to be selling a process. Frank: 00:26:12 Yeah, yeah, yeah. Well I could do the same by, uh, doing like get branch tricks. So I could say that there is a release branch or something like that. 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. But that's a semi esoteric process. Obviously even as I just described it, I came even remember how it works. So, uh, having a UI in this case, I'm there with you. Um, it, my UI for the system would then be like, pick a branch at the top and then pick which of these Gates you want to open and close. Can you get the UI that simple? James: 00:26:52 That's exactly how it is. 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. And I have three Gates. So there's, there's on my screen, I'm looking at it right now. There are, there's a release which says this happened from VNX, which is my current branch that I'm on, like I specified find things from v-necks. 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. So vision three boxes, horizontal. I'm liking it. I like big boxes. One says dev and it's green and it succeeded because that one auto deploys, right. It automatically deploys. Sure. Frank: 00:27:43 Why not make your, make your D Oh, that's not testers is it? Okay, I'll, I'll let you finish. James: 00:27:49 Dev. Yes. Then I have testers or in my test for this app, it's public preview. Okay. So my testers is a public preview link, but this could be internal testers and that's another box in the middle. And currently it is blue and it says pending approval. Okay. And there's another button right underneath it which says approve. And if you click that button then the release to my testers starts. Okay. Frank: 00:28:20 Sounds fantastic. Just how I want it to work. I'm, I'm hoping this UI is as elegant and as simple as I'm imagining. We'll see. James: 00:28:30 Yes. Now there's a third box that says app store. Now sometimes you might have multiple boxes, like ones to test flight ones to the apps or whatever. Maybe alpha, Google, and then BA, whatever you want. Right. So you're gonna miss multiple boxes. But I have a third one that says app store. And specifically for iOS, I just go to like I go to, um, I go to test flight first and then I always download from test flight. And then I also have a uh, Google play alpha and I'll tap a release there first. And what that does, it has another blue box that you can't get to until you do a, uh, your testers go through and there's another approved box. So once you do that, it goes now behind each of these boxes Frank are steps. There's tasks that you want to do. 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. And what's cool about app center distribute is a few things that I really, really like. 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 Speaker 4: 00:29:42 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. So ship it to a test flight or ship it to whatever. So app center becomes my distribution where from any ECI service you can ship it into app center, right. And app center will then, you know, send your users and email. 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. And app center is where I sign into my Google account and sign into my Apple account and I let app center do all the distribution because app center also does my analytics crash reporting, push notifications and things like that. And what's nice is that I also send them my debug symbols, right? Speaker 4: 00:30:30 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. So if I get a crash app center is aware of the debug symbols and I can see the better crash logs in it. So Azure dev ops is just managing when things happen. And for this thing, I am saying distribute this app to app center, you know, a developer group test or group or the app center group or sorry, the test flight group. And at the same time I'm also releasing my Azure function backend directly into Azure, all from the same pipeline. Like I had those Gates in place to say when I finally go through this then publish my backend when everybody needs to hit it at the same time. So my apps and my backend are all in sync in a beautiful little flow there. Um, if that makes sense. Frank: 00:31:25 Yes sir. Wow. Okay. I like what I hear. Um, I want to go back to the buttons again though. Okay. So, um, yup. Are yours chain T I'm just curious. Personal preference here are yours chained together. Like you have to go through dev and then you have to go through, um, test and then you have to go through deployment. Because I was thinking while you were talking to Mike, that's not how I would wire it up cause I would definitely want to skip the testers. I skipped testers way too often. And so, um, I'm pretty sure that's how I would set up my graph, but I was just curious how you set up yours. Speaker 4: 00:32:03 Yeah. So what you can do is, um, you're really in control of this so you can have it. 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 approved buttons. So you can say, Oh no, this one I actually want to release just to the app store. Go. Or another thing you can do too is, um, 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. So like, you can do this thing, you can do a manual release and say, you know what, skip these and then just ship that other thing out. Frank: 00:32:42 Okay, that's fair. I just want to stay in button world. Uh, but you didn't answer the question, sir. You personally, are they, uh, chained together or are they independent of each other? They're always chained together. Yeah. Yeah. Okay. Uh, so I did get lost in one little thing. So I love, uh, some line you said about dev ops is just what you're using to orchestrate all this thing. It's just handling the events and kicking things off. And he made that really clear with the app center thing. I had never considered using app center in that way. It seems a little bit abusive because they, they have a nice UI. I like the app center UI, but I never considered just having scripts, just shoving data into it. So that's very clever. Uh, never considered that, but I'm going back to the dev ops. Can you do, uh, builds in that too? So you can say dev ops run this script on a Xamarin machine or are you, or do you have a different CIS system from dev ops? Speaker 4: 00:33:46 From the CD, the, the release part, you mean? Frank: 00:33:48 Yeah. Are they two different ones or are you a all in one? Speaker 4: 00:33:52 So, great question. So every stage in the, in the build and in the release is on a fresh machine. Okay. However, if you want to, you can have one of your release stages. Um, you can, you can pick the machine that it's building it, shipping it from, so it needs to spin up a machine. So like if I just have a, 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 Linux or a Mac machine and then ship it via curl. Right? Or just put it over there. Um, and then via the, the, you know, there's a restful API for them to send it over there. But what you could do for instances like one of those stages can have multiple steps. So you could say, Hey, download this artifact on this Mac machine, install my provisioning profiles or resign this application and then ship it wherever you want. Speaker 4: 00:34:52 Or you can, you can do anything that you did in the, in the continuous integration. You could do it in the release pipeline if you really want it to. So maybe you want to run tasks or UI tasks 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. And I don't care about the dev part. I want to make sure that, you know, I run an additional suite of tasks. 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. Is that the question you're asking? Frank: 00:35:24 Yeah. But you keep saying you could, it's are you saying you shouldn't? What is the recommended a place? Like where do the getting started doc say I should do my bills. Speaker 4: 00:35:36 Well see all of your, so James: 00:35:38 here's what I like to think. I like to think that, that everybody has their own way that works best for them. So you do your own thing. But I like my build to be the build, right? Like this is the artifacts that I want to do stuff with. And, and those artifacts are, are the distribution part of it. But I do think that part of the distribution should be additional tasks or load testing of a website or something else to make sure that Hey, you know, everything worked great in dev and you know, my test scores are okay, but I want to have this additional checklist that says, before I released to the app store, before I put this website on the internet, make sure that there's an additional suite there. And I think that's okay. I think that your, your build can do tasks, but I like my bills to happen fast and I would rather that my build went green fast and then my release failed because, uh, my tests, you know, failed or whatever and my low testing failed or something like that. James: 00:36:48 Um, and I think you just need to be aware of like, where would you like your things to fail at what point? Right? And sometimes it's, I want my, you, my unit test to fail, right? Cause unit tests are really fast to run. So if I'm building a library or a website, like run my unit tests when I'm building my app. So if those fail, then it's as if my build failed. But if I'm low 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. I think that 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. Frank: 00:37:27 Okay. Let's, uh, clarify with a concrete example because one thing, one question I still have is whether builds kickoff the dev ops process or commits the get hub or is it a polling system and Azure is just always querying different things. So let's say I have a built on bit rise. Hypothetically James, um, would I run a script at the end of my bill that pokes dev ops and says, Hey, Hey, here's a bunch of files, uh, begin this process now or something else. Or is it that triggers dev ops? James: 00:38:09 Yeah. So this is a great question. So the first part, which is the for both bit rise and Azure dev ops and app center. Anything else? Like that, right. The build phase. So the, the build pipeline where you're going to build your artifacts, that is kicked off via a commit. Okay. Frank: 00:38:34 Yeah. That have done, that's the Speaker 4: 00:38:36 CII part that I do for all my libraries and all that. That part I'm solid. Yes. Now the continuous delivery part, so the release pipeline that is triggered by, um, an artifact drop. So it's like a commit of artifacts somewhere on the internet. Does that make sense? Okay. Frank: 00:38:59 Yeah, that makes absolute sense. Because at the end of a CEI process, you always have to decide which artifacts you want to export from your, uh, process. So for me, that's usually I'm dead signed, built apps, things like that. But for all your, my libraries, it's a bunch of packages. So that makes absolute sense to me. And I love that because I was worried that it was going to be like some API that you had to encode in a funny way. I'm sure it still is, but in some way you just have to take a bunch of files and dump them on a server somewhere and that kicks things off. Speaker 4: 00:39:35 That's correct. So if you're doing it inside of, so if you're doing it inside of Azure dev ops, it's really easy because when you're build completes, like the artifact is dropped and then the release pipeline says, Hey, there's a new thing. Go start up this release pipeline. Um, which is there now that release pipeline from in Azure dev ops can be triggered in one of nine ways. Frank, are you ready? Okay. So it can be triggered via a build in Azure dev ops. That makes sense. Uh, it can be triggered via, I think, source code repository. So a get a get hub, the TFTC I think that like if you commit something there, it can also trigger the pipeline do occur. Um, you can ship items to Azure artifacts, you can do it ideally off of get hub releases. So if you had a release, you could be listening for new releases to get hub. There's also, Frank: 00:40:39 that's nice for libraries, but I won't, I'm not ever going to put my app on get hub releases. I don't think, Oh, I, you know what, I take that back when you were saying releases. I was thinking that you're forced to put the binary's up there, but no, it's more of just a tag. So cool. Okay. So yeah, Speaker 4: 00:40:57 and then I think you can also put them in like Docker containers or Docker hubs or even like Jenkins, like you can like link it to a Jenkins job. Now I'm not sure what the best way to do it is. If you're going to use bit rise to build your app, my assumption is you'd either tag it in a get release or upload it to Azure artifacts somehow and like basically drop something in there like drop a package or something like that. I'm not 100% sure to be honest with you. Frank: 00:41:26 That would be the simplest, most ideal solution for me. That would be wonderful if that's how it works. Cause you could always use curl or something to upload a bunch of files. But knowing the internet, I'm sure it's complicated, Jason API then I'm going to have to learn to use James: 00:41:43 probably probably, but I mean Ruby. Yeah, I mean and like I said, you could most likely accomplish this. What I used to do in bet rises, I would have multiple workflows based off the branch and then each branch would do something. But the reason I didn't like that was because then I'm building my app again, right? Like I'm, I've built my app in master and then I have to like magically pull the code up into this release branch and then I have to build again and then it goes through a different flow. So instead of like 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. And that's kind of my idea. Frank: 00:42:24 Yup. Okay. So I like all of this. I like it all. You, you, you have me sold. Okay. But I have a concern. James. I have a concern. We are managing a lot of configurations and services and things like that. I wonder if it's truly saving me any work, uh, because I have to maintain these processes. Let me actually start over. I'm going to turn this into a question instead of a concern. Let's say I put all this effort into this for ice circuit and it's glorious. I have the most beautiful graph ever. It does the best things for the Gates and builds and all that versioning. Great. What do I do for Kalka? Can I just take like some Jason file or Jamo phone apply to Calca or do I have to rebuild all that work and effort, uh, again for another app? James: 00:43:24 Yeah, it's a good question. Um, the build pipelines, so if you're like your CII part of it, that's, you can just do that all in a gamble file and make your, make that part of your code for the release pipeline. There is no Yammel today in there. However, you can go into a release and then say export, like export this and then re-import it into another one. You know what I mean? So cool. What does it, just out of curiosity, what is the key for you when you hit export? I'm going to do it right now. So it gives you a Jason, just curious Jason. Okay. So Frank: 00:44:04 it really is adjacent file at the end. Um, that's cool. So you can ostensibly check that in if you ever are, 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, uh, I like you eyes, I love them. 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. I maintain five, six apps and it's a bit of effort. So, um, any process I come up with gets multiplied by five. That's kind of my concern. 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 4: 00:44:54 Yeah. You know, and I, and 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 new get. And inside of my Azure dev ops project, it's called my plugins. And my plugins has, you know, 15 build pipelines. And whenever I add a new library, I just right click copy and then duplicate basically. And same thing with release. I just right click and I say, you know, duplicate this and then it duplicates it there it is a little bit tedious if I have to go through and update all of them. But I will say like that's like if I had to change something I'm like, Oh I need to add this new step cause I want to do this thing. I have to update all of them. But then I think well there'd be no difference if that was Yammel because I would have to go update 15 Amels right. Speaker 4: 00:45:43 All with different properties. So it's similar and I think it is one of those risk verse rewards where especially if your a solo developer like you and me, is it really worth my time and energy to go through this, this experience. And it takes some time, right? I think you have to invest a little bit of time in it. However, once you've done it, I mean every time I add something new, it's like butter. It's just like it takes the second time I do it. Like if the first time it took me eight hours, the next time takes me four hours, the next time it takes me 30 minutes and then the next time takes me two minutes. Right? And now I'm just like, Oh, I just, I know exactly what I'm doing. [inaudible] and um, and ideally nothing breaks. I would say that my releases, my release pipelines have like never broken because releasing something to new get, or at least saying something to app center has not changed. Speaker 4: 00:46:38 Um, and even releasing to test flight has not really changed from a CEI point. The pipelines always changed because of the building, because of what you said, right? Visual studio is updating X codes, updating, all this stuff is updating. And that's the trickier part sometimes is, is, uh, is making sure that, that those environments don't change. The release part is fine because it's, you already, you already did all the hard work, right? You already did the thing. 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. 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 Devlin and here's my tests or one and here's my other one. And like it just goes into the right places like that could totally be a thing like your ad hoc little or at least pipelines via, you know, bash scripts. Yeah. That's what I see Frank doing in the future. Frank: 00:47:35 No. Uh, I'm, I kind of liked the app center part because one of my biggest concerns with the CD part was that interface with the Apple uploading stuff to them is notoriously difficult to automate. So I love that other people are working on that problem and I don't have to deal with it. That sounds really good. Yeah. Yeah. So I like what you're said about, uh, the plugins because it actually got me thinking about, um, multi-platform for myself. So this whole time we've been talking, uh, Android and iOS, but, uh, apps like ice circuit are, is on, um, three shipping, three different platforms right now. He used to be on like five different platforms. And so having those separate builds is really important to me. And orchestrating the whole thing. I'm definitely not good at, I added a little feature or I did some bug fixing to one version and have I released it to all three or four distribution channels? And the answer James is usually no. 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. And that's a, it's making me think a bit that maybe I should, uh, look into this. Speaker 4: 00:49:01 Yeah. You know, I think that what happens is once you invest in it, the payoff, maybe it's a non, right? Maybe you're like, you know what, I set up this thing. It's taken me the same amount of time if I had just done it manually. But then over time, ideally it means that you can ship new features to your testers faster. So you get that feedback faster. Ideally you can ship an up update without having to be at your computer because you could change some code. I was at, this was actually kind of cool. I was at Lance, I think McCarthy is his last name and it works at Tellerik progress. And I was at the Deveridge conference in Bulgaria and he talked about how he shipped an update to the conference app from his Android phone. He had no computer, he was on a flight, he was on a flight in the air. Frank, he made a code because Apple had rejected his app, he made a code change in get hub like online, which kicked off of a dev ops, you know, build an Azure dev ops. And then kicked off is continuous delivery part. And when he got off the plane he could download the updated app, validate it, and then from his phone he said released to Apple and it like released to Apple automatically. Like that's kind of freaking cool. Right. Frank: 00:50:23 Okay. So one quick, yes, it is obviously very cool. I hope to never be in that situation. I hope to. Absolutely. Never ever release an app that way, but sure, absolutely. Cool. Uh, shoot, I just totally forgot my question, but I had, Oh, I'm sorry. So when you say a release to Apple, when you do it manually, it's a two step process. So you upload your binary and then you either approve it for testing and distributed to testers or you submit it as an update and in which case you should get give update, taxed and other details like that. 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, ah, Speaker 4: 00:51:13 new new version? No, I mean you can totally specify release note information directly for the app store update. Now what does James do? James does not ever directly, I never directly submit my application to the release. I always like, this is my, my final step for both. You could do this, right? But my final thing is like from my, my distribution pipeline, my final step. So where it ends is a distribution to test flight and a distribution to Google play alpha. And 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. Um, for me though, I don't like that for some reason. Like I like to always download a task via test flight validated. Like I know that like this is the build and then I just go into the app center connect. Speaker 4: 00:52:18 And I, and I, when I, I flip that switch, right? I say, use this build, submit for review, make sure everything's valid. 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. Um, just so I have a peace of mind. Right? And if you, if you want to skip all that, you can totally have your dev ops pipeline do all that stuff. But for me, I like that final little validation phase. That's kinda like my, my, my own personal gate. Right. I like to have that Frank: 00:52:53 [inaudible] so to be clear, and I'm a little bit, uh, in shock here, you never log into iTunes connect. Speaker 4: 00:53:02 No, no, no, I, I'm saying that I always log into iTunes connect. Frank: 00:53:06 Oh, okay. Okay. So you have a test flight, build an iTunes connect, you go in there and you say new release type in a new version, type in release notes, hit submit. But you're saying that could also technically be automated via dev op? Speaker 4: 00:53:20 Yeah, correct. You could totally just Stan automate that. Frank: 00:53:24 Okay. Now through app center, that's what I was a little curious, is it app center or dev ops that can automate that? Speaker 4: 00:53:31 Um, I guess I think both. Can, I think both can Frank: 00:53:35 well, yeah, once probably using the other very interesting stuff. I realize now that I'm a wimp and I've always just been afraid of [inaudible] setting up a complex process, but I should, uh, I should not be a wimp because I would love to have simultaneous releases of my app. Could you imagine James releasing on all platforms on the same day? I, I can't personally, Speaker 4: 00:54:01 you, um, it's all possible. Right. I think then the problem with that is then for like for Apple, you're, you're just submitting it for app store review, right? You're not actually getting it into the app store. So you're really, you want it to be held for release and then toggle back somehow. So yeah. Frank: 00:54:21 Gay and dev ops and I'll just have, when I, when I clicked that button approved, then it'll actually send it the other ones to Android. So I thought Android had a little delay too. Or is that pretty instant? Speaker 4: 00:54:32 It's two hours, usually two hours. Okay. Yeah, that's sort of the phase roll out. They scan your APK for malicious stuff and then, um, it releases in phases out to the internet, basically CDN updates, right. Takes some time. Yeah. Frank: 00:54:48 Well even after, um, app store approval, it takes time to actually distribute throughout the store, Speaker 4: 00:54:54 so that's fine. Yeah. I don't think there's, I don't think that it's possible. I mean there's, I don't think it's humanly possible to simultaneously release an app at the same time on the same day to everybody. Right. I just don't think that that's humanly possible. I think you can get really close by and through this. Right. Is your challenge accepted? All right. All right. All right. I love it. Okay. Yeah, I like, I would like, I would like if, uh, if it was possible, but I'm not sure if it is. Frank: 00:55:29 I think the windows store approval processes pretty fast, so I'm thinking, yeah, I could do this. That'd be cool. We'll see. We'll see. Ah, well that was fun James. Somehow we talked for 55 minutes about dev ops. I, it's like, did we talk about machine learning? And then we've talked about dev ops, but we didn't talk about machine learning, so I guess we're going to have to go back and forth on that pendulum. But either way, 55 minutes of dev ops, Speaker 4: 00:55:57 right? Yeah. I'm curious also what our listeners, um, are doing too. Like is that, did everything that I just say like make sense and that's what you're doing or is that complete ridiculousness? To be honest with you, I, I don't, I don't know what people are gonna think. So let us know. You can write into us, um, by going to merge conflict out FM. Um, and send us an email. We, we read those or you can leave a comment. Um, in general, we actually got a lot of comments recently and uh, I figured I'd take a few minutes here, Frank, at the end of the podcast talking about listener feedback. I love feedback. Okay. So the first one I want to talk about, I will put this into the show notes, but if you go to episode one 74, uh, Louise from Brazil, he, uh, we, this was episode where we're talking about C sharp eight and specifically we were talking about arrow pattern. You remember arrow code [inaudible] um, apparently in Brazil they call this a Dukin indentation via street fighter. And he put in a, a graphic of rye. You from street fighter doing a fireball high Duke in with the arrow going into it. Yeah. It's, it's amazing. It's amazing. Yes. Frank: 00:57:11 Perfect. Makes yes. Awesome. Love it. Uh, Speaker 4: 00:57:17 excellent. Yep. That wasn't good. Why he should have better graphics. There's like every time, like every time you do something or you reformat it, like if it just knew how to do something, some cool animation came and it was like smush. Right. That'd be, that'd be amazing. Frank: 00:57:32 Or just Clippy shows up and says, I see you've nested your if statement a few too many times. Speaker 4: 00:57:38 Yeah, that'd be great. Ah, ah. All right. Um, uh, two more here. So from episode one 75, Jim wrote and he said, um, specifically this is about knowable. So we are on the C sharp eight train apparently, and this is a nullable enable talking about Nobel reference types. Uh, Jim's had a great topic and discussion. I started down that, um, pound knowable path following your advice and counsel. Wow. People did it based on this. Yeah. Yes. Yeah. So he said, uh, specifically, I'll make sure that you read this. It's a little bit in depth, but he said, uh, he was stumped a little bit when it came to understanding, um, when Nobles enabled default types. Um, so often he said, I would expect that the default of string does not equal null. To my surprise, the default of string is no, that's actually correct. It is. How does, how does that make any sense? If default of string equals equals string dot empty, then we can initialize properties with, you know, public string name equals default unknown string is a special type, right? It's like it's a, it's an object. Frank: 00:58:48 Yeah. Yeah. It's, it's an object. And um, well in this case it's an object reference. It's a pointer in the old SeaWorld. And the easiest way to remember is that all memory in.net gets initialized to zero. And so if you have a reference, a pointer and it gets initialized to zero, well that's no, why does it do that? Because it's fast because that's how it was designed. Uh, this is obviously very smart. Default could be stringed out, emptied, uh, in the [inaudible] world, but basically, um, stop using default string. I don't use that anymore, but uh, yeah, sorry Joe. But it's a, it's a great question and yeah, if the language was being designed today, they might change that rule, but uh, yeah. Can't change that. [inaudible] Speaker 4: 00:59:42 I feel like that's why half the reason why nullable happened is because of string, to be honest with you. Frank: 00:59:47 Yeah, for sure. A string is or is not, are empty. Um, it's like just a sign that you have no idea what's going on in your code. And I do like, um, the default thing, but I, I, I take that back. I don't like the fall. I never use it in my own code. I guess only if I'm writing generic code or something like that. Uh, it's just, I'd rather put the number in. Like even I get yelled at by the IDE for initializing fields to zero. It's like, Hey, by default things are initialized to zero. And I'm like, yeah, but I used to be a C programmer and we had to initialize things and if not bad things happened. And so it's just, it's built into my brain. I have to initialize things with good values. Speaker 4: 01:00:30 Yeah. I, I get with, I get that with bulls too because it is false, but I'm like, Oh, you know, [inaudible] blah, blah, blah. That's why I like, often I'll use some people just be like bull, like log it, logged in equals false, and then it'll be like, Oh, don't worry, it's a bul so you can drop that. But if you use VAR, then VAR has to be initialized. Right. Because it doesn't know what it is. Frank: 01:00:52 Yup. Yup. So subtle things like that. But yeah, uh, uh, you know, it's not a perfect language that shows it's C heritage sometimes. Speaker 4: 01:01:05 All right. Last one, Frank, because last week's episode on the ultimate developer machine and my blog, it got a lot of feedback frying guys, awesome back. Um, Frank: 01:01:16 people love it when we talk about overpriced hardware, not overpriced. I got to keep catching myself very expensive. We priced very costly hardware. Speaker 4: 01:01:24 Yes. And, uh, Twitter, there was a lot more feedback, but I figured on the website since I'm on the, Hey, you should leave comments on our website. Why don't I read the comments on our website? Um, Jimmy Scott wrote in, um, and he said, Hey, he said, without sounding smug, because we definitely probably sounded smug throughout the entire podcast. Um, he, he said that he has a similarly SPECT portable laptop maxed out and it is not a massive alien ware thing. One, I'm also interested in what it is. He didn't say what it is, but I'm, I'm curious. Um, he says it's his only machine and he regularly has multiple VMs running. So that validates what we were thinking about modern day Dez, we have multiple things running. Um, so he says it's definitely possible to use a laptop as a primary workstation. I gree. Um, he said the difference in why he didn't get a Mac MacBook is that a Mac book is about 1800 pounds. Speaker 4: 01:02:20 So he must be living in the UK more expensive than the machine that he built. And in the grand feats grand scheme of things, it's not that much if you're using it every day. However, there's a few things that he likes. He says hard drives. I can easily change them out. If they die, I can rip out the memory. Um, if one, so dim dies. He likes that, you know, it's modular basically compared to a Mac. But he says the biggest thing is support. Um, he says if you have a primary workstation, like this is what happens when it goes to something goes wrong with it. He said his model that he bought has a four year next day onsite support. And he says with Apple, you need to take that into consideration with AppleCare I guess how many days before it's fixed and what's the cost to you or your business? Speaker 4: 01:03:07 That's a good question. I guess last time I bought an iOS device, I bought Apple care and then on my surface go that I bought, I bought Microsoft care. I guess that's why I don't know what it's called. Um, and that was, I literally took, I actually had problems with my surface go the bottom part of the Touchstream stop working. So I took it in the, gave me a brand new one within 30 minutes. So it was kind of cool. I don't know about Apple of, yeah, a lot of, um, have you ever had a lot of interaction with Apple store and old machines and things? I feel like they're pretty good, but I could be wrong. I don't know. Frank: 01:03:39 I try to, I avoid them like the plague even though I'm on my, uh, I have one computer with a broken part that's technically under, um, what do you call that? Product exchange, whatever they're supposed to fix it, but I don't want to make an appointment. I don't care. I have like glue holding it up and the glue seems to be working just fine for now. So this is a pretty great situation. This though has gotten himself into, I don't know how many people have four year next day onsite support. It's not something I see offered in Seattle that often, especially for the price he's talking but pretty awesome. A good deal. Especially if it's not a giant laptop that you know the lights blink when you plug it in kind of thing. But yeah, I don't know man. Like Apple, I don't like the Apple store just cause it's always so busy. But I still in the back of my head feel like if anything went wrong I could probably get things fixed pretty quickly. Speaker 4: 01:04:38 I feel like they would, they would handle that I think. Frank: 01:04:41 Yeah. Yup. I called them up once when my office was broken into, uh, they had stolen all my computers. And so I called the Apple and I said, hi, uh ha any, do you have any high end computers? And he said, sure thing I do. I'm like, okay, have it ready for me. When I, when I arrived and I arrived and he had the computer, I gave him money and I walked out and it was so fast and so simple. I was like, that's how you do an Apple store Speaker 4: 01:05:09 and that's how you get it done. That's awesome. Oh my goodness. Uh, well, um, that's it. Thanks everyone for writing in. I, I like, uh, listening to you, Frank, and I also like reading from our listeners and it actually shows that people, people actually listened to this podcast. Did you know that Frank? Frank: 01:05:28 Ooh, that's it. That's interesting. But now I see that they're commenting and I want to go back and read all these comments. I see there's some comments from episode one 57, one 37. Ah, sorry, everyone, I need to read these more often and I'll get on that. Speaker 4: 01:05:44 Yeah, I think it's the, the problem is I always like going to different websites and checking stuff, but we'll do a better job, we swear and um, you know, go over to merge conflict and bottom your friends dev ops it. Ooh, make it an event. Yeah. Probably have some Gates and then we have to review it. And then we have to, did we talk about in the podcast? Oh no, no, no. I need just an email. So, all right, well that's going to do it for this and we expired castings. Everyone who wrote in and thanks for everyone who listened and thanks Frank for putting up with my nasally. Still sick after a week voice. Hopefully you didn't tell. And that means I've been muting constantly. Frank: 01:06:19 Oh yeah, you've done an excellent job. Well, I was sick for the last two recordings, so, uh, sorry, I must have passed it on through the electrons. Speaker 4: 01:06:29 I believe so. Um, but yeah, you know, Hey, at least I can snuggle up with this one hour and six minute podcast to get me through the sickness. So that's going to do it for this week's podcast. And until next time, I'm James Monson Magnum. Speaker 1: 01:06:41 I pray Kroger, thank for listening for an hour and six minutes.