Fix GitLab instances with non-standard ports#187
Closed
Conversation
Co-authored-by: dvershinin <250071+dvershinin@users.noreply.github.com>
Co-authored-by: dvershinin <250071+dvershinin@users.noreply.github.com>
Co-authored-by: dvershinin <250071+dvershinin@users.noreply.github.com>
|
Copilot
AI
changed the title
[WIP] Lastversion fails for GitLab instances with non-standard ports
Fix GitLab instances with non-standard ports
Sep 30, 2025
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.



Problem
Lastversion fails when querying GitLab instances that use non-standard ports. For example:
This would fail because the port number was being stripped from the hostname during URL parsing, causing API calls to be directed to the wrong URL (missing the
:9000port).Root Cause
The issue was in two places:
holder_factory.py: Usedparsed.hostnamewhich excludes the port numberbase.py: Used naive string splitting (repo.split("/")) which doesn't properly handle URLs with portsSolution
Updated URL Parsing Logic
Changed from using
parsed.hostnameto intelligently usingparsed.netloc(which includes the port) when a non-standard port is present:Proper URL Parsing
Replaced string splitting with
urllib.parse.urlparsefor robust URL handling:Updated Hostname Matching
Modified
is_matching_hostname()to strip ports before comparing with default hostnames:Behavior
https://gitlab.vci.rwth-aachen.de:9000/...gitlab.vci.rwth-aachen.de:9000https://gitlab.com/...gitlab.comhttps://gitlab.com:443/...gitlab.comhttp://gitlab.com:80/...gitlab.comImpact
This fix applies to all self-hosted instances that can use non-standard ports:
Testing
Added comprehensive test
test_gitlab_url_parsing_with_port()that verifies:Fixes the issue reported in the original bug report where lastversion would fail with:
Now it correctly constructs API URLs like
https://gitlab.vci.rwth-aachen.de:9000/api/v4instead of the incorrecthttps://gitlab.vci.rwth-aachen.de/api/v4.Warning
Firewall rules blocked me from connecting to one or more addresses (expand for details)
I tried to connect to the following addresses, but was blocked by firewall rules:
gitlab.compython3 -m pytest tests/test_gitlab.py::test_gitlab_1 -v(dns block)gitlab.vci.rwth-aachen.defrom src.lastversion.holder_factory import HolderFactory
from src.lastversion.repo_holders.gitlab import GitLabRepoSession
Test the full flow
url = 'REDACTED'
print('Testing full flow for:', url)
Simulate what get_instance_for_repo does
from urllib.parse import urlparse
parsed = urlparse(url)
hostname = parsed.netloc if parsed.port else parsed.hostname
repo = parsed.path.lstrip('/')
print(f'Hostname extracted: {hostname}')
print(f'Repo extracted: {repo}')
Test is_matching_hostname
matches = GitLabRepoSession.is_matching_hostname(hostname)
print(f'Matches GitLab (subdomain indicator): {matches}')
Create an instance
instance = GitLabRepoSession(repo, hostname)
print(f'Instance created: {type(instance).name}')
print(f'Instance hostname: {instance.hostname}')
print(f'Instance api_base: {instance.api_base}')
print(f'Expected api_base: REDACTED')
print(f'API base is correct: {instance.api_base == "REDACTED"}')` (dns block)
Test the full flow
url = 'REDACTED'
print('Testing full integration for:', url)
This should select GitLab as the holder
from unittest.mock import Mock, patch
from src.lastversion.repo_holders.gitlab import GitLabRepoSession
with patch.object(GitLabRepoSession, 'get') as mock_get:
mock_response = Mock()
mock_response.status_code = 200
mock_response.json.return_value = {'id': 123, 'path_with_namespace': 'OpenVolumeMesh/OpenVolumeMesh'}
mock_get.return_value = mock_response
Test the full flow with mocked GitLabRepoSession.init
url = 'REDACTED'
print('Testing full integration for:', url)
Mock the entire initialization to avoid network calls
original_init = GitLabRepoSession.init
def mock_init(self, repo, hostname):
# Call parent init
from src.lastversion.repo_holders.base import BaseProjectHolder
BaseProjectHolder.init(self, repo, hostname)
self.pa_token = None
self.hostname = hostname
if not self.hostname:
self.hostname = self.DEFAULT_HOSTNAME
self.api_base = f'https://{self.hostname}/api/v4'
self.repo = repo # Skip find_gitlab_project_path
self.formal_releases_by_tag = None
with patch.object(GitLabRepoSession, 'init', mock_init):
holder = HolderFactory.get_instance_for_repo(url)
print(f'Holder type: {type(holder).name}')
print(f'Holder hostname: {holder.hostname}')
print(f'Holder repo: {holder.repo}')
print(f'Holder api_base: {holder.api_base}')
print(f'Expected api_base: REDACTED')
print(f'Success: {holder.api_base == "REDACTED"}')` (dns block)
Original prompt
💬 Share your feedback on Copilot coding agent for the chance to win a $200 gift card! Click here to start the survey.