AzureDevOps - Different behavior from custom task for Services and Server - azure-devops

I created a custom task using the documentation, however it works on Azure DevOps Services but on Server it gives the error
An error occurred while loading the YAML build pipeline. Value cannot be null. Parameter name: key
My first thoughts are "what is the parameter that is missing?" so i filled all the available and possible parameters and still continued with the error.
After that i went to the event viewer in the machine running Azure DevOps Server and got this error:
Detailed Message: The subscriber Pipelines Check Run: build completed event listener raised an exception while being notified of event Microsoft.TeamFoundation.Build2.Server.BuildCompletedEvent.
Exception Message: Value cannot be null.
Parameter name: definition and repository (type ArgumentNullException)
Exception Stack Trace: at Microsoft.TeamFoundation.Pipelines.Server.Providers.TfsGitProvider.TfsGitConnectionCreator.IsProviderDefinition(IVssRequestContext requestContext, BuildDefinition definition)
at Microsoft.TeamFoundation.Pipelines.Server.Extensions.BuildCompletedEventListener2.HandleCompletedEvent(IVssRequestContext requestContext, IReadOnlyBuildData build, BuildDefinition definition)
at Microsoft.TeamFoundation.Pipelines.Server.Extensions.BuildCompletedEventListener.ProcessEvent(IVssRequestContext requestContext, NotificationType notificationType, Object notificationEvent, Int32& statusCode, String& statusMessage, ExceptionPropertyCollection& properties)
at Microsoft.TeamFoundation.Framework.Server.TeamFoundationEventService.SubscriptionList.Notify(IVssRequestContext requestContext, NotificationType notificationType, Object notificationEventArgs, String& statusMessage, ExceptionPropertyCollection& properties, Exception& exception)
task.json:
{
"id": "25156245-9317-48e2-bcf4-7dab4c130a3e",
"name": "ping-pong-build-trigger",
"friendlyName": "Ping Pong Build Trigger",
"description": "Randomly trigger builds to find a sequenced build order",
"helpMarkDown": "https://github.com/brunomartinspro/Ping-Pong-Build-Trigger-AzureDevOps",
"category": "Build",
"author": "Bruno Martins (brunomartins.pro)",
"version": {
"Major": 1,
"Minor": 0,
"Patch": 0
},
"instanceNameFormat": "Ping Pong Build Trigger",
"properties": {
"mode": {
"type": "string",
"description": "Mode to be used",
"label": "Mode",
"required": "true"
},
"apiKey": {
"type": "string",
"label": "PAT",
"defaultValue": "",
"description": "Personal Access Token.",
"required": "true"
},
"source": {
"type": "string",
"label": "AzureDevOps Project URI",
"defaultValue": "http://kamina.azuredevops.local/DefaultCollection/Kamina",
"description": "AzureDevOps Project URI.",
"required": "true"
},
"projectName": {
"type": "string",
"label": "AzureDevOps Project Name",
"defaultValue": "Kamina",
"description": "AzureDevOps Project Name.",
"required": "true"
},
"sourceBranch": {
"type": "string",
"label": "Git Source Branch",
"defaultValue": "develop",
"description": "The branch the builds will trigger",
"required": "true"
},
"lastKnownFile": {
"type": "string",
"label": "Sequence Location",
"defaultValue": "",
"description": "The location of the Build Order.",
"required": "true"
},
"maxErrorCycles": {
"type": "int",
"label": "Maximum Error Cycles",
"defaultValue": 10,
"description": "The number of fails allowed.",
"required": "true"
},
"infiniteCycles": {
"type": "string",
"label": "Infinite Cycles",
"defaultValue": "false",
"description": "Infinite Cycles - only ends until everything succeeds.",
"required": "true"
}
},
"inputs": [{
"name": "mode",
"type": "string",
"label": "Mode",
"defaultValue": "AzureDevOps",
"helpMarkDown": "Mode to be used.",
"required": "true"
},
{
"name": "apiKey",
"type": "string",
"label": "PAT",
"defaultValue": "",
"helpMarkDown": "Personal Access Token.",
"required": "true"
},
{
"name": "source",
"type": "string",
"label": "AzureDevOps Project URI",
"defaultValue": "http://kamina.azuredevops.local/DefaultCollection/Kamina",
"helpMarkDown": "AzureDevOps Project URI.",
"required": "true"
},
{
"name": "projectName",
"type": "string",
"label": "AzureDevOps Project Name",
"defaultValue": "Kamina",
"helpMarkDown": "AzureDevOps Project Name.",
"required": "true"
},
{
"name": "sourceBranch",
"type": "string",
"label": "Git Source Branch",
"defaultValue": "develop",
"helpMarkDown": "The branch the builds will trigger",
"required": "true"
},
{
"name": "lastKnownFile",
"type": "string",
"label": "Sequence Location",
"defaultValue": "",
"helpMarkDown": "The location of the Build Order.",
"required": "true"
},
{
"name": "maxErrorCycles",
"type": "int",
"label": "Maximum Error Cycles",
"defaultValue": 10,
"helpMarkDown": "The number of fails allowed.",
"required": "true"
},
{
"name": "infiniteCycles",
"type": "string",
"label": "Infinite Cycles",
"defaultValue": "false",
"helpMarkDown": "Infinite Cycles - only ends until everything succeeds.",
"required": "true"
}
],
"execution": {
"PowerShell": {
"target": "ping-pong-build-trigger.ps1",
"argumentFormat": ""
}
}
}
vss-extension.json
{
"manifestVersion": 1,
"id": "ping-pong-build-trigger-task",
"name": "Ping Pong Build Trigger",
"version": "1.0.0",
"publisher": "BrunoMartinsPro",
"targets": [{
"id": "Microsoft.VisualStudio.Services"
}],
"description": "Randomly trigger builds to find a sequenced build order",
"categories": [
"Azure Pipelines"
],
"icons": {
"default": "extensionIcon.png"
},
"files": [{
"path": "task"
}],
"contributions": [{
"id": "ping-pong-build-trigger",
"type": "ms.vss-distributed-task.task",
"targets": [
"ms.vss-distributed-task.tasks"
],
"properties": {
"name": "task"
}
}]
}
How can i use a custom task in both Services and Server?
The .vsix can be downloaded in the release page of the Github Repository: https://github.com/brunomartinspro/Ping-Pong-Build-Trigger-AzureDevOps
Developer Community: https://developercommunity.visualstudio.com/content/problem/715570/server-and-services-have-different-behavior.html

So it appears that there is some sort of cache mechanism in the extensions, i need 3 azure devops server editions to debug.
The first one was used for development, the second one also for development but uninstalled and installed again, the third one for testing public releases.
I couldn't find the physical directory of where the cache gets stored, if there is cache at all.

Related

How to resolve "Validation error: The task.json file was not found in contribution task." when validating Azure DevOps extension?

I am attempting to build and validate an Azure DevOps extension that contains a task contribution but it fails to validate and returns "Validation error: The task.json file was not found in contribution task."
This is an example extension I have created that contains two things:
The root vss-extension.json file
A folder called "task" containing the "task.json" file
The command that I am running to validate the extension is as follows. I am running this from the root folder containing the vss-extension.json file.
tfx extension isvalid --publisher my-publisher --extension-id my-id --service-url https://marketplace.visualstudio.com/
vss-extension.json
{
"manifestVersion": 1,
"id": "demo-extension",
"name": "Demo Extension",
"version": "1.0.0",
"publisher": "demo-publisher",
"targets": [
{
"id": "Microsoft.VisualStudio.Services"
}
],
"description": "Demo extension",
"categories": ["Azure Pipelines"],
"files": [
{
"path": "task"
}
],
"contributions": [
{
"id": "build-task",
"type": "ms.vss-distributed-task.task",
"targets": ["ms.vss-distributed-task.tasks"],
"properties": {
"name": "task"
}
}
]
}
task/task.json
{
"$schema": "https://raw.githubusercontent.com/Microsoft/azure-pipelines-task-lib/master/tasks.schema.json",
"id": "a81df1d3-750f-4d60-a8dc-21970f1956e2",
"name": "DemoBuild",
"friendlyName": "Demo task",
"instanceNameFormat": "Demo task",
"description": "Demo task",
"helpMarkDown": "",
"category": "Build",
"author": "Demo Company",
"version": {
"Major": 0,
"Minor": 1,
"Patch": 0
},
"groups": [
{
"name": "someinput",
"displayName": "SomeInput",
"isExpanded": true
}
],
"inputs": [
{
"name": "someinput",
"type": "string",
"label": "Some Input",
"defaultValue": "",
"required": true,
"helpMarkDown": "Input something",
"groupName": "someinput"
}
],
"execution": {
"Node10": {
"target": "index.js"
}
}
}
In addition to the above I have also downloaded and attempted to validate these official Microsoft extensions with the same error message:
https://github.com/microsoft/azure-devops-extension-tasks
https://github.com/microsoft/PR-Metrics
How might I go about fixing this issue please?

How to reference already existing Azure Portal created storage accounts in an ARM template

I want to create a function app with ARM template such that the ARM template references already existing storage accounts (inputstgdev and outputstgdev) which I have already parameterized. I would like the ARM template to use the inputstgdev storage account as its attached storage account such that it does not have to create a new storage account. The source control of the function app is referenced to a Gitrepo which I have also parameterized in the ARM template. Each time I run the ARM template I get the following error message
##[error]Deployment template validation failed: 'The resource '/subscriptions/bea8ac84-24a4-4e53-9198-e3b0107547d4/resourceGroups/dev-rgp/providers/Microsoft.Web/sites/functionapp/sourcecontrols/web' at line '1' and column '3069' doesn't depend on parent resource '/subscriptions/bea8ac84-24a4-4e53-9198-e3b0107547d4/resourceGroups/dev-rgp/providers/Microsoft.Web/sites/functionapp'. Please add dependency explicitly using the 'dependsOn' syntax. Please see aka.ms/arm-template/#resources for
Any suggestions what the issue might be or possible solutions.
I look forward to your response
{
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"InputstorageAccount": {
"defaultValue": "inputstgdev",
"type": "String"
},
"GitrepoBranch": {
"type": "string",
"defaultValue": "master",
"metadata": {
"description": "Name of the branch to use when deploying (Default = master)."
}
},
"GitrepoURL": {
"type": "string",
"defaultValue": "https://github.com/FBoucher/AzUnzipEverything.git",
"metadata": {
"description": "URL to repo (Default = master)."
}
},
"InputcontainerName": {
"type": "string",
"defaultValue": "inputcontainer",
"metadata": {
"description": "Specifies the name of the blob container."
}
},
"OutputstorageAccount": {
"defaultValue": "outputstgdev",
"type": "String"
},
"OutputcontainerName": {
"type": "string",
"defaultValue": "outputcontainer",
"metadata": {
"description": "Specifies the name of the blob container."
}
}
},
"variables": {},
"resources": [
{
"type": "Microsoft.Storage/storageAccounts/blobServices/containers",
"apiVersion": "2019-06-01",
"name": "[concat(parameters('InputstorageAccount'), '/default/', parameters('InputcontainerName'))]",
"properties": {
"publicAccess": "None"
}
},
{
"type": "Microsoft.Storage/storageAccounts/blobServices/containers",
"apiVersion": "2019-06-01",
"name": "[concat(parameters('OutputstorageAccount'), '/default/', parameters('OutputcontainerName'))]",
"properties": {
"publicAccess": "None"
}
},
{
"name": "serviceplan",
"type": "Microsoft.Web/serverfarms",
"apiVersion": "2018-02-01",
"location": "[resourceGroup().location]",
"sku": {
"name": "F1",
"capacity": 1
},
"tags": {
"displayName": "serviceplan"
},
"properties": {
"name": "serviceplan"
}
},
{
"name": "functionapp",
"type": "Microsoft.Web/sites",
"apiVersion": "2018-11-01",
"location": "[resourceGroup().location]",
"kind": "functionapp",
"dependsOn": [
"[resourceId('Microsoft.Web/serverfarms', 'serviceplan')]",
"[resourceId('Microsoft.Storage/storageAccounts', parameters('InputstorageAccount'))]"
],
"properties": {
"serverFarmId": "[resourceId('Microsoft.Web/serverfarms', 'serviceplan')]",
"siteConfig": {
"appSettings": [
{
"name": "AzureWebJobsDashboard",
"value": "[concat('DefaultEndpointsProtocol=https;AccountName=', parameters('InputstorageAccount'), ';AccountKey=', listKeys(parameters('InputcontainerName'),'2015-05-01-preview').key1)]"
},
{
"name": "AzureWebJobsStorage",
"value": "[concat('DefaultEndpointsProtocol=https;AccountName=', parameters('InputstorageAccount'), ';AccountKey=', listKeys(parameters('InputcontainerName'),'2015-05-01-preview').key1)]"
},
{
"name": "WEBSITE_CONTENTAZUREFILECONNECTIONSTRING",
"value": "[concat('DefaultEndpointsProtocol=https;AccountName=', parameters('InputstorageAccount'), ';AccountKey=', listKeys(parameters('InputcontainerName'),'2015-05-01-preview').key1)]"
},
{
"name": "WEBSITE_CONTENTSHARE",
"value": "[toLower('functionapp')]"
},
{
"name": "FUNCTIONS_EXTENSION_VERSION",
"value": "~2"
},
{
"name": "APPINSIGHTS_INSTRUMENTATIONKEY",
"value": "[reference(resourceId('microsoft.insights/components/', 'applicationInsightsName'), '2015-05-01').InstrumentationKey]"
},
{
"name": "FUNCTIONS_WORKER_RUNTIME",
"value": "dotnet"
}
]
}
},
"resources":[
{
"apiVersion": "2015-08-01",
"name": "web",
"type": "sourcecontrols",
"dependsOn": [
"[resourceId('Microsoft.Web/sites/', parameters('InputstorageAccount'))]"
],
"properties": {
"RepoUrl": "[parameters('GitrepoURL')]",
"branch": "[parameters('GitrepoBranch')]",
"publishRunbook": true,
"IsManualIntegration": true
}
}
]
}
]
}
You encountered this error message due to the wrong dependency.
You should use "[resourceId('Microsoft.Web/sites/', 'functionapp')]" instead of "[resourceId('Microsoft.Web/sites/', parameters('InputstorageAccount'))]".
And you should delete the storage dependency.
"[resourceId('Microsoft.Storage/storageAccounts', parameters('InputstorageAccount'))]"
By the way, as you already have a storage account, you just need to paste your connection string in the value of AzureWebJobsStorage and AzureWebJobsDashboard.
Just like
{
"name": "AzureWebJobsDashboard",
"value": "{connectionstring}"
}

GWD Custom component

I've created a custom component but the problem is that when I preview or export that component the image aren't exported
{
/* ... */
"attributes": [
{
"name": "bkgmap",
"label": "bkgmap",
"type": "string",
"required": true,
"description": "desc",
"gwdSpecific": {
"label": "bkgmapImg",
"sync": "src"
}
},
{
"name": "bkgback",
"label": "bkgback",
"type": "string",
"required": true,
"description": "desc",
"gwdSpecific": {
"label": "bkgbackImg",
"sync": "src"
}
},
{
"name": "bkgfore",
"label": "bkgfore",
"type": "string",
"required": true,
"description": "desc",
"gwdSpecific": {
"label": "bkgforeImg",
"sync": "src"
}
},
{
"name": "bar",
"label": "bar",
"type": "string",
"required": true,
"description": "desc",
"gwdSpecific": {
"label": "barImg",
"sync": "src"
}
} /* ... */
],
}
In this way, with the sync property I'm able to export only one image, someone know how is it possible to achieve the image inclusion? And also someone know how to set up a file upload type? the attributes type "file" works but isn't possibile to select any file, also if I specify the accept property.
{
"name": "dragIcon",
"label": "Drag Icon",
"type": "file",
"description": "Choose the images",
"required": true,
"accept": "image/*",
"bindable": false
},

ARM Template for Redis Cache failing to deploy

I am trying to deploy Redis Cache using an ARM Template but it keeps failing with the following error:
{"code":"DeploymentFailed","message":"At least one resource deployment
operation failed. Please list deployment operations for details.
Please see https://aka.ms/arm-debug for usage
details.","details":[{"code":"BadRequest","message":"{\r\n \"error\":
{\r\n \"code\": \"LinkedInvalidPropertyId\",\r\n \"message\":
\"Property id 'GET-PREREQ-existingDiagnosticsStorageAccountId' at path
'properties.storageAccountId' is invalid. Expect fully qualified
resource Id that start with '/subscriptions/{subscriptionId}' or
'/providers/{resourceProviderNamespace}/'.\"\r\n }\r\n}"}]}
Scoured resources online but I'm unable to figure out what exactly is going wrong. The Redis Cache resource does get created but the deployment isn't completely successful. The following seems to be failing:
https://imgur.com/a/xsp0OqL
https://imgur.com/a/mpBBIAm
azuredeployredis.json
{
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json",
"contentVersion": "1.0.0.0",
"parameters": {
"redisCacheName": {
"type": "string",
"defaultValue": "defaultRedisCacheName",
"metadata": {
"description": "The name of the Azure Redis Cache to create."
}
},
"redisCacheSKU": {
"type": "string",
"allowedValues": [
"Basic",
"Standard",
"Premium"
],
"defaultValue": "Standard",
"metadata": {
"description": "The pricing tier of the new Azure Redis Cache."
}
},
"redisCacheFamily": {
"type": "string",
"defaultValue": "C",
"metadata": {
"description": "The family for the sku."
},
"allowedValues": [
"C",
"P"
]
},
"redisCacheCapacity": {
"type": "int",
"allowedValues": [
0,
1,
2,
3,
4,
5,
6
],
"defaultValue": 1,
"metadata": {
"description": "The size of the new Azure Redis Cache instance. "
}
},
"enableNonSslPort": {
"type": "bool",
"defaultValue": false,
"metadata": {
"description": "A boolean value that indicates whether to allow access via non-SSL ports."
}
},
"diagnosticsEnabled": {
"type": "bool",
"defaultValue": false,
"metadata": {
"description": "A value that indicates whether diagnostics should be saved to the specified storage account."
}
},
"existingDiagnosticsStorageAccountId": {
"type": "string",
"metadata": {
"description": "Existing storage account for diagnostics."
}
}
},
"resources": [
{
"apiVersion": "2015-08-01",
"name": "[parameters('redisCacheName')]",
"type": "Microsoft.Cache/Redis",
"location": "[resourceGroup().location]",
"properties": {
"enableNonSslPort": "[parameters('enableNonSslPort')]",
"sku": {
"capacity": "[parameters('redisCacheCapacity')]",
"family": "[parameters('redisCacheFamily')]",
"name": "[parameters('redisCacheSKU')]"
}
},
"resources": [
{
"apiVersion": "2017-05-01-preview",
"type": "Microsoft.Cache/redis/providers/diagnosticsettings",
"name": "[concat(parameters('redisCacheName'), '/Microsoft.Insights/', parameters('redisCacheName'))]",
"location": "[resourceGroup().location]",
"dependsOn": [
"[concat('Microsoft.Cache/Redis/', parameters('redisCacheName'))]"
],
"properties": {
"storageAccountId": "[parameters('existingDiagnosticsStorageAccountId')]",
"metrics": [
{
"timeGrain": "AllMetrics",
"enabled": "[parameters('diagnosticsEnabled')]",
"retentionPolicy": {
"days": 90,
"enabled": "[parameters('diagnosticsEnabled')]"
}
}
]
}
}
]
}
]
}
azuredeployredis.parameters.json:
{
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentParameters.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"redisCacheName": {
"value": "xyz-redis-cache"
},
"existingDiagnosticsStorageAccountId": {
"value": "GET-PREREQ-existingDiagnosticsStorageAccountId"
}
}
}
I mean, the error clearly says you need to pass in resourceId, not resource name to the properties.storageAccountId. it should look like this:
/subscriptions/guid/resourceGroups/rgname/providers/Microsoft.Storage/storageAccounts/storagename
you can use resourceId() function to calculate that:
resourceId('subscriptionId', 'resourceGroupname', 'Microsoft.Storage/storageAccounts', 'storageaccountname')
subscriptionid and resourcegroupname are only needed if storage account is in different subscription and\or resource group

How to add extension settings schema on vscode?

The settings in VS Code supports graphic panel like below:
I am developing an extension in vscode but I couldn't find a document or example to show how to add these settings. Is there any tutorial I can read for doing that?
I tried below configuration but the GUI doesn't show panel for these fields:
"configuration": [
{
"type": "object",
"title": "MongoDB Runner Configuration",
"properties": {
"mongoRunner": {
"type": "object",
"default": {},
"description": "Complete connection configuration for your MongoDB.",
"properties": {
"connection": {
"title": "MongoDB Runner Configuration",
"type": "object",
"properties": {
"url": {
"type": "string",
"default": "mongodb://",
"description": "MongoDB URI"
},
"activeOnStartUp": {
"type": "boolean",
"default": false,
"description": "whether launch mongodb runner on start up"
}
}
}
}
}
}
}
]
below is the json file format I need to support:
"mongoRunner": {
"connection": {
"activeOnStartUp": true,
"url": "mongodb://localhost:27017"
}
},
Is this what you're looking for?
You can use markdown in the description (property markdownDescription), and the checkbox appears by using type boolean.
Example:
"configuration": {
"type": "object",
"title": "Test configuration",
"properties": {
"test.usingUI": {
"type": "boolean",
"default": false,
"markdownDescription": "**Some bold text**\nYes or no?"
},
"test.text": {
"type": ["string", "null"],
"default": null,
"description": "You can't edit me now!"
}
}
},
Looking in the UI like
this
Edit - 2:
In this case your syntax is malformed, try this:
"configuration": {
"type": "object",
"title": "MongoDB Runner Configuration",
"properties": {
"mongoRunner.url": {
"type": "string",
"default": "mongodb://",
"description": "MongoDB URI"
},
"mongoRunner.activeOnStartUp": {
"type": "boolean",
"default": false,
"description": "whether launch mongodb runner on start up"
}
}
},
-> UI