Guest Post: Securing and Versioning Xamarin Apps with Mobile.BuildTools

Avatar

Dan

Dan Siegel is a Microsoft MVP, maintainer of the Prism Library, author of numerous dev tools and OSS libraries, leader of the San Diego Xamarin Dev’s Meetup, and a Xamarin blogger. Dan works as a Cross-Platform and Cloud Consultant at AvantiPoint and has a passion for DevOps and automation.

Mobile.BuildTools

Writing mobile apps can be hard work. There is a long list of things to be set up for each project, in addition to the technical challenges that need to be overcome for the sake of security or to configure. The Mobile.BuildTools were born out of a desire to make DevOps easy and consistent to set up from one project to the next. The Build Tools aren’t just another library to install to your project, and they don’t add yet another dll that only adds to your final app size. Instead, they contain several tasks designed to make developing apps easier by training MSBuild to do some common DevOps tasks with some idea of whether you are building your app locally or on a CI Server. It also considers which CI Server you are building on for maximum efficiency.

Secrets

Secrets are the very heart of the Build Tools. Nearly every app has some concept of a secret or at least something that should not be checked into source control. It could be your App Secret from AppCenter, your App’s Client Id for an OAuth provider, or perhaps it’s just the URL for the backend API. Regardless of what specifically the variable is for, injecting these variables with configuration files is not something you can do for Mobile like you could with a conventional desktop or web project. Trying to make it easier for other developers to work on the project, build the project in CI, and prevent the accidental check-in of an actual value being used by a developer on your team can be challenging.

Adding secrets to your app is as simple as adding a single JSON file to your project and then adding it to your .gitignore file. Even better is that secrets support string’s, bool’s, int’s and double’s opening up additional options of what you could potentially inject at build.

.gitignore

secrets.json

Foo.cs

using AwesomeApp.Helpers;

namespace AwesomeApp
{
    public class Foo
    {
        public void DoFoo()
        {
            if(Secrets.SomeBool)
            {
                Console.WriteLine(Secrets.SomeVar);
            }
        }
    }
}

secrets.json

{
    "SomeVar": "A Value",
    "SomeBool": true,
    "SomeInt": 1,
    "SomeDouble": 2.0
}

Build Server Secrets

The whole notion of adding a JSON file may sound nifty for local development, it is certainly an easy way to add constant values that you need in your code. At some point though your project won’t be built in your local environment where you can just add a JSON file. Instead, you will need to support it being built as part of a CI build perhaps in VSTS or AppCenter. Working with App Secrets in your projects couldn’t be easier in CI. By adding a variable prefixed with Secret_, the name following the prefix will be added to the JSON file, along with the value. Your Secrets class will be automatically generated without a single script as well.

App Manifests

Sometimes secrets go beyond code, and they are a problem that you need to deal with in an app manifest. A perfect example of this is when using the [AppCenter Distribution SDK], you must update your Info.plist to include a custom URL Scheme that contains your App’s AppCenter secret.

Info.plist

CFBundleURLTypes

    
        CFBundleURLSchemes
        
            appcenter-$$APP_SECRET$$
        
    

(Refer to Microsoft documentation App Center SDK -> Modify your Infoplist)

This can be easily overcome by tokenizing your manifests as shown here. Of course, this isn’t always practical to be developing with a tokenized Manifest as it could lead to an exception or you may have tokenized your Bundle Id. As a result, it opens up risks of accidentally checking in a value used during development. The solution is simple, exclude the manifest from source control, then place the tokenized version somewhere in your repo. The Build Tools will use conventions to locate your manifests and replace tokens from environment variables and then copy the missing manifest into your project. Similar to injecting Secrets, you simply need to add the prefix Manifest_ for the Build Tools to locate the value of the replacement.

Advanced Tasks & App Versioning

The Build Tools keep getting smarter. In fact, they are currently able to determine whether you are building on AppCenter, AppVeyor, Jenkins, or VSTS. For those brave enough to write create their own build tasks, you can benefit from this by conditionally executing some logic based on your build environment.

The Build Tools uses this understanding of your environment in a few ways. To start it will assist you by copying your Android APK, and your iOS IPA and dSYM to an Artifacts directory under your Solution root folder. This makes it easy to locate your build artifacts. Copying these artifacts to the same directory doesn’t always make sense though. For that reason, you’ll find that the Build Tools when determines the build environment is VSTS, it will automatically adjust the copy directory to $(Build.ArtifactStagingDirectory), and will disable the unnecessary task altogether on AppCenter.

Building Mobile Apps also means that you need to think about Versioning. The chances are unless you are a Library author, you probably don’t do much versioning. Versioning becomes critical though as you cannot submit version 1.0 to the AppStore multiple times. Automatic versioning though couldn’t be easier than with the Build Tools as you can set it up to version every single build, only local builds, or only builds on a CI Server. You can also choose between using the timestamp or you can prefer to use the build number. In order to enable Automatic Versioning, you simply need to add a property to your project with the version format you prefer. By default, every build will then get a version number.

AutomaticVersionOffset0
AutomaticVersionEnvironmentAll
AutomaticVersionBehaviorPreferBuildNumber or Timestamp

gistfile1.txt




  
    Debug
    iPhoneSimulator
    8.0.30703
    2.0
    {9F0236FA-9A36-40CB-924F-4CA379E05CE1}
    {FEACFBD2-3405-455C-9665-78FE426C6842};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
    Exe
    Contoso.iOS
    Resources
    Contoso.iOS
    
    PreferBuildNumber
  
  
 

SCSS for Xamarin Forms

CSS is undoubtedly one of the most powerful changes made to styling for XAML. While this is an exciting new enhancement to Xamarin.Forms, it also can quickly become hard to maintain on larger projects. The Build Tools provides an easy solution with bundled support for LibSass with SCSS stylesheets. Since LibSass is bundled there is no requirement that your machine needs Node or the Sass cli, it simply works by building your project. By using SCSS you get support for variables, functions and partial stylesheets making it easier to generate consistent styles in a manageable fashion.

The Xamarin.Forms CSS spec allows you to generate styles that apply to all elements of a given type as well as derived types by prefacing the type with ^. This isn’t actually valid CSS, and as a result, the LibSass compiler will not compile this. By updating your style as shown below to use either the ‘any’ or ‘all’ selector, you are able to write valid CSS and as a result, LibSass is able to compile to CSS. The Build Tools are then able to post-process the CSS to match the Xamarin.Forms spec.

Wrapping Up

It’s easy to get started with the Mobile.BuildTools. Head to GitHub to see a fully working demo built on AppCenter without a single build script. Check out the project ReadMe for more information on to set up custom configurations.

0 comments

Comments are closed.