Azure devops 调试Azure DevOps任务扩展(TypeScript)
我在Azure devops 调试Azure DevOps任务扩展(TypeScript),azure-devops,azure-pipelines-build-task,Azure Devops,Azure Pipelines Build Task,我在PowerShell中开发了所有任务扩展,现在我开始将第一个扩展翻译成TypeScript。扩展是一个小任务,应该在构建或发布管道中运行。该任务应部署到Azure DevOps Server 2020.1(在prem上) 准备工作 教程 我遵循教程并用它构建了一个示例应用程序 我克隆并签出编程风格 系统设置 Launch.json Index.ts(入口点): 输出(无): Index.ts(修改): 输出(修改): 显然,它会停止,因为所需的变量Template没有传递给应用程序
PowerShell
中开发了所有任务扩展,现在我开始将第一个扩展翻译成TypeScript
。扩展是一个小任务,应该在构建或发布管道中运行。该任务应部署到Azure DevOps Server 2020.1(在prem上)
准备工作 教程
- 我遵循教程并用它构建了一个示例应用程序
- 我克隆并签出编程风格
Launch.json
Index.ts
(入口点):
输出(无):
Index.ts
(修改):
输出(修改):
显然,它会停止,因为所需的变量Template
没有传递给应用程序
问题
- 有没有办法调试azure devops任务扩展
- 是否可以通过
传递参数并加载它们tl.getInput
- 如何开发azure devops任务扩展,是否有最先进的技术或完整的指南
azure pipelines任务库
会遇到问题。但是我希望可以模拟所需的管道变量并在本地运行此库。如果使用azure管道任务库
意味着您必须部署扩展并在管道中运行它以进行测试,那么使用它开发任务会有点像komplex,或者
编辑1: 我发现不推荐使用的存储库大约。在
azure pipelines tasks/docs/debug.md
中,手动调试该库。本文作者描述了一个示例launch.json
配置,我根据自己的用例修改了它:
{
"name": "Launch tar.gz",
"type": "node",
"request": "launch",
"program": "${workspaceFolder}/dist/task/index.js",
"stopOnEntry": false,
"args": [],
"cwd": "${workspaceRoot}/task",
"preLaunchTask": "tsc: build - tsconfig.json",
"runtimeExecutable": null,
"runtimeArgs": ["--nolazy"],
"env": {
"NODE_ENV": "development",
"INPUT_Separator": ";",
"BUILD_SOURCESDIRECTORY": "C:\\agents\\latest\\_work\\21\\s"
},
"sourceMaps": true,
"outFiles": ["${workspaceRoot}/dist"]
}
我可以确认可以启动调试,并且tl.getInput(“分隔符”)
将返回代码>
有没有办法调试azure devops任务扩展
是的,根据文章“”中的说明,在安装所有必需的库和依赖项并添加所有必需的任务实现文件后,您可以使用PowerShell或其他Shell。默认情况下,任务以调试模式运行。见下面我分享的例子
是否可以通过tl.getInput传递参数并加载它们
当然,您可以将tl.getInput的值作为参数传递。见下面我分享的例子
如何开发azure devops任务扩展,是否有最先进的技术或完整的指南
目前,关于DevOps扩展的Microsoft文档是我们开发DevOps扩展的最佳指南
按照您的情况,我也会在我这边进行测试,下面是我使用的主要源代码:
- task.json
{
“$schema”:”https://raw.githubusercontent.com/Microsoft/azure-pipelines-task-lib/master/tasks.schema.json",
“id”:“dc7322d8-6c98-4be7-91c9-dcbf7f4df7dd”,
“名称”:“buildAndReleaseTask”,
“friendlyName”:“构建和发布任务”,
“描述”:“测试创建生成和发布任务”,
“帮助标记”:“,
“类别”:“实用程序”,
“作者”:“光明冉”,
“版本”:{
“主要”:0,
“小调”:1,
“补丁”:0
},
“instanceNameFormat”:“Echo$(用户名)”,
“投入”:[
{
“名称”:“用户名”,
“类型”:“字符串”,
“标签”:“用户名”,
“defaultValue”:“,
“必需”:正确,
“帮助标记”:“用户名”
}
],
“执行”:{
“节点10”:{
“目标”:“index.js”
}
}
}
- App.ts(与您的几乎相同)
- index.ts(与您的几乎相同)
- 编译并运行任务的结果
从结果中,您可以看到这两个参数可以正常传递。在我的帮助下,我可以做以下事情:
- 从导入tl=require(“azure管道任务库/任务”)
导入*连接到Azure DevOps服务器,并使用新建azdev.WebApi
launch.json 连接到azure devops服务器:
rest.ts
import tl = require("azure-pipelines-task-lib/task");
export const App = {
// ------------------------------------------------------------ param
Param: {
WebhookUrl: tl.getDelimitedInput("WebhookUrl", "\n", true),
Template: tl.getInput("Template", true)
},
// ------------------------------------------------------------ env
Env: {
Agent: {
Jobstatus: getVariable("AGENT_JOBSTATUS"),
Name: getVariable("AGENT_NAME"),
},
...
System: {
AccessToken: getVariable("SYSTEM_ACCESSTOKEN"),
DefinitionName: getVariable("SYSTEM_DEFINITIONNAME"),
TeamFoundationServerUri: getVariable("SYSTEM_TEAMFOUNDATIONSERVERURI"),
TeamProject: getVariable("SYSTEM_TEAMPROJECT"),
},
// ------------------------------------------------------------ debug
Debug: {
Pat: getVariable("DEBUG_PAT"),
},
}
function getVariable(name: string): string {
// get variable
let v = tl.getVariable(name);
if (v === undefined) return "";
return v;
}
import { App } from "./app";
import * as azdev from "azure-devops-node-api";
import * as ba from "azure-devops-node-api/BuildApi";
export class Rest {
static AuthHanlder: IRequestHandler = Rest.Auth();
static Connection: azdev.WebApi = new azdev.WebApi(App.Env.System.TeamFoundationServerUri, Rest.AuthHanlder);
static Auth(): IRequestHandler {
// auth
if (App.Env.System.AccessToken === "") return azdev.getPersonalAccessTokenHandler(App.Debug.Pat);
// no sure if this works on production
return azdev.getBearerHandler(App.Env.System.AccessToken);
}
}
嗨@MarTin,很高兴你解决了这个问题,谢谢你分享你的经验。你能把你的答案标记为这个题目的答案吗?这可能对那些正在寻找类似问题解决方案的人非常有帮助。
import { App } from "./app";
function run() {
console.log("Hello");
console.log(App.Param.Test);
}
run();
import { App } from "./app";
function run() {
console.log("Hello");
// console.log(App.Param.Test);
}
run();
Hello
{
"name": "Launch tar.gz",
"type": "node",
"request": "launch",
"program": "${workspaceFolder}/dist/task/index.js",
"stopOnEntry": false,
"args": [],
"cwd": "${workspaceRoot}/task",
"preLaunchTask": "tsc: build - tsconfig.json",
"runtimeExecutable": null,
"runtimeArgs": ["--nolazy"],
"env": {
"NODE_ENV": "development",
"INPUT_Separator": ";",
"BUILD_SOURCESDIRECTORY": "C:\\agents\\latest\\_work\\21\\s"
},
"sourceMaps": true,
"outFiles": ["${workspaceRoot}/dist"]
}
import tl = require("azure-pipelines-task-lib/task");
export const App = {
Param: {
Here: "Here",
UserName: tl.getInput("UserName", true),
}
}
import { App } from "./App";
function run() {
console.log("Hello,", App.Param.UserName);
console.log("Look", App.Param.Here);
}
run();
tsc
$env:INPUT_USERNAME="xxxx"
node index.js
{
"name": "Run TypeScript",
"type": "pwa-node",
"request": "launch",
"internalConsoleOptions": "openOnSessionStart",
"stopOnEntry": false,
// path to your ts file
"args": ["index.ts"],
"cwd": "${workspaceRoot}/task",
"runtimeArgs": ["--nolazy", "-r", "ts-node/register/transpile-only"],
"env": {
"NODE_ENV": "development",
// param (enter your input params here!)
"INPUT_WebhookUrl": "MyVariables",
"INPUT_Template": "Empty",
"INPUT_Json": "{\"text\":\"I am a test message\",\"attachments\":[{\"text\":\"And here’s an attachment!\"}]}",
"INPUT_Separator": ";",
// env
"AGENT_JOBSTATUS": "Succeeded",
"AGENT_NAME": "MyAgent",
"BUILD_BUILDID": "5",
"BUILD_BUILDNUMBER": "20210108.1",
"BUILD_REASON": "Scheduled",
"BUILD_REPOSITORY_NAME": "MyRepo",
"BUILD_SOURCEBRANCHNAME": "master",
"BUILD_SOURCEVERSION": "122a24f",
"BUILDCONFIGURATION": "Debug",
"BUILDPLATFORM": "Any CPU",
"SYSTEM_ACCESSTOKEN": "",
"SYSTEM_DEFINITIONNAME": "MyDefinitionName",
"SYSTEM_TEAMFOUNDATIONSERVERURI": "https://myurl.de/mycollection/",
"SYSTEM_TEAMPROJECT": "PSItraffic",
// debug
"DEBUG_PAT": "my debug pat"
},
"skipFiles": ["<node_internals>/**"]
}
import tl = require("azure-pipelines-task-lib/task");
export const App = {
// ------------------------------------------------------------ param
Param: {
WebhookUrl: tl.getDelimitedInput("WebhookUrl", "\n", true),
Template: tl.getInput("Template", true)
},
// ------------------------------------------------------------ env
Env: {
Agent: {
Jobstatus: getVariable("AGENT_JOBSTATUS"),
Name: getVariable("AGENT_NAME"),
},
...
System: {
AccessToken: getVariable("SYSTEM_ACCESSTOKEN"),
DefinitionName: getVariable("SYSTEM_DEFINITIONNAME"),
TeamFoundationServerUri: getVariable("SYSTEM_TEAMFOUNDATIONSERVERURI"),
TeamProject: getVariable("SYSTEM_TEAMPROJECT"),
},
// ------------------------------------------------------------ debug
Debug: {
Pat: getVariable("DEBUG_PAT"),
},
}
function getVariable(name: string): string {
// get variable
let v = tl.getVariable(name);
if (v === undefined) return "";
return v;
}
import { App } from "./app";
import * as azdev from "azure-devops-node-api";
import * as ba from "azure-devops-node-api/BuildApi";
export class Rest {
static AuthHanlder: IRequestHandler = Rest.Auth();
static Connection: azdev.WebApi = new azdev.WebApi(App.Env.System.TeamFoundationServerUri, Rest.AuthHanlder);
static Auth(): IRequestHandler {
// auth
if (App.Env.System.AccessToken === "") return azdev.getPersonalAccessTokenHandler(App.Debug.Pat);
// no sure if this works on production
return azdev.getBearerHandler(App.Env.System.AccessToken);
}
}