-
Notifications
You must be signed in to change notification settings - Fork 1
Description
Feature Request: Auto-link resources by name for PM-in-UI workflows
Summary
When Product Managers create events/categories in the RudderStack UI and engineers use the CLI to manage tracking plans, there's significant friction due to the requirement for explicit metadata.import stanzas with remote_id mappings. This creates maintenance burden and error-prone manual steps.
Current Workflow
Our team follows this workflow:
- PM creates events/categories in the RudderStack staging UI
- Engineer imports using
rudder-cli import workspace - Engineer manually adds
metadata.importsections withremote_idmappings to link local definitions to remote resources - Engineer pushes to git
- GitHub Action applies to production on merge
The Problem
Resources created in the UI don't have external_id set, so the CLI treats them as "invisible" when loading remote state:
// category.go line 170
categories, err := p.client.GetCategories(ctx, catalog.ListOptions{HasExternalID: lo.ToPtr(true)})This means engineers must:
- Run
import workspaceto get resources into animported/directory - Manually copy
remote_idvalues from imported files - Add
metadata.import.workspacesstanzas to their existing files - For each workspace (staging, production), repeat this process with different
remote_idvalues
Example of the friction
A simple category import requires this boilerplate:
metadata:
name: event-categories
import:
workspaces:
- workspace_id: "STAGING_WORKSPACE_ID"
resources:
- local_id: "canvas"
remote_id: "cat_3xxxxxxxxxxxxexxxxxxxxxxxx"
- workspace_id: "PRODUCTION_WORKSPACE_ID"
resources:
- local_id: "canvas"
remote_id: "cat_DIFFERENT_PROD_ID"This scales linearly - every PM-created resource needs entries for every workspace.
Error we encounter without this
Error: syncing the state: creating category resource in upstream catalog:
sending request: http status code: 400, error code: '',
error: 'Category with name Canvas already exists'
Proposed Solutions
Option 1: --match-by-name flag (Recommended)
Add a flag to apply that enables name-based matching for resources without external_id:
rudder-cli tp apply -l . --match-by-nameBehavior:
- When a local resource doesn't exist in remote state (no matching
external_id) - AND a remote resource with the same
nameexists (withoutexternal_id) - Prompt user: "Found existing 'Canvas' category. Link and set external_id? [y/n]"
- If yes, perform an import operation instead of create
Option 2: --auto-link flag with interactive confirmation
rudder-cli tp apply -l . --auto-link
# Output:
# The following resources exist remotely but aren't linked:
# - category:canvas (remote: cat_37tIcdNnXjm90UeONAx737RgfJm)
# - event:canvas-project-created (remote: ev_37tL0Edtrdzhz8TWoXm1Jj9Y5Hh)
#
# Link these resources? [y/n]Option 3: Import-and-merge mode
rudder-cli import workspace -l . --mergeInstead of writing to imported/ directory, automatically:
- Match imported resources to existing local definitions by
id - Add/update
metadata.importsections in-place - Report what was merged
Option 4: Workspace-agnostic external_id
If the CLI set external_id on resources at creation time AND the UI also set external_id, resources would be trackable across both interfaces without explicit mappings.
Environment
- CLI Version: 0.11.2
- Workflow: PM creates in staging UI → Engineer imports → GitHub Action applies to production
Workaround
Currently we:
- Temporarily remove new resources from local files
- Run
import workspace - Copy
remote_idvalues from imported files - Restore local files with added
metadata.importstanzas - Repeat for each workspace
This is error-prone and doesn't scale.
Impact
- Developer time: ~10-15 minutes per resource for the import dance
- Error prone: Manual copy-paste of UUIDs
- Maintenance burden: Import stanzas grow linearly with resources × workspaces
- Onboarding friction: New engineers struggle with this non-obvious workflow
Related
- The
HasExternalID: truefilter inLoadResourcesFromRemotemethods is the root cause - Name-based matching would need collision handling (prompt user if ambiguous)