How to specify git author/committer for PullRequest merge in Azure DevOps? - azure-devops-rest-api

I have defined a release pipeline to synchronize code between two git repositories in Azure DevOps. The process requires a PullRequest in the destination repo which is created and completed using the WebAPI.
The pipeline is executed by the build agent running using a Windows domain service account. So, the PullRequest is created and completed on behalf of the service account, which is also mentioned as author, committer, etc. in the git history after merge is completed. (According to our rules the PR must be merged using squash commit.)
I would like see a different user in the git history after (squash) merge.
Can I specify the user (e.g. the user triggering the release pipeline) using WebAPI?
I did not find such option in the API documentation.
Any other recommendation? Maybe convention like adding "co-authored-by" to commit message like github?

When you use Pull Requests-Create rest api to create a pull request, the pull request creator is determined by the creator of the PAT you used for authentication (e.g. I used the PAT of hughl01 user as the authentication to create the pull request, then the creator of the pull request is hughl01).
Test in Postman:
Sample test script in powershell task:
$token = "{User-created PAT}"
$url = "https://dev.azure.com/{org}/{pro}/_apis/git/repositories/{repoId}/pullrequests?api-version=6.0"
$token = [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes(":$($token)"))
$JSON = #'
{
"sourceRefName": "refs/heads/dev2",
"targetRefName": "refs/heads/master",
"title": "ForTest",
"description": "Adding a new feature"
}
'#
$response = Invoke-RestMethod -Uri $url -Headers #{Authorization = "Basic $token"} -Method Post -ContentType application/json -body $JSON
You can create a variable group, with the release trigger as the variable name, and the PAT corresponding to the user as the variable value and set the value of the variable to secret. Then get the name of the triggerer through the predefined variable $(Release.RequestedFor) in the script, then obtain the corresponding PAT according to the trigger name to create pull request.

Related

How to get Package ID given a package name via AzureDevOps REST API

If I have just the package name, is it possible to get the package ID using a single API call. Looks like Package ID is required for any further API calls - to get versions of a package etc.,
Or is the only way to get all the packages from the feed, match with the name and then get the ID from that?
Reference API: https://learn.microsoft.com/en-us/rest/api/azure/devops/artifacts/artifact%20%20details/get%20package?view=azure-devops-rest-6.0
You can specify a packageNameQuery query parameter in the Get Packages rest api to retrieve the package's information with a given name.
GET https://feeds.dev.azure.com/{organization}/{project}/_apis/packaging/Feeds/{feedId}/packages?protocolType={protocolType}&packageNameQuery={packageNameQuery}&normalizedPackageName={normalizedPackageName}&includeUrls={includeUrls}&includeAllVersions={includeAllVersions}&isListed={isListed}&getTopPackageVersions={getTopPackageVersions}&isRelease={isRelease}&includeDescription={includeDescription}&$top={$top}&$skip={$skip}&includeDeleted={includeDeleted}&isCached={isCached}&directUpstreamId={directUpstreamId}&api-version=6.0-preview.1
For Organization scoped feeds:
$url= "https://feeds.dev.azure.com/{organization}/_apis/packaging/Feeds/{feedid or feedName}/packages?packageNameQuery={package Name}&api-version=6.0-preview.1"
For Project scoped feeds:
$url= "https://feeds.dev.azure.com/{organization}/{project}/_apis/packaging/Feeds/{feedid or feedName}/packages?packageNameQuery={package Name}&api-version=6.0-preview.1"
See below example:
#Organization scoped feed
$url= "https://feeds.dev.azure.com/{organization}/_apis/packaging/Feeds/{feedid or feedName}/packages?packageNameQuery={package Name}&api-version=6.0-preview.1"
$PAT="Personal Access Token"
$base64AuthInfo= [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes(":$($PAT)"))
$ArtInfo = Invoke-RestMethod -Uri $url -Headers #{Authorization = ("Basic {0}" -f $base64AuthInfo)} -Method get

Get default Testers for Test Suite with powershell script

trying to get the default testers that are assigned to a test suite in azure devops with a powershell script
$coreAreaId = "3b95fb80-fdda-4218-b60e-1052d070ae6b"
$tfsBaseUrl = GetUrl -orgUrl $orgUrl -header $header -AreaId $coreAreaId
$testerUrl = "$($tfsBaseUrl)$projectname/_apis/test/Plans/$testplanid/suites/$testsuiteid" +"?" + "`$expand" + "=1&api-version=5.0"
$tester = Invoke-RestMethod -Uri $testerUrl -Method Get -ContentType "application/json" -Headers $header
Url is like this:
"https://example.com/xxx/_apis/test/Plans/12572/suites/12583?$expand=1&api-version=5.0"
In the data I get back from devops there is no item
"defaultTesters ShallowReference[] Test suite default testers"
as described here:
https://learn.microsoft.com/en-us/rest/api/azure/devops/test/test%20%20suites/get%20test%20suite%20by%20id?view=azure-devops-server-rest-5.0
I tried and got the same result with powershell script calling test suite by id,
BTW,I found there was not an option allowing me to set a default tester for a test suite. Do not know how you assign a default tester to a test suite?
But for specific test case, assigned tester can be retrieved by rest API.
I have submitted an issue to Microsoft document team to track this issue.

Is it possible to use a variable in the Agent.Name demand for tfs?

I am trying to force the run of a specific agent phase on a specific agent. My variable however does not seems to be picked up. I get the error:
No agent found in pool TEST which satisfies the specified demands:
Agent.Name -equals $(Release.ReleaseName)
vstest
Agent.Version -gtVersion 2.103.0
Is this possible?
I wanted to do something similar. I had 2 "environments" in the TFS release definition. The first one ("MyEnvironment-Setup") did setup like big file copies and database script generation. The second ("MyEnvironment") did the actual deployment. I needed them both to run on the same agent.
What I ended up doing is using the TFS API during "MyEnvironment-Setup" to modify the currently running release instance and set the agent demand for "MyEnvironment".
Several things were necessary to make this happen.
In "MyEnvironment-Setup" > Run on Agent > Additional Options, I enabled "Allow scripts to access the OAuth token"
In the left pane of the release definition screen where it lists all release definitions, I clicked the ellipsis next to "All release definitions" and selected "Security". Then for the "Project Collection Build Service (TEAM FOUNDATION)" user, I set "Edit release definition" and "Manage releases" to "Allow".
I called the following Powershell method in "MyEnvironment-Setup"
function Set-FinalAgent()
{
# Force the "MyEnvironment" step to run on the same agent as the "MyEnvironment-Setup" step
$baseApiUrl = "$($env:SYSTEM_TEAMFOUNDATIONCOLLECTIONURI)$env:SYSTEM_TEAMPROJECTID/_apis"
$apiVersion = "3.1-preview"
$header = #{ Authorization = "Bearer $env:SYSTEM_ACCESSTOKEN" }
$environmentToModify = $($env:Release_EnvironmentName).Replace("-Setup", "")
$releaseID = $env:Release_ReleaseID
$release = Invoke-RestMethod -Uri "$baseApiUrl/release/releases/$($releaseID)?api-version=$apiVersion" -Method GET -Header $header
($release.environments | where name -eq $environmentToModify).deployPhasesSnapshot[0].deploymentInput.demands += "Agent.Name -equals $($env:Agent_Name)"
# Compression is needed for the body to contain all of the info for larger release definitions when running on older servers
$body = $release | ConvertTo-Json -Depth 100 -Compress
Invoke-RestMethod -Uri "$baseApiUrl/release/releases/$($releaseID)?api-version=$apiVersion" -Method PUT -Header $header -ContentType application/json -Body $body
}
If you want to test and tweak this in Powershell ISE or something where you don't have access to the OAuth token, you can use a personal access token instead. In the top-right of your TFS Web UI, click your profile picture and select "Security" to generate a PAT. Then you can replace the header in the script above with the following:
$header = #{Authorization = 'Basic ' + [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(":$($personalAccessToken)"))}

How to Login to VSTS programmatically

I have an automatic branching utility that does various operations.
We have upgraded to VSTS and I am having trouble using the Tfs calls with the new server:
//login
NetworkCredential netCred = new NetworkCredential("emailAddress", password");
BasicAuthCredential basicCred = new BasicAuthCredential(netCred);
TfsClientCredentials tfsCred = new TfsClientCredentials(basicCred);
tfsCred.AllowInteractive = false;
TfsTeamProjectCollection tfsServer = new TfsTeamProjectCollection(new Uri("https://myco.visualstudio.com/mycoll"), tfsCred);
// get a local workspace
VersionControlServer sc = server.GetService(typeof(VersionControlServer)) as VersionControlServer;
... other code
and then boom!
"You are not authorized to access https://myco.visualstudio.com/mycoll"
Is there some setting somewhere?
Should I try and use the REST API?
Am I calling something I shouldn't?
I've tried all sorts of formats for the URI, with :8080, with /tfs in the path to no avail!
You can use PAT (Personal Access Token) to access VSTS. Click on your profile in VSTS and go to security menu item. You can define a PAT in there. Keep the PAT saved as it will only be shown once.
Define the scope as per your needs
You can use the PAT to access TFS REST API as shown in following PowerShell sample. Using https://yourAccount.visualstudio.com or https://yourAccount.visualstudio.com/DefaultCollection for ColletionUri parameter is OK.
param(
[Parameter(Mandatory=$true)]
[string] $token,
[Parameter(Mandatory=$true)]
[string] $collectionUri
)
$User=""
# Base64-encodes the Personal Access Token (PAT) appropriately
$base64AuthInfo = [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(("{0}:{1}" -f $User,$token)));
$header = #{Authorization=("Basic {0}" -f $base64AuthInfo)};
$Uri = $collectionUri + '/_apis/projects?api-version=1.0'
$projects = Invoke-RestMethod -Method Get -ContentType application/json -Uri $Uri -Headers $header
You can find C# code samples here https://www.domstamand.com/accessing-tfs-2017-programmatically/

Error 400 Bad Request when attempting to pull Skype for Business activity via Graph API

Alright, so after chatting with Microsoft "Professional Support" they couldn't help me. Told me to access the reports via the SfB Report GUI and export to Excel.
Yeah that's completely worthless to me.
After doing a lot more reading, my 1st example to authenticate was out of date.
Now I have a fully functional oAuth2 PowerShell script that gets me a valid token.
But I'm having the same issue when I use the Graph Explorer (403 Forbidden).
I know the token is working because I can query other information \ if I take away the VAR for the token from the GET header it errors stating the the Bearer Token is empty so everything is right.
Microsoft, if you're out there can someone please confirm that the SfB Report API is up and running for the statistics I'm attempting to pull?
UPDATED SCRIPT
#Obtaining oAuth2 Token from Microsoft Azure \ communicate with Microsoft Graph API
$ClientID = "MyID"
$client_Secret = "MySecretKey"
#Define URI for Azure Tenant
$Uri = "https://login.microsoftonline.com/MyTenantID/oauth2/token"
#Define Microsoft Graph - Skype for Business reports interface URI
$exportSfB = "https://graph.microsoft.com/beta/reports/SfbActivity(view='Detail',date='2017-04-11')/content"
#Define the body of the request
$Body = #{grant_type='client_credentials';client_id=$ClientID;client_secret=$client_secret;resource='https://graph.microsoft.com'}
#Define the content type for the request
$ContentType = "application/x-www-form-urlencoded"
#Invoke REST method. This handles the deserialization of the JSON result. Less effort than invoke-webrequest
$admAuth=Invoke-RestMethod -Uri $Uri -Body $Body -Method Post
#Construct the header value with the access_token just recieved
$HeaderValue = "Bearer " + $admauth.access_token
#Query Microsoft Graph with new Token
$result = Invoke-RestMethod -Headers #{Authorization=$HeaderValue} -Uri $exportSfB –Method Get -Verbose
#Results should be a .CSV
$result.string.'#text'
ORIGINAL THREAD
Can someone please have a look at this REST code and tell me what they think?
I'm receiving:
Invoke-RestMethod : The remote server returned an error: (400) Bad Request.
CategoryInfo : InvalidOperation
I haven't been able to pull a single Skype for Business activity report using Graph.
$tenant = "MyTenant.onmicrosoft.com"
function GetAuthToken
{
param
(
[Parameter(Mandatory=$true)]
$TenantName
)
$adal = "${env:ProgramFiles(x86)}\Microsoft SDKs\Azure\PowerShell\ServiceManagement\Azure\Services\Microsoft.IdentityModel.Clients.ActiveDirectory.dll"
$adalforms = "${env:ProgramFiles(x86)}\Microsoft SDKs\Azure\PowerShell\ServiceManagement\Azure\Services\Microsoft.IdentityModel.Clients.ActiveDirectory.WindowsForms.dll"
[System.Reflection.Assembly]::LoadFrom($adal) | Out-Null
[System.Reflection.Assembly]::LoadFrom($adalforms) | Out-Null
$clientId = "MyID"
$redirectUri = "urn:ietf:wg:oauth:2.0:oob"
$resourceAppIdURI = "https://graph.microsoft.com/"
$authority = "https://login.windows.net/$TenantName"
$authContext = New-Object "Microsoft.IdentityModel.Clients.ActiveDirectory.AuthenticationContext" -ArgumentList $authority
$authResult = $authContext.AcquireToken($resourceAppIdURI, $clientId,$redirectUri, "Auto")
return $authResult
}
# Set Token var
$token = GetAuthToken -TenantName $tenant
# Building Rest Api header with authorization token
$authHeader = #{
'Content-Type'='application\json'
'Authorization'=$token.CreateAuthorizationHeader()
}
$uri = "https://graph.microsoft.com/beta/reports/SfbActivity(view='Detail',date='2017-04-11')"
$output = (Invoke-RestMethod -Uri $uri –Headers $authHeader –Method Get –Verbose).value
You're missing /content in your URI. See doc here.
$uri = "https://graph.microsoft.com/beta/reports/SfbActivity(view='Detail',date='2017-04-11')/content"
Ok so after messing with the API and reading I decided to start over from scratch.
Turns out the problem the entire time was the App type in Azure. I was using an app that someone had created prior to me taking on the project. It's application type was set to "Web \ API" in Azure which was incorrect apparently. I created a new App with application type "Native", altered my code with the new secret access key and application client ID and I was able to start pulling down .csv files. The problem now is that the PSTN data isn't there. I created a ticket with the Microsoft Graph group on GitHub requesting information about whether or not they're aware of this problem. At this time, I'm unable to find a programmatic method of exporting PSTN call details via the API. You can keep an eye on their progress here for that request but beyond that I'm stuck until Microsoft Dev makes the SfBActivity detail report include those data fields: https://github.com/microsoftgraph/microsoft-graph-docs/issues/1133

Resources