> 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/internal-developer-portal/use-idp/software-catalog/create-entity/catalog-discovery/integrations/harness-ci.md).

# Harness CI

Discover Harness CI pipelines and the repos they build, merge them into catalog entities, and view build metrics on the entity CI tab.

The Harness CI integration discovers CI pipelines (and the repositories those pipelines build), lets you merge them into existing catalog entities, and displays build metrics and executions on the **CI** tab of the catalog entity. See the [How discovery works](#how-discovery-works) section to know the detailed mechanism of discovery.

The integration is **uni-directional**, i.e., the data flows from Harness CI into the IDP Catalog. Changes you make on a catalog entity are not written back to CI.

{% hint style="warning" %}
**THIS IS NOT GITHUB OR HARNESS CODE REPOSITORY DISCOVERY**

The repository in this integration is the codebase that a Harness CI pipeline builds. It is the stage-level repository URL that CI records for that pipeline.

It is not:

* Every repository in Harness Code Repository (HCR)
* The [GitHub integration](/internal-developer-portal/use-idp/software-catalog/create-entity/catalog-discovery/integrations/github.md), which discovers repositories from your GitHub organization
* Any other Git provider catalog of repos

If a repo exists in HCR or GitHub but no in-scope CI pipeline has executed against it, this integration will not discover that repo.
{% endhint %}

For each resource, the integration provides the following:

| Resource       | What it provides                                                                                                                         |
| -------------- | ---------------------------------------------------------------------------------------------------------------------------------------- |
| **Pipeline**   | CI pipelines in the selected scope that have recent executions. You merge a pipeline into a catalog entity to show that entity's builds. |
| **Repository** | The repo URL the pipeline builds (stage-level codebase). Used when you choose repository-based discovery.                                |
| **CI tab**     | On a merged catalog entity: success rate, build failure rate, average build duration, and a builds table.                                |

{% hint style="info" %}
You can create only one Harness CI integration per account.
{% endhint %}

***

## Before you begin

Make sure the following prerequisites are met:

1. The **`IDP_INTEGRATIONS`** and **`IDP_CI_INTEGRATION`** feature flags should be enabled for your account. Contact [Harness Support](https://www.harness.io/support) to enable them.
2. **Harness CI** is enabled on the same account you use for Harness IDP, and you have pipelines that actually run. Go to [When pipelines and repositories appear](#when-pipelines-and-repositories-appear) to confirm which pipelines qualify.
3. You have the **IDP Integration Edit** permission (`IDP_INTEGRATION_EDIT`) on the **IDP Integration** resource type (`IDP_INTEGRATION`).
4. Catalog entities already exist for the services you want to enrich. This integration has `Merge` option only. It does not register new catalog entities.

***

## Create the Harness CI integration

### 1. Navigate to the integrations page

To open the integrations page, complete the following steps:

1. In Harness, open the **Internal Developer Portal**.
2. From the left sidebar, go to **Configure** → **Integrations**.
3. Click **+ New Integration** and choose **Harness Integrations**.

   ![](https://1305598861-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F1bzrz9ybUGCcYdvS4u0z%2Fuploads%2Fgit-blob-ac097bbe04ea93556107f57e0843424d31b248ea%2Fharness-integrations.png?alt=media)

### 2. Enter the integration details

In the **Integration Details** section:

1. Enter a name in the **Integration Name** field, for example `Harness CI Integration`.
2. From the **Choose Integration** dropdown, select **Continuous Integration (CI)**.

   ![](https://1305598861-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F1bzrz9ybUGCcYdvS4u0z%2Fuploads%2Fgit-blob-a437254183bda96eb0628b5f92e5ee0e76170c84%2Fci-int-details.png?alt=media)

### 3. Set the integration scope

In the **Integration Scope** section, choose one of the following:

* **All projects** - Pipeline and repository data across all projects is imported. This is limited to the projects you can access.
* **Particular projects** - Pipeline and repository data is imported only from the scopes you select. A **Scopes** picker appears where you can search for a project or organization and select from **Favorite Projects** and **Recent Projects**.

  ![](https://1305598861-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F1bzrz9ybUGCcYdvS4u0z%2Fuploads%2Fgit-blob-af900ce4c2fff07a01e39684409d71ed4ff51d22%2Fci-int-scope.png?alt=media)

There is no cross-account or out-of-scope leakage. Out-of-scope items do not appear on [Discovered tab](#discovered-tab).

### 4. Configure mapping and correlation

In the **Mapping & Correlation** section, you can choose only one CI stream that defines how entities are mapped and correlated to your catalog.

| CI stream      | What appears on Discovered tab |
| -------------- | ------------------------------ |
| **Pipeline**   | CI pipelines in scope          |
| **Repository** | Repos those pipelines build    |

![](https://1305598861-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F1bzrz9ybUGCcYdvS4u0z%2Fuploads%2Fgit-blob-6bfeae62de89a764b721285a169d568a434aa89b%2Fci-int-mapping.png?alt=media)

{% hint style="warning" %}
**YOU CANNOT ENABLE BOTH STREAMS ON THE SAME INTEGRATION**

To switch streams (pipeline ⇄ repository) later, open the **Configuration** page of this integration and supply correlation for the new stream. Previously discovered items for the old stream are removed, and imported links for the old stream are unlinked or no longer populate the entity **CI** tab.
{% endhint %}

Next, set the mapping:

1. Select the **Kind**, which defaults to `Component`. The **Select Kind** modal is searchable and paginated, and it includes custom kinds alongside the built-in ones.

   ![](https://1305598861-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F1bzrz9ybUGCcYdvS4u0z%2Fuploads%2Fgit-blob-33951b3b61ff555eceb8013a622f4adc8ade0dab%2Fci-int-kind.png?alt=media)
2. Select the **Type**, which defaults to `Service`. The dropdown lists the types already present in your catalog, and freeform types are allowed.

   Merge suggestions only include catalog entities of the selected kind and type. If nothing in the catalog matches, you can still merge with a manual override.
3. Set the correlation row:
   * **Ingested Data Path** - The CI field to match on, selected from a dropdown.
   * **Operator** - `Equals`.
   * **Catalog YAML Path** - The field on your catalog entity, for example `NAME`.

{% hint style="warning" %}
**THE OPERATOR CANNOT BE CHANGED AFTER CREATE**

Only `Equals` is supported. [JQ](https://jqlang.org/) and other transforms are not supported in this phase, and the operator is locked once the integration is created. You can still edit the correlation path later.
{% endhint %}

### 5. Confirm

Select **Confirm** to create the integration. Selecting **Back** returns you to the previous step, and discarding leaves no integration behind.

Discovery starts once the integration is created and active.

***

## Discover, merge, and import

After enabling, open the integration and use the **Discovered** and **Imported** tabs. A chip below the tabs shows which CI stream is active, for example **Pipeline**.

### Discovered tab

![](https://1305598861-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F1bzrz9ybUGCcYdvS4u0z%2Fuploads%2Fgit-blob-8e6db9331e3185c7e879615555028a1f2576de7f%2Fci-discovered-tab-complete.png?alt=media)

The table shows the following:

| Column           | Description                                                                                           |
| ---------------- | ----------------------------------------------------------------------------------------------------- |
| **CI Pipelines** | The pipeline name and its ID. Select the column header to sort. Use the search box to filter by name. |
| **Action**       | Always **Merge** for this integration, with a **Select an entity to merge with** dropdown.            |
| **Kind**         | The catalog entity kind configured on the integration, for example `component`.                       |
| **Type**         | The catalog entity type configured on the integration, for example `service`.                         |
| **Scope**        | The Harness project and organization the pipeline belongs to.                                         |

{% hint style="info" %}
**PERMISSIONS FOR THE DISCOVERED TAB**

Opening **Discovered** requires **IDP Integration View**. Listing CI pipelines and opening their details also requires **Pipeline View** in those projects. Users who only hold the integration role can open the page but will not see CI entities they cannot already view.
{% endhint %}

{% hint style="info" %}
**MERGE ONLY - MANUAL OR AUTO**

The only write action is **Merge**.

**Register** and **Merge & Register** are not offered for Harness CI. You always attach CI sources to catalog entities you already have.

**Auto Import** - Toggle **Auto-import future discovered entities** in the top right of the Discovered tab to automatically merge future pipelines into their matching catalog entity, without manual review. You can change this preference at any time.
{% endhint %}

### Merge a source onto a catalog entity

| Action                | What happens                                                                                                               |
| --------------------- | -------------------------------------------------------------------------------------------------------------------------- |
| **Recommended merge** | Rows that already match a catalog entity of the configured kind and type. Confirm the merge to link them.                  |
| **Manual override**   | For an unmatched row, pick a catalog entity of the configured kind and type, then merge. A recommendation is not required. |

{% hint style="info" %}
**Cardinality rules for this phase**

* Many pipelines or many repos to **one** catalog entity is not supported. For example, two pipelines that both build the same service cannot both be linked to it.
* One pipeline (or one repo) to **many** catalog entities is not supported. Monorepo splits are out of scope.
* A source that is already imported cannot be merged onto a second entity without unlinking the first. If you merge the same pipeline or repo onto a different catalog entity, the previous entity is unlinked (override). The source is never linked to two entities at once.
  {% endhint %}

After a merge, the row appears in the [Imported tab](#imported-tab).

### Imported tab

This section shows the link between the CI pipeline or repo and the catalog entity.

![](https://1305598861-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F1bzrz9ybUGCcYdvS4u0z%2Fuploads%2Fgit-blob-772516a6b77db3fa6f128a031082471cc1f0fe28%2Fci-int-imported.png?alt=media)

| Column           | Description                                                                 |
| ---------------- | --------------------------------------------------------------------------- |
| **CI Pipelines** | The CI pipeline name and its ID.                                            |
| **Entity**       | The linked IDP catalog entity and its ID. Select the column header to sort. |
| **Kind**         | The catalog entity kind.                                                    |
| **Type**         | The catalog entity type.                                                    |
| **Scope**        | The Harness project and organization.                                       |
| **Imported At**  | The date and time the source was imported.                                  |

To remove a mapping, open the three-dot menu on the row and select **Unlink**. The source returns to **Discovered**, and the entity **CI** tab drops only that source.

{% hint style="warning" %}
**DELETING A PIPELINE IN HARNESS CI IS NOT HANDLED**

If a pipeline or repo is already **Imported** and you then delete that pipeline in the Harness CI module, IDP does not drop the imported link, clean up **Imported**, or clear the entity **CI** tab. Unlink the source in IDP if you need the mapping removed. Source deletion for imported entities is not supported in this phase.
{% endhint %}

***

## View Harness CI builds in the catalog

After at least one pipeline or repo is merged onto a catalog entity, developers use the entity **CI** tab.

### Layout for CI data

CI data will not appear until you add the CI tab to the [catalog entity layout](/internal-developer-portal/admin-and-customization/layout-and-appearance/catalog.md). This is a one-time configuration per entity kind and type.

1. From the left sidebar of IDP, go to **Configure** → **Layout** → **Catalog Entities**.
2. Select the **Entity Kind** (for example, `component`) and the **Entity Type** (for example, `service`) that matches your merged entities, then select **Edit Layout**.
3. In the YAML editor, add the following definition inside the `tabs` block:

   ```yaml
       - name: CI
         path: /ci-dashboard
         title: CI
         contents:
           - component: CiMetricsTab
   ```

   ![](https://1305598861-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F1bzrz9ybUGCcYdvS4u0z%2Fuploads%2Fgit-blob-261bbb75c7d5356dca66bba2bc33706f261dc81f%2Fci-int-layout.png?alt=media)
4. Select **Save**.

The **CI** tab now appears on every entity detail page of the selected kind and type that has CI data linked to it.

### Filters, metrics, and builds

![](https://1305598861-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F1bzrz9ybUGCcYdvS4u0z%2Fuploads%2Fgit-blob-a74a40526040e5bea465f0f0610f5bf3b0a67151%2Fci-int-tab.png?alt=media)

The **CI** tab shows the following:

* **Filters** - A duration filter (1, 7, 30, or 90 days), plus repo and pipeline filters. The duration filter applies to both the metric cards and the builds table.
* **Metrics** - Success rate, failure rate, and average build time, each with a trend against the previous equal window. When there is not enough history to compute a trend, the tab does not raise an error; the trend is simply not shown.
* **Builds** - Newest first, paginated. Columns include pipeline name, status, trigger summary, execution start time, and duration. Status filters (failed, running, aborted, and so on) apply to the builds table only, not to the metric cards.

{% hint style="info" %}
**Points to Remember**

* For pipeline-based or repo-based linkage, only a single pipeline or a single repo is linked.
* For pipeline-based linkage, you can view the pipeline along with all its executions. If any repo URLs are found, you can further filter the executions by each repo. The same is true for repo-based linkage.
* Even though the filter is shown as **All Repositories**, it shows all executions across all repos for that pipeline, without any repo filter. These executions may or may not have an associated repository URL. If a pipeline execution failed before the stage trigger, that execution is visible under **All Repositories** but not in repo filter.
* If the integration is disabled, or the entity has no CI mapping, the tab is empty or shows a **Not Configured** state. Re-enable the integration or merge a source to restore data.
  {% endhint %}

### Ingested properties

In the entity, open the Entity Inspector from the top by clicking **View YAML** → **Ingested Properties**.

![](https://1305598861-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F1bzrz9ybUGCcYdvS4u0z%2Fuploads%2Fgit-blob-aa969cd26d572e4dbc5d487ff7b42e81cc3a0e48%2Fci-int-ingested.png?alt=media)

Values live under `metadata.integration_properties.HarnessCI` and include `accountIdentifier`, `orgIdentifier`, `projectIdentifier`, `pipelineId`, `pipelineName`, `lastBuiltAt`, and `repositoryUrl`.

***

## Manage the Harness CI integration

### Edit the integration

To change the scope, CI stream, kind, type, or correlation path, open the integration and select **Configuration** at the top right. Update the fields and confirm.

You can edit while the integration is active. You do not need to suspend it first, and discovery refreshes with the new configuration.

If you shrink the scope, out-of-scope items leave **Discovered**. Imported links remain unless you unlink them, and they stop receiving new discovery for that scope until you add the scope back.

### Suspend the integration

Suspending keeps the configuration but stops CI data from appearing in the IDP Catalog and on entity pages. **Discovered** and **Imported** become read-only.

1. Open the integration and select **Configuration**.
2. Scroll to the **Danger Zone** section.
3. Under **Suspend the CI integration**, select **Suspend**.

Resuming restores the same mappings and entity tab data. It does not create duplicate imported rows, and it does not delete catalog entities or the integration configuration.

***

## How discovery works

Discovery reads CI execution data, not the static list of pipeline YAML or Git remotes. Understanding this determines what you will and will not see on the **Discovered** tab.

### When pipelines and repositories appear

Pipelines and repositories appear under the following conditions:

* A pipeline appears on **Discovered** only if it has at least one execution in the lookback window (executions from the last **730 days**). A pipeline that exists in the CI module but has never run, or has not run in more than 730 days, is not discovered.
* All CI pipelines are discovered. There is no filter on whether a CI pipeline has at least one stage of type build.
* A repository appears only if a pipeline execution recorded that repo as the stage-level codebase. Go to [How repository URLs are discovered](#how-repository-urls-are-discovered) to review the discovery rules.
* If a pipeline fails before the stage trigger, it is not discovered through repo-based discovery.
* After a pipeline runs, allow about **five minutes** before the pipeline or repo shows up on **Discovered**. Data is ingested asynchronously.

### How repository URLs are discovered

Harness CI stores a single codebase at stage level. That is the only repo URL this integration can discover and show on the **Discovered** tab when the Repository stream is selected.

Keep these rules in mind when you design pipelines and when you interpret **Discovered** results:

1. **Only the stage-level repo URL is populated** - That is the URL IDP discovers for repos. Clone URLs that exist only as step inputs are not used.
2. **Git Clone steps and shell scripts are ignored** - If a stage has multiple Git Clone steps, those extra repo URLs are not discovered. Repo URLs that you set only inside a Shell Script (or similar) step are also not discovered.
3. **One repo URL per pipeline, shared across stages** - If the pipeline has several CI stages, they share the same stage-level codebase. Each stage can toggle whether to use that repo URL, but you cannot set a different repo URL per stage for discovery.

{% hint style="info" %}
**CODEBASE VERSUS EXTRA CLONES**

A typical CI pipeline sets **Codebase** (the stage-level repo) once. Additional `git clone` commands in later steps can still run in CI; they simply never appear as discovered repositories in IDP.
{% endhint %}
