> For the complete documentation index, see [llms.txt](https://docs.coherent.global/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.coherent.global/ci-cd/how-to-deploy-with-azure-devops.md).

# How to: Deploy with Azure DevOps

Promotion of Spark services from one tenant to another using the [ImpEx APIs](/spark-apis/impex-apis.md) can be integrated with [Azure DevOps Pipelines](https://azure.microsoft.com/en-us/products/devops/pipelines) facilitated by [PowerShell](https://learn.microsoft.com/en-us/powershell/) scripting.

## Prerequisites

* [Client Credentials](/identity-and-access-management/client-credentials.md) configured in both the source and destination tenants with access to the source and destination targets.
* All referenced services must have a compiled [Neuron](/build-spark-services/neuron.md) WebAssembly module.
* Any destination folders need to already exist and be accessible with the provided authorization.

## Information flow

<figure><img src="/files/ayySC95URVCDd8CLSBjP" alt="" width="375"><figcaption></figcaption></figure>

1. [Azure DevOps Pipelines](https://azure.microsoft.com/en-us/products/devops/pipelines) is used to execute the attached PowerShell script.
2. The [PowerShell](https://learn.microsoft.com/en-us/powershell/) script performs the following steps:
   1. Acquires client access tokens for both the source and destination tenants via using [Client Credentials grant (OAuth 2.0)](/identity-and-access-management/client-credentials/client-credentials-grant-oauth-2.0.md).
   2. Initiates the [Export](/spark-apis/impex-apis/export.md) API package generation job in the source tenant.
   3. Checks the [Export](/spark-apis/impex-apis/export.md#get-export-status) API for the completed job.
   4. Once completed, it downloads the package.
   5. The package is then uploaded to the destination tenant and deployed using the [Import](/spark-apis/impex-apis/import.md) API.

{% file src="/files/GYOi3edjpy7ngi4jKkPh" %}

## PowerShell script parameters

The parameters for the PowerShell script are aligned with those from the [Export](/spark-apis/impex-apis/export.md) and [Import](/spark-apis/impex-apis/import.md) APIs. It is recommended to understand the capability there before defining the parameters of the script.

| Key                                                                                                   | Value                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 |
| ----------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `exportEndpoint`                                                                                      | <p>Reference <a data-mention href="/pages/s2dRmJ2TUUDNkVyp44Vw">/pages/s2dRmJ2TUUDNkVyp44Vw</a> <a data-mention href="/pages/s2dRmJ2TUUDNkVyp44Vw#uri">/pages/s2dRmJ2TUUDNkVyp44Vw#uri</a><br><code><https://excel.{environment}.coherent.global/{tenant}/api/v4/export></code></p>                                                                                                                                                                                                                                                   |
| `importEndpoint`                                                                                      | <p>Reference <a data-mention href="/pages/UOnc8KEmYFHBx4RkykKf">/pages/UOnc8KEmYFHBx4RkykKf</a> <a data-mention href="/pages/UOnc8KEmYFHBx4RkykKf#uri">/pages/UOnc8KEmYFHBx4RkykKf#uri</a><br><code><https://excel.{environment}.coherent.global/{tenant}/api/v4/import></code></p>                                                                                                                                                                                                                                                   |
| <p><code>serviceUriSource</code><br>and<br><code>serviceUriDestination</code></p>                     | <p>Reference <a data-mention href="/pages/s2dRmJ2TUUDNkVyp44Vw">/pages/s2dRmJ2TUUDNkVyp44Vw</a> <a data-mention href="/pages/s2dRmJ2TUUDNkVyp44Vw#request-body">/pages/s2dRmJ2TUUDNkVyp44Vw#request-body</a> <code>inputs.services</code> and <a data-mention href="/pages/UOnc8KEmYFHBx4RkykKf">/pages/UOnc8KEmYFHBx4RkykKf</a> <a data-mention href="/pages/UOnc8KEmYFHBx4RkykKf#request-body">/pages/UOnc8KEmYFHBx4RkykKf#request-body</a><br><code>inputs.services\_modify</code><br>Example: <code>myfolder/myservice</code></p> |
| `sourceSystem`                                                                                        | <p>Reference <a data-mention href="/pages/s2dRmJ2TUUDNkVyp44Vw">/pages/s2dRmJ2TUUDNkVyp44Vw</a> <a data-mention href="/pages/s2dRmJ2TUUDNkVyp44Vw#request-body">/pages/s2dRmJ2TUUDNkVyp44Vw#request-body</a> <code>source\_system</code><br>Example: <code>mycicd</code></p>                                                                                                                                                                                                                                                          |
| `correlationId`                                                                                       | <p>Reference <a data-mention href="/pages/s2dRmJ2TUUDNkVyp44Vw">/pages/s2dRmJ2TUUDNkVyp44Vw</a> <a data-mention href="/pages/s2dRmJ2TUUDNkVyp44Vw#request-body">/pages/s2dRmJ2TUUDNkVyp44Vw#request-body</a> <code>correlation\_id</code><br>Example: <code>456</code></p>                                                                                                                                                                                                                                                            |
| `servicesExisting`                                                                                    | <p>Reference <a data-mention href="/pages/UOnc8KEmYFHBx4RkykKf">/pages/UOnc8KEmYFHBx4RkykKf</a> <a data-mention href="/pages/s2dRmJ2TUUDNkVyp44Vw#request-body">/pages/s2dRmJ2TUUDNkVyp44Vw#request-body</a> <code>servicesExisting</code><br>Example: <code>add\_version</code></p>                                                                                                                                                                                                                                                  |
| <p><code>sourceKeycloakMetadataUri</code><br>and<br><code>destinationKeycloakMetadataUri</code></p>   | <p>Source of the Keycloak OpenID endpoint configuration.<br><code><https://keycloak.{> environment}.coherent.global/auth/realms/{tenant}/protocol/openid-connect/token</code></p>                                                                                                                                                                                                                                                                                                                                                     |
| <p><code>sourceKeycloakClientId</code><br>and<br><code>destinationKeycloakClientId</code></p>         | <p>The client ID for the source Keycloak client.<br>Example: <code>client-credentials</code></p>                                                                                                                                                                                                                                                                                                                                                                                                                                      |
| <p><code>sourceKeycloakClientSecret</code><br>and<br><code>destinationKeycloakClientSecret</code></p> | <p>The client secret for the source Keycloak client.<br>Example: <code>9Oh1nscDtPzMehwA3ejKJFAar3RRktHY</code></p>                                                                                                                                                                                                                                                                                                                                                                                                                    |

## Setup the pipeline in Azure DevOps

1. Read the article [Use a PowerShell script to customize your pipeline](https://learn.microsoft.com/en-us/azure/devops/pipelines/scripts/powershell?view=azure-devops\&tabs=yaml) and follow the appropriate instructions for your Azure instance.
2. Push the PowerShell script `ImpEx.ps1` to the root of the project repository.
3. Add the completed YAML code to the pipeline file.

   <table><thead><tr><th>Empty template</th><th>Sample</th></tr></thead><tbody><tr><td><pre class="language-yaml"><code class="lang-yaml">- powershell: .\ImpEx.ps1 `
       -exportEndpoint " exportEndpoint " `
       -importEndpoint " importEndpoint " `
       -serviceUriSource " serviceUriSource " `
       -serviceUriDestination " serviceUriDestination " `
       -sourceSystem " sourceSystem" `
       -correlationId " correlationId " `
       -servicesExisting " servicesExisting " `
       -sourceKeycloakMetadataUri " sourceKeycloakMetadataUri " `
       -sourceKeycloakClientId " sourceKeycloakClientId " `
       -sourceKeycloakClientSecret " sourceKeycloakClientSecret " `
       -destinationKeycloakMetadataUri " destinationKeycloakMetadataUri " `
       -destinationKeycloakClientId " destinationKeycloakClientId " `
       -destinationKeycloakClientSecret " destinationKeycloakClientSecret "
   </code></pre></td><td><pre class="language-yaml"><code class="lang-yaml">- powershell: .\ImpEx.ps1 `
       -exportEndpoint "https://excel.my-source-environment.coherent.global/my-source-tenant/api/v4/export" `
       -importEndpoint "https://excel.my-destination-environment.coherent.global/my-destination-tenant/api/v4/import" `
       -serviceUriSource "CICD-SOURCE/Service2" `
       -serviceUriDestination "CICD-DESTINATION/Service2" `
       -sourceSystem "mycicd" `
       -correlationId "456" `
       -servicesExisting "add_version" `
       -sourceKeycloakMetadataUri "https://keycloak.my-source-environment.coherent.global/auth/realms/my-source-tenant/protocol/openid-connect/token" `
       -sourceKeycloakClientId "client-credentials" `
       -sourceKeycloakClientSecret "9Oh1nscDtPzMehwA3ejKJFAar3RRktHY" `
       -destinationKeycloakMetadataUri "https://keycloak.my-destination-environment.coherent.global/auth/realms/my-destination-tenant/protocol/openid-connect/token" `
       -destinationKeycloakClientId "client-credentials" `
       -destinationKeycloakClientSecret "lZai8ARrLUBpLBLbueHusWUfCoYZ6DxN"
   </code></pre></td></tr></tbody></table>
