Azure Devops - download a file from the API with a tfvc repos - azure-devops

Is it possible to use an Rest API to download a file from a TFVC repos in Azure DevOps Service?
I find a lot of topics that talk about downloading with a Git repos, but not with TFVC.

You can use the REST API Items - Get to get a file from TFVC repos.
GET https://dev.azure.com/{organization}/{project}/_apis/tfvc/items?path={path}&download=true&api-version=6.0
Here are a few points that need your attention:
The path parameter omits the name of the TFVC repo. For example, if I want to get a file $/{name}/A.txt, then I need to set path=A.txt.
You need to specify the file path instead of the folder path. Otherwise only the folder information will be returned and the file will not be downloaded. If you want to download multiple files, you need to use the REST API Items - Get Items Batch.
Set download parameter to true to download the file. Otherwise only the file information will be returned and the file will not be downloaded.

Using PowerShell and Items - Get API:
$ADOHeaders = #{
Authorization = 'Basic ' + [Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes(":ado_personalaccesstoken"))
Accept = 'application/zip'
}
Invoke-WebRequest `
-Uri "https://dev.azure.com/{organization}/{project}/_apis/tfvc/items?path=%24/full/path/to/folder/&download=true&api-version=7.1-preview.1" `
-Headers $ADOHeaders `
-OutFile ./files.zip

Related

Is there a way to list pull request files(from source branch) with it's location in Azure Devops using APIs? Is there any other way using C#?

My requirement is to read/extract source code of each file present in an Azure DevOps pull request using APIs or C#.
I am able to download the code for a particular file using sample URL below -
GET https://dev.azure.com/{organization}/{project}/_apis/git/repositories/{repositoryId}/items?path=/{CodePath}&version={branch name}&api-version=5.1
Now I need, list of files with location where it is stored in a branch of Azure DevOps
I have tried different GET calls from REST APIs available.
For example:
GET https://dev.azure.com/{organization}/{project}/_apis/git/repositories/{repositoryId}/pullRequests/{pullRequestId}/iterations/{iterationId}?api-version=5.1
or
GET https://dev.azure.com/{organization}/{project}/_apis/git/repositories/{repositoryId}/pullRequests/{pullRequestId}/attachments/{fileName}?api-version=5.1-preview.1
These calls are returning information:
About file commits
About documents attached in description
Information I have to fulfill the requirement:
Organization name, Repository name, Branch Name, Pull request ID
Is there a way to list pull request files(from source branch) with it's location in Azure Devops using APIs? Is there any other way using C#?
I am afraid there is no such out of way to list pull request files(from source branch) with it's location in Azure Devops using APIs.
First, when we use the pull request API, we could get the Organization name and Pull request ID directly.
Then we could use the REST API Pull Requests - Get Pull Requests to get the repository name and sourceRefName (Branch Name):
GET https://dev.azure.com/{organization}/{project}/_apis/git/repositories/{repositoryId}/pullrequests?api-version=5.1
Second, we could use the REST API Pull Request Commits - Get Pull Request Commits to get the commits in the PR:
Then, we could use the commit id with REST API Commits - Get Changes to file path:
Now, we get all the info what we want.
Hope this helps.
According to #Leo Liu answer, this is my code in powershell (working great!):
$AzureDevOpsPAT = "$(System.AccessToken)";
$headers = #{Authorization = 'Basic ' + [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(":$AzureDevOpsPAT")) }
$organization = "YOUR ORGANIZATION"
$project = "YOUR PROJECT"
$repoId = "YOUR REPOSITORY ID"
$baseUrl = "https://dev.azure.com/$organization/$project/_apis/git/repositories/$repoId"
$pullRequest = $(System.PullRequest.PullRequestId);
$commits = Invoke-RestMethod -Method Get -Headers $headers "$baseUrl/pullRequests/$pullRequest/commits" -verbose
if ($commits.count -gt 0) {
foreach ($commit in $commits.value) {
$commitId = $commit.commitId
$changes = Invoke-RestMethod -Method Get -Headers $headers "$baseUrl/commits/$commitId/changes" -verbose
foreach ($change in $changes.changes) {
write-host $change.item.path
}
}
}

Connecting Build pipeline in AzureDevOps to newly created repos with certain prefix Automatically

I have a created a build pipeline in Azure DevOps and it is connected to one repo that I have in my Github. However, I want to connect/clone this build pipeline into any newly created repo in my github with a certain prefix in its name, like the word 'Build'.
You can navigate to your Build Pipeline, select the Option menu from the right hand side on the pipeline details page, and choose the Clone item.
You can then point the cloned build pipeline to your new Git repository and change the pipeline's name to have the prefix you wish.
Connecting Build pipeline in AzureDevOps to newly created repos with certain prefix Automatically
To automate the process, you need use the definition REST AP get the json body:
https://learn.microsoft.com/en-us/rest/api/azure/devops/build/definitions/get?view=azure-devops-rest-5.0
Then we could change the json file whatever we feel necessary, like Repository URL, change it to the new path for your newly created repo in my github.
At last, we could use create definition REST API with above Json file to create new pipeline:
https://learn.microsoft.com/en-us/rest/api/azure/devops/build/definitions/create?view=azure-devops-rest-5.0
$thisBuildDef.Name = $Clone_Name
$thisBuildDef.path = $BuildDefURL # Relative to the Project name; like "Release/2019"
$thisBuildDef.buildNumberFormat = $BuildNumberFormat
# Update source control path to new branch
$defAsJson = $thisBuildDef | ConvertTo-Json -Depth 100
$defAsJson = $defAsJson.Replace($sourceControlMainline, $sourceControlBranch)
$Uri = "https://dev.azure.com/{organization}/{project}/_apis/build/definitions?api-version=2.0"
$newBuildDef = Invoke-RestMethod -Uri $Uri -Headers #{Authorization=("Basic {0}" -f $base64AuthInfo)} -Method Post -Body $defAsJson -ContentType "application/json" -ErrorAction Stop
Check the document Using JSON via REST to create build definitions in VSO and the vsts-clone-build-with-powershell.ps1 sample.
Hope this helps.

How do I get the PackageID for Azure Devops API?

I need the list of available versions for a Universal Package stored in Azure Devops. My thought is to call the REST API Get Package Versions to get a list of the versions for packages on a feed.
GET https://feeds.dev.azure.com/{organization}/{project}/_apis/packaging/Feeds/{feedId}/Packages/{packageId}/versions?api-version=5.1-preview.1
The problem is that it requires a packageId, which is the GUID and I only know the name. The only way I've figured out so far to convert a package name to a GUID is using "Get Packages" but that returns every package on the feed (which for me includes thousands of NPM packages) and that makes the download very large for the handful of items I need. Is there some way to extract the packageId for a given package name? Or is there a better way to extract all the versions for a package?
Someone pointed out to me that the Get Packages API has options for IncludeAllVersions and packageNameQuery to achieve what I want rather than using GetAllVersions.
https://feeds.dev.azure.com/{organization}/{project}/_apis/packaging/Feeds/{feedId}/Packages?includeAllVersions=true&packageNameQuery={packageName}&protocol​Type=nuget
I assume you have checked some docs and found there's no direct API can let you get specified packaged ID, right? Also, as the doc said, the package name could not be used in this API:
In fact, you have very close to the answer. Just add some filter while you running Get Packages. But this need you execute some script in Powershell command line or Powershell ISE which is the most convenient approach can for you use. You can also run below script in Azure Devops pipeline, but compare with running in command line, it is a bit cumbersome.
Run below script in your Powershell command line or Powershell ISE:
$token = "{your PAT token}"
$url = 'https://feeds.dev.azure.com/{org name}/_apis/packaging/Feeds/{feed ID}/packages'
$token = [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes(":$($token)"))
$response = Invoke-RestMethod -Uri $url -Headers #{Authorization = "Basic $token"} -Method Get
$results = $response.value | Where {$_.name -eq "{Package Name}"} #|
Write-Host "results = $($results | ConvertTo-Json -Depth 100)"
Note: In the above script, you just need to replace the value of PAT token, Organization name and your package name.
Then you will get the info of the specified package, and you can copy the package ID from the command line and apply it in another place :
Note: The above script can also be applied in the Powershell task of Azure Devops without change anything.

Azure DevOps integration in Sentry: Associate commits

Did someone manage to integrate Azure DevOps in Sentry (sentry.io)? I stuck on "Associate commits with a Release" (see: https://docs.sentry.io/workflow/releases/?platform=browser#associate-commits-with-a-release)
I can not figure out a way how I can tell Sentry (by API) which commit ids are associated with a current release/deploy. How can I add a task to the pipeline which will post the commit ids to Sentry API? Or is there some other way to do it?
In azure devops, the Powershell task also support curl. So, you can execute the api in powershell task of VSTS pipeline directly.
In release pipeline, there has a pre-defined release variable, it stores the commit id which is associated with the current release pipeline: $(Release.Artifacts.{alias}.SourceVersion). Here alias is the artifacts name, and you can get it by getting $(Release.PrimaryArtifactSourceAlias).
First, create variables like this:
Then you can apply the variable $(id) into that API, and execute the api in powershell task:
"refs": [{
"commit":"$(id)"
}]
Now, the commit id could be packed into the body of this api, and send to the Sentry server.
If there has multiple commits associate with this release, since the variable $(Release.Artifacts.{alias}.SourceVersion) I mentioned above only store the latest commit message, here you may need add additional scripts to get what you want by Build id.
In release pipeline, with $(Build.BuildId) you can get the corresponding buildid which associate with this release. And then, you could get the commits(changes) by using this API:
GET https://dev.azure.com/{organization}/{project}/_apis/build/changes?fromBuildId={fromBuildId}&toBuildId={toBuildId}&api-version=5.1-preview.2
You could apply these powershell script into your task without change anything because this script is universal among powershell-ise, powershell command line and powershell task in VSTS.
$token = "{PAT token}"
$url="https://dev.azure.com/{org name}/{project name}/_apis/build/changes?fromBuildId={id1}&toBuildId={id2}"
$token = [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes(":$($token)"))
$response = Invoke-RestMethod -Uri $url -Headers #{Authorization = "Basic $token"} -Method Get
Write-Host "results = $($response.value.id | ConvertTo-Json -Depth 100)"
Now, you could get the list of commits which associate with the build and corresponding release.

Upload Files to Azure Web App using Kudu Rest API - 409 Error

I'm trying to upload some files to my webapp using Kudu to the below url:
https://($websitename.scm.azurewebsites.net/api/vfs/site/wwwroot/ using powershell
I have obtained the publishing username and password and can authenticate fine
However when i try to upload the files i'm getting the below error using the below code:
function Upload-FileToWebApp($kuduHeader,$KuduURL,$files)
{
$kuduURL = https://$websitename.scm.azurewebsites.net/api/vfs/site/wwwroot/
$result = Invoke-RestMethod -Uri $kuduUrl `
-Headers #{Authorization=$kuduheader;"If-Match"="*"} `
-Method PUT `
-InFile $files `
-ContentType "multipart/form-data"
Invoke-RestMethod : {"Message":"The resource represents a directory which can not be updated."}
I have tried to access this URL using the ARC chrome addin and this brings back the same error '409 conflict Message": "The resource represents a directory which can not be updated."
Get seems to work fine
Thanks in Advance!
The problem is that you are doing a PUT on a directory, which has the semantic of creating the directory, when what you're trying to do is upload a file.
You need to change https://$websitename.scm.azurewebsites.net/api/vfs/site/wwwroot/ to https://$websitename.scm.azurewebsites.net/api/vfs/site/wwwroot/MyFile.txt.
And note that the vfs API can only upload one file at a time. If you want to upload multiple, you can use the zip API. See https://github.com/projectkudu/kudu/wiki/REST-API#zip for details.