Automatically set relations between entities with automation
This guide demonstrates how to set up an automation in Port that automatically creates relations between entities. We will use a specific example of automatically linking new service entities to their owning teams based on GitHub repository metadata.
Once implemented, when a new service entity is created with a repository relation, the automation will automatically link it to the appropriate team based on the GitHub organization name.
Common use casesโ
- Team ownership: Automatically link services to their owning team based on repository metadata
- Environment mapping: Connect deployments to their target environments based on branch names or tags
- Service dependencies: Link services to their dependencies based on configuration files or API calls
- Infrastructure relationships: Connect cloud resources to the services that consume them based on tags or naming conventions
Prerequisitesโ
This guide assumes the following:
- You have a Port account and have completed the onboarding process.
- Port's GitHub app is installed in your account.
- You have setup automatic discovery between the serviceandrepositoryblueprints.
- Permissions to create and edit Port automations.
Set up data modelโ
After completing the onboarding process, you should have both a service blueprint and a team blueprint.
If you have installed the GitHub app, you should have a repository blueprint and
your service blueprint should have a repository relation.  Now we need to add a relation between the service and the team blueprints.
Add team relation to the service blueprint
- 
Go to your Builder page. 
- 
Find and click on the Serviceblueprint.
- 
Click on New relation.
- 
Fill out the form: - Title: Owning Team
- Identifier: owning_team
- Target Blueprint: Team
- Limit: 1 entity
- Required: False
 
- Title: 
- 
Click Createto add the relation.
Set up the automationโ
Now let's create an automation that automatically sets the team relation when a service is created.
- 
Go to the Automations page in your portal. 
- 
Click on + Automationto create a new automation.
- 
Copy and paste the following JSON structure for your automation: Auto-assign service owner (Click to expand){
 "identifier": "auto_assign_service_owner",
 "title": "Auto-assign Service Owner",
 "description": "Automatically assigns services to teams based on repository owner",
 "trigger": {
 "type": "automation",
 "event": {
 "type": "ENTITY_CREATED",
 "blueprintIdentifier": "service"
 },
 "condition": {
 "type": "JQ",
 "expressions": [
 ".diff.after.relations.repository != null"
 ],
 "combinator": "and"
 }
 },
 "invocationMethod": {
 "type": "UPSERT_ENTITY",
 "blueprintIdentifier": "service",
 "mapping": {
 "identifier": "{{ .event.diff.after.identifier }}",
 "title": "{{ .event.diff.after.title }}",
 "properties": {},
 "relations": {
 "repository": "{{ .event.diff.after.relations.repository }}",
 "owning_team": "{{ .event.diff.after.relations.repository | split(\"_\") | .[0] | split(\"/\") | .[1] | gsub(\"-\"; \"_\") }}"
 }
 }
 },
 "publish": true
 }
- 
Click Saveto create the automation.
How the automation worksโ
When a service entity is created with a repository relation, the automation will:
- 
Extract the GitHub organization from the repository identifier (e.g., myorganization/acme-corp_my-serviceโacme_corp)
- 
Automatically set the owning_teamrelation toacme_corp(assuming you have a team with that identifier)
- 
The service is now linked to its owning team 
The automation uses this JQ expression to extract the team name:
.event.diff.after.relations.repository | split("_") | .[0] | split("/") | .[1] | gsub("-"; "_")
This expression works as follows:
- 
split("_")splitsmyorganization/acme-corp_my-serviceโ["myorganization/acme-corp", "my-service"]
- 
.[0]takes the first part โ"myorganization/acme-corp"
- 
split("/")splits that โ["myorganization", "acme-corp"]
- 
.[1]takes the second part โ"acme-corp"
- 
gsub("-"; "_")converts hyphens to underscores โ"acme_corp"
This automation assumes your team identifiers use underscores and match your GitHub organization names, and that repository identifiers follow the pattern username/organization_repository-name. If your naming convention is different, you'll need to adjust the JQ expression in the owning_team mapping accordingly.
Customizationsโ
You can customize this automation to fit your specific naming conventions:
Different repository patterns
- 
If your repository naming convention uses dashes instead of underscores: "owning_team": "{{ .event.diff.after.relations.repository | split(\"-\") | .[0] | split(\"/\") | .[1] | gsub(\"-\"; \"_\") }}"
- 
If your GitHub organization name preserves hyphens (no conversion to underscores): "owning_team": "{{ .event.diff.after.relations.repository | split(\"_\") | .[0] | split(\"/\") | .[1] }}"
- 
If your team names have regional suffixes (e.g., acme-corp-regionโacme_corp_region):"owning_team": "{{ .event.diff.after.relations.repository | split(\"_\") | .[0] | split(\"/\") | .[1] | gsub(\"-\"; \"_\") }}"
- 
If your team names have role-based suffixes (e.g., rnd-taskforceโrnd_taskforce):"owning_team": "{{ .event.diff.after.relations.repository | split(\"_\") | .[0] | split(\"/\") | .[1] | gsub(\"-\"; \"_\") }}"
- 
If your team names are complex with multiple segments (e.g., rnd-developer-team-productโrnd_developer_team_product):"owning_team": "{{ .event.diff.after.relations.repository | split(\"_\") | .[0] | split(\"/\") | .[1] | gsub(\"-\"; \"_\") }}"
Team suffix patterns
If your team identifiers include a suffix like "_team":
"owning_team": "{{ (.event.diff.after.relations.repository | split(\"_\") | .[0] | split(\"/\") | .[1] | gsub(\"-\"; \"_\")) + \"_team\" }}"
Additional conditions
To ensure the automation only runs when the service doesn't already have an owner:
"condition": {
  "type": "JQ",
  "expressions": [
    ".diff.after.relations.repository != null",
    ".diff.before.relations.owning_team == null"
  ],
  "combinator": "and"
}
Additional examplesโ
Here are more examples of automations that automatically set relations between entities:
Environment-based deployment relationships
Link deployments to environments based on branch names (Click to expand)
{
  "identifier": "link_deployment_to_environment",
  "title": "Link Deployment to Environment",
  "description": "Automatically links deployments to environments based on branch name",
  "trigger": {
    "type": "automation",
    "event": {
      "type": "ENTITY_CREATED",
      "blueprintIdentifier": "deployment"
    },
    "condition": {
      "type": "JQ",
      "expressions": [
        ".diff.after.properties.branch != null"
      ],
      "combinator": "and"
    }
  },
  "invocationMethod": {
    "type": "UPSERT_ENTITY",
    "blueprintIdentifier": "deployment",
    "mapping": {
      "identifier": "{{ .event.diff.after.identifier }}",
      "title": "{{ .event.diff.after.title }}",
      "properties": {},
      "relations": {
        "environment": "{{ if (.event.diff.after.properties.branch | test(\"^main$|^master$\")) then \"production\" elif (.event.diff.after.properties.branch | test(\"^develop$|^dev$\")) then \"development\" elif (.event.diff.after.properties.branch | test(\"^staging$|^stage$\")) then \"staging\" else \"development\" end }}"
      }
    }
  },
  "publish": true
}
Cloud resource to service mapping
Link AWS resources to services based on tags (Click to expand)
{
  "identifier": "map_aws_resources_to_services",
  "title": "Map AWS Resources to Services",
  "description": "Links AWS resources to services based on the 'service' tag",
  "trigger": {
    "type": "automation",
    "event": {
      "type": "ENTITY_CREATED",
      "blueprintIdentifier": "awsResource"
    },
    "condition": {
      "type": "JQ",
      "expressions": [
        ".diff.after.properties.tags != null",
        ".diff.after.properties.tags | has(\"service\")"
      ],
      "combinator": "and"
    }
  },
  "invocationMethod": {
    "type": "UPSERT_ENTITY",
    "blueprintIdentifier": "awsResource",
    "mapping": {
      "identifier": "{{ .event.diff.after.identifier }}",
      "title": "{{ .event.diff.after.title }}",
      "properties": {},
      "relations": {
        "consumingService": "{{ .event.diff.after.properties.tags.service }}"
      }
    }
  },
  "publish": true
}
Conclusionโ
By leveraging Port's automation capabilities, you can create a self-maintaining software catalog that automatically establishes relationships between entities. This approach saves time, ensures consistency, reduces errors, and scales effortlessly to handle hundreds or thousands of entities automatically.
Start with simple property-based mappings and gradually implement more sophisticated logic as your needs grow.