> For the complete documentation index, see llms.txt.
Skip to main content

Check out Port for yourself ➜ 

Connect GitHub CODEOWNERS with Repository, Team & User

Implement with AI

Send this guide to your coding agent.

Prerequisite: Install Port MCP

Open plan mode. Implement this Port guide in my org via MCP:

https://docs.port.io/guides/all/connect-github-codeowners-with-service-team-and-user/

Goal: get the guide's core flow working end-to-end in my org; adapting it to fit my existing setup takes priority over matching the guide 1:1.

Plan:
1. Confirm MCP is connected, in the right org, with sufficient permissions.
2. Diff the guide's data model (blueprints, properties, relations, actions, agents, automations, integrations, secrets) against mine.
3. Propose adaptations for gaps, reusing existing blueprints/relations over guide-named duplicates.
4. Flag what needs a UI click, credential, or secret from me, testing MCP capability empirically before ruling anything out.
5. Stop on any blocker and give me options. Approving this plan authorizes the writes it lists; pause only for writes beyond what's listed.

Build:
- Extend blueprint schema additively when upserting; don't remove or overwrite existing properties, and treat type conflicts as a blocker, not an auto-fix.
- List any mock data in the plan, minimal and labeled mock; once approved, seed it without re-asking, and tell me what you seeded.
- For anything the guide writes downstream (e.g. a webhook target), use a real entity, not a mock.
- For pages/widgets, use the real page identifier from the app URL, not a guessed slug.
- When you hit a UI step confirmed (not assumed) unsupported via MCP, pause, give exact clicks, then resume via MCP.
- Validate and give links after each meaningful step (only a tool-returned URL, no guessed paths); don't proceed if the last run wasn't a success.

Done:
- Confirm the guide's expected output exists and runs in Port.
- Summarize adaptations, seeded data, what was mocked or skipped, remaining UI steps, and how to verify.

This guide demonstrates how to map CODEOWNERS files in GitHub to their respective repositories, teams and users in Port using the built-in User and Team blueprints.

Prerequisites

Default GitHub blueprints

Once you install GitHub Ocean, the following blueprints will be automatically created in your data model: Repository, Pull Request, Github User, Github Team.

Set up data model

First, let's create the necessary blueprint to store the Codeowners data, then we will set up the mapping configuration.

Create the Codeowners blueprint

To add the CODEOWNERS blueprint:

  1. Navigate to your data model page in Port.

  2. Click on the + Blueprint button.

  3. Click on the Edit JSON button.

  4. Copy the following definition and paste it in the editor, then click Save:

    CODEOWNERS blueprint (Click to expand)
    {
    "identifier": "githubCodeowners",
    "description": "This blueprint represents a CODEOWNERS file in a service",
    "title": "Github Codeowners",
    "icon": "Github",
    "schema": {
    "properties": {
    "location": {
    "type": "string",
    "title": "File location",
    "description": "File path to CODEOWNERS file"
    },
    "scope": {
    "icon": "DefaultProperty",
    "type": "string",
    "title": "Scope",
    "description": "The scope which the user/team owns."
    }
    },
    "required": []
    },
    "mirrorProperties": {},
    "calculationProperties": {},
    "aggregationProperties": {},
    "relations": {
    "users": {
    "title": "Users",
    "target": "_user",
    "required": false,
    "many": true
    },
    "teams": {
    "title": "Teams",
    "target": "_team",
    "required": false,
    "many": true
    },
    "repository": {
    "title": "Repository",
    "description": "The repository which the CODEOWNERS file resides in",
    "target": "githubRepository",
    "required": true,
    "many": false
    }
    }
    }

Set up mapping configuration

  1. Go to the data sources page in Port.

  2. Under Exporters, click on your installed GitHub ocean integration.

  3. A window will open containing the default YAML configuration of your GitHub ocean integration.

  4. In the bottom-left corner you can modify the configuration to suit your needs, by adding/removing entries.

  5. Copy the following configuration and paste it in the editor, then click Save & Resync:

    CODEOWNERS mapping configuration (Click to expand)
    resources:
    - kind: file
    selector:
    query: .repository.archived == false
    files:
    - path: '**/.github/CODEOWNERS'
    organization: my-org # Optional if githubOrganization is set (required if not set)
    # repos: # Optional: omit to scan all repos
    # - name: my-repo
    # branch: main
    port:
    itemsToParse: >-
    (. as $root | .content | split("\n") | map(trim) |
    map(select((test("^[[:space:]]*#") | not) and (length > 0))) | map(
    (split(" ") | map(select(length > 0))) as $tokens
    | {
    scope: ($tokens[0]),
    # Replacing ** and * characters since the identifier can't contain special characters
    identifier: ($tokens[0]
    | gsub("\\*\\*"; "doublestar")
    | gsub("\\*"; "star")),
    # Extracting users and teams to their respective arrays
    users: (
    $tokens[1:]
    | map(select(contains("/") | not)
    | gsub("@" ; "")
    )
    ),
    teams: (
    $tokens[1:]
    | map(select(test("^@[^ ]+/[^ ]+$"))
    | split("/")
    | .[-1]
    ))
    }
    )
    )
    entity:
    mappings:
    identifier: .repository.full_name + "_" +.item.identifier + "_codeowners"
    title: .item.scope + " codeowners"
    blueprint: '"githubCodeowners"'
    properties:
    scope: .item.scope
    location: .path
    relations:
    repository: .repository.full_name
    teams:
    combinator: '''and'''
    rules:
    - property: '"$title"'
    value: .item.teams
    operator: '"in"'
    users:
    combinator: '''and'''
    rules:
    - property: '"git_hub_username"'
    value: .item.users
    operator: '"in"'

Ocean differences

GitHub (Ocean) uses .content instead of .file.content for file content, and .path instead of .file.path. The repository relation uses .repository.full_name. Add organization and repos to the file selector to scope which repositories are scanned.

Example

For the following CODEOWNERS file example:

CODEOWNERS file example (Click to expand)
# Default owner for all files in the repo
* @sivanelk97 @sivan27

# Backend ownership
/backend/ @sivanelk97 @sivan-org/backend-team @sivan-org/docs-team

# Frontend ownership (multiple owners)
/frontend/ @sivanelk97

# Specific file
/README.md @sivanelk97

# JavaScript files in any folder
**/*.js @sivanelk97

# Terraform files anywhere
**/*.tf @sivanelk97

# CI/CD workflows
.github/workflows/ @sivanelk97

# Config files named 'config.yaml' in any folder
**/config.yaml @sivanelk97

# Markdown documentation files
*.md @sivanelk97 @sivan27 @sivan-org/docs-team

The context lake Codeowners page should display the corresponding Codeowners entities:

GitHub Codeowners catalog with users and teams