Related
I have the following definition in my pipeline that I am running on Azure DevOps Server Version Dev17.M153.3
After saving the change I can see the following content has been added to pipeline definition
"approvals": [
{
"rank": 1,
"isAutomated": false,
"isNotificationOn": false,
"approver": {
"displayName": "Aouslender, Alexey",
"url": "http://tdc1tfsapp01:8080/tfs/DefaultCollection/_apis/Identities/2d86d86b-fe02-4e22-aa53-4315cdb3821c",
"_links": {
"avatar": {
"href": "http://tdc1tfsapp01:8080/tfs/DefaultCollection/_apis/GraphProfile/MemberAvatars/win.Uy0xLTUtMjEtMzMwNDk4NzQ2Ni0xODkxMDA3NDIzLTI5MjUxNTc3OTctNDU4NDA1"
}
},
"id": "2d86d86b-fe02-4e22-aa53-4315cdb3821c",
"uniqueName": "DOMAIN\\PXXXXXX",
"imageUrl": "http://tdc1tfsapp01:8080/tfs/DefaultCollection/_apis/GraphProfile/MemberAvatars/win.Uy0xLTUtMjEtMzMwNDk4NzQ2Ni0xODkxMDA3NDIzLTI5MjUxNTc3OTctNDU4NDA1",
"descriptor": "win.Uy0xLTUtMjEtMzMwNDk4NzQ2Ni0xODkxMDA3NDIzLTI5MjUxNTc3OTctNDU4NDA1"
},
"id": 3546
}
]
Now I am exporting pipeline, using export option. Then I am deleting pipeline and importing it using exported json file.
The imported pipeline missing the Approvers definition, nevertheless I can see the definition in exported json.
"preDeployApprovals": {
"approvals": [
{
"rank": 1,
"isAutomated": false,
"isNotificationOn": false,
"approver": {
"displayName": "Aouslender, Alexey",
"url": "http://tdc1tfsapp01:8080/tfs/DefaultCollection/_apis/Identities/2d86d86b-fe02-4e22-aa53-4315cdb3821c",
"_links": {
"avatar": {
"href": "http://tdc1tfsapp01:8080/tfs/DefaultCollection/_apis/GraphProfile/MemberAvatars/win.Uy0xLTUtMjEtMzMwNDk4NzQ2Ni0xODkxMDA3NDIzLTI5MjUxNTc3OTctNDU4NDA1"
}
},
"id": "2d86d86b-fe02-4e22-aa53-4315cdb3821c",
"uniqueName": "DOMAIN\\PXXXXXX",
"imageUrl": "http://tdc1tfsapp01:8080/tfs/DefaultCollection/_apis/GraphProfile/MemberAvatars/win.Uy0xLTUtMjEtMzMwNDk4NzQ2Ni0xODkxMDA3NDIzLTI5MjUxNTc3OTctNDU4NDA1",
"descriptor": "win.Uy0xLTUtMjEtMzMwNDk4NzQ2Ni0xODkxMDA3NDIzLTI5MjUxNTc3OTctNDU4NDA1"
},
"id": 3535
}
],
"approvalOptions": {
"requiredApproverCount": null,
"releaseCreatorCanBeApprover": true,
"autoTriggeredAndPreviousEnvironmentApprovedCanBeSkipped": false,
"enforceIdentityRevalidation": false,
"timeoutInMinutes": 0,
"executionOrder": 1
}
}
Am I missing something here or is it actually a Microsoft bug?
It's by design. Following properties in the release definition are not imported: Agent Queues, Deployment Groups, Deployment Group Tags, Approvals, Variable Groups and values of secret variables.
Generally if in the same team project you can Clone the release definition directly.
We have a Azure DevOps Pipeline Release Definition, and i am looking at putting in place some automation for a new 'Stage' to be created from a template when a pull request is triggered on branch x, and the stage to be removed when the branch is deleted. i will be using github actions for this.
The API doc's are not super easy to follow.
My question are:
is this possible, dose the API support making such adding and removing of stage's to a _releaseDefinition ?
if so is there any examples on how to do this ?
Doc's
https://learn.microsoft.com/en-us/rest/api/azure/devops/release/releases/update%20release?view=azure-devops-rest-5.1#releasedefinitionshallowreference
The api you should use is Update-definition api:
PUT https://vsrm.dev.azure.com/{org name}/{project name}/_apis/release/definitions?api-version=5.1
For the request body of adding stage/removing stage, it in fact only made changes into environments parameter:
One stage definition corresponds to one grey code block.
Adding stage: Add a template JSON code block of stage definition(the grey one display in my left screenshots). This code structure is fixed.
Removing stage: Remove the complete corresponding stage definition.
Here is the one complete stage definition sample:
{
"id": -1,
"name": "Stage 3",
"rank": 3,
"variables": {},
"variableGroups": [],
"preDeployApprovals": {
"approvals": [
{
"rank": 1,
"isAutomated": true,
"isNotificationOn": false,
"id": 7
}
],
"approvalOptions": {
"requiredApproverCount": null,
"releaseCreatorCanBeApprover": false,
"autoTriggeredAndPreviousEnvironmentApprovedCanBeSkipped": false,
"enforceIdentityRevalidation": false,
"timeoutInMinutes": 0,
"executionOrder": "beforeGates"
}
},
"deployStep": {
"id": 8
},
"postDeployApprovals": {
"approvals": [
{
"rank": 1,
"isAutomated": true,
"isNotificationOn": false,
"id": 9
}
],
"approvalOptions": {
"requiredApproverCount": null,
"releaseCreatorCanBeApprover": false,
"autoTriggeredAndPreviousEnvironmentApprovedCanBeSkipped": false,
"enforceIdentityRevalidation": false,
"timeoutInMinutes": 0,
"executionOrder": "afterSuccessfulGates"
}
},
"deployPhases": [
{
"deploymentInput": {
"parallelExecution": {
"parallelExecutionType": "none"
},
"agentSpecification": {
"identifier": "vs2017-win2016"
},
"skipArtifactsDownload": false,
"artifactsDownloadInput": {
"downloadInputs": []
},
"queueId": 247,
"demands": [],
"enableAccessToken": false,
"timeoutInMinutes": 0,
"jobCancelTimeoutInMinutes": 1,
"condition": "succeeded()",
"overrideInputs": {}
},
"rank": 1,
"phaseType": "agentBasedDeployment",
"name": "Agent job",
"refName": null,
"workflowTasks": []
}
],
"environmentOptions": {
"emailNotificationType": "OnlyOnFailure",
"emailRecipients": "release.environment.owner;release.creator",
"skipArtifactsDownload": false,
"timeoutInMinutes": 0,
"enableAccessToken": false,
"publishDeploymentStatus": true,
"badgeEnabled": false,
"autoLinkWorkItems": false,
"pullRequestDeploymentEnabled": false
},
"demands": [],
"conditions": [],
"executionPolicy": {
"concurrencyCount": 1,
"queueDepthCount": 0
},
"schedules": [],
"owner": {
"displayName": "{user name}",
"id": "{user id}",
"isContainer": false,
"uniqueName": "{creator account}",
"url": "https://dev.azure.com/{org name}/"
},
"retentionPolicy": {
"daysToKeep": 30,
"releasesToKeep": 3,
"retainBuild": true
},
"processParameters": {},
"properties": {
"BoardsEnvironmentType": {
"$type": "System.String",
"$value": "unmapped"
},
"LinkBoardsWorkItems": {
"$type": "System.String",
"$value": "False"
}
},
"preDeploymentGates": {
"id": 0,
"gatesOptions": null,
"gates": []
},
"postDeploymentGates": {
"id": 0,
"gatesOptions": null,
"gates": []
},
"environmentTriggers": [],
"badgeUrl": "https://vsrm.dev.azure.com/{org}/_apis/{project name}/Release/badge/3c3xxx6414512/2/3"
},
Here has some key parameters you need pay attention: id, owner, rank and conditions.
id: This is the stage id you specified to stage, its value must less than 1. Any value that less than 1 is okay here.
owner: This is required. Or you will receive the message that notify you the stage must has owner.
rank: The natural numbers greater than 1. Here I suggest you increment it based on other stages.
conditions: This is the one which you can configure which stage the current new one will depend on. The nutshell is it used to specify stage execution location of release.
When you updating release, you must pack and set the whole release definition as request body. Get the original one, add new customized stage definition part into it. Then update to api.
In fact, I suggest you do adding a stage with UI for test. Then go History tab of release definition page. Then choose Compare difference of three dots.
We provided you the difference of definition in the panel(left panel is the original, the right is updated), and you can clearly get what you should focus on to apply your idea.
Title is a good summary.
The /api/get_checklists POST is deprecated and returns back empty data. So I use the GET /fieldapi/checklists/v1/ to get the list of checklist items, and then I used the id in the GET /fieldapi/checklists/v1/:id to get the 'complete details.' Unfortunately the JSON data does not include the location/area (I have verified this by querying the data, then changing the location, querying it again, and comparing the results). Looking for a way to get this information.
Side note: Not a fan of including the ticket in the URL param. The GET does support including the ticket in the body though... (not a very good RESTFUL design though).
Using postman to query the information.
Some sample outputs (I scrubbed most of the values):
{
"id": "",
"project_id": "",
"created_at": "",
"updated_at": "",
"created_by": "",
"status": "Open",
"company": {},
"description": "",
"source": [
{
"id": "",
"type": "Equipment"
}
],
"identifier": "",
"template": {
"id": "",
"name": ""
},
"checklist_type": "",
"name": "",
"priority": "",
"signatures": [],
"attachments": [],
"custom_field_values": [
{
"id": "",
"name": "",
"value": "",
"display_type": "",
"possible_values": [
"",
"",
"",
""
]
},
{
"id": "",
"name": "",
"value": "",
"display_type": "",
"possible_values": [
"",
"",
"",
"",
"",
"",
"",
"",
""
]
}
],
"comments": [],
"sections": [
]
}
our engineer team confirmed it is true the location isn’t included in fieldapi/checklists/v1:id. And the example in API document result doesn’t show it returns location. Sorry if this a bad news to you. I logged a wish CS-35616 to ask for exposing location with fieldapi/checklists/v1:id.
As to The /api/get_checklists POST is deprecated and returns back empty data. , you might need to specify ‘checklist_ids’ and ‘forced_checklist_ids’in the call. While by api/get_checklist_headers, get the ids ( completed_checklist_id) as the input.
I have an Azure Functions (2.0) instance deployed by an ARM Template using Azure DevOps pipelines. I have another pipeline that deploys a functions application to the instance through zip deploy. This almost works perfectly, however, if I deploy the functions Infrastructure as Code, then deploy the app and then redeploy the Infrastructure as Code, my functions app is removed and all the functions disappear. I am using the incremental deployment so I cont see why it does this. Any thoughts on why it is behaving like this or how to troubleshoot?
I have copied my resource group deployment script and ARM template below.
New-AzureRmResourceGroupDeployment -Name ((Get-ChildItem $TemplateFile).BaseName + '-' + ((Get-Date).ToUniversalTime()).ToString('MMdd-HHmm')) `
-ResourceGroupName $ResourceGroupName `
-TemplateFile $TemplateFile `
-TemplateParameterFile $TemplateParametersFile `
-Mode Incremental `
#OptionalParameters `
-Force -Verbose `
-AdminsGroup $AdminsGroup `
-AdminsGroupObjectId $AdminsGroupObjectId `
-ErrorVariable ErrorMessages
ARM template
{
"type": "Microsoft.Web/serverfarms",
"sku": {
"name": "Y1",
"tier": "Dynamic",
"size": "Y1",
"family": "Y",
"capacity": 0
},
"kind": "app",
"apiVersion": "2016-09-01",
"name": "[variables('FunctionPlanNameMyStuff')]",
"location": "[resourceGroup().location]",
"properties": {
"name": "[variables('FunctionPlanNameMyStuff')]",
"perSiteScaling": false,
"reserved": false,
"targetWorkerCount": 0,
"targetWorkerSizeId": 0
}
},
{
"comments": "MyStuff Functions Site",
"type": "Microsoft.Web/sites",
"kind": "functionapp",
"name": "[variables('FunctionSiteNameMyStuff')]",
"apiVersion": "2016-08-01",
"location": "[resourceGroup().location]",
"identity": {
"type": "SystemAssigned"
},
"scale": null,
"properties": {
"enabled": true,
"hostNameSslStates": [
{
"name": "[concat(variables('FunctionSiteNameMyStuff'),'.azurewebsites.net')]",
"sslState": "Disabled",
"virtualIP": null,
"thumbprint": null,
"toUpdate": null,
"hostType": "Standard"
},
{
"name": "[concat(variables('FunctionSiteNameMyStuff'),'.scm.azurewebsites.net')]",
"sslState": "Disabled",
"virtualIP": null,
"thumbprint": null,
"toUpdate": null,
"hostType": "Repository"
}
],
"serverFarmId": "[resourceId('Microsoft.Web/serverfarms', variables('FunctionPlanNameMyStuff'))]",
"reserved": false,
"siteConfig": null,
"scmSiteAlsoStopped": false,
"hostingEnvironmentProfile": null,
"clientAffinityEnabled": false,
"clientCertEnabled": false,
"hostNamesDisabled": false,
"containerSize": 1536,
"dailyMemoryTimeQuota": 0,
"cloningInfo": null
},
"resources": [
{
"apiVersion": "2015-08-01",
"name": "appsettings",
"type": "config",
"dependsOn": [
"[resourceId('Microsoft.Web/Sites', variables('FunctionSiteNameMyStuff'))]",
"[resourceId('Microsoft.Storage/storageAccounts', variables('FunctionStorageAccountMyStuff'))]"
],
"properties": {
"AzureWebJobsStorage": "[concat('DefaultEndpointsProtocol=https;AccountName=', variables('FunctionStorageAccountMyStuff'), ';AccountKey=', listKeys(variables('FunctionStorageResourceIdMyStuff'), '2017-10-01').keys[0].value)]",
"AzureWebJobsDashboard": "[concat('DefaultEndpointsProtocol=https;AccountName=', variables('FunctionStorageAccountMyStuff'), ';AccountKey=', listKeys(variables('FunctionStorageResourceIdMyStuff'), '2017-10-01').keys[0].value)]",
"WEBSITE_CONTENTAZUREFILECONNECTIONSTRING": "[concat('DefaultEndpointsProtocol=https;AccountName=', variables('FunctionStorageAccountMyStuff'), ';AccountKey=', listKeys(variables('FunctionStorageResourceIdMyStuff'),'2015-05-01-preview').key1)]",
"WEBSITE_CONTENTSHARE": "[toLower(variables('FunctionSiteNameMyStuff'))]",
"FUNCTIONS_EXTENSION_VERSION": "~2",
"FUNCTIONS_WORKER_RUNTIME": "dotnet",
"FUNCTION_APP_EDIT_MODE": "readwrite",
"KeyVaultUrl": "[concat('https://', variables('KeyVaultName'), '.vault.azure.net/')]",
"DeveloperMode": false
}
}
],
"dependsOn": [
"[resourceId('Microsoft.Web/serverfarms', variables('FunctionPlanNameMyStuff'))]",
"[resourceId('Microsoft.Storage/storageAccounts', variables('FunctionStorageAccountMyStuff'))]"
]
},
{
"comments": "Functions web site config",
"type": "Microsoft.Web/sites/config",
"name": "[concat(variables('FunctionSiteNameMyStuff'), '/', 'web')]",
"apiVersion": "2016-08-01",
"location": "[resourceGroup().location]",
"tags": {
},
"scale": null,
"properties": {
"numberOfWorkers": 1,
"defaultDocuments": [
"Default.htm",
"Default.html",
"Default.asp",
"index.htm",
"index.html",
"iisstart.htm",
"default.aspx",
"index.php",
"hostingstart.html"
],
"netFrameworkVersion": "v4.0",
"phpVersion": "5.6",
"pythonVersion": "",
"nodeVersion": "",
"linuxFxVersion": "",
"requestTracingEnabled": false,
"remoteDebuggingEnabled": false,
"remoteDebuggingVersion": null,
"httpLoggingEnabled": false,
"logsDirectorySizeLimit": 35,
"detailedErrorLoggingEnabled": false,
"publishingUsername": "[concat('$', variables('FunctionSiteNameMyStuff'), 'pubuser')]",
"publishingPassword": "[concat(variables('FnAppPublishingPasswordMyStuff'), uniqueString(resourceGroup().id))]",
"appSettings": null,
"metadata": null,
"connectionStrings": null,
"machineKey": null,
"handlerMappings": null,
"documentRoot": null,
"scmType": "None",
"use32BitWorkerProcess": true,
"webSocketsEnabled": false,
"alwaysOn": false,
"javaVersion": null,
"javaContainer": null,
"javaContainerVersion": null,
"appCommandLine": "",
"managedPipelineMode": "Integrated",
"virtualApplications": [
{
"virtualPath": "/",
"physicalPath": "site\\wwwroot",
"preloadEnabled": false,
"virtualDirectories": null
}
],
"winAuthAdminState": 0,
"winAuthTenantState": 0,
"customAppPoolIdentityAdminState": false,
"customAppPoolIdentityTenantState": false,
"runtimeADUser": null,
"runtimeADUserPassword": null,
"loadBalancing": "LeastRequests",
"routingRules": [],
"experiments": {
"rampUpRules": []
},
"limits": null,
"autoHealEnabled": false,
"autoHealRules": null,
"tracingOptions": null,
"vnetName": "",
"siteAuthEnabled": false,
"siteAuthSettings": {
"enabled": null,
"unauthenticatedClientAction": null,
"tokenStoreEnabled": null,
"allowedExternalRedirectUrls": null,
"defaultProvider": null,
"clientId": null,
"clientSecret": null,
"issuer": null,
"allowedAudiences": null,
"additionalLoginParams": null,
"isAadAutoProvisioned": false,
"googleClientId": null,
"googleClientSecret": null,
"googleOAuthScopes": null,
"facebookAppId": null,
"facebookAppSecret": null,
"facebookOAuthScopes": null,
"twitterConsumerKey": null,
"twitterConsumerSecret": null,
"microsoftAccountClientId": null,
"microsoftAccountClientSecret": null,
"microsoftAccountOAuthScopes": null
},
"cors": null,
"push": null,
"apiDefinition": {
"url": "[concat('https://', variables('FunctionPlanNameMyStuff'), '.azurewebsites.net/swagger/docs/v1')]"
},
"autoSwapSlotName": null,
"localMySqlEnabled": false,
"managedServiceIdentityId": null,
"ipSecurityRestrictions": null,
"http20Enabled": false,
"minTlsVersion": "1.0"
},
"dependsOn": [
"[resourceId('Microsoft.Web/sites', variables('FunctionSiteNameMyStuff'))]"
]
},
Add this app setting to your template:
{ "name": "WEBSITE_RUN_FROM_PACKAGE", "value": "1" }
Functions can only be run from zip file if this setting is present, and redeploying a template without it will remove existing value for this setting (if there was any).
So #curiouscoder's answer does work but it requires more than a one liner really so I'm expanding on it here.
I hit this issue after adding some CORS origins to my ARM template, when I ran the template it removed the functions, to fix it you need to do the following (this assumes a Windows based function app which yours is and so is mine and that you're deploying from Azure DevOps):
Add the WEBSITE_RUN_FROM_PACKAGE setting to your function's app service settings and set it to 1 (can also be set to a URL where the package is but that affects cold start up negatively for function apps)
Now confusingly in your Azure DevOps release pipeline set your deployment method to "zip deploy" and not to "run from package"!
Re-running your ARM template with changes will now not remove the site
The function app will now be running from the zip file rather from a deployment direct to the wwwroot folder, this means the wwwroot folder is made readonly. You'll get errors if you try to edit anything there:
The benefit of this approach is that you can't half deploy your app and having it read only means you can't accidentally mess with it once deployed.
The above does not work as smoothly as a slot change and will require the app to be restarted so it needs to be used in conjunction with a staging app or slots although as of writing the latter are still in preview for function apps.
The original github announcement is worth a read here as they're more detailed than the docs.
Your ARM template is problematic because it sets the App Settings as a separate action from the app creation, which is not supported when using Azure Files.
See this sample for guidance.
I need to fail a build on TFS 2018 if its pipeline is not fully complete. Batching just the build is not enough; the linked release must be finished as well before another build can begin. My idea is to do this in a PowerShell script via the REST API.
I see in the official documentation here that there's a property called TaskStatus. It provides a value of inProgress, presumably for releases that are in progress. This might do the trick, but there's no indication of how to actually use it.
Using the REST API, how can I get the TaskStatus of a given release?
The in process and some other values such as succeeded, canceled just stand for the status of a task in release pipeline.
You could simply use the Rest API to get a release
GET https://fabrikam.vsrm.visualstudio.com/MyFirstProject/_apis/release/releases/{releaseId}?api-version=4.1-preview.6
There should be a value called status:
"id": 18,
"name": "Release-18",
"status": "abandoned",
"createdOn": "2017-06-16T01:36:20.397Z",
"modifiedOn": "2017-06-16T01:36:21.07Z",
"modifiedBy": {
"id": "4adb1680-0eac-6149-b5ee-fc8b4f6ca227",
"displayName": "Chuck Reinhart",
"uniqueName": "fabfiber#outlook.com",
"url": "https://app.vssps.visualstudio.com/A168224e4-29ff-4081-9954-c8780ce81117/_apis/Identities/4adb1680-0eac-6149-b5ee-fc8b4f6ca227",
"imageUrl": "https://fabfiber-inc.visualstudio.com/_api/_common/identityImage?id=4adb1680-0eac-6149-b5ee-fc8b4f6ca227"
},
"createdBy": {
"id": "4adb1680-0eac-6149-b5ee-fc8b4f6ca227",
"displayName": "Chuck Reinhart",
"uniqueName": "fabfiber#outlook.com",
"url": "https://app.vssps.visualstudio.com/A168224e4-29ff-4081-9954-c8780ce81117/_apis/Identities/4adb1680-0eac-6149-b5ee-fc8b4f6ca227",
"imageUrl": "https://fabfiber-inc.visualstudio.com/_api/_common/identityImage?id=4adb1680-0eac-6149-b5ee-fc8b4f6ca227"
},
"environments": [
{
"id": 69,
"releaseId": 18,
"name": "Dev",
"status": "notStarted",
"variables": {},
"preDeployApprovals": [],
"postDeployApprovals": [],
"preApprovalsSnapshot": {
"approvals": [
{
"rank": 1,
"isAutomated": false,
"isNotificationOn": false,
"approver": {
"id": "4adb1680-0eac-6149-b5ee-fc8b4f6ca227",
"displayName": "Chuck Reinhart",
"uniqueName": "fabfiber#outlook.com",
"url": "https://app.vssps.visualstudio.com/A168224e4-29ff-4081-9954-c8780ce81117/_apis/Identities/4adb1680-0eac-6149-b5ee-fc8b4f6ca227",
"imageUrl": "https://fabfiber-inc.visualstudio.com/_api/_common/identityImage?id=4adb1680-0eac-6149-b5ee-fc8b4f6ca227"
},
"id": 0
}
You could fetch the value status in your return json file, and judge if the release succeed or failed. Finally according to this status to trigger another build or not.
Update
A sample of the returned json with task's status info:
"deploymentJobs": [
{
"job": {
"id": 5,
"timelineRecordId": "855ea6d6-9ed0-442d-b921-0c4add8bb068",
"name": "Release",
"dateStarted": "2018-07-04T08:53:05.9133333Z",
"dateEnded": "2018-07-04T08:53:21.34Z",
"startTime": "2018-07-04T08:53:05.9133333Z",
"finishTime": "2018-07-04T08:53:21.34Z",
"status": "succeeded",
"rank": 1,
"issues": [],
"agentName": "DFA00"
},
"tasks": [
{
"id": 1,
"timelineRecordId": "fa3bb635-eab4-4c1b-9cc0-fdccd7ced33f",
"name": "Initialize Job",
"dateStarted": "2018-07-04T08:53:06.5833333Z",
"dateEnded": "2018-07-04T08:53:06.8033333Z",
"startTime": "2018-07-04T08:53:06.5833333Z",
"finishTime": "2018-07-04T08:53:06.8033333Z",
"status": "succeeded",
"rank": 1,
"issues": [],
"agentName": "DFA00",
"logUrl": "http://xxxx:8080/tfs/DefaultCollection/7658559e-6e61-422a-952b-a5fce0b6ca1d/_apis/Release/releases/49/environments/49/tasks/1/logs?releaseDeployPhaseId=54"
},
There should be timelinerecord, starttime, finishtime, status for a task deployment result in a single release.