Compare commits
3 Commits
c0a973a339
...
850bc99aa2
| Author | SHA1 | Date | |
|---|---|---|---|
| 850bc99aa2 | |||
| e4c3346080 | |||
| c63595c9fa |
15
.vscode/launch.json
vendored
Normal file
15
.vscode/launch.json
vendored
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
{
|
||||||
|
// Use IntelliSense to learn about possible attributes.
|
||||||
|
// Hover to view descriptions of existing attributes.
|
||||||
|
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
||||||
|
"version": "0.2.0",
|
||||||
|
"configurations": [
|
||||||
|
{
|
||||||
|
"name": "Python Debugger: Harvester",
|
||||||
|
"type": "debugpy",
|
||||||
|
"request": "launch",
|
||||||
|
"program": "${workspaceFolder}/harvester.py",
|
||||||
|
"console": "integratedTerminal"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
57
devops.py
57
devops.py
@@ -1,29 +1,74 @@
|
|||||||
|
from unicodedata import name
|
||||||
import requests
|
import requests
|
||||||
import urllib.request
|
import urllib.request
|
||||||
import urllib.parse
|
import urllib.parse
|
||||||
import json
|
import json
|
||||||
|
from uuid import UUID
|
||||||
|
|
||||||
DEVOPS_SCOPE = "https://app.vssps.visualstudio.com/.default"
|
DEVOPS_SCOPE = "https://app.vssps.visualstudio.com/.default"
|
||||||
DEVOPS_API_VERSION = "7.1"
|
DEVOPS_API_VERSION = "7.1"
|
||||||
|
|
||||||
class Client:
|
class Organization:
|
||||||
def __init__(self, org_url: str, token: str, api_version: str = DEVOPS_API_VERSION):
|
def __init__(self, org_url: str, token: str, api_version: str = DEVOPS_API_VERSION):
|
||||||
self._org_url = org_url.rstrip("/") + "/" # Ensure trailing slash
|
self._org_url = org_url.rstrip("/") + "/" # Ensure trailing slash
|
||||||
self._token = token
|
self._token = token
|
||||||
self._api_version = api_version
|
self._api_version = api_version
|
||||||
|
|
||||||
def get(self, path: str, params: dict = {}):
|
def get(self, path: str, params: dict = {}):
|
||||||
p = {
|
request_parameters = {
|
||||||
"api-version": self._api_version,
|
"api-version": self._api_version,
|
||||||
**params
|
**params
|
||||||
}
|
}
|
||||||
url = self._org_url + path.lstrip("/") # Ensure single slash between base and path
|
encoded_path = urllib.parse.quote(path.lstrip("/")) # Ensure single slash between base and path
|
||||||
r = requests.get(url=url, params=p, headers={
|
url = self._org_url + encoded_path
|
||||||
|
r = requests.get(url=url, params=request_parameters, headers={
|
||||||
"Authorization": f"Bearer {self._token}"
|
"Authorization": f"Bearer {self._token}"
|
||||||
})
|
})
|
||||||
return r
|
return r
|
||||||
|
|
||||||
def get_projects(self):
|
@property
|
||||||
|
def projects(self):
|
||||||
r = self.get("_apis/projects")
|
r = self.get("_apis/projects")
|
||||||
r.raise_for_status()
|
r.raise_for_status()
|
||||||
return r.json()
|
|
||||||
|
# Return a list of Project instances
|
||||||
|
projects_data = r.json().get("value", [])
|
||||||
|
return [
|
||||||
|
Project(self,
|
||||||
|
id=proj.get("id"),
|
||||||
|
name=proj.get("name"),
|
||||||
|
url=proj.get("url"),
|
||||||
|
description=proj.get("description"),
|
||||||
|
) for proj in projects_data
|
||||||
|
]
|
||||||
|
|
||||||
|
class Project:
|
||||||
|
def __init__(self, org: Organization, id: str, name: str | None = None, url: str | None = None, description: str | None = None):
|
||||||
|
self._org = org
|
||||||
|
|
||||||
|
# Check, if the id is a valid UUID
|
||||||
|
try:
|
||||||
|
self._id = str(UUID(id))
|
||||||
|
except ValueError:
|
||||||
|
raise ValueError(f"Invalid project ID: {self._id}")
|
||||||
|
|
||||||
|
if name is not None and url is not None and name != "" and url != "":
|
||||||
|
self._name = name
|
||||||
|
self._url = url
|
||||||
|
self._description = description if description is not None else "" # Ensure description is a string
|
||||||
|
else:
|
||||||
|
# Fetch project details from the API
|
||||||
|
r = org.get(f"_apis/projects/{urllib.parse.quote(self._id)}")
|
||||||
|
r.raise_for_status()
|
||||||
|
proj_data = r.json()
|
||||||
|
self._id = proj_data.get("id", "")
|
||||||
|
self._name = proj_data.get("name", "")
|
||||||
|
self._url = proj_data.get("url", "")
|
||||||
|
self._description = proj_data.get("description", "")
|
||||||
|
|
||||||
|
@property
|
||||||
|
def name(self):
|
||||||
|
return self._name
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return f"Project(name={self._name}, id={self._id})"
|
||||||
|
|||||||
15
harvester.py
15
harvester.py
@@ -1,14 +1,13 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
from devops import Client, DEVOPS_SCOPE
|
from devops import Organization, Project, DEVOPS_SCOPE
|
||||||
from azure.identity import DefaultAzureCredential
|
from azure.identity import DefaultAzureCredential
|
||||||
from json import dumps
|
from json import dumps
|
||||||
|
|
||||||
def main():
|
org = Organization("https://dev.azure.com/mcovsandbox", DefaultAzureCredential().get_token(DEVOPS_SCOPE).token)
|
||||||
token = DefaultAzureCredential().get_token(DEVOPS_SCOPE).token
|
projects = org.projects
|
||||||
client = Client("https://dev.azure.com/mcovsandbox", token)
|
print([str(p) for p in projects])
|
||||||
projects = client.get_projects()
|
|
||||||
print(dumps(projects, indent=2))
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
ado_sandbox = Project(org, id="bafe0cf1-6c97-4088-864a-ea6dc02b2727")
|
||||||
main()
|
|
||||||
|
print(ado_sandbox)
|
||||||
|
|||||||
@@ -1 +1,3 @@
|
|||||||
azure-identity
|
debugpy==1.8.17
|
||||||
|
azure-identity==1.25.1
|
||||||
|
requests==2.32.5
|
||||||
|
|||||||
Reference in New Issue
Block a user