Continuous integration

Note

This is an advanced topic that is closely tied with the further development and customization of the nRF Asset Tracker for your purposes. See the GitHub project page of the nRF Asset Tracker for Azure for an implementation of the process outlined in this section.

Continuous integration involves the following actions:

  • Every change to the project is tested against an Azure account, which must be manually prepared.
  • A Behavior Driven Development (BDD) test suite of end-to-end tests is run. The test suite is written in Gherkin, which describes the tests in English.

In this way, the tests are not tied to the implementation and you cannot accidentally drop tests during refactoring. Tests written for test runners like Jest tend to be closely tied to the API of the source code implementation. In the case of a larger refactoring, the tests often need to be refactored as well. Since the BDD tests are purely testing based on the public API of the project (which is a mix of the native Azure API and a custom REST API), they can be kept unchanged during refactoring.

Prepare your Azure account

Note

The setup process in Azure is more complicated when compared to the AWS continuous integration setup since it involves many manual steps, which cannot be automated. If you have ideas to simplify the process, provide your input.

Log in and create the resource group

To create the resource group for the CI resources, complete the following steps:

  1. Log in to the shell:

    az login
    
  2. Export the identifier of the subscription that contains the nRF Asset Tracker resources:

    export SUBSCRIPTION_ID="subscription id"
    
  3. Make sure that you have enabled the correct subscription by using the following commands:

    az account set --subscription $SUBSCRIPTION_ID
    # Verify that it is set to default
    az account list --output table
    
  4. Choose a resource group name for the solution and export it as RESOURCE_GROUP. In this example, nrfassettrackerci is used as the resource group name.

    export RESOURCE_GROUP="nrfassettrackerci"
    
  5. Choose a name for the solution and export it as APP_NAME. Use a short name (not more than 16 characters) composed of numbers and lowercase letters only. In this example, nrfassettrackerci is used as the application name.

    export APP_NAME="nrfassettrackerci"
    
  6. Configure your preferred location (you can list the locations using az account list-locations) and export it on the environment variable LOCATION. In this example, northeurope is used as the location name.

    export LOCATION="northeurope"
    
  7. Create a resource group for the CI resources:

    az group create --name ${RESOURCE_GROUP:-nrfassettrackerci} --location ${LOCATION:-northeurope}
    

Create a secondary tenant (Azure Active Directory B2C)

  1. Create an Azure Active Directory B2C. Currently, it is not possible to create an Active Directory B2C and application through the ARM template (see GitHub issue).

    1. Follow the instructions in the tutorial for creating an Azure Active Directory B2C tenant and create a B2C tenant.

    2. Follow the instructions in the tutorial for setting up a resource owner password credentials flow in Azure Active Directory B2C and register an application. Make sure to set the following parameters:

      • Set the Supported account types to All users

      • Update the Azure Active Directory app manifest and allow implicit grant flow for OAuth2:

        {"oauth2AllowImplicitFlow": true}
        
  2. Export the initial domain name that you used:

    export B2C_TENANT="Initial domain name" # For example, "nrfassettrackerciusers"
    
  3. Export the Application (client) ID and the Directory (tenant) ID of the created Active Directory B2C App:

    export APP_REG_CLIENT_ID="Application (client) id"
    export B2C_TENANT_ID="Directory (tenant) ID"
    
  4. For enabling the test-runner to programmatically log in users, enable the resource owner password credentials (ROPC) flow with the following settings on the Active Directory B2C:

    1. Name - B2C_1_developer.
    2. Click Application claims, select Show more … and then mark Email Addresses as a return claim.
  5. Grant the B2C directory API permissions for authenticating users:

    1. In the left menu, under Manage, select API permissions. Add the permission to manage user accounts (Microsoft Graph -> Application permission -> User.ReadWrite.All).
  6. Grant the B2C directory API permissions for the function app:

    1. Click Expose an API and set the Application ID URI field to api.
    2. Click + Add a scope and create a new scope with the following values and click Add a scope:
      • Scope name - nrfassettracker.admin
      • Admin consent display name - Administrator access to the nRF Asset Tracker API
      • Admin consent description - Allows administrator access to all resources exposed through the nRF Asset Tracker API
    3. Click API permissions and then click + Add a permission. Under My APIs, select the app registration.
    4. Enable the nrfassettracker.admin permission and click Add permission.
  7. Click Grant admin consent for <your B2C directory>.

  8. Create a new client secret for the App registration (for example, 12OzW72ie-U.vlmzik-eO5gX.x26jLTI6U) and note it down.

    export B2C_CLIENT_SECRET="client secret"
    
  9. Link this Azure AD B2C tenant to the subscription for CI by following the Billing guide.

Set up continuous integration on GitHub

  1. Create the CI credentials:

    az ad sp create-for-rbac --name 'https://nrfassettracker.invalid/ci' \
       --role contributor \
       --scopes \
          "/subscriptions/${SUBSCRIPTION_ID}/resourceGroups/${RESOURCE_GROUP:-nrfassettracker}"\
       --sdk-auth \
       > ci-credentials.json
    
  2. Fork the nRF Asset Tracker for Azure project.

  3. Add the following secrets to an environment called ci:

    • RESOURCE_GROUP
    • APP_REG_CLIENT_ID
    • AZURE_CREDENTIALS (the contents of ci-credentials.json)
    • B2C_CLIENT_SECRET
    • B2C_TENANT_ID
    • APP_NAME
    • B2C_TENANT

Commit and push a change

Now, commit and push a change to your repository. This will trigger the CI run.

You can also manually trigger a deployment on the Test and Release workflow.

Running the solution during development

To run the end-to-end tests against the solution during development, run the following commands:

# Install dependencies
npm ci

# One time operation: create an intermediate CA certificate
node cli create-ca-root
node cli proof-ca-root-possession
node cli create-ca-intermediate

# Run tests
npm run test:e2e

Note

Azure functions allow only one Client ID and Issuer URL in the Active Directory authentication configuration. So, you cannot interact with this instance from the end-to-end tests and the web application since the user flow name differs (B2C_1_developer for end-to-end tests and B2C_1_signup_signin for the web application) and it is part of the Issuer URL (for example, https://${TENANT_DOMAIN}.b2clogin.com/${TENANT_DOMAIN}.onmicrosoft.com/v2.0/.well-known/openid-configuration?p=B2C_1_developer).