Search code examples
pythongitazure-devopsazure-pipelinesado

How can I extract file contents of a specific commit using Azure Devops API (Python)?


Here's what I want to do: every time there is a commit to a specific branch in my repo, I want to extract all the YAML files being changed in that commit, make some modifications to their contents and then push the result as a PR into a new, separate branch. I have figured out most of the steps here, but I am stuck at the parsing commit file contents part. I have tried get_item_content and get_blob_content on a commit but I did not see any file being downloaded. So I specifically want to know:

  1. if it's possible to get the changed files from a commit (NOT a PR) and parse them.
  2. Or if not, then atleast I want to cherry-pick YAML file changes from the commit into a new branch and create a PR. Is cherry-picking specific files possible?

Solution

  • Yes, you can get the changed files from a commit (NOT a PR) and parse them. Please check the sample code below:

    from azure.devops.connection import Connection
    from msrest.authentication import BasicAuthentication
    from azure.devops.v7_0.git.models import GitVersionDescriptor
    
    
    # Set up connection
    personal_access_token = 'PAT'
    organization_url = 'https://dev.azure.com/ORGNAME'
    credentials = BasicAuthentication('', personal_access_token)
    connection = Connection(base_url=organization_url, creds=credentials)
    
    # Get the Git client
    git_client = connection.clients.get_git_client()
    repository_id = 'REPOID'
    commit_id = 'COMMITID'      # it's the 40-character string commit id
    
    # Get the changes for the commit
    changes = git_client.get_changes(commit_id, repository_id)
    
    changed_files = [change['item']['path'] for change in changes.changes]
    
    
    # Filter for YAML files
    yaml_files = [file for file in changed_files if file.endswith('.yaml') or file.endswith('.yml')]
    print(yaml_files)
    
    # Get the contents of each YAML file
    for file_path in yaml_files:
        version_descriptor = GitVersionDescriptor(version=commit_id, version_type='commit')
        item_content = git_client.get_item_content(repository_id, path=file_path, version_descriptor=version_descriptor)
        
        # Read the content from the generator
        content = b''.join(item_content).decode('utf-8')
        print(f"Contents of {file_path}:\n{content}")
    
    

    It prints out the changed yaml file, and file content as below:

    enter image description here