microsoft / microsoft/azure-devops-python-api

Deleting Pull Request Attachments Prevents Reading Attachments

Ouverte
#499 1 commentaire 0 réactions 0 personnes assignées Voir sur GitHub

Personne n'a encore pris cette issue.

Langage dominant
Python
Étoiles
684
Forks
218
Merge moyen
8 j 10 h
PR mergées (30 j)
1

Description

Hello,

I recently ran in to this issue while attempting to manage pull request attachments. It could be a bug with the AZDO API, but I'm specifically using azure-devops-python-api.

Steps to Reproduce

  1. Create multiple pull request attachments via GitClient, and delete at least one. The specific order doesn't matter; you can create two attachments then delete one of them, or create a single attachment, delete it, and create a second attachment.
  2. Attempting to access any non-deleted attachment (via the attachment URL) results in the following error:
{
    "$id": "1",
    "innerException": null,
    "message": "TF400714: File ID 123456789 not found.",
    "typeName": "Microsoft.TeamFoundation.Framework.Server.FileIdNotFoundException, Microsoft.TeamFoundation.Framework.Server",
    "typeKey": "FileIdNotFoundException",
    "errorCode": 0,
    "eventId": 4005
}

Example Code

delete_attachment_bug.py

from azure.devops.v7_0.git.models import *
from azure.devops.v7_0.git.git_client import GitClient
from msrest.authentication import BasicAuthentication
from azure.devops.connection import Connection
from random import randint

import os

def fix_create_attachment(client: GitClient):
    """
    See https://github.com/microsoft/azure-devops-python-api/issues/322 for documentation of this issue.
    """

    def create_attachment(upload_stream, file_name, repository_id, pull_request_id, project=None):
        route_values = {}
        if project is not None:
            route_values['project'] = client._serialize.url('project', project, 'str')
        if file_name is not None:
            route_values['fileName'] = client._serialize.url('file_name', file_name, 'str')
        if repository_id is not None:
            route_values['repositoryId'] = client._serialize.url('repository_id', repository_id, 'str')
        if pull_request_id is not None:
            route_values['pullRequestId'] = client._serialize.url('pull_request_id', pull_request_id, 'int')
        # content = self._client.stream_upload(upload_stream, callback=callback)
        response = client._send(http_method='POST',
                                location_id='965d9361-878b-413b-a494-45d5b5fd8ab7',
                                version='7.0',
                                route_values=route_values,
                                content=upload_stream.read(),
                                media_type='application/octet-stream')
        return client._deserialize('Attachment', response)

    client.create_attachment = create_attachment

pat = os.environ.get("mypersonalaccesstoken")
auth = BasicAuthentication("", pat)
connection = Connection("https://dev.azure.com/someorganization/", auth)
client: GitClient = connection.clients.get_git_client()
fix_create_attachment(client)
pr_id = 123456
project_id = "MyProject"
repo_id = "MyRepo"

def create_attachment():
    with open("cool_pic.png", "rb") as file:
        # Create random name for attachment
        name = f"{randint(0,10000)}.png"
        attachment: Attachment = client.create_attachment(file, name, repo_id, pr_id, project_id)
        print(f"Created attachment: {name}\n(URL: {attachment.url})")

def delete_attachment(name):
    client.delete_attachment(name, repo_id, pr_id, project_id)
    print(f"Deleted attachment: {name}")

This code can be used along with the Python shell to reproduce the issue:

python -i delete_attachment_bug.py
>>> create_attachment()
>>> delete_attachment("nameFromPreviousCall")
>>> create_attachment()

Trying to access the most recently created attachment (via the attachment URL) results in the above error.

I'm using Python 3.7.4 and azure-devops==7.1.0b4.

I haven't been able to find a workaround yet. Note the example code includes a workaround for #322.

Guide de contribution

Aucun guide de contribution indexé pour ce dépôt

Par où commencer

  1. Lisez l'issue en entier, puis le guide de contribution du projet.
  2. Signalez en commentaire que vous la prenez — cela évite que deux personnes fassent le même travail.
  3. Forkez le dépôt et travaillez sur une branche.
  4. Ouvrez une pull request qui référence le numéro de l'issue.

Piste de recherche

Commencez par delete_attachment_bug.py et les appels GitClient create_attachment et delete_attachment, puis reproduisez la séquence dans le shell Python. Comparez les requêtes et les URL des attachments renvoyées après la suppression afin de déterminer si le client ou l’Azure DevOps API provoque la FileIdNotFoundException. C’est terminé lorsque la cause est établie et que les attachments non supprimés restent lisibles après la séquence.

Rédigé par le modèle d'indexation à partir du texte de l'issue.

Évaluation

Stack technique
azure, devops, python
Domaine
api, devops
Type d'issue
Bug
Difficulté
4/5
Temps estimé
3-5 jours
Activité
À l'abandon
Clarté
Plutôt claire
Accessibilité débutants
35/100

Recevez les nouvelles issues par e-mail

Un résumé court des issues GitHub adaptées aux débutants.