For the complete documentation index, see llms.txt. This page is also available as Markdown.

Migrate deployment repo to Application Set references

Move GitOps services from the deprecated Deployment Repository manifest to Application Set references (appsetConfigs) so Fetch Linked Apps and related pipelines keep working.

A Deployment Repository tells Harness where to look for an ApplicationSet: a connector, a branch or commit, and a file path. At runtime, Fetch Linked Apps fetched that file from git and read its metadata.name. Application Set references store the answer instead of the lookup. Each reference names one ApplicationSet directly, along with the GitOps agent that manages it, so Harness no longer reads git to learn which ApplicationSet a service deploys.

This guide shows you how to find the right names and agents for your service, apply the change through the UI, YAML, the API, or Terraform, and confirm that your pipelines still return the same applications.

What you will learn from this topic

Before you begin

  • Service edit access: Create or Edit permission on the GitOps service you are migrating. Go to the permissions reference to review required roles.

  • GitOps visibility: View permission on GitOps Applications and ApplicationSets so you can confirm ApplicationSet names, agents, and child Applications during discovery. Go to the permissions reference to review GitOps permissions.

  • Agent access: The GitOps agents that run your ApplicationSets must be connected and mapped to the Harness project you are working in.


Understand the migration

Migration changes the service. You add appsetConfigs with the ApplicationSet names and agents, then remove the Deployment Repository manifests. Release Repository, pipeline YAML, and GitOps Sync normally stay as they are, because Fetch Linked Apps reads this configuration from the service at run time.

Make the change in two stages. Add the references while the Deployment Repository is still in place: Fetch Linked Apps prefers appsetConfigs whenever both exist, so the new configuration takes effect immediately and you can compare its results against the old behavior. Remove the Deployment Repository only after that comparison passes.


Compare the service configuration


Choose a migration path

Start with the service YAML, then follow the branch that matches how its Deployment Repository store resolves.

Use these outcomes:

  • Existing references: Fetch Linked Apps already prefers them, so the Deployment Repository is inactive for that step. Go to Validate the migration to compare the results, then remove it.

  • Fixed store: Resolve one ApplicationSet name from git and find every agent that manages that name. Go to Identify Application Set names and agents.

  • Dynamic store: The right answer depends on whether the identity is constant, follows a rule, or is unbounded. Go to Handle expressions and runtime inputs.

  • Unknown name or agent: Do not guess. Confirm the live ApplicationSet and its agents before you remove a working Deployment Repository.

  • More than one Deployment Repository: You can save a service with several, but the legacy Fetch Linked Apps path fails at run time unless exactly one is present, so such a service is already broken. Work out which ApplicationSet the pipeline is meant to use, add references for it, and remove all of the Deployment Repository manifests.


Identify Application Set names and agents

The legacy configuration stores a git location. The replacement stores explicit identities. Work out those identities in this order.

  1. Resolve the git location.

    • For fixed values, use the configured branch or commit and the first entry in paths.

    • For folderPath, use the first ApplicationSet YAML file returned from that folder.

    • For expressions or runtime inputs, open a representative pipeline execution and record the resolved connector, repository, branch or commit, and path. The Fetch Linked Apps task log also reports the resolved AppSet name for that run.

  2. Read metadata.name. Open the resolved file and copy the ApplicationSet metadata.name. Do not derive the name from the file name.

  3. Find every agent for that name.

    • Go to GitOps > Applications and select ApplicationSets. Search for the exact metadata.name, then record the agent for every matching row.

    • Also inspect the generated Applications. Confirm that their ApplicationSet owner name matches and record each agent that hosts those children.

    • Do not rely on harness.io/serviceRef labels to discover the mapping. Older or custom templates may omit those labels.

  4. Create one pair per agent. If payments has child Applications on agent-us and agent-eu, add two references with the same appSetIdentifier and different agentIdentifier values.

ApplicationSet not found in Harness

An ApplicationSet can exist in your Argo CD cluster and generate child Applications even when it does not appear in the Harness ApplicationSets list. Harness inventories Applications and ApplicationSets separately, so the child Application records can remain available when the corresponding ApplicationSet inventory row is missing.

An empty ApplicationSets list does not block Fetch Linked Apps. The step does not read that list. It queries child Applications by the ApplicationSet name in their Kubernetes owner reference, then filters them by agent. A correct metadata.name and agent are sufficient for migration and runtime discovery.

ApplicationSet does not appear in the Harness ApplicationSets list

Harness inventories Applications and ApplicationSets on separate agent paths. The Argo CD ApplicationSet controller creates child Applications with a Kubernetes owner reference to the ApplicationSet, and the agent reports those children to Harness, which stores the owner name as parentAppRef. The agent reports ApplicationSets only when ApplicationSet reconciliation is available and enabled on that agent, so child Applications can appear in Harness while the parent ApplicationSet stays absent from the UI.

Check these causes, in order:

  1. The GitOps agent is too old to inventory ApplicationSets. ApplicationSet reconciliation first shipped in agent v0.90.0. Agents older than v0.90.0 reconcile Applications but do not reconcile ApplicationSets. In that case you see healthy child Applications with an ApplicationSet owner, and zero ApplicationSet rows for that agent. Upgrade the agent to v0.116.0 or later, where ApplicationSet reconciliation is always on.

  2. ApplicationSet reconciliation is disabled on the agent. Agent versions v0.90.1 through v0.115.x gate ApplicationSet inventory behind GITOPS_AGENT_APPSET_RECONCILE_ENABLE (default false). When that setting is unset or false, the agent continues to report Applications and skips ApplicationSets. Set GITOPS_AGENT_APPSET_RECONCILE_ENABLE=true on those versions, then restart or roll the agent so the setting takes effect. In the Harness GitOps agent Helm values, this maps to harness.configMap.reconcile.appsetReconcile: true. From agent v0.116.0 the gate is removed and ApplicationSet reconciliation is always on, so the env var is ignored if still present.

  3. The Argo CD project is not mapped to a Harness project. The agent reports ApplicationSets whose spec.template.spec.project maps to a Harness project. An unmapped project prevents a healthy ApplicationSet from appearing.

  4. You are viewing a different project or agent. ApplicationSets are scoped to the project and the agent that reported them.

  5. The agent is disconnected or has not reconciled recently. Check the agent status and its last heartbeat after you upgrade or enable reconciliation.

  6. You do not have ApplicationSet view permission.

To fix: confirm that child Applications exist for the ApplicationSet owner name while ApplicationSets lists nothing for the same agent, check the agent version and the agent ConfigMap or Helm values, upgrade the agent to v0.116.0 or later (on v0.90.1 through v0.115.x, set GITOPS_AGENT_APPSET_RECONCILE_ENABLE=true instead), then wait for the next successful reconcile and refresh ApplicationSets.

Service editor cannot select an ApplicationSet that is missing from the list

Read the ApplicationSet owner name and the agent from the child Applications and use exactly those values. Fetch Linked Apps queries the Kubernetes owner reference on the child Applications, so it works without a UI row. Configure the reference through YAML, the API, or Terraform instead of the UI selector, then repair the agent inventory (upgrade the agent or enable ApplicationSet reconciliation) so the UI selector works later.

Then continue based on what does exist:

  • The ApplicationSet was renamed or deleted. Use the current live name, and reconcile or remove stale child Applications before you compare results.

  • Nothing exists on any agent. Do not create a speculative reference. Apply or reconcile the ApplicationSet on the intended agent first.

  • Applications have no ApplicationSet owner. Those applications cannot map to Application Set references. Keep their existing label or explicit GitOps Sync selection, and migrate only the ApplicationSet-owned workflow.

Example: one ApplicationSet on two agents

The first Deployment Repository file contains:

Harness shows child Applications owned by payments on agent-us and agent-eu. Preserve the legacy all-agent behavior with two references:

If you omit agent-eu, Fetch Linked Apps no longer returns the Applications on that agent.

Example: multiple paths or a folder path

For this store, only appsets/payments.yaml supplied the name at runtime:

Read metadata.name from appsets/payments.yaml. Do not create a reference for orders unless another supported input or service explicitly selects it.

For folderPath: appsets/, inspect the first YAML file returned from that folder. If file ordering is unclear, use a successful Fetch Linked Apps task log to confirm the AppSet name before you migrate.


Use the matching recipe

Fixed store and confirmed inventory

  • Recognize it: Connector, repository, branch or commit, and path are fixed values. The ApplicationSet name and all agents are known.

  • Action: Add one Application Set reference per name and agent pair. Keep any Release Repository unchanged.

  • Test: Add the references while the Deployment Repository still exists, run Fetch Linked Apps, compare application names and agents, then remove the Deployment Repository.

Existing Application Set references

  • Recognize it: The service contains both appsetConfigs and one or more type: DeploymentRepo manifests.

  • Action: Review the existing pairs. Fetch Linked Apps already uses appsetConfigs, so the Deployment Repository is inactive for that step.

  • Test: Confirm the returned applications, then remove every Deployment Repository manifest.

Git Experience or template-backed service

  • Recognize it: The service has storeType: REMOTE, or its service definition comes from a service template.

  • Action: Change the YAML in the owning git file or template. Do not create an inline copy that will drift from the source.

  • Test: Commit the git change or publish the template version, then run each service that consumes it.

Fetch without GitOps Sync

  • Recognize it: The pipeline runs Update Release Repo, Merge PR, and Fetch Linked Apps, but Argo CD auto-sync performs the cluster rollout.

  • Action: Check whether a downstream expression reads the Fetch Linked Apps output. If nothing consumes it and the selection is unbounded, go to Unbounded selection to remove unused discovery. Otherwise, migrate the service and validate Fetch Linked Apps. The rollout mechanism does not change.

GitOps sync without fetching linked apps

  • Recognize it: GitOps Sync selects applications by name, list, regex, or parent Application without a prior Fetch Linked Apps step.

  • Action: The Deployment Repository does not supply that Sync selection. Remove it if no Fetch Linked Apps step uses it, and confirm the existing Sync inputs remain unchanged.


Apply the migration

Use the interface that owns your service. Every method writes the same service YAML.

Use the UI after you have a confirmed list of AppSet and agent pairs.

  1. In the service definition, add an Application Set reference for each pair:

    • App Set: Exact ApplicationSet metadata.name.

    • Agent: Agent that owns the matching child Applications.

  2. Keep the Deployment Repository in place and save the service. The new references now take precedence in Fetch Linked Apps.

  3. Go to Validate the migration to compare the results.

  4. Once the results match, remove every Deployment Repository manifest. Keep the Release Repository.

If the AppSet does not appear in the selector, do not choose a similar name. Repair or confirm GitOps inventory first. Use the YAML, API, or Terraform method only after you confirm the exact name and agent.

Add appsetConfigs next to manifests. Keep Release Repository and other manifests unchanged:

Apply and validate this intermediate configuration while the Deployment Repository still exists. Once the results match, delete only manifest entries whose type is DeploymentRepo.

For a remote service, commit this change to the git file that owns the service. For a template-backed service, update and publish the template, then test every consuming service.

The public Service API reads and replaces the full service YAML. It does not provide a Deployment Repository migration endpoint or a partial PATCH operation.

Set the identifiers and read the current service:

Edit service.yaml: add the confirmed appsetConfigs, preserve all unrelated fields and Release Repository manifests, and keep the Deployment Repository for the first comparison run.

Build the full update request from the GET response:

Compare the results. Then repeat the GET, edit, and PUT flow to remove type: DeploymentRepo. Always start from a fresh GET so that you do not overwrite a concurrent service change.

The harness_platform_service resource stores the complete service definition in its yaml argument. There is no harness_platform_service_v2 resource and no structured appsetConfigs block.

Before migration:

Once the results match:

If Terraform does not manage the service yet, import it at the correct scope before you add the resource configuration:

Run terraform plan, inspect the complete YAML diff, then run terraform apply. Validate the intermediate configuration before you remove the Deployment Repository from the heredoc.

Do not use harness_platform_gitops_applicationset as a service reference. That resource creates or manages an ApplicationSet CR on an agent; it does not populate serviceDefinition.spec.appsetConfigs.


Handle expressions and runtime inputs

Treat the store as dynamic when the outer store, connector, repository, branch, commit, path, or folder path contains <+...> or a runtime input. A default value does not make a runtime input fixed.

Fixed application set identity

A path can vary while the ApplicationSet identity stays the same. Test every supported input value. If each resolved file has metadata.name: payments and runs on agent-prod, use one fixed reference:

Expression-based identity

This is the closest replacement for a dynamic Deployment Repository. Both appSetIdentifier and agentIdentifier accept Harness expressions and resolve per execution, so one reference resolves to exactly one ApplicationSet and agent in each run, just as the old path resolved to one file.

Use this only when the naming rule holds for every environment and input the service supports. Verify the rule against each one: if an expression resolves to a name that does not exist, the reference returns no applications, and the step reports fewer applications instead of failing.

Configure expression-based references through YAML, the API, or Terraform. The service editor App Set field accepts only fixed values from the ApplicationSets list, and the Agent field accepts fixed values or runtime inputs.

Variable application set identity

When the names follow no single rule, list every known pair:

Because both references apply to every run, set filterByServiceEnvCluster: true on the Fetch Linked Apps step so that the step keeps only the applications that match the current service, environment, and cluster.

Use this option only when every generated Application has the correct Harness service, environment, and cluster references. The filter drops an Application when it cannot match those references. If your ApplicationSet templates do not add that metadata, do not enumerate the pairs. Use one expression-based reference per run or split the service instead.

Unbounded selection

There is no lossless direct mapping when a runtime input can select arbitrary connectors, repositories, entire stores, model names, namespaces, or unknown future files. A floating branch or commit creates the same problem when the selected file can change its metadata.name.

Use this order to decide what to change:

  1. Check whether Fetch Linked Apps has a consumer. Look for a later GitOps Sync step or an expression that reads the Fetch Linked Apps output. If neither exists and Merge PR plus Argo CD auto-sync performs the rollout, remove Fetch Linked Apps and the Deployment Repository together. You do not need appsetConfigs only to preserve unused discovery.

  2. Pass identity instead of location. Replace arbitrary repository and path inputs with explicit appSetName and gitOpsAgent inputs on the pipeline or template. Restrict those inputs through approved input sets, triggers, or allowed values. Use them directly in appSetIdentifier and agentIdentifier.

  3. Use a verified naming rule. If the exact ApplicationSet name and agent can be computed from existing inputs for every run, use one expression-based reference. Test every supported environment, region, and agent.

  4. Split the service. Create a service for each deployment domain when one service can select unrelated repositories, models, ApplicationSets, or agents and no single verified rule produces the pair.

  5. Keep the Deployment Repository until the contract changes. Do not replace it with a snapshot of recent pairs when callers can introduce new values.

Worked example: model and environment select the AppSet file

Consider a path with pipeline variables:

This pattern can reuse one service across model names, environments, namespaces, regions, and agents. Recent runs can show many parent ApplicationSet names across many agents even when the service has no serviceRef labels and the ApplicationSet page has no matching rows.

Do not copy those observed pairs into one static list. Every pair would apply to every run, and service filtering cannot recover the intended subset when the generated Applications lack Harness service and environment references.

Apply the first option that fits:

  1. Remove unused discovery: If no GitOps Sync step or downstream expression consumes the Fetch Linked Apps output, remove Fetch Linked Apps and the Deployment Repository. Keep Update Release Repo and Merge PR unchanged so Argo CD auto-sync continues the rollout.

  2. Make the pair an input: Add explicit ApplicationSet name and agent inputs to the shared pipeline template. Populate them from approved input sets or triggers for each model, environment, and region. Reference those values from appSetIdentifier and agentIdentifier.

  3. Express a complete rule: Use expressions only when the rule produces the exact ApplicationSet metadata.name and agent for every supported combination. A rule based only on modelName is incomplete when the real names also vary by region or agent.

  4. Split the service: Create separate services when callers can introduce arbitrary models or repositories, or when no stable expression maps the inputs to one pair.

Before you remove the Deployment Repository, run one case for each supported environment and agent. Compare the Fetch Linked Apps output with the legacy result. Also test a value that callers must no longer use and confirm that the new input contract rejects it.


Validate the migration

The Fetch Linked Apps step lists the applications it discovered in its step output. That list is what you compare. Run the same pipeline with the same inputs before and after the change, and check that the same applications appear.

  1. Record a baseline. With the Deployment Repository still active, run the pipeline and open the Fetch Linked Apps step output. Note every application name and its agent. Repeat for each environment or runtime input the service supports.

  2. Add the references. Save the service with both appsetConfigs and the Deployment Repository present. Fetch Linked Apps now uses the references.

  3. Run the same inputs again and compare. The application and agent pairs in the step output should match the baseline exactly. More applications than the baseline usually means references for another environment are being included, so revisit Handle expressions and runtime inputs. Fewer usually means a missing agent or an ApplicationSet name that does not exist.

  4. Remove the Deployment Repository. Delete every manifest whose type is DeploymentRepo, keep the Release Repository, and run the pipeline once more.

Before you call the migration complete, confirm that the step output matches the baseline for every supported input, that Sync or Argo CD auto-sync behavior is unchanged, and that no DeploymentRepo manifest remains on the service.


Understand behavior after migration

  • No delegate for discovery: Fetch Linked Apps no longer runs a delegate task. It resolves applications from the service configuration, so its delegate selectors no longer affect discovery. Other steps, such as Update Release Repo and Merge PR, still need a delegate.

  • Explicit agent scope: The legacy path returned children for the resolved ApplicationSet name across all agents. The new path returns children only for the agents named in appsetConfigs.

  • Every reference applies to every run: The step combines the results of all references on the service. Select Filter applications per configured service/env when you need a per-run subset limited to the pipeline service, environment, and cluster.

  • No location-only lookup: A reference must provide the ApplicationSet name, or an expression that produces it. It cannot discover a name from a git file or folder location alone.


Deployment Repository removal

After October 4, 2026, the Deployment Repository manifest is removed, and pipelines that still depend on it fail loudly instead of changing behavior silently:

  • Fetch Linked Apps fails with an explicit error. A run whose service still relies on a Deployment Repository fails the step with an error that directs you to migrate to Application Set references, and the pipeline stops at that step unless you have configured a custom failure strategy.

  • No silent fallback. The step does not degrade to a partial or different set of applications. A pipeline that used to sync a group of ApplicationSet-generated applications does not start syncing a smaller set or a single application; it fails until you migrate the service.

  • Other steps do not read the Deployment Repository. Update Release Repo, Merge PR, and GitOps Sync are unaffected by the removal itself, but a failed Fetch Linked Apps step still prevents later steps in the stage from running under the default failure strategy.

Migrate each service before the deprecation date so that your pipelines keep working without interruption.


Next steps

Last updated

Was this helpful?