# 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>


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.coherent.global/ci-cd/how-to-deploy-with-azure-devops.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
