How to: Create and Deploy a new Microfrontend inside edX

Create Your Microfrontend's Repository

Note that throughout this How-to we use XXX to represent the name of your repository/app, and YYY to represent the sub-domain you've chosen.

  1. Pick a name.  It should follow the convention: frontend-app-XXX.

    1. The repo name may or may not correspond with the sub-domain.  Examples:

      1. frontend-app-profile is served at profile.edx.org

      2. frontend-app-ecommerce is served at orders.edx.org

      3. If you can keep it one word it will make things easier

  2. We have a GitHub template repository to help bootstrap your new application.

    1. If you have permission to create new repositories:

      1. Visit https://github.com/edx/frontend-template-application

      2. Click the "Use this template" button.

      3. Put in your chosen micro-frontend application name.

      4. Make sure to create it in the edX organization.

    2. If you do not have permission to create a new repository:

      1. Get someone to do the above steps for you.  You can read through How to request a new GitHub Repo to find a way to get someone to help you.

    3. Do a find and replace in your new repository to replace frontend-template-application with frontend-app-XXX.

    4. Similarly, there's an example module which demonstrates a basic module.  Feel free to rename the "example" directory or delete it.

  3. Add a link to your new repo to Frontend Repos.

  4. If you are replacing an existing legacy frontend, update accordingly.


Setup Automated Deployment

We serve our frontend applications from S3 through CloudFlare distributions.  We deploy them with GoCD. We manage the creation of these resources/pipelines via configuration in edx/terraform and edx/edx-internal.

In this section you will be creating a series of pull requests for the following:

  1. The AWS resources like the S3 Bucket and Route53 domain name

    1. To add these you will need to open a PR to https://github.com/edx/terraform (e.g. https://github.com/edx/terraform/pull/2728/files)

    2. The Route53 domain and S3 Bucket are created using the frontend.hostname variable (the creation of which you can see in the above PR)

  2. The remote config blocks for Related Django services

    1. To add these you will need to open a PR to https://github.com/edx/edx-internal and optionally https://github.com/edx/edge-internal (e.g. https://github.com/edx/edx-internal/pull/2374/files)

  3. The GoCD deployment pipelines

    1. See https://github.com/edx/edx-internal/blob/master/gocd/README#L31-L39

  4. Sandboxes

    1. Beware of dragons, this will require a PR to https://github.com/edx/configuration , please see for more information.

After all your PRs are made, you will create an SRE Support ticket or a ticket to your eSRE for review.


1: edx/terraform

Terraform is a tool for building, changing, and versioning infrastructure safely and efficiently. This repo contains terraform modules for deploying our applications on AWS, Cloudflare, NewRelic, Kubernetes and Snowflake.

Here we will leverage an existing frontend terraform module for provisioning new frontend infrastructure.

Create a branch/PR with the following changes:

  1. In edx/terraform, create two files:

    plans/edx/prod-frontends/frontend-app-XXXXX.tf

    variable "frontend_app_XXXXX_hostname" { type = string description = "Hostname of the frontend-app-XXXXX used for bucket naming and routing" } module "frontend_app_XXXXX_frontend" { source = "../../../modules/frontends/frontend" cloudflare_record_name = "XXXXX" route53_zone_id = var.route53_zone_id_edx_org frontend_hostname = var.frontend_app_XXXXX_hostname internal_frontend_hostname = "${var.environment}-XXXXX.edx.org" aws_region = var.aws_region deployer_user = aws_iam_user.frontend_deployer_user.arn cloudflare_zone_id = var.cloudflare_zone_id_edx_org cdn_type = "cloudflare" }


    plans/edx/stage-frontends/frontend-app-XXXXX.tf

    variable "frontend_app_XXXXX_hostname" { type = string description = "Hostname of the frontend-app-XXXXX used for bucket naming and routing" } module "frontend_app_XXXXX_frontend" { source = "../../../modules/frontends/frontend" cloudflare_record_name = "XXXXX.stage" route53_zone_id = var.route53_zone_id_edx_org frontend_hostname = var.frontend_app_XXXXX_hostname internal_frontend_hostname = "${var.environment}-XXXXX.edx.org" aws_region = var.aws_region deployer_user = aws_iam_user.frontend_deployer_user.arn cloudflare_zone_id = var.cloudflare_zone_id_edx_org cdn_type = "cloudflare" }

    Note the only difference between the stage plan and the prod plan is the cloudflare_record_name. For examples, see the existing plans/edx/prod-frontends/frontend-app-* configurations.

  2. Add variables for your application for stage and prod:

    plans/edx/prod-frontends/terraform.tfvars

    ... # frontend-app-XXXXX frontend_app_XXXXX_hostname = "YYYYY.edx.org"


    plans/edx/stage-frontends/terraform.tfvars

     

  3. Optional for edge deployment


2: edx/edx-internal (and edge-internal)

EdX Internal is a private configuration repo for the edx.org deployment. It contains private but not restricted/secure data. Here we will add configuration variable files for your frontend application to edx-internal/frontends.

Create a branch/PR with the following changes.

  • Create a subdirectory in edx-internal/frontends for your app: edx-internal/frontends/frontend-app-XXX

  • Add the following two files:

    prod_config.yml

     

    stage_config.yml

     

    For examples, see the existing frontend-app-* configurations in edx-internal/frontends.

If you're setting up NewRelic alerts, or Segment tracking there's additional configuration to define (NEW_RELIC_APP_ID and SEGMENT_KEY) in this repository that's described below.  You may want to do it as part of the same PR to save time.

Optional: ecommerce access

If you need to call ecommerce, you need to add your domain to the CORS_ORIGIN_WHITELIST variables

  1. Add the following changes to your edx-remote-config PR/branch.

  2. Add your domain in:

     

  3. Also add it in ansible/vars/stage-edx.yml

Optional: edge-internal configuration for edge deployment

Add configuration for edge deployments in https://github.com/edx/edge-internal

Create a branch/PR with the following changes.


GoCD Pipeline Steps

We define our GoCD pipelines and their stages, jobs, and tasks in yaml. Here we will provision GoCD deployment pipelines for our app.

Create a PR/branch with the following changes.

  1. Add your frontend application to  in order to provision Go CD pipelines. 
    See:
    https://github.com/edx/edx-internal/blob/master/gocd/README#L31-L39

  2. Your pipelines will be generated once your PR is merged.

 

Enable edge deployment

In the config https://github.com/edx/edx-internal/blob/master/gocd/generated-pipelines/frontend-generator-inputs.yaml  flip is_deployed_to_edge to true and make a PR, your pipeline definition will be regenerated with an edge deployment.

 

4: edx/configuration (optional)

This repository is a collection of tools and scripts that edx.org uses to deploy openedx. The purpose of this repository is to share portions of our toolchain with the community.  This directory contains ansible playbooks that can be used to configure individual services in the openedx platform.

Create a PR/branch with the following changes:

  1. Edit playbooks/roles/edxapp/defaults/main.yml to add the microfrontend URL defined above in edx/edx-internal.  



  2. Also add it to the lms_env_config in the same file:

     



Setup Devstack

You should be able to run your micro-frontend out-of-the-box with:

However, the next two optional steps may make development a bit more seamless.

Allow LMS login redirection in Devstack

  • Add the netloc (localhost:$PORT) of your new micro-frontend to the LOGIN_REDIRECT_WHITELIST for Devstack LMS.

Add your MFE to Devstack

Adding your MFE to the devstack repository is optional. The main benefit is that you will be able to bring up the MFE and any required backend services with a singular command: make dev.up.frontend-app-XXXX. Whether or not you do this step, you should be able to run your MFE directly with npm install && npm start.

If you choose to add it to Devstack, here is an example PR to follow: https://github.com/edx/devstack/pull/556/files. For the depends_on key in docker-compose.yml, specify the backend services that your MFE needs running in order to function.


Setup Segment

  1. See Setting up new Segment projects

    • See "frontend-app-profile-prod" and "frontend-app-profile-stage" as examples (that use LMS property in Google Analytics).

    • To create a new source, file a support ticket with Data Engineering. Make sure that you have the necessary permissions to view the write key associated with the source.

  2. Add the Segment write keys (SEGMENT_KEY) to prod_config.yml and stage_config.yml in your edx-internal/frontends sub-directory. You created it above during "Setup Automated Deployment".

  3. Make sure that you are using frontend-platform's builtin support for segment page tracking by using PageRoute, which is a drop-in replacement for react’s normal Route. (Or alternatively, AuthenticatedPageRoute for login-required pages.)

  4. Verification:

    • Using Segment Debugger for the new Segment sources (stage and prod), verify that identify/page events are being sent to Segment.

    • To verify Prod events, go to Snowflake and verify your events are appearing. Or have on-call for (Slack) #data-engineering do it, if it’s a one-off and you don’t have access.


Setup New Relic

We use this procedure to insert Browser's JavaScript snippet for browser monitoring into our frontends, see New Relic’s docs for more details.

See "prod-frontend-app-profile" and "stage-frontend-app-profile" for example configurations.

  1. Go to one.newrelic.com  > Browser > Add more data

  2. Click on “New Relic Browser”.

  3. Select Copy/Paste JavaScript Code, leave Pro + SPA checked and switch on Distributed Tracing.

  4. Enter an app name as "prod-frontend-app-XXX" and click Enable

  5. In the Javascript snippet that appears, copy the "applicationID" value out of the last line before the closing </script> tag:

     

  6. Add the NewRelic application ID you just copied to prod_config.yml as its NEW_RELIC_APP_ID value.  You created this file during "Setup Automated Deployment" in your edx-internal/frontends sub-directory. 

  7. Repeat steps 1 through 6 for stage_config.yml.  You should have a different application ID for staging.


Setup New Relic alerts in Opsgenie

FYI – Alerts used to be set up via terraform via terraform/plans/newrelic/edx/channels.tf

  1. If your team doesn’t already have a New Relic integration, go to Opsgenie > Teams and choose a team

    1. Click integrations.

    2. Click Add Integration

    3. Search for New Relic (New) and click add

    4. Follow the instructions on the page to use the api key to add a notification channel in New Relic.

  2. Go to New Relic Browser

  3. Under your app go to alert conditions

  4. Click Manage Alert Policies and search for the name of your app to find its alert policy

  5. Add an Apdex and JS Error conditions as seen here https://one.nr/0mMRNPPqlQn for prod-frontend-app-learning

  6. Add a New Relic notification channel

    1. If your team doesn’t already have one, you may need to ask your eSRE or file an SRE support ticket to copy in the API key from the Opsgenie integration.


Create a support ticket with SRE for your PRs

At this point you'll want to create an SRE ticket to review your PRs and give you a sanity check on everything else.

  1. The creation of the ticket depends on whether you have an eSRE on your team. If you do & you’re not sure what process to follow, consult them.

    1. If your team does not have an eSRE, then you should create a SRE Support ticket via the old process.

  2. In filing the ticket, include links to all the PRs you created above.

  3. Include also your Opsgenie New Relic API Key if you want to set up alerting.


Add Annotated Feature Toggle

This is only needed if you want a rollout feature toggle (from LMS for example) to your new page.


Configure i18n Jenkins and Transifex

  1. Follow

    1. New docs in @edx/frontend-platform https://github.com/edx/frontend-platform/blob/master/docs/how_tos/i18n.rst  

    2. Old docs for @edx/frontend-i18n i18n how-to documentation

    3. If you created the shell of your application code as described above, many of the steps in this documentation will already be done for you.

  2. Actual i18n code should be completed separately as strings are added to the code.


Backend JWT Cookies Support

At this point, most IDAs support JWT cookie, but not all.