Skip to content

Conversation

@zzstoatzz
Copy link
Collaborator

Summary

Fixes #19861
Related: #19296

PR #19236 refactored git credential formatting to move provider-specific logic from _format_token_from_credentials into Block.format_git_credentials() methods on each integration. This was intended to improve separation of concerns.

However, the refactor inadvertently broke YAML deployments that use block references like:

pull:
  - prefect.deployments.steps.git_clone:
      repository: https://gitlab.com/org/repo.git
      credentials: "{{ prefect.blocks.gitlab-credentials.my-block }}"

When credentials are specified this way, resolve_block_document_references returns a dict (expected behavior per @desertaxle), not a Block instance. Since dicts don't implement the _GitCredentialsFormatter protocol, the formatting logic was skipped entirely, causing GitLab authentication to fail (missing oauth2: prefix).

Changes

Restores the netloc-based provider detection in _format_token_from_credentials for dict credentials:

  • GitLab (gitlab in URL): Adds oauth2: prefix for PATs, handles deploy tokens
  • BitBucket Cloud (bitbucket in URL): Adds x-token-auth: prefix
  • BitBucket Server (bitbucketserver in URL): Requires username:token format
  • GitHub and others: Plain token (no prefix)

Block instances still use the protocol-based format_git_credentials() method - this change only affects the dict fallback path.

Test Plan

Added 4 regression tests covering dict credential formatting for GitLab, BitBucket, and GitHub URLs.

Reproduction script
import asyncio
from unittest.mock import AsyncMock, patch

from prefect.utilities.templating import resolve_block_document_references
from prefect.runner.storage import GitRepository, _GitCredentialsFormatter


async def demonstrate_issue():
    # Simulate the block document data that would come from the API
    mock_block_data = {
        "token": "my-gitlab-token",
        "url": None,
    }

    mock_block_document = AsyncMock()
    mock_block_document.data = mock_block_data

    mock_client = AsyncMock()
    mock_client.read_block_document_by_name = AsyncMock(return_value=mock_block_document)

    template = "{{ prefect.blocks.gitlab-credentials.my-block }}"

    with patch("prefect.utilities.templating.inject_client", lambda f: f):
        resolved = await resolve_block_document_references(template, client=mock_client)

    print(f"Resolved type: {type(resolved).__name__}")  # dict
    print(f"Implements protocol: {isinstance(resolved, _GitCredentialsFormatter)}")  # False

    repo = GitRepository(
        url="https://gitlab.com/org/repo.git",
        credentials=resolved,
    )
    url_with_creds = repo._repository_url_with_credentials
    print(f"URL: {url_with_creds}")
    # Before fix: https://[email protected]/org/repo.git (BROKEN)
    # After fix:  https://oauth2:[email protected]/org/repo.git (CORRECT)


if __name__ == "__main__":
    asyncio.run(demonstrate_issue())

🤖 Generated with Claude Code

When credentials are specified via block references in deployment YAML:

    credentials: "{{ prefect.blocks.gitlab-credentials.my-block }}"

they resolve to dicts, not Block instances. PR #19236 moved provider-specific
credential formatting logic to Block.format_git_credentials(), but this broke
the YAML deployment path because dicts don't implement that protocol.

This restores the netloc-based provider detection that was removed, providing
sensible defaults for GitLab (oauth2: prefix), BitBucket (x-token-auth: prefix),
and BitBucket Server (username:token format) when credentials are dicts.

Block instances still use the protocol-based format_git_credentials() method.

Fixes #19861
Related: #19296

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <[email protected]>
@github-actions github-actions bot added the bug Something isn't working label Dec 18, 2025
@codspeed-hq
Copy link

codspeed-hq bot commented Dec 18, 2025

CodSpeed Performance Report

Merging #19873 will not alter performance

Comparing fix/restore-netloc-credential-formatting (a69bc17) with main (bcc62ca)

Summary

✅ 2 untouched

@zzstoatzz zzstoatzz marked this pull request as ready for review December 18, 2025 19:28
@zzstoatzz zzstoatzz merged commit 26a09e3 into main Dec 18, 2025
59 checks passed
@zzstoatzz zzstoatzz deleted the fix/restore-netloc-credential-formatting branch December 18, 2025 19:30
devin-ai-integration bot added a commit that referenced this pull request Dec 18, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Block references in deployment YAML resolve to dicts instead of Block instances

3 participants