Skip to content

Conversation

50-Course
Copy link

@50-Course 50-Course commented Oct 12, 2025

Description

What

Ocean's integration for GoHarbor. Allows data synchronization with Harbor's resources, currently, four major sources:

  • Projects
  • Users
  • Repositories
  • Artifacts

Why -

How

Performs data resync via connection polling, leveraging the framework's internals and the integration to work these resource kinds - effectively keeping information in-sync across both platforms.

Type of change

  • New Integration (non-breaking change which adds a new integration)

All tests should be run against the port production environment(using a testing org).

Core testing checklist

  • Integration able to create all default resources from scratch
  • Resync finishes successfully
  • Resync able to create entities
  • Resync able to update entities
  • Resync able to detect and delete entities
  • Scheduled resync able to abort existing resync and start a new one
  • Tested with at least 2 integrations from scratch
  • Tested with Kafka and Polling event listeners
  • Tested deletion of entities that don't pass the selector

Integration testing checklist

  • Integration able to create all default resources from scratch
  • Completed a full resync from a freshly installed integration and it completed successfully
  • Resync able to create entities
  • Resync able to update entities
  • Resync able to detect and delete entities
  • Resync finishes successfully
  • If new resource kind is added or updated in the integration, add example raw data, mapping and expected result to the examples folder in the integration directory.
  • If resource kind is updated, run the integration with the example data and check if the expected result is achieved
  • If new resource kind is added or updated, validate that live-events for that resource are working as expected
  • Docs PR link here

Preflight checklist

  • Handled rate limiting
  • Handled pagination
  • Implemented the code in async
  • Support Multi account

Screenshots

Include screenshots from your environment showing how the resources of the integration will look.

API Documentation

Provide links to the API documentation used for this integration.

@50-Course 50-Course force-pushed the feat_goharbor_port_ocean_integration branch from d7c4475 to 7173c6b Compare October 12, 2025 14:02
@50-Course 50-Course marked this pull request as ready for review October 12, 2025 14:04
@Copilot Copilot AI review requested due to automatic review settings October 12, 2025 14:04
Copy link
Contributor

qodo-merge-pro bot commented Oct 12, 2025

PR Compliance Guide 🔍

Below is a summary of compliance checks for this PR:

Security Compliance
Hardcoded local path

Description: Makefile contains an absolute path to a developer's local filesystem which can leak
environment structure and break builds; replace with a relative path to avoid exposure.
Makefile [1-1]

Referred Code
/home/erioluwa/projects/ocean/port_ocean/cli/cookiecutter/../../../integrations/_infra/Makefile
SSL verification bypass

Description: SSL verification flag is accepted but not enforced in the HTTP client, potentially causing
requests to skip certificate verification unintentionally.
client.py [80-86]

Referred Code
self.base_url = f"{base_url.rstrip('/')}/api/{API_VERSION}"
self.username = username
self.password = password
self.verify_ssl = verify_ssl  # do we really need SSL, let's just have it

self.client, self.client.timeout = http_async_client, Timeout(DEFAULT_TIMEOUT)
Weak auth handling

Description: Basic Auth header construction is manual without using secure httpx auth mechanisms;
ensure transmission occurs only over HTTPS and secrets are not logged.
auth.py [4-11]

Referred Code
def generate_basic_auth_header(username: str, password: str) -> tuple[str, str]:
    """
    Returns the Basic Auth header for given username and password
    """
    credentials = f"{username}:{password}"
    encoded = base64.b64encode(credentials.encode('utf-8')).decode('utf-8')

    return 'Authorization', f'Basic {encoded}'
Ticket Compliance
🎫 No ticket provided
  • Create ticket/issue
Codebase Duplication Compliance
Codebase context is not defined

Follow the guide to enable codebase context checks.

Custom Compliance
No custom compliance provided

Follow the guide to enable custom compliance check.

  • Update
Compliance status legend 🟢 - Fully Compliant
🟡 - Partial Compliant
🔴 - Not Compliant
⚪ - Requires Further Human Verification
🏷️ - Compliance label

Copy link
Contributor

@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR introduces a new integration for GoHarbor container registry, enabling synchronization of Harbor resources into Port. The integration supports fetching projects, users, repositories, and artifacts through Harbor's v2.11.0 API.

  • Implements a comprehensive Harbor API client with pagination, authentication, and error handling
  • Provides resource synchronization for projects, users, repositories, and artifacts
  • Includes complete test coverage for core functionality including pagination and client operations

Reviewed Changes

Copilot reviewed 25 out of 34 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
integrations/goharbor_ocean/tests/test_pagination.py Comprehensive test suite for pagination functionality across different Harbor resource types
integrations/goharbor_ocean/tests/test_client.py Unit tests for Harbor client initialization and API request handling
integrations/goharbor_ocean/tests/fixtures.py Test fixtures and mock objects for Harbor API responses
integrations/goharbor_ocean/tests/conftest.py Test configuration setup
integrations/goharbor_ocean/harbor/client.py Core Harbor API client implementation with async pagination and error handling
integrations/goharbor_ocean/harbor/utils/constants.py Harbor API constants and configuration values
integrations/goharbor_ocean/harbor/utils/auth.py Authentication utilities for Basic Auth
integrations/goharbor_ocean/harbor/schemas.py TypedDict schemas for Harbor API response structures
integrations/goharbor_ocean/harbor/exceptions.py Custom exception classes for Harbor integration errors
integrations/goharbor_ocean/main.py Integration entry point with resource synchronization logic
integrations/goharbor_ocean/.port/spec.yaml Integration specification and configuration schema
integrations/goharbor_ocean/.port/resources/blueprints.json Port blueprints for Harbor entities
integrations/goharbor_ocean/.port/resources/port-app-config.yml Entity mapping configuration
integrations/goharbor_ocean/pyproject.toml Python project configuration and dependencies
Comments suppressed due to low confidence (2)

integrations/goharbor_ocean/tests/test_pagination.py:1

  • The pagination logic assigns 'page' to 'page_size' instead of 'page'. This will cause incorrect API requests with the page number as the page size.
import pytest

integrations/goharbor_ocean/harbor/client.py:1

  • Incorrect access to call_args.args - should be call_args[1] since call_args is already the args tuple.
"""

Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.

mock_http_response,
mocked_artifact_response,
):
# should fetch artifats when both project_name and repository_name are provided
Copy link

Copilot AI Oct 12, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Corrected spelling of 'artifats' to 'artifacts'.

Suggested change
# should fetch artifats when both project_name and repository_name are provided
# should fetch artifacts when both project_name and repository_name are provided

Copilot uses AI. Check for mistakes.

async def test_handles_server_error(
self, harbor_client_mocked, mock_async_client, mock_http_error
):
# should gracefuly handle server errors
Copy link

Copilot AI Oct 12, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Corrected spelling of 'gracefuly' to 'gracefully'.

Suggested change
# should gracefuly handle server errors
# should gracefully handle server errors

Copilot uses AI. Check for mistakes.

verify_ssl: bool = False,
):
"""
Initalizes Harbor API client
Copy link

Copilot AI Oct 12, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Corrected spelling of 'Initalizes' to 'Initializes'.

Suggested change
Initalizes Harbor API client
Initializes Harbor API client

Copilot uses AI. Check for mistakes.

Copy link
Contributor

qodo-merge-pro bot commented Oct 12, 2025

PR Code Suggestions ✨

Explore these optional code suggestions:

CategorySuggestion                                                                                                                                    Impact
Possible issue
Fix incorrect pagination query parameter

Fix the pagination loop by setting the page query parameter instead of
incorrectly overwriting page_size.

integrations/goharbor_ocean/harbor/client.py [278-286]

 while True:
-    query_params['page_size'] = page
+    query_params["page"] = page
 
     try:
         response_data = await self._send_api_request(
-            "GET",
-            endpoint,
-            params=query_params
+            "GET", endpoint, params=query_params
         )
  • Apply / Chat
Suggestion importance[1-10]: 10

__

Why: This suggestion identifies a critical bug in the pagination logic where page_size is incorrectly used instead of page, which would break data synchronization.

High
Avoid modifying shared client headers

Store authentication headers in an instance variable instead of modifying the
shared global http_async_client to prevent authentication conflicts.

integrations/goharbor_ocean/harbor/client.py [85-92]

-self.client, self.client.timeout = http_async_client, Timeout(DEFAULT_TIMEOUT)
+self.client = http_async_client
+self.client.timeout = Timeout(DEFAULT_TIMEOUT)
 
 auth_header_name, auth_header_value = generate_basic_auth_header(
     username, password
 )
-if not hasattr(self.client, "headers"):
-    self.client.headers = {}
-self.client.headers[auth_header_name] = auth_header_value
+self.auth_headers = {auth_header_name: auth_header_value}
  • Apply / Chat
Suggestion importance[1-10]: 9

__

Why: The suggestion correctly identifies a critical bug where modifying the shared http_async_client can cause authentication conflicts between integrations, and it proposes the correct fix.

High
Pass authentication headers with requests

Pass the instance-specific authentication headers with each API request to
ensure proper authentication.

integrations/goharbor_ocean/harbor/client.py [139-144]

+# Get a copy of the headers to avoid modifying the original
+request_headers = self.auth_headers.copy()
+
 response = await self.client.request(
     method=method,
     url=url,
     params=params,
     json=json_data,
+    headers=request_headers,
 )
  • Apply / Chat
Suggestion importance[1-10]: 9

__

Why: This suggestion is the necessary second part of the fix for the critical authentication bug, ensuring that the instance-specific headers are actually used in API requests.

High
Handle null values in JQ
Suggestion Impact:The commit updated the JQ expression to use (.tags // []) | map(.name), exactly applying the suggested null-safe handling.

code diff:

-            tags: .tags | map(.name)
+            tags: (.tags // []) | map(.name)

In the JQ mapping for tags, handle cases where .tags is null by providing a
default empty array [] to prevent the map filter from failing.

integrations/goharbor_ocean/.port/resources/port-app-config.yml [69]

-tags: .tags | map(.name)
+tags: (.tags // []) | map(.name)

[Suggestion processed]

Suggestion importance[1-10]: 8

__

Why: The suggestion correctly identifies a potential mapping failure for artifacts without tags and provides a robust fix using a default empty array, preventing runtime errors during data ingestion.

Medium
  • Update

@50-Course 50-Course force-pushed the feat_goharbor_port_ocean_integration branch from ddc9dee to a4eda10 Compare October 12, 2025 14:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant