Skip to main content

Check out Port for yourselfΒ 

Enrich services using GitOps

This guide will walk you through the process of enriching a service in Port using Gitops.
In practice, this can be used by developers to independently add additional valuable data to their services in Port.

Common use cases​

  • Developers can enrich their services without needing to nag devops engineers.
  • Platform engineers can create RBAC-controlled actions for developers, empowering their independence.
  • R&D managers can track additional, valuable data about services in the organization.

Prerequisites​

  • A Port account with permissions to create self-service actions.
  • The Git Integration that is relevant for you needs to be installed.
  • Automatic discovery of services using git as source of truth is set up.
  • A repository in your Git provider in which you can create a workflow/pipeline. If you don't have one, we recommend creating a new repository named Port-actions.

Set up data model​

To support GitOps-based repository enrichment in your portal, we will add two new properties to the existing service blueprint, and create a new Domain blueprint that groups related services together.

Let's add the following properties to track important metadata about our services:

  • A Type property to classify services (e.g., microservice, library, CLI)
  • A Lifecycle property to track development stages (development, staging, production)

Add new properties to the service blueprint​

  1. Go to your Builder, expand the service blueprint, and click on New property.

  2. The first property will be the service Type, chosen from a predefined list of options. Fill out the form like the example below, and click Create:

  3. The second property will be the lifecycle state of the service, also chosen from a predefined list of options. Fill out the form like the example below, and click Create:

    Note the colors of the inputs, this will make it easier to see a repository's lifecycle in your catalog 😎

Create a Domain blueprint​

To group services by business or functional areas, let's define a Domain blueprint:

  1. In your Builder, click on the + Blueprint button:

  2. Click on the Edit JSON button in the top right corner, replace the content with the following definition, then click Create:

    Blueprint JSON (click to expand)
    {
    "identifier": "domain",
    "title": "Domain",
    "icon": "TwoUsers",
    "schema": {
    "properties": {
    "architecture": {
    "title": "Architecture",
    "type": "string",
    "format": "url",
    "spec": "embedded-url"
    }
    },
    "required": []
    },
    "mirrorProperties": {},
    "calculationProperties": {},
    "relations": {}
    }

Connect services to domains​

Now that we have a blueprint to represent a domain, let's connect it to our services. We will do this by adding a relation to the service blueprint:

  1. Go to your Builder, expand the service blueprint, and click on New relation:

  2. Fill out the form like this, then click Create:



Create domains via Gitops​

Now that we have a Domain blueprint, we can create some domains in Port. This can be done manually from the UI, or via Gitops which is the method we will use in this guide.

  1. In your Port-actions (or equivalent) Github repository, create a new file named port.yml in the root directory, and use the following snippet as its content:

    port.yml (click to expand)
    - identifier: payment
    title: Payment
    blueprint: domain
    properties:
    architecture: https://lucid.app/documents/embedded/c3d64493-a5fe-4b18-98d5-66d355080de3
    - identifier: shipping
    title: Shipping
    blueprint: domain
    properties:
    architecture: https://lucid.app/documents/embedded/c3d64493-a5fe-4b18-98d5-66d355080de3
  2. Head back to your software catalog, you will see that Port has created two new domain entities:

The architecture property is a URL to a Lucidchart diagram. This is a handy way to track a domain's architecture in your software catalog.


Create an action to enrich services​

As platform engineers, we want to enable our developers to perform certain actions on their own. Let's create an action that developers can use to add data to a service, and allocate it to a domain.

  1. Head to the Self-service page of your portal.

  2. Click on the + Action button in the top-right corner :

  3. Fill the basic form with the following:

    • Title: Enter Enrich Service

    • Identifier Toggle the switch icon off and type a service_enrich_service

    • Description: Enter the description (e.g., Enrich service with data.)

    • Icon: Type Microservice and choose the Icon (optional)

    • Operation: Choose Day-2 from the dropdown

    • Blueprint: Choose Service from the dropdown


  4. Click on Next, and add the Domain input:

    • Click on + Input.

    • Enter the Title Domain.

    • Select the Type Entity selection.

    • Add the Description (optional).

    • Set Required to True.

    • Select Domain as the Blueprint

    • Click on the Create button.




      Entity selection input type

      The Entity selection type allows the executing user to choose an entity directly from the catalog.

  5. Click on + Input again to add the Type input:

    • Enter the Title Type.

    • Select the Type Select.

    • Add the Options frontend, backend, library.

    • Add the Description (optional).

    • Set Required to True.

    • Click on the Create button.




  6. Click on + Input one more time to add the Lifecycle input:

    • Enter the Title Lifecycle.

    • Select the Type Select.

    • Add the Options Production, Experimental, Deprecated.

    • Add the Description (optional).

    • Set Required to True.

    • Click on the Create button.




  7. Click on Next to configure the Backend.

Define backend type​

Now we'll define the backend of the action. Port supports multiple invocation types, for this tutorial we will use a Github workflow, a GitLab pipeline, or a Jenkins pipeline (choose this option if you are using Bitbucket).

Note that you will need to have Port's Github app installed in your Github organization (the one that contains the repository you'll work with).
Follow these steps to setup the backend:

  1. Select Run Github Workflow as the invocation type.

  2. Fill out the form with your values:

    • Replace the Organization and Repository values with your values (this is where the workflow will reside and run).

    • Name the workflow port-enrich-service.yml.

    • Fill out your workflow details:

    • Scroll down to the Configure the invocation payload section.
      This is where you can define which data will be sent to your backend each time the action is executed.

      For this example, we will send some details that our backend needs to know - the user inputs, the entity, and the id of the action run.
      Copy the following JSON snippet and paste it in the payload code box:

      {
      "port_context": {
      "entity": "{{ .entity.identifier }}",
      "runId": "{{ .run.id }}"
      },
      "domain": "{{ .inputs.domain.identifier }}",
      "type": "{{ .inputs.type }}",
      "lifecycle": "{{ .inputs.lifecycle }}"
      }

The last step is customizing the action's permissions. For simplicity's sake, we will use the default settings. For more information, see the permissions page. Click Create.

Setup the action's backend​

Our action will create a pull-request in the repository, containing a port.yml file that will add data to the repository in Port. Choose a backend type below to setup the workflow:

  1. First, let's create the necessary token and secrets. If you've already completed the scaffold a new service guide, you should already have these configured and you can skip this step.

    • Go to your Github tokens page, create a personal access token with repo and admin:org scope, and copy it (this token is needed to create a pull-request from our workflow).

    • Go to your Port application, click on the ... in the top right corner, then click Credentials. Copy your Client ID and Client secret.

  2. In your Port-actions (or equivalent) Github repository, create 3 new secrets under Settings->Secrets and variables->Actions:

    • ORG_ADMIN_TOKEN - the personal access token you created in the previous step.
    • PORT_CLIENT_ID - the client ID you copied from your Port app.
    • PORT_CLIENT_SECRET - the client secret you copied from your Port app.



We will now create a YML file that will serve as a template for our repository's port.yml configuration file.

  • In your repository, create a file named enrichService.yml under /templates/ (its path should be /templates/enrichService.yml).
  • Copy the following snippet and paste it in the file's contents:
enrichService.yml (click to expand)
# enrichService.yml

- identifier: "{{ service_identifier }}"
blueprint: service
properties:
type: "{{ service_type }}"
lifecycle: "{{ service_lifecycle }}"
relations:
domain: "{{ domain_identifier }}"

Now let's create the file that contains our logic:

In the same repository, under .github/workflows, create a new file named port-enrich-service.yml and use the following snippet as its content:

Github workflow (click to expand)
name: Enrich service
on:
workflow_dispatch:
inputs:
port_context:
required: true
description: Includes the entity identifier and the action's run id
domain:
required: true
description: The domain to assign the service to
type: string
type:
required: true
description: The type of the service
type: string
lifecycle:
required: true
description: The lifecycle state of the service
type: string
jobs:
enrichService:
runs-on: ubuntu-latest
steps:
# Checkout the workflow's repository
- uses: actions/checkout@v4

# Extract repository name
- name: Extract repository name
id: repo-name
run: |
entity="${{ fromJson(inputs.port_context).entity }}"
repo_name=${entity#*/} # Remove everything before the first '/'
echo "repo_name=$repo_name" >> $GITHUB_OUTPUT

# Checkout the service's repository
- uses: actions/checkout@v4
with:
repository: "${{ github.repository_owner }}/${{ steps.repo-name.outputs.repo_name }}"
path: ./targetRepo
token: ${{ secrets.ORG_ADMIN_TOKEN }}

- name: Copy template yml file
run: |
cp templates/enrichService.yml ./targetRepo/port.yml

- name: Update new file data
run: |
sed -i "s|{{ service_identifier }}|${{ fromJson(inputs.port_context).entity }}|" ./targetRepo/port.yml
sed -i "s|{{ domain_identifier }}|${{ inputs.domain }}|" ./targetRepo/port.yml
sed -i "s|{{ service_type }}|${{ inputs.type }}|" ./targetRepo/port.yml
sed -i "s|{{ service_lifecycle }}|${{ inputs.lifecycle }}|" ./targetRepo/port.yml

- name: Open a pull request
uses: peter-evans/create-pull-request@v5
with:
token: ${{ secrets.ORG_ADMIN_TOKEN }}
path: ./targetRepo
commit-message: Enrich service - ${{ fromJson(inputs.port_context).entity}}
committer: GitHub <noreply@github.com>
author: ${{ github.actor }} <${{ github.actor }}@users.noreply.github.com>
signoff: false
branch: add-port-yml
delete-branch: true
title: Create port.yml - ${{ fromJson(inputs.port_context).entity }}
body: |
Add port.yaml to enrich service in Port.
draft: false

- name: Create a log message
uses: port-labs/port-github-action@v1
with:
clientId: ${{ secrets.PORT_CLIENT_ID }}
clientSecret: ${{ secrets.PORT_CLIENT_SECRET }}
baseUrl: https://api.getport.io
operation: PATCH_RUN
runId: ${{ fromJson(inputs.port_context).runId }}
logMessage: Pull request to add port.yml created successfully for service "${{ fromJson(inputs.port_context).entity }}" πŸš€
Selecting a Port API URL by account region

The baseUrl, port_region, port.baseUrl, portBaseUrl, port_base_url and OCEAN__PORT__BASE_URL parameters are used to select which instance or Port API will be used.

Port exposes two API instances, one for the EU region of Port, and one for the US region of Port.


The action is ready to be executed πŸš€

Execute the action​

  1. After creating an action, it will appear under the Self-service page. Find your new Enrich service action, and click on Execute.

  2. Choose a service from the dropdown, a domain to assign it to, and any values for its type and lifecycle, then click Execute:

  3. Click on the running actions icon on the top right conner to view running actions.:


  4. Head over to your repository, you will see that a new pull-request was created:

    This page provides details about the action run. We can see that the backend returned Success and the pull-request was created successfully.

  5. Merge the pull-request, then head back to your software catalog.

  6. Find your service, and click on its identifier. This will take you to the service's entity page, where you can see your new properties populated with data:


Possible enhancements​

  • More Custom Properties: Add extra fields (e.g., repository owner, security posture) to your Repository blueprint.
  • Sentry or Other Integrations: Fetch data from tools like Sentry or Jira and reflect it in your software catalog automatically.
  • Customized GitOps Templates: Adjust the enrichRepository.yml file for more complex updatesβ€”e.g., adding environment variables, custom tags, or even provisioning logic.
  • Advanced RBAC: Limit who can run the "Enrich repository" action or which properties certain teams can modify.
  • Multi-step Workflows: Chain additional steps to notify Slack, create a Jira ticket, or update other systems before merging.

Conclusion​

Gitops is a common practice in modern software development, as it ensures that the state of your infrastructure is always in sync with your codebase.
Port allows you to easily integrate your Gitops practices with your software catalog, reflecting the state of your infrastructure, and allowing you to empower your developers with controlled actions.

More guides & tutorials will be available soon, in the meantime feel free to reach out with any questions via our community slack or Github project.