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

Check out Port for yourself ➜ 

Enforce code maturity with GitLab file search

Implement with AI

Send this guide to your coding agent.

Prerequisite: Install Port MCP

Open plan mode if your tool supports it; otherwise present the plan below filled in and wait for my approval. Implement this Port guide in my org via MCP:

https://docs.port.io/guides/all/track-gitlab-project-maturity-with-scorecards

Read the raw markdown version at https://docs.port.io/guides/all/track-gitlab-project-maturity-with-scorecards.md - it contains every tab and code block without page markup.

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. If the guide offers alternative implementation paths (tabs), pick the one matching my installed integrations and tools, confirm it with me, and implement only that path.
3. Diff the guide's data model (blueprints, properties, relations, workflows, actions, agents, automations, integrations, webhook data sources, secrets) against mine.
4. Propose adaptations for gaps, reusing existing blueprints/relations over guide-named duplicates.
5. Flag what needs a UI click, credential, or secret from me, testing MCP capability empirically before ruling anything out. If the guide has a "Set up via API" section, use it for anything MCP can't do before treating a step as UI-only.
6. 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.
- Never print secret values into the chat or logs; ask me to set them in Port, or write them via the secrets API without echoing them back.
- 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 and not covered by the guide's API sections, 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:
- Run the guide's "Let's test it" steps where possible (e.g. execute a workflow test run) and confirm the expected output exists in Port.
- Summarize adaptations, seeded data, what was mocked or skipped, remaining UI steps, and how to verify.

Code maturity standards help teams to consistently follow engineering best practices like testing, linting, documentation, and CI. By tracking these signals with Port scorecards via GitLab file search, teams can monitor compliance, guide maturity, and reduce production risk.

This guide demonstrates how to set up a GitLab integration that uses file search to detect the presence of key configuration files (like .gitlab-ci.yml, README.md, or package.json), and then visualize and score these practices in Port.

Common use cases

  • Encourage consistency: Ensure all services have testing and deployment pipelines in place.
  • Track adoption of practices: Identify which services still lack key maturity signals (e.g., no README, no linter config).
  • Gate production deployments: Require a certain maturity level before deploying new services.

Prerequisites

Set up data model

Follow the steps below to update the Service blueprint:

  1. Navigate to the Service blueprint in your Port Builder.

  2. Hover over it, click on the ... button on the right, and select Edit JSON.

  3. Add the following boolean properties to capture repository maturity signals:

    Repository file check properties (Click to expand)
    "hasCI": {
    "type": "boolean",
    "title": "Has CI"
    },
    "hasLicense": {
    "type": "boolean",
    "title": "Has License"
    },
    "usingFastapiPackage": {
    "type": "boolean",
    "title": "Uses FastAPI"
    },
    "usingOldLoggingPackage": {
    "type": "boolean",
    "title": "Use Old Logging"
    },
    "hasTests": {
    "type": "boolean",
    "title": "Has Test"
    },
    "hasContributingGuide": {
    "type": "boolean",
    "title": "Has Contributing Guide"
    },
    "hasLinter": {
    "type": "boolean",
    "title": "Has Linter"
    },
    "hasPoetryLock": {
    "type": "boolean",
    "title": "Has Poetry Lock"
    },
    "hasPythonVersionInPoetry": {
    "type": "boolean",
    "title": "Has Python Version in Poetry"
    },
    "hasTestInCi": {
    "type": "boolean",
    "title": "Has Test in CI"
    },
    "hasReadme": {
    "type": "boolean",
    "title": "Has Readme"
    }
  4. Click Save to update the blueprint.

Update GitLab integration configuration

  1. Go to your Data Source page.

  2. Select the GitLab integration.

  3. Add the following YAML block into the Mapping editor to detect file presence:

    GitLab Code Maturity Check Configuration (Click to expand)
    - kind: project
    selector:
    query: 'true'
    searchQueries:
    - name: hasLicense
    scope: blobs
    query: 'filename:"LICENSE"'
    - name: usingFastapiPackage
    scope: blobs
    query: 'fastapi filename:pyproject.toml'
    - name: hasCI
    scope: blobs
    query: 'filename:.gitlab-ci.yml'
    - name: usingOldLoggingPackage
    scope: blobs
    query: 'logging extension:py'
    - name: hasTests
    scope: blobs
    query: 'filename:test_* extension:py'
    - name: hasContributingGuide
    scope: blobs
    query: 'filename:CONTRIBUTING.md'
    - name: hasLinter
    scope: blobs
    query: 'flake8 | black filename:pyproject.toml'
    - name: hasPoetryLock
    scope: blobs
    query: 'filename:poetry.lock'
    - name: hasPythonVersionInPoetry
    scope: blobs
    query: '"python =" filename:pyproject.toml'
    - name: hasTestInCi
    scope: blobs
    query: 'pytest | python -m unittest filename:.gitlab-ci.yml'
    - name: hasReadme
    scope: blobs
    query: 'filename:README.md'
    port:
    entity:
    mappings:
    identifier: .path_with_namespace | gsub(" "; "")
    title: .name
    blueprint: '"gitlabRepository"'
    properties:
    url: .web_url
    description: .description
    language: .__languages | to_entries | max_by(.value) | .key
    namespace: .namespace.name
    fullPath: .namespace.full_path
    defaultBranch: .default_branch
    hasLicense: .__searchQueries["hasLicense"]
    usingFastapiPackage: .__searchQueries["usingFastapiPackage"]
    hasCI: .__searchQueries["hasCI"]
    usingOldLoggingPackage: .__searchQueries["usingOldLoggingPackage"]
    hasTests: .__searchQueries["hasTests"]
    hasContributingGuide: .__searchQueries["hasContributingGuide"]
    hasLinter: .__searchQueries["hasLinter"]
    hasPoetryLock: .__searchQueries["hasPoetryLock"]
    hasPythonVersionInPoetry: .__searchQueries["hasPythonVersionInPoetry"]
    hasTestInCi: .__searchQueries["hasTestInCi"]
    hasReadme: .__searchQueries["hasReadme"]
  4. Click Save & Resync to apply the mapping.

Set up scorecard

Let's create a scorecard to assess code maturity based on the files present in each repo:

  1. Go to your Builder page.

  2. Search for the Service blueprint and select it.

  3. Click on the Scorecards tab.

  4. Click on + New Scorecard to create a new scorecard.

  5. Add this JSON configuration:

    Code Maturity Scorecard (click to expand)
    {
    "identifier": "code_maturity",
    "title": "Code Maturity",
    "levels": [
    {
    "color": "paleBlue",
    "title": "Basic"
    },
    {
    "color": "darkGray",
    "title": "Low"
    },
    {
    "color": "orange",
    "title": "Medium"
    },
    {
    "color": "red",
    "title": "High"
    }
    ],
    "rules": [
    {
    "identifier": "has_ci",
    "title": "CI/CD Configuration",
    "description": "Ensures that CI pipelines exist to automate testing and deployments.",
    "level": "High",
    "query": {
    "combinator": "and",
    "conditions": [
    {
    "operator": "=",
    "property": "hasCI",
    "value": true
    }
    ]
    }
    },
    {
    "identifier": "has_license",
    "title": "License File",
    "description": "Project contains a LICENSE file. Indicates the project's usage and distribution rights.",
    "level": "Low",
    "query": {
    "combinator": "and",
    "conditions": [
    {
    "operator": "=",
    "property": "hasLicense",
    "value": true
    }
    ]
    }
    },
    {
    "identifier": "has_readme",
    "title": "Has README",
    "description": "Project contains a README file to describe the purpose, usage, and setup instructions. Encouraged for onboarding and documentation clarity.",
    "level": "Medium",
    "query": {
    "combinator": "and",
    "conditions": [
    {
    "operator": "=",
    "property": "hasReadme",
    "value": true
    }
    ]
    }
    },
    {
    "identifier": "has_tests",
    "title": "Has Tests",
    "description": "Project contains test files. This is a basic engineering quality requirement.",
    "level": "High",
    "query": {
    "combinator": "and",
    "conditions": [
    {
    "operator": "=",
    "property": "hasTests",
    "value": true
    }
    ]
    }
    },
    {
    "identifier": "has_tests_in_ci",
    "title": "Tests Run in CI",
    "description": "Ensures tests are executed in the CI pipeline, validating builds before deployment.",
    "level": "Medium",
    "query": {
    "combinator": "and",
    "conditions": [
    {
    "operator": "=",
    "property": "hasTestInCi",
    "value": true
    }
    ]
    }
    },
    {
    "identifier": "has_contrib_guide",
    "title": "Contributing Guide",
    "description": "Presence of a CONTRIBUTING.md file helps standardize external and internal collaboration.",
    "level": "Low",
    "query": {
    "combinator": "and",
    "conditions": [
    {
    "operator": "=",
    "property": "hasContributingGuide",
    "value": true
    }
    ]
    }
    },
    {
    "identifier": "has_linter",
    "title": "Code Linter Configured",
    "description": "Project includes standard linting configurations to enforce code quality and consistency.",
    "level": "Medium",
    "query": {
    "combinator": "and",
    "conditions": [
    {
    "operator": "=",
    "property": "hasLinter",
    "value": true
    }
    ]
    }
    },
    {
    "identifier": "uses_fastapi",
    "title": "Uses FastAPI",
    "description": "Project uses FastAPI, a modern Python web framework ideal for high-performance APIs.",
    "level": "Low",
    "query": {
    "combinator": "and",
    "conditions": [
    {
    "operator": "=",
    "property": "usingFastapiPackage",
    "value": true
    }
    ]
    }
    },
    {
    "identifier": "uses_old_logging",
    "title": "Uses Old Logging",
    "description": "Project uses the standard `logging` module. Consider structured logging or better alternatives like Loguru.",
    "level": "Low",
    "query": {
    "combinator": "and",
    "conditions": [
    {
    "operator": "=",
    "property": "usingOldLoggingPackage",
    "value": true
    }
    ]
    }
    },
    {
    "identifier": "has_poetry_lock",
    "title": "Poetry Lock File Present",
    "description": "Presence of `poetry.lock` indicates project uses Poetry for dependency management.",
    "level": "High",
    "query": {
    "combinator": "and",
    "conditions": [
    {
    "operator": "=",
    "property": "hasPoetryLock",
    "value": true
    }
    ]
    }
    },
    {
    "identifier": "has_python_version",
    "title": "Python Version Defined in Poetry",
    "description": "Specifying Python version in `pyproject.toml` improves reproducibility and environment stability.",
    "level": "Medium",
    "query": {
    "combinator": "and",
    "conditions": [
    {
    "operator": "=",
    "property": "hasPythonVersionInPoetry",
    "value": true
    }
    ]
    }
    }
    ]
    }
  6. Click on Save to create the scorecard.

After setting up the scorecard metrics on a service, it should look like this:

GitLab project code maturity scorecard results