Continuous integration

Continuous integration involves the following actions:

  • Every change to the project is tested against an Azure account, which must be manually prepared.

  • A BDD test-suite of end-to-end tests written in Gherkin, which describes the tests in English, is run.

In this way, the tests are not tied to the implementation and during refactoring, and you cannot accidentally drop tests. Tests written for test-runners like Jest tend to be closely tied to the API of the source-code implementation. In the case of bigger refactoring, the tests themselves usually 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.

Note

This is an advanced topic for those who need to further develop and customize Bifravst. See the Bifravst for Azure GitHub project page, for the implementation of the process outlined in this section.

The project also provides an easily understandable description of the available (and implemented) features, in a single folder called features.

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.

To prepare your Azure account, complete the following steps:

  1. Create a new tenant (Azure Active Directory B2C).

  2. Create a subscription.

  3. Create a secondary tenant (Azure Active Directory B2C).

Create a new tenant (Azure Active Directory)

To separate the CI test runs from the production resources, navigate to the Azure Portal and create a new Azure Active Directory tenant with the following values:

  • Organization name - Bifravst (CI).

  • Initial domain name - bifravstci (Customize the name since it is globally unique).

  • Country - Choose your preferred country.

After you submit, the tenant will be created in a few minutes.

Note down the initial domain name that you used:

export TENANT_DOMAIN="<Primary domain>" # For example, "bifravstci"

Create subscription

To create a subscription, complete the following steps:

  1. Login to the Azure portal.

  2. Navigate to the Subscriptions blade and create a new subscription for the CI tenant. This subscription creation will make it easier to identify the costs for the purpose.

  3. After creating the subscription, change its directory to the one created in the previous section.

Note down the Subscription ID, which you can find in the Subscriptions blade:

export SUBSCRIPTION_ID="<Subscription ID>" # For example, "1aae311f-12d6-419e-8c6b-ebcf3ec4ed15"

Create a secondary tenant (Azure Active Directory B2C)

  1. Create a new Azure Active Directory B2C tenant, which is used as the identity management solution for the user accounts of the Bifravst instance.

  2. Follow the Create Tenant guide to create a new Azure AD B2C tenant with the following values:

    • Organization name - Bifravst (CI) Users.

    • Initial domain name - bifravstciusers (Customize the name since it is globally unique).

    • Country - Choose your preferred country.

  3. Note down the initial domain name that you used:

    export B2C_TENANT="<Primary domain>" # For example, "bifravstciusers"
    
  4. Link this Azure AD B2C tenant to the subscription for CI by following the Billing guide.

Create the Azure Active Directory B2C application

To create the Azure Active Directory B2C application, complete the following steps:

  1. Follow the instructions in the Continous Deployment instructions to create a new App registration with the following values:

    • Name - Bifravst Web App.

    • Redirect URI (make sure to select SPA) - https://bifravstciapp.z16.web.core.windows.net/ (Choose a name that fits your project instead of bifravstciapp since bifravstciapp is globally unique).

  2. Export the Application (client) ID and the Directory (tenant) ID of the created Active Directory B2C App registration into the APP_REG_CLIENT_ID and B2C_TENANT_ID parameters:

    export APP_REG_CLIENT_ID="<Application (client) id>"
    export B2C_TENANT_ID="<Directory (tenant) ID>"
    
  3. For enabling the test-runner to programmatically login users, enable the resource owner password credentials (ROPC) flow with the following settings:

    • Name - B2C_1_developer.

    • Application claims - Select Show more ... and then mark Email Addresses as a return claim.

  4. Add the permission to manage user accounts (Microsoft Graph > User.ReadWrite.All) and grant admin consent.

  5. In the left menu, under Manage, select Authentication. Allow the Implicit grant for Access and ID tokens and select Yes for Treat application as a public client.

  6. Create a new client secret for the App registration and note it down:

    export B2C_CLIENT_SECRET="<Client Secret Value>" # For example, "12OzW72ie-U.vlmzik-eO5gX.x26jLTI6U"
    

Deploy the solution

To deploy the solution, complete the following steps:

  1. Login to the shell:

    az login
    
  2. Make sure that you have enabled the right subscription by using the following commands:

    az account set --subscription $SUBSCRIPTION_ID
    # Verify that it is set to default
    az account list --output table
    
  3. Enable the required resources

    az provider register --namespace Microsoft.AzureActiveDirectory
    az provider register --namespace Microsoft.Storage
    az provider register --namespace Microsoft.Insights
    az provider register --namespace Microsoft.SignalRService
    az provider register --namespace Microsoft.DocumentDB
    az provider register --namespace Microsoft.Devices
    az provider register --namespace Microsoft.Web
    
  4. Create the CI credentials:

    az ad sp create-for-rbac --name https://github.com/ --role Contributor --sdk-auth --scopes /subscriptions/${SUBSCRIPTION_ID} > ci-credentials.json
    
  5. Create a resource group for Bifravst:

    az group create --name ${RESOURCE_GROUP_NAME:-bifravst} --location ${LOCATION:-northeurope}
    
  6. Deploy the resources:

    az deployment group create \
    --resource-group ${RESOURCE_GROUP_NAME:-bifravst} \
    --mode Complete \
    --template-file azuredeploy.json \
    --parameters \
    appName=${APP_NAME:-bifravst} \
    location=${LOCATION:-northeurope} \
    appRegistrationClientId=$APP_REG_CLIENT_ID \
    b2cTenant=$B2C_TENANT \
    b2cFlowName=B2C_1_developer
    
  7. Publish the functions:

    func azure functionapp publish ${APP_NAME:-bifravst}API --typescript
    

    Docker variant for publishing the functions (in case you get a Permission denied error):

    docker run --rm -v ${PWD}:/workdir -v ${HOME}/.azure:/root/.azure bifravst/azure-dev:latest \
        func azure functionapp publish ${APP_NAME:-bifravst}API --typescript
    

Running the solution during development

To run the solution during development, run the following commands:

export API_ENDPOINT=https://`az functionapp show -g ${RESOURCE_GROUP_NAME} -n ${APP_NAME:-bifravst}api --query 'defaultHostName' --output tsv | tr -d '\n'`/

npm ci
npm run test:e2e

Note

Azure functions allow only one 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).

Setup the solution on GitHub

To setup the solution on GitHub, provide the following environment variables for GitHub Actions of the project:

  • E2E_APP_REG_CLIENT_ID

  • E2E_AZURE_CREDENTIALS (the contents of ci-credentials.json)

  • E2E_B2C_CLIENT_SECRET

  • E2E_B2C_TENANT_ID