> For the complete documentation index, see [llms.txt](https://developer.harness.io/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://developer.harness.io/continuous-delivery/use-continuous-delivery/cd-building-blocks/services/add-a-custom-artifact-source-for-cd.md).

# Add a custom artifact source for CD

Fetch a JSON payload of artifacts from a custom repository using a shell script, then reference the artifact version in your deployment.

{% hint style="info" %}
**Custom artifact source requires a feature flag**

This feature is behind the feature flag `CUSTOM_ARTIFACT_NG`. Contact [Harness Support](mailto:support@harness.io) to enable it. Harness includes artifact sources for the most common repositories, such as GCR, ECR, Nexus, Artifactory, and any Docker registry such as Docker Hub.
{% endhint %}

For cases where you use a custom artifact repository, you can use the **Custom Artifact** repository type. The custom artifact uses a shell script to fetch a JSON payload of the artifacts from your repository, and then you can reference the artifact version to use in your deployment. You can also reference any metadata in the payload.

This topic describes how to use the custom artifact repository type in your Harness service and how to reference its artifact information from the JSON payload.

***

## What you will learn from this topic

* **Custom artifact source setup:** How to add a [custom artifact source](#add-a-custom-artifact-source) to a Kubernetes, SSH, or WinRM service.
* **Script input variables:** How to use [script input variables](#script-input-variables) to template your fetch script.
* **Additional attributes:** How to map extra payload fields using [additional attributes](#additional-attributes-metadata).
* **Referencing the artifact:** How to [reference the custom artifact](#reference-custom-artifact) in a manifest or Shell Script step.

***

## Before you begin

* Custom artifact is supported in the [Kubernetes](/continuous-delivery/use-continuous-delivery/deploy-services-on-different-platforms/kubernetes/kubernetes-cd-quickstart.md), [SSH](/continuous-delivery/use-continuous-delivery/deploy-services-on-different-platforms/traditional/ssh-ng.md), and [WinRM](/continuous-delivery/use-continuous-delivery/deploy-services-on-different-platforms/traditional/win-rm-tutorial.md) deployment types only.
* The payload returned from your repository must be a JSON formatted array.

***

### Create a service

Create a new service in Harness.

For **Deployment Type**, select **Kubernetes**. Custom Artifact is supported in the Kubernetes deployment type.

You can now see the **Manifests** and **Artifacts** sections.

This section focuses on **Artifacts** to demonstrate custom artifact, but you can find information on manifests in [Kubernetes Services](/continuous-delivery/use-continuous-delivery/deploy-services-on-different-platforms/kubernetes/kubernetes-services.md).

### Add a custom artifact source

In **Artifacts**, select **Add Primary Artifact**.

Custom artifact is also supported in **Sidecar**. In **Specify Artifact Repository Type**, select one of the following options, then select **Continue**.

{% tabs %}
{% tab title="Manually enter an artifact version" %}
In **Version**, enter the version of the artifact you want to deploy.

You can set **Version** as a [runtime input](https://developer.harness.io/harness-platform/use-harness-platform/variables-and-expressions/runtime-inputs), and then enter the version when you run the pipeline that deploys this service. You can also use an [expression](https://developer.harness.io/harness-platform/use-harness-platform/variables-and-expressions/harness-variables) that is evaluated at runtime.
{% endtab %}

{% tab title="Provide a script to dynamically pull the artifact location" %}
In **Script**, enter a script to fetch a JSON payload and add it to the Harness variable `$HARNESS_ARTIFACT_RESULT_PATH`.

**Example:**

```
curl -X GET "https://nexus3.dev.harness.io/service/rest/v1/components?repository=cdp-qa-automation-1" -H "accept: application/json" > $HARNESS_ARTIFACT_RESULT_PATH
```

The following is an example of the JSON payload returned from the cURL command:

```json
{
  "items" : [ {
    "id" : "Y2RwLXFhLWF1dG9tYXRpb24tMTo5M2I5YjllYjlhN2VjYjA2NWJlYjdkNWUxNDgyMDFjOQ",
    "repository" : "cdp-qa-automation-1",
    "format" : "docker",
    "group" : null,
    "name" : "nginx",
    "version" : "latest",
    "assets" : [ {
      "downloadUrl" : "https://nexus3.dev.harness.io/repository/cdp-qa-automation-1/v2/nginx/manifests/latest",
      "path" : "v2/nginx/manifests/latest",
      "id" : "Y2RwLXFhLWF1dG9tYXRpb24tMTo5MTJkMGZlN2I4MTkyMzkyODc0NTUyYTgyZWVmYzhkZQ",
      "repository" : "cdp-qa-automation-1",
      "format" : "docker",
      "checksum" : {
        "sha1" : "33acb567b9635e73ae566691eb22a89c84138c0b",
        "sha256" : "bb129a712c2431ecce4af8dde831e980373b26368233ef0f3b2bae9e9ec515ee"
      }
    } ]
...
```

Next, in **Artifacts Array Path**, define where to find each artifact in the array (`$.items`).

Next, in **Versions Path**, define where to find the artifact versions in your payload (`version`).

Once done, the artifact details look something like this:

![Artifact details page showing the configured artifacts array path and versions path for a custom artifact source](https://3694223630-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fy1JhZ4oKIppwY7d5AhPj%2Fuploads%2Fgit-blob-c0a74a3023416c7342d49888565abd654ffc9859%2Fadd-a-custom-artifact-source-for-cd-07.png?alt=media)

Enter the following settings:

* **Timeout**: Enter a time limit for the script to execute before failing the artifact JSON retrieval.
* **Script**: Enter a script to fetch a JSON payload and add it to the Harness variable `$HARNESS_ARTIFACT_RESULT_PATH`.

  **Example:**

  ```
  curl -X GET "https://nexus3.dev.harness.io/service/rest/v1/components?repository=cdp-qa-automation-1" -H "accept: application/json" > $HARNESS_ARTIFACT_RESULT_PATH
  ```

  The shell script you enter queries the Custom Artifact repository and outputs the JSON payload to a file on the Harness Delegate host, using the environment variable `HARNESS_ARTIFACT_RESULT_PATH`, initialized by Harness. `HARNESS_ARTIFACT_RESULT_PATH` is a random, unique file path created on the Delegate by Harness.

  You can use [Harness text secrets](https://developer.harness.io/harness-platform/use-harness-platform/secrets/add-use-text-secrets) in the script. For example:

  ```
  curl -u 'harness' <+secrets.getValue("repo_password")> https://myrepo.example.io/todolist/json/ > $HARNESS_ARTIFACT_RESULT_PATH
  ```

  You must delete the Artifact Source and add it again to re-collect the artifacts if the Artifact Source or its script information changes.
* **Artifacts Array Path**: Enter the path in the payload array to the artifacts listing. For example, in the following payload the artifacts are listed using `items`, so in Artifacts Array Path you reference the path with `$.items`.

  **Example:**

  ```json
  {
    "items" : [ {
      "id" : "Y2RwLXFhLWF1dG9tYXRpb24tMTo5M2I5YjllYjlhN2VjYjA2NWJlYjdkNWUxNDgyMDFjOQ",
      "repository" : "cdp-qa-automation-1",
      "format" : "docker",
      "group" : null,
      "name" : "nginx",
      "version" : "latest",
      "assets" : [ {
        "downloadUrl" : "https://nexus3.dev.harness.io/repository/cdp-qa-automation-1/v2/nginx/manifests/latest",
        "path" : "v2/nginx/manifests/latest",
        "id" : "Y2RwLXFhLWF1dG9tYXRpb24tMTo5MTJkMGZlN2I4MTkyMzkyODc0NTUyYTgyZWVmYzhkZQ",
        "repository" : "cdp-qa-automation-1",
        "format" : "docker",
        "checksum" : {
          "sha1" : "33acb567b96xxx9c84138c0b",
          "sha256" : "bb129a712cxxx33ef0f3b2bae9e9ec515ee"
        }
      } ]
  ...
  ```
* **Version Path**: Enter the path in the payload array to the version. Using the payload example above, the path is `version`.
* **Version**: Enter the version number for this deployment, or select Runtime Input or Expression to select the version dynamically.

  For more information on Fixed Value, Runtime Input, and Expression, go to [Fixed Values, Runtime Inputs, and Expressions](https://developer.harness.io/harness-platform/use-harness-platform/variables-and-expressions/runtime-inputs).

  When you are done, Artifact Details looks something like this:

  ![Artifact details page showing the configured version path and version settings for a custom artifact source](https://3694223630-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fy1JhZ4oKIppwY7d5AhPj%2Fuploads%2Fgit-blob-c0a74a3023416c7342d49888565abd654ffc9859%2Fadd-a-custom-artifact-source-for-cd-07.png?alt=media)

  Later, you can reference the Version using this expression format, which resolves to the version pulled from the array at runtime:

  `<+pipeline.stages.[stage_Id].spec.serviceConfig.output.artifactResults.primary.version>`
  {% endtab %}
  {% endtabs %}

### Script input variables

While you can declare a variable in your script using a Harness expression or string for its value, using **Script Input Variables** provides some additional benefits:

* You can more easily identify and manage the Harness expressions used in your script.
* You can template your script.

You can declare the variable using **Name** and **Value** in **Script Input Variables** and then reference the variable in the script just as you would any other variable: `$var_name`.

### Additional attributes (metadata)

In **Additional Attributes**, you can map any additional values from your JSON array.

For example, the following payload has `downloadUrl` and `path` in its `assets`:

```json
{
  "items" : [ {
    "id" : "Y2RwLXFhLWF1dG9tYXRpb24tMTo5M2I5YjllYjlhN2VjYjA2NWJlYjdkNWUxNDgyMDFjOQ",
    "repository" : "cdp-qa-automation-1",
    "format" : "docker",
    "group" : null,
    "name" : "nginx",
    "version" : "latest",
    "assets" : [ {
      "downloadUrl" : "https://nexus3.dev.harness.io/repository/cdp-qa-automation-1/v2/nginx/manifests/latest",
      "path" : "v2/nginx/manifests/latest",
      "id" : "Y2RwLXFhLWF1dG9tYXRpb24tMTo5MTJkMGZlN2I4MTkyMzkyODc0NTUyYTgyZWVmYzhkZQ",
      "repository" : "cdp-qa-automation-1",
      "format" : "docker",
      "checksum" : {
        "sha1" : "33acb567b96xxx9c84138c0b",
        "sha256" : "bb129a712cxxx33ef0f3b2bae9e9ec515ee"
      }
    } ]
...
```

You can assign these items to variables. In **Name**, enter the variable name and in **Value** enter the path to the item.

For example, to reference `downloadUrl` and `path` in the first item in the array:

* `assets[0].downloadUrl`
* `assets[0].path`

**Example:**

![Additional attributes mapping showing the Name and Value fields for downloadUrl and path](https://3694223630-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fy1JhZ4oKIppwY7d5AhPj%2Fuploads%2Fgit-blob-ca1c87dc901bd19e256e1bc70cb4f179f0aa6976%2Fadd-a-custom-artifact-source-for-cd-09.png?alt=media)

Later, in a **Shell Script** step, you can reference these attributes using the expression format:

`<+pipeline.stages.[stage_Id].spec.serviceConfig.output.artifactResults.primary.metadata.[attribute_name]>`

For example:

```
echo "URL: <+pipeline.stages.Kube.spec.serviceConfig.output.artifactResults.primary.metadata.URL>"
echo "Path: <+pipeline.stages.Kube.spec.serviceConfig.output.artifactResults.primary.metadata.path>"
```

At runtime, these expressions resolve to the data from the array.

### Reference custom artifact

You can reference the custom artifact in your *values.yaml* file and in a Shell Script step.

**Values YAML in manifests**

You add a *values.yaml* file along with your manifests in the **Manifests** section of the service.

The *values.yaml* file can use Harness expressions to reference artifacts in the **Artifacts** section of the service.

To reference the artifact, use the expression `<+artifact.image>` in your *values.yaml* file.

**Example:**

```yaml
name: example
replicas: 2

image: <+artifact.image>
# dockercfg: <+artifact.imagePullSecret>

createNamespace: true
namespace: <+infra.namespace>

...
```

For details on using *values.yaml* in Harness, go to [Kubernetes Services](/continuous-delivery/use-continuous-delivery/deploy-services-on-different-platforms/kubernetes/kubernetes-services.md).

[Harness Variables and Expressions](https://developer.harness.io/harness-platform/use-harness-platform/variables-and-expressions/harness-variables) can be added to values files (for example, values.yaml), not the manifests themselves. This provides more flexibility.

### Shell script step

In the stage **Execution** section, add a [Shell Script](/continuous-delivery/use-continuous-delivery/cd-building-blocks/cd-steps/utilities/shell-script-step.md) step.

In **Script**, reference the artifact and any additional attributes you configured. The following is an example where the stage is named Kube:

```
echo "Version: <+pipeline.stages.Kube.spec.serviceConfig.output.artifactResults.primary.version>"
echo "URL: <+pipeline.stages.Kube.spec.serviceConfig.output.artifactResults.primary.metadata.URL>"
echo "Path: <+pipeline.stages.Kube.spec.serviceConfig.output.artifactResults.primary.metadata.path>"
```

***

## Next steps

You have configured a custom artifact source and referenced its data in a manifest and a Shell Script step. For related tasks, go to:

* [Kubernetes Services](/continuous-delivery/use-continuous-delivery/deploy-services-on-different-platforms/kubernetes/kubernetes-services.md): Configure manifests and other artifact sources for a Kubernetes service.
* [Using Shell Scripts in CD Stages](/continuous-delivery/use-continuous-delivery/cd-building-blocks/cd-steps/utilities/shell-script-step.md): Reference artifact variables and metadata in a Shell Script step.

{% @harness-feedback/feedback %}
