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.
Deployment Repository is being deprecated
The Deployment Repository manifest on GitOps services is being deprecated and will stop working on October 4, 2026. If your service still uses a Deployment Repository, follow this guide to migrate to Application Set references before then so that Fetch Linked Apps and PR 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
How to choose the right migration path for your service
How to identify Application Set names and agents from git or from live GitOps inventory
How to apply the migration through the UI, YAML, the API, or Terraform
How to handle expressions and runtime inputs when the Deployment Repository store is dynamic
How to validate the migration and what happens after Deployment Repository removal
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
Use the Application Set name, not the file name
Fetch Linked Apps historically read the first YAML file from the Deployment Repo (paths[0] or the first file under folderPath) and used metadata.name. Always migrate that name. A path like foo.yaml that declares metadata.name: payments must become appSetIdentifier: payments.
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.
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.
Read
metadata.name. Open the resolved file and copy the ApplicationSetmetadata.name. Do not derive the name from the file name.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/serviceReflabels to discover the mapping. Older or custom templates may omit those labels.
Create one pair per agent. If
paymentshas child Applications onagent-usandagent-eu, add two references with the sameappSetIdentifierand differentagentIdentifiervalues.
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.
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.
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
appsetConfigsand one or moretype: DeploymentRepomanifests.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.
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.
Keep the Deployment Repository in place and save the service. The new references now take precedence in Fetch Linked Apps.
Go to Validate the migration to compare the results.
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.
Every reference applies to every run
With a Deployment Repository, the path could be an expression such as <+env.identifier>/appset.yaml. Each pipeline run resolved that expression once, using that run's variables, and fetched exactly one file, so the run itself chose the ApplicationSet:
A run deploying to
devresolved the path todev/appset.yaml, which definedpayments-dev.A run deploying to
prodresolved the same path toprod/appset.yaml, which definedpayments-prod.
Application Set references do not work that way. Fetch Linked Apps queries every reference on the service and returns the combined result. If you migrate by listing every identity the path could ever resolve to (the superset of all resolutions), then:
Both
payments-devandpayments-prodapply to every run, whichever environment you deploy to.A
devrun also fetches theprodapplications, and aprodrun also fetches thedevapplications.A downstream GitOps Sync step would sync applications for environments the run did not target.
To preserve the old per-run behavior, put the expression on the reference itself instead of listing the superset. Both appSetIdentifier and agentIdentifier accept Harness expressions and resolve per execution, so a single reference resolves to exactly one ApplicationSet and agent in each run, the same resolution the dynamic path used to perform:
When the identity follows no such rule, enumerate the pairs and set filterByServiceEnvCluster: true on the Fetch Linked Apps step so each run keeps only the applications that match its own service, environment, and cluster. Go to Variable application set identity.
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:
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
appsetConfigsonly to preserve unused discovery.Pass identity instead of location. Replace arbitrary repository and path inputs with explicit
appSetNameandgitOpsAgentinputs on the pipeline or template. Restrict those inputs through approved input sets, triggers, or allowed values. Use them directly inappSetIdentifierandagentIdentifier.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.
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.
Keep the Deployment Repository until the contract changes. Do not replace it with a snapshot of recent pairs when callers can introduce new values.
No lossless snapshot
A list of pairs observed in recent runs does not cover values that have never run. Do not remove the Deployment Repository until the supported input domain is explicit and every value has a replacement.
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.
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.
Add the references. Save the service with both
appsetConfigsand the Deployment Repository present. Fetch Linked Apps now uses the references.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.
Remove the Deployment Repository. Delete every manifest whose
typeisDeploymentRepo, 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
Go to GitOps services to review service configuration.
Go to GitOps PR pipelines to review Fetch Linked Apps and Sync behavior.
Go to ApplicationSet basics to review ApplicationSet concepts.
Last updated
Was this helpful?