generated from redhat-developer/new-project-template
-
Notifications
You must be signed in to change notification settings - Fork 53
RHIDP-7556: Orchestrator flavor in RHDH Operator #1305
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Gerry-Forde
merged 25 commits into
redhat-developer:main
from
jmagak:RHIDP-7556-Orchestrator-flavor-in-RHDH-Operator
Aug 20, 2025
Merged
Changes from all commits
Commits
Show all changes
25 commits
Select commit
Hold shift + click to select a range
2a5ae32
Orchestrator flavor in RHDH Operator
invalid-email-address 07e45f2
Orchestrator flavor in RHDH Operator
invalid-email-address f20bc79
Orchestrator flavor in RHDH Operator
invalid-email-address 606922e
Orchestrator flavor in RHDH Operator
invalid-email-address 138ed44
Orchestrator flavor in RHDH Operator
invalid-email-address 2a453c0
Orchestrator flavor in RHDH Operator
invalid-email-address 55a2d7d
Orchestrator flavor in RHDH Operator
invalid-email-address ad8e206
Orchestrator flavor in RHDH Operator
invalid-email-address 603f654
Orchestrator flavor in RHDH Operator
invalid-email-address 2eafe22
Orchestrator flavor in RHDH Operator
invalid-email-address dc991b1
Orchestrator flavor in RHDH Operator
invalid-email-address e4101ad
Orchestrator flavor in RHDH Operator
invalid-email-address faec098
Orchestrator flavor in RHDH Operator
invalid-email-address dad9952
Orchestrator flavor in RHDH Operator
invalid-email-address ab3fb01
Apply suggestions
invalid-email-address 99882e7
Apply suggestions
invalid-email-address 785455f
Apply suggestions
invalid-email-address 4c27dfa
Apply suggestions
invalid-email-address d1af1c8
Apply suggestions
invalid-email-address b094be2
Apply suggestions
invalid-email-address 9ee8d26
Apply suggestions
invalid-email-address e90dcca
Apply suggestions
invalid-email-address 3945099
Apply suggestions
invalid-email-address 4fac0a2
Apply suggestions
invalid-email-address 08d352a
Apply suggestions
invalid-email-address File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
:_mod-docs-content-type: ASSEMBLY | ||
|
||
ifndef::context[] | ||
[id="install-rhdh-orchestrator.adoc"] | ||
endif::[] | ||
ifdef::context[] | ||
[id="assembly-install-rhdh-orchestrator"] | ||
endif::[] | ||
:context: install-rhdh-orchestrator | ||
= Installing {product} with Orchestrator | ||
|
||
To install {product}, use one of the following methods: | ||
|
||
* The {product} Operator | ||
* The {product} Helm chart | ||
|
||
// {product} Operator | ||
include::modules/orchestrator/proc-install-orchestrator-plugin.adoc[leveloffset=+1] | ||
|
||
// {product} Helm chart | ||
include::modules/orchestrator/proc-install-rhdh-with-orchestrator-helm-cli.adoc[leveloffset=+1] | ||
|
||
include::modules/orchestrator/proc-install-rhdh-with-orchestrator-helm-webui.adoc[leveloffset=+1] | ||
|
||
include::modules/orchestrator/ref-orchestrator-resource-limits.adoc[leveloffset=+1] | ||
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
:_mod-docs-content-type: ASSEMBLY | ||
|
||
ifndef::context[] | ||
[id="assembly-orchestrator-rhdh.adoc"] | ||
endif::[] | ||
ifdef::context[] | ||
[id="assembly-orchestrator-rhdh"] | ||
endif::[] | ||
:context: orchestrator-rhdh | ||
= About Orchestrator in {product} | ||
|
||
You can streamline and automate your work by using the Orchestrator in {product}. It enables you to: | ||
jmagak marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
* Design, run, and monitor workflows to simplify multi-step processes across applications and services. | ||
* Standardize onboarding, migration, and integration workflows to reduce manual effort and improve consistency. | ||
* Extend {product-very-short} with enterprise-grade Orchestration features to support collaboration and scalability. | ||
|
||
[NOTE] | ||
==== | ||
Orchestrator currently supports only {ocp-short}; it is not available on AKS, EKS, or GKE. | ||
==== | ||
|
||
To start using Orchestrator in {product-very-short}, you must: | ||
|
||
* Install the required infrastructure components, such as Red Hat OpenShift Serverless Operator, Knative Serving, Knative Eventing, and OpenShift Serverless Logic Operator | ||
* Configure your {product-custom-resource-type} custom resource (CR) for Orchestrator | ||
* Import the Orchestrator software templates into the {product} catalog | ||
|
||
// orchestrator architecture | ||
include::modules/orchestrator/con-supported-architecture-for-orchestrator.adoc[leveloffset=+1] | ||
|
||
// provisioning plugin dependencies | ||
include::modules/orchestrator/con-orchestrator-plugin-dependencies.adoc[leveloffset=+1] | ||
|
||
// installing the components for the orchestrator plugin | ||
include::modules/orchestrator/proc-install-components-for-orchestrator-plugin.adoc[leveloffset=+1] |
53 changes: 53 additions & 0 deletions
53
modules/orchestrator/con-orchestrator-plugin-dependencies.adoc
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
:_mod-docs-content-type: CONCEPT | ||
[id="con-orchestrator-plugin-dependencies_{context}"] | ||
= Orchestrator Plugin dependencies | ||
|
||
The Orchestrator plugin in {product-very-short} requires components such as SonataFlow and supporting network policies to run. When you enable the plugin in your {product-custom-resource-type} custom resource (CR), the Operator automatically provisions these dependencies for you: | ||
|
||
* A `SonataflowPlatform` CR | ||
* `NetworkPolicies` that allow traffic between infrastructure resources (Knative, Serverless Logic Operator), monitoring traffic, and intra-namespace traffic | ||
|
||
[NOTE] | ||
==== | ||
Orchestrator currently supports only {ocp-short}; it is not available on AKS, EKS, or GKE. | ||
==== | ||
|
||
The `orchestrator-backend` plugin uses the `sonataflow-platform-data-index-service`, which the `SonataFlowPlatform` CR creates to communicate with the SonataFlow platform. | ||
|
||
The Operator resolves the dependency reference SonataFlow against the `sonataflow.yaml` manifest included in its profile configuration (`config/profile/rhdh/plugin-deps/sonataflow.yaml`) and applies it to create the required resources. | ||
|
||
The Operator automatically applies the `sonataflow.yaml` manifest, creating the `SonataFlowPlatform` CR and required `NetworkPolicy` resources in the {product-custom-resource-type} CR namespace. | ||
|
||
[IMPORTANT] | ||
==== | ||
The `SonataFlowPlatform` CR contains Data Index service that requires PostgreSQL database as shown in the following example: | ||
+ | ||
[source,yaml,subs="+quotes,+attributes"] | ||
---- | ||
persistence: | ||
postgresql: | ||
secretRef: | ||
name: backstage-psql-secret-{{backstage-name}} | ||
userKey: POSTGRES_USER | ||
passwordKey: POSTGRES_PASSWORD | ||
serviceRef: | ||
name: backstage-psql-{{backstage-name}} # # Namespace where the {product-custom-resource-type} CR is created | ||
namespace: {{backstage-ns}} # Namespace where the {product-custom-resource-type} (CR) is created | ||
databaseName: backstage_plugin_orchestrator | ||
---- | ||
==== | ||
|
||
By default, the Orchestrator plugin dependencies use the following: | ||
|
||
* The PostgreSQL database named `backstage_plugin_orchestrator` created by {product-custom-resource-type} | ||
* A Secret created by {product-custom-resource-type} Operator for the PostgreSQL with `POSTGRES_USER` and `POSTGRES_PASSWORD` keys as the database credentials in the {product-custom-resource-type} CR namespace. | ||
* A Service created by {product-custom-resource-type} Operator for the PostgreSQL database with the name `backstage-psql-{{backstage-name}}` in the {product-custom-resource-type} CR namespace. | ||
|
||
For more information about automatic plugin dependency creation when the {product-custom-resource-type} CR is applied to the cluster, see link:https://github.com/redhat-developer/rhdh-operator/blob/release-1.7/docs/dynamic-plugins.md#dynamic-plugins-dependency-management[Dynamic plugins dependency management]. | ||
|
||
[NOTE] | ||
==== | ||
To enable the {product-custom-resource-type} Operator to work with the SonataFlow platform, its `ServiceAccount` must have the appropriate permissions. | ||
|
||
The Operator automatically creates the required Role and _RoleBinding_ resource in `profile/rhdh/plugin-rbac` directory. | ||
==== |
12 changes: 12 additions & 0 deletions
12
modules/orchestrator/con-supported-architecture-for-orchestrator.adoc
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
:_mod-docs-content-type: CONCEPT | ||
[id="con-supported-architecture-for-orchestrator_{context}"] | ||
= Supported architecture for Orchestrator | ||
|
||
You can use Orchestrator to design, run, and monitor workflows that automate key tasks. It builds on components like SonataFlow and OpenShift Serverless, which provide the runtime environment and event-driven capabilities needed to power your workflows. | ||
|
||
To help you get started quickly, the following Orchestrator plugin components are included by default in the `dynamic-plugins.default.yaml` file: | ||
|
||
* `"@redhat/backstage-plugin-orchestrator"` | ||
* `"@redhat/backstage-plugin-orchestrator-backend-dynamic"` | ||
* `"@redhat/backstage-plugin-scaffolder-backend-module-orchestrator-dynamic"` | ||
* `"@redhat/backstage-plugin-orchestrator-form-widgets"` |
74 changes: 74 additions & 0 deletions
74
modules/orchestrator/proc-install-components-for-orchestrator-plugin.adoc
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
:_mod-docs-content-type: PROCEDURE | ||
[id="proc-install-components-for-orchestrator-plugin_{context}"] | ||
= Installing the components for the Orchestrator plugin on {ocp-short} | ||
jmagak marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
jmagak marked this conversation as resolved.
Show resolved
Hide resolved
|
||
To run the Orchestrator plugin successfully on {ocp-short}, you must install components that provide the runtime environment and the dependencies that the plugin requires. | ||
|
||
.Prerequisites | ||
|
||
* To install the Orchestrator plugin on {ocp-short}, you require the following components installed: | ||
|
||
** OpenShift Serverless Operator | ||
** Knative Serving | ||
** Knative Eventing | ||
** OpenShift Serverless Logic Operator | ||
+ | ||
[NOTE] | ||
==== | ||
The {product} Operator provisions these components automatically. Alternatively, you can install them manually by using another Operator. | ||
==== | ||
jmagak marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
.Procedure | ||
|
||
To install components (Operators) that provide the dependencies required by the Orchestrator plugin on {ocp-short}, use the following methods: | ||
|
||
* Manual installation | ||
* {product-very-short} helper script | ||
* {product-very-short} Orchestrator Infra Helm Chart | ||
+ | ||
These components enable the creation of the `SonataFlowPlatform` custom resource and several supporting `NetworkPolicy` resources. | ||
|
||
.Manual installation | ||
|
||
Use manual installation for production environments. Choose this method when you have installed the required components versions, such as when other applications are using OpenShift Serverless. | ||
|
||
For more information on preparing the required infrastructure, see link:https://docs.redhat.com/en/documentation/red_hat_openshift_serverless/1.36[Red Hat OpenShift Serverless] to do the following: | ||
|
||
* Prepare for OpenShift Serverless installation | ||
jmagak marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
* Install the OpenShift Serverless Operator | ||
|
||
* Install Knative Serving | ||
|
||
* Install Knative Eventing | ||
|
||
* Install the OpenShift Serverless Logic Operator | ||
|
||
.{product-very-short} helper script | ||
|
||
You can install the OpenShift Serverless infrastructure for the Orchestrator plugin using the {product-very-short} helper script. You can use the script in empty clusters, however, use with caution in production clusters because the script installs Operators with automatic upgrades and default settings, which can introduce unplanned changes, version conflicts, or policy misalignments. | ||
jmagak marked this conversation as resolved.
Show resolved
Hide resolved
|
||
You can install the OpenShift Serverless infrastructure for the Orchestrator plugin in empty clusters by using the {product-very-short} helper script. | ||
|
||
For more information on controlling the installation of the Operators, see link:https://olm.operatorframework.io/docs/tasks/install-operator-with-olm/[Install your Operator with OLM]. | ||
|
||
[WARNING] | ||
==== | ||
This method of installation is not suitable for production clusters. The {product-very-short} helper script installs Operators with automatic upgrades and default settings, which can introduce unplanned changes, version conflicts, or policy misalignments. | ||
jmagak marked this conversation as resolved.
Show resolved
Hide resolved
|
||
==== | ||
|
||
.Procedure | ||
. Download the `plugin-infra.sh` script as shown in the following example: | ||
+ | ||
[code,terminal] | ||
---- | ||
curl -sSLO https://raw.githubusercontent.com/redhat-developer/rhdh-operator/refs/heads/release-${PRODUCT_VERSION}/config/profile/rhdh/plugin-infra/plugin-infra.sh # Specify the {product} version in the URL or use main | ||
---- | ||
. Run the script as shown in the following example: | ||
+ | ||
[source,shell] | ||
---- | ||
$ ./plugin-infra.sh | ||
---- | ||
|
||
.{product-very-short} Orchestrator Infra Helm Chart | ||
You can use {product-very-short} Orchestrator Infra Helm Chart to install components for the Orchestrator plugins in empty clusters. |
75 changes: 75 additions & 0 deletions
75
modules/orchestrator/proc-install-orchestrator-plugin.adoc
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
:_mod-docs-content-type: PROCEDURE | ||
[id="proc-install-orchestrator-plugin_{context}"] | ||
= Installing the Orchestrator plugin using Operator | ||
jmagak marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
You can enable the Orchestrator plugin in {product-very-short} by configuring dynamic plugins in your {product-custom-resource-type} custom resource (CR). | ||
|
||
.Prerequisites | ||
* You have installed {product-very-short} on {ocp-short}. | ||
* You have access to edit or create ConfigMaps in the namespace where the {product-custom-resource-type} CR is deployed. | ||
|
||
.Procedure | ||
. Identify the Orchestrator plugin dynamic plugins that are included by default in the default `dynamic-plugins.yaml` file of the `install-dynamic-plugins` container: | ||
jmagak marked this conversation as resolved.
Show resolved
Hide resolved
|
||
+ | ||
* `@redhat/backstage-plugin-orchestrator` (frontend) | ||
* `@redhat/backstage-plugin-orchestrator-backend-dynamic` (backend) | ||
* `@redhat/backstage-plugin-scaffolder-backend-module-orchestrator-dynamic` | ||
* `@redhat/backstage-plugin-orchestrator-form-widgets` | ||
jmagak marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
. To enable the Orchestrator plugin, update the ConfigMap file with the following data: | ||
+ | ||
jmagak marked this conversation as resolved.
Show resolved
Hide resolved
|
||
[source,yaml,subs="+attributes,+quotes"] | ||
+ | ||
---- | ||
includes: | ||
- dynamic-plugins.default.yaml | ||
plugins: | ||
- package: "@redhat/[email protected]" | ||
disabled: false | ||
- package: "@redhat/[email protected]" | ||
disabled: false | ||
dependencies: | ||
- ref: sonataflow | ||
- package: "@redhat/backstage-plugin-scaffolder-backend-module-orchestrator-dynamic@1.6.0" | ||
disabled: false | ||
- package: "@redhat/backstage-plugin-orchestrator-form-widgets@${ORCHESTRATOR_PLUGIN_VERSION}" | ||
disabled: false | ||
---- | ||
|
||
.Example: Complete configuration of the Orchestrator plugin | ||
[source,yaml] | ||
---- | ||
apiVersion: v1 | ||
kind: ConfigMap | ||
metadata: | ||
name: orchestrator-plugin | ||
data: | ||
dynamic-plugins.yaml: | | ||
includes: | ||
- dynamic-plugins.default.yaml | ||
plugins: | ||
- package: "@redhat/[email protected]" | ||
disabled: false | ||
- package: "@redhat/[email protected]" | ||
disabled: false | ||
dependencies: | ||
- ref: sonataflow | ||
- package: "@redhat/backstage-plugin-scaffolder-backend-module-orchestrator-dynamic@1.6.0" | ||
disabled: false | ||
- package: "@redhat/[email protected]" | ||
disabled: false | ||
--- | ||
apiVersion: rhdh.redhat.com/v1alpha3 | ||
kind: Backstage | ||
metadata: | ||
name: orchestrator | ||
spec: | ||
application: | ||
appConfig: | ||
configMaps: | ||
- name: app-config-rhdh | ||
dynamicPluginsConfigMapName: orchestrator-plugin | ||
---- | ||
|
||
.Verification | ||
* In the {product-very-short} console, confirm that the Orchestrator frontend and backend features are available. |
86 changes: 86 additions & 0 deletions
86
modules/orchestrator/proc-install-rhdh-with-orchestrator-helm-cli.adoc
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
:_mod-docs-content-type: PROCEDURE | ||
[id="proc-install-rhdh-with-orchestrator-helm-cli_{context}"] | ||
= Installing {product} ({product-very-short}) on {ocp-short} with the Orchestrator using the Helm CLI | ||
|
||
You can install {product} ({product-very-short}) on {ocp-short} with the Orchestrator by using the Helm CLI. The installation automatically enables the required dynamic plugins and integrates workflow infrastructure. | ||
|
||
.Prerequisites | ||
|
||
* You are logged in as an administrator and have access to the {product} Helm chart repository. | ||
* You can install the necessary infrastructures resources, such as SonataFlow, alongside {product-very-short} in the same namespace. | ||
+ | ||
This is a one-off requirement and must be completed before enabling the Orchestrator plugin. | ||
jmagak marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
.Procedure | ||
|
||
. As an administrator, install relevant cluster-wide resources. | ||
+ | ||
[source,yaml,subs="+quotes,+attributes"] | ||
---- | ||
helm repo add openshift-helm-charts https://charts.openshift.io/ | ||
helm install `<release_name>` openshift-helm-charts/redhat-developer-hub-orchestrator-infra | ||
---- | ||
+ | ||
[IMPORTANT] | ||
jmagak marked this conversation as resolved.
Show resolved
Hide resolved
|
||
==== | ||
You must be a cluster administrator to install the `redhat-developer-hub-orchestrator-infra` Helm chart because it deploys additional cluster-scoped OpenShift Serverless and OpenShift Serverless Logic Operators. As an administrator, you need to manually approve the install plans for OpenShift Serverless and Serverless Logic Operators. | ||
==== | ||
|
||
. Install the Backstage chart with the orchestrator enabled as shown in the following example: | ||
+ | ||
[source,terminal,subs="attributes+"] | ||
---- | ||
$ helm install <release_name> openshift-helm-charts/redhat-developer-hub --version {product-chart-version} \ | ||
--set orchestrator.enabled=true | ||
---- | ||
|
||
. (Optional) Enable *Notifications* and *Signals* plugins by adding them to the `global.dynamic.plugins` list in your `values.yaml` file as shown in the following example: | ||
+ | ||
[source,yaml] | ||
---- | ||
global: | ||
dynamic: | ||
plugins: | ||
- disabled: false | ||
package: "./dynamic-plugins/dist/backstage-plugin-notifications" | ||
- disabled: false | ||
package: "./dynamic-plugins/dist/backstage-plugin-signals" | ||
- disabled: false | ||
package: "./dynamic-plugins/dist/backstage-plugin-notifications-backend-dynamic" | ||
- disabled: false | ||
package: "./dynamic-plugins/dist/backstage-plugin-signals-backend-dynamic" | ||
---- | ||
|
||
. (Optional) You can disable the Serverless Logic and Serverless Operators individually or together by setting their values to `false`, as shown in the following example: | ||
jmagak marked this conversation as resolved.
Show resolved
Hide resolved
|
||
+ | ||
[source,terminal,subs="attributes+"] | ||
---- | ||
helm install <release_name> openshift-helm-charts/redhat-developer-hub \ | ||
jmagak marked this conversation as resolved.
Show resolved
Hide resolved
|
||
--version {product-chart-version} \ | ||
--set orchestrator.enabled=true \ | ||
--set orchestrator.serverlessOperator=false \ | ||
--set orchestrator.serverlessLogicOperator=false | ||
---- | ||
|
||
. (Optional) If you are using an external database, add the following configuration under `orchestrator.sonataflowPlatform` in your `values.yaml` file: | ||
+ | ||
[source,yaml] | ||
---- | ||
orchestrator: | ||
sonataflowPlatform: | ||
externalDBsecretRef: "<cred-secret>" | ||
externalDBName: "<database_name>" # The name of the user-configured existing database (Not the database that the orchestrator and sonataflow resources use). | ||
externalDBHost: "<database_host>" | ||
externalDBPort: "<database_port>" | ||
---- | ||
+ | ||
[NOTE] | ||
==== | ||
This step only configures the Orchestrators use of an external database. To configure {product} to use an external PostgreSQL instance, follow the steps in link:{configuring-book-url}#proc-configuring-postgresql-instance-using-helm_configuring-external-postgresql-databases[Configuring a PostgreSQL instance using Helm]. | ||
==== | ||
|
||
.Verification | ||
|
||
. Verify that the Orchestrator plugin is visible in the {product} UI. | ||
|
||
. Create and run sample workflows to confirm the orchestration is functioning correctly. |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.