Em alguns casos, é necessário criar uma extensão personalizada para o Azure DevOps, seja para adicionar funcionalidades que não estão disponíveis nativamente ou para modificar alguma funcionalidade existente que não atenda às necessidades do projeto. Neste artigo, mostraremos como criar uma extensão personalizada para o Azure DevOps e como publicá-la no Marketplace do Azure DevOps.
npm i -g tfx-cli
.Crie uma pasta para a extensão, por exemplo, my-extension
e dentro desta pasta crie a uma subpasta, por exemplo, task
.
Abra o terminal na pasta criada e execute o comando npm init -y
, o parâmetro -y
é para aceitar todas as opções padrão. Você vai notar que foi criado um arquivo chamado package.json
e nele estão as informações da extensão.
{
"name": "my-extension",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"build": "tsc ./index.ts",
},
"keywords": [],
"author": "",
"license": "ISC"
}
Adicione a azure-pipelines-task-lib como dependência da extensão, execute o comando npm i azure-pipelines-task-lib --save-dev
.
Adicione também as tipificações do TypeScript, execute o comando npm i @types/node --save-dev
e npm i @types/q --save-dev
.
Crie um arquivo .gitignore
na pasta raiz da extensão e adicione o seguinte conteúdo:
node_modules
Instale o compilador de TypeScript, execute o comando npm i typescript --save-dev
.
Crie um arquivo tsconfig.json
na pasta raiz da extensão e adicione o seguinte conteúdo:
{
"compilerOptions": {
"target": "es6", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', or 'ESNEXT'. */
"module": "commonjs", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */
"strict": true, /* Enable all strict type-checking options. */
"esModuleInterop": true, /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */
"skipLibCheck": true, /* Skip type checking of declaration files. */
"forceConsistentCasingInFileNames": true /* Disallow inconsistently-cased references to the same file. */
}
}
Crie um arquivo chamado vss-extension.json
na pasta raiz da extensão my-extension
e adicione o seguinte conteúdo:
{
"manifestVersion": 1,
"id": "<<Guid ID>>",
"version": "1.0.0",
"publisher": "<<Nome do publisher>>",
"name": "My Extension",
"description": "My Extension",
"public": false,
"categories": [
"Azure Pipelines"
],
"targets": [
{
"id": "Microsoft.VisualStudio.Services"
}
],
"icons": {
"default": "images/icon.png"
},
"files": [
{
"path": "task"
}
],
"contributions": [
{
"id": "my-extension",
"description": "My Extension",
"type": "ms.vss-distributed-task.task",
"targets": [
"ms.vss-distributed-task.tasks"
],
"properties": {
"name": "my-extension"
}
}
]
}
Substitua o <<Guid ID>>
por ID único de cada extensão, você pode gerar um ID aqui. Substitua o <<Nome do publisher>>
pelo publisher ID criado no passo 1 da etapa de publish.
Na pasta raiz da sua extensão my-extension
, crie uma pasta chamada images
e adicione uma imagem chamada icon.png
com o tamanho de 128x128 pixels. Essa imagem será usada como ícone da sua extensão no Marketplace.
Depois de configurar o ambiente, você pode criar a extensão.
Na pasta task
crie um arquivo chamado task.json
e adicione o seguinte conteúdo:
{
"$schema": "https://raw.githubusercontent.com/Microsoft/azure-pipelines-task-lib/master/tasks.schema.json",
"id": "<<Guid ID>>",
"name": "My Extension",
"friendlyName": "My Extension",
"description": "My Extension",
"helpMarkDown": "",
"category": "Utility",
"visibility": [
"Build",
"Release"
],
"author": "Your Name",
"version": {
"Major": 1,
"Minor": 0,
"Patch": 0
},
"groups": [],
"inputs": [],
"execution": {
"Node16": {
"target": "index.js"
}
}
}
Substitua o <<Guid ID>>
pelo mesmo GUID gerado no passo 8 da etapa de preparação de ambiente de desenvolvimento.
Esse arquivo descreve a extensão que será executada no pipeline. Nesse caso, a extensão ainda não faz nada, mas você pode adicionar os inputs e a lógica para executar qualquer coisa.
Na sequência crie um arquivo chamado index.js
e adicione o seguinte conteúdo:
const tl = require('azure-pipelines-task-lib/task');
async function run() {
try {
tl.setResult(tl.TaskResult.Succeeded, 'My Extension Succeeded!');
}
catch (err) {
if (err instanceof Error) {
tl.setResult(tl.TaskResult.Failed, err.message);
}
}
}
run();
Esse arquivo é o responsável por executar a extensão. Nesse caso, ele apenas retorna uma mensagem de sucesso. Você pode adicionar a lógica para executar qualquer coisa.
Adicione na pasta task
uma imagem chamada icon.png
com o tamanho de 32x32 pixels. Essa imagem será usada como ícone da sua extensão no Azure Pipelines.
No terminal, execute o comando tsc
, para compilar o código Typescript para Javascript. Esse comando irá gerar um arquivo chamado index.js
na pasta task
.
Para executar a extensão localmente, execute o comando node index.js
. Você deve ver a mensagem My Extension Succeeded!
.
C:\temp\my-extension\task> node index.js
##vso[task.debug]agent.TempDirectory=undefined
##vso[task.debug]agent.workFolder=undefined
##vso[task.debug]loading inputs and endpoints
##vso[task.debug]loading INPUT_CLEANTARGETFOLDER
##vso[task.debug]loading INPUT_CLIENTID
##vso[task.debug]loading INPUT_CLIENTSECRET
##vso[task.debug]loading INPUT_CONFLICTBEHAVIOUR
##vso[task.debug]loading INPUT_CONTENTS
##vso[task.debug]loading INPUT_DRIVEID
##vso[task.debug]loading INPUT_failOnEmptySource
##vso[task.debug]loading INPUT_FLATTENFOLDERS
##vso[task.debug]loading INPUT_SOURCEFOLDER
##vso[task.debug]loading INPUT_TARGETFOLDER
##vso[task.debug]loading INPUT_TENANTID
##vso[task.debug]loaded 11
##vso[task.debug]Agent.ProxyUrl=undefined
##vso[task.debug]Agent.CAInfo=undefined
##vso[task.debug]Agent.ClientCert=undefined
##vso[task.debug]Agent.SkipCertValidation=undefined
##vso[task.debug]task result: Succeeded
##vso[task.complete result=Succeeded;]My Extension Succeeded!
C:\temp\my-extension\task>
Quando a sua extensão estiver pronta, você pode publicá-la no Marketplace. Para isso será necessário criar um editor de extensão no Marketplace.
Acesse o Marketplace e clique em Publish Extension
. Após fazer o login, você será redirecionado para a página de criação de um editor de extensão. Preencha os campos e clique em Create
.
No terminal execute o comando tfx extension create --manifest-globs vss-extension.json
, na pasta My-Extension
. Esse comando irá gerar um arquivo chamado publishID-1.0.0.vsix
, que é o arquivo que será publicado no Marketplace.
Acesse a página de publicação de extensão no Marketplace e clique New extension
e seguida Azure DevOps
. Selecione o arquivo my-extension-1.0.0.vsix
e clique em Upload
.
Se tudo ocorrer bem, você verá algo como a imagem abaixo.
Com a extensão publicada, será necessário compartilhá-la com a sua organização. Para isso, clique no menu de contexto da extensão e clique em Share/UnShare
.
Clique em + Organization
.
E digite o nome da sua Organização, ao clicar fora da caixa de digitação a validação é feita e o compartilhamento é realizado.
Após publicar a extensão no Marketplace, você pode instalá-la na sua organização, para isso siga os passos abaixo.
Clique no menu de contexto da extensão e clique em View Extension
.
Você verá algo como a imagem abaixo.
Clique em Get it free
.
Verifique se sua organização está selecionada e clique em Install
.
Se a instalação ocorrer tudo bem, você verá algo como a imagem abaixo.
Após a instalação, você verá a extensão na lista de extensões instaladas e poderá ser utilizada nos seus pipelines.
O uso de extensões customizadas no Azure DevOps desbloqueiam funcionalidades que não estão disponíveis. Neste artigo, você aprendeu como criar uma extensão customizada e como publicá-la no Marketplace. Espero que tenha gostado e que possa aplicar o conhecimento adquirido em seus projetos.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.