Creating applications from multiple repositories
Release works well with both large complex applications and many smaller applications all talking to each other. If you fall into the latter category, our solution to a microservices architecture is the App Imports feature. App Imports creates single-direction dependencies from one application to another with all services being brought up in the same namespace. This means there is one hard requirement for using App Imports: you cannot have two services with the same name. See Unique service names for further explanation.
Here's an example of setting up App Imports in the Application Template:
- name: backend
- name: redis
The documentation for the schema can be viewed in the Application Template guide. In our example, an application
frontenduses App Imports with an application named
frontendapp adds an
app_importssection to its template to import
backend, then whenever an environment for
frontendis created, an environment for
backendwill also be created. This is the single-direction of the import. If someone were to create an environment for
backend, only the environment for
backendwould be created.
To create bi-directional imports, both applications need to have an
app_importssection in their template.
If bi-directional imports are set up, you will not create an infinite loop. You might think that
backendwhich would import
frontendand create an infinite loop, but the import will only occur once with
backendand finishing. This is because:
App Imports are not recursive. So if A imports B and B imports A, you will not get ABABABAB. If A imports B and B imports C, you will get AB when you deploy A, and you will get BC when you deploy B, and you will get C when you deploy C. You will not get ABC in any scenario.
This makes it very simple to reason about what will be deployed for a given template. If you see that application A imports B, then you will just deploy A and B and you need not investigate what the application template for B looks like.
Branch selection has a fallback order that includes three different options. They are:
- 1.The branch is set in the Application Template
app_importssection via the
branchkey as described above. If set, all environments will always use this branch. Remember that the branch attribute is optional in the template.
- 2.A matching branch on GitHub. If
frontendis on branch
example, then Release will query GitHub and see if the repository used for
backendalso has a branch named
example. If there is a match, that branch will be used.
- 3.The default (or "main") branch that is set for the repository on GitHub.
Release autogenerates environment variables in the form of
<SERVICE_NAME>_INGRESS_URLwhen the service is exposed to the internet. If, for example,
backendhas a service named
api, then Release will generate an environment variable named
API_INGRESS_URL. If our
frontendapp has a service named
web, then Release will generate the
WEB_INGRESS_URLenvironment variable too.
When using App Imports, the ingress environment variables are shared between between all environments. This means that
frontendwill have access to
API_INGRESS_VARIABLEand its own
WEB_INGRESS_URL, and the same will apply for
backend. Release shares all the environment variables in case two or more imported apps need to be able to communicate.
Given that the ingress environment variables are available, you may need to map those to another environment variable your application is expecting. If
frontendwas using the environment variable
REACT_APP_BACKEND_APIto talk to its API, then we would want to map the
API_INGRESS_URLto it. This can be achieved using environment variable mapping.
Environment Variable Mapping Example
Warning: Unexpected behavior is caused by using services with the same name.
frontendhas a service named
backendhas a service named
api, Release will try to deploy two services named
apiinto the same namespace. By default, Kubernetes will remove the first service and replace it with the second – this is a function of how Kubernetes works and is not Release-specific. To avoid naming conflicts, we suggest adding the name of the application as a prefix to the service name to differentiate between the services in each app, for example,
When using App Imports, all the services are placed into the same namespace. This means that when viewing the "Instances" table on an environment's details page, you will be able to see the services from all the applications.
If you look under the
Namespacesection in the top left, you'll see that the environment
jer-k-mainfrom the application
backendis imported into this namespace. The
backendapplication defines the
sidekiqservices, which can see seen in the "Instances" table. The
frontendapplication defines the
appservice, which can also seen.