Adicionar uma extensão de tarefa de pipelines personalizados

Azure DevOps Services | Azure DevOps Server 2022 – Azure DevOps Server 2019 | TFS 2018

Saiba como instalar extensões em sua organização para tarefas personalizadas de build ou lançamento no Azure DevOps.

Essas tarefas aparecem ao lado de tarefas fornecidas pela Microsoft no assistente Adicionar Etapa .

Captura de tela do catálogo de tarefas Build para extensões no Azure DevOps.

Para obter mais informações sobre o novo sistema de build/lançamento multiplataforma, consulte o que é o Azure Pipelines?.

Observação

Este artigo aborda as tarefas do agente em extensões baseadas em agente. Para obter informações sobre tarefas de servidor/extensões baseadas em servidor, confira a Documentação do GitHub da Tarefa do Servidor.

Pré-requisitos

Para criar extensões para o Azure DevOps, você precisa dos seguintes softwares e ferramentas:

  • Uma organização no Azure DevOps. Para obter mais informações, consulte Criar uma organização.

  • Um editor de texto. Para muitos dos tutoriais, usamos Visual Studio Code, que fornece suporte para intellisense e depuração. Vá para code.visualstudio.com para baixar a versão mais recente.

  • A versão mais recente do Node.js. O ambiente de produção usa apenas Node10 ou Node6 (usando o "Node""execution" objeto em vez de Node10).

  • O Compilador typeScript 2.2.0 ou superior, embora recomendemos a versão 4.0.2 ou mais recente para tarefas que usam o Node10. Vá para npmjs.com baixar o compilador.

  • CLI multiplataforma do Azure DevOps para empacotar suas extensões. Você pode instalar o tfx-cli usando npmum componente do Node.js, executando npm i -g tfx-cli.

  • Um home diretório para seu projeto. O home diretório de uma extensão de tarefa de build ou versão deve se parecer com o exemplo a seguir depois de concluir as etapas neste tutorial:

    |--- README.md    
    |--- images                        
        |--- extension-icon.png  
    |--- buildandreleasetask            // where your task scripts are placed
    |--- vss-extension.json             // extension's manifest
    
  • A instalação do pacote vss-web-extension-sdk.

Importante

O computador de desenvolvimento precisa executar o Node v10.21.0 para garantir que o código gravado seja compatível com o ambiente de produção no agente e a versão mais recente não prévia do azure-pipelines-task-lib.

Desenvolver no Unix vs. Windows

Fizemos este passo a passo no Windows com o PowerShell. Tentamos torná-lo genérico para todas as plataformas, mas a sintaxe para obter variáveis de ambiente é diferente.

Se você estiver usando um Mac ou Linux, substitua todas as instâncias por $env:<var>=<val>export <var>=<val>.

Etapa 1: Criar uma tarefa personalizada

Configure sua tarefa. Faça todas as partes da Etapa 1 dentro da buildandreleasetask pasta.

Criar scaffolding de tarefas

Crie a estrutura de pastas para a tarefa e instale as bibliotecas e dependências necessárias.

Criar um diretório e um arquivo package.json

De dentro da pasta buildandreleasetask , execute o seguinte comando:

npm init --yes

npm init cria o package.json arquivo. Adicionamos o --yes parâmetro para aceitar todas as opções padrão npm init .

Dica

O agente não instala automaticamente os módulos necessários porque espera que sua pasta de tarefas inclua os módulos de nó. Para atenuar isso, copie o node_modules para buildandreleasetask. À medida que sua tarefa aumenta, é fácil exceder o limite de tamanho (50 MB) de um arquivo VSIX. Antes de copiar a pasta do nó, talvez você queira executar npm install --production ou npm prune --productionescrever um script para compilar e empacotar tudo.

Adicionar azure-pipelines-task-lib

Fornecemos uma biblioteca, azure-pipelines-task-lib, que deve ser usada para criar tarefas. Adicione-o à biblioteca.

npm install azure-pipelines-task-lib --save

Adicionar digitações para dependências externas

  • Verifique se as digitações typeScript estão instaladas para dependências externas.

    npm install @types/node --save-dev
    npm install @types/q --save-dev
    
  • Crie um .gitignore arquivo e adicione node_modules a ele. Seu processo de build deve fazer um npm install e um typings install para que node_modules sejam criados a cada vez e não precisem ser verificados.

    echo node_modules > .gitignore
    
  • Instalar o Mocha como uma dependência de desenvolvimento:

    npm install mocha --save-dev -g
    npm install sync-request --save-dev
    npm install @types/mocha --save-dev
    

Escolher a versão do TypeScript

As tarefas podem usar as versões 2.3.4 ou 4.0.2 do TypeScript.

Observação

Para ter o tsc comando disponível, verifique se o TypeScript está instalado globalmente com o npm em seu ambiente de desenvolvimento.

Você pode instalar a versão do TypeScript escolhida usando este comando:

npm install typescript@4.0.2 -g --save-dev

Se você ignorar essa etapa, o TypeScript versão 2.3.4 será usado por padrão e ainda precisará instalar o pacote globalmente para ter o tsc comando disponível.

Criar opções do compilador tsconfig.json

Esse arquivo garante que seus arquivos TypeScript sejam compilados em arquivos JavaScript.

tsc --init --target es6

Queremos compilar para o padrão ES6 em vez de ES5. Para garantir que o padrão ES6 seja usado, adicionamos o --target es6 parâmetro.

Implementação da tarefa

Agora que o scaffolding está concluído, podemos criar nossa tarefa personalizada.

task.json

Em seguida, criamos um task.json arquivo na pasta buildandreleasetask. O task.json arquivo descreve a tarefa de build ou versão e é o que o sistema de build/versão usa para renderizar as opções de configuração para o usuário e saber quais scripts executar no momento da compilação/lançamento.

Copie o código a seguir e substitua as {{placeholders}} informações da sua tarefa. O espaço reservado mais importante é o taskguid, e ele deve ser exclusivo.

{
    "$schema": "https://raw.githubusercontent.com/Microsoft/azure-pipelines-task-lib/master/tasks.schema.json",
    "id": "{{taskguid}}",
    "name": "{{taskname}}",
    "friendlyName": "{{taskfriendlyname}}",
    "description": "{{taskdescription}}",
    "helpMarkDown": "",
    "category": "Utility",
    "author": "{{taskauthor}}",
    "version": {
        "Major": 0,
        "Minor": 1,
        "Patch": 0
    },
    "instanceNameFormat": "Echo $(samplestring)",
    "inputs": [
        {
            "name": "samplestring",
            "type": "string",
            "label": "Sample String",
            "defaultValue": "",
            "required": true,
            "helpMarkDown": "A sample string"
        }
    ],
    "execution": {
        "Node10": {
            "target": "index.js"
        }
    }
}

componentes task.json A seguir estão as descrições de alguns dos componentes do task.json arquivo:

Propriedade Descrição
id Um GUID exclusivo para sua tarefa.
name Nome sem espaços.
friendlyName Nome descritivo (espaços permitidos).
description Descrição detalhada do que sua tarefa faz.
author Cadeia de caracteres curta que descreve a entidade que está desenvolvendo a tarefa de build ou lançamento, por exemplo: "Microsoft Corporation".
instanceNameFormat Como a tarefa é exibida na lista de etapas de build ou versão. Você pode usar valores variáveis usando $(variablename).
groups Descreve grupos pelos quais as propriedades da tarefa podem ser agrupadas logicamente na interface do usuário.
inputs Entradas a serem usadas quando sua tarefa de build ou versão for executada. Essa tarefa espera uma entrada com o nome samplestring.
execution Opções de execução para essa tarefa, incluindo scripts.
restrictions As restrições que estão sendo aplicadas à tarefa sobre a tarefa de comandos do Visual Studio Codespaces podem ser chamadas e a tarefa variáveis pode ser definida. Recomendamos que você especifique o modo de restrição para novas tarefas. Para obter mais informações, confira como posso restringir o uso de comandos do Visual Studio Codespaces para tarefa?

Observação

Para obter uma visão mais detalhada do arquivo task.json ou para saber como agrupar várias versões em sua extensão, confira a referência da tarefa build/versão.

index.ts

Crie um index.ts arquivo usando o código a seguir como referência. Esse código é executado quando a tarefa é chamada.

import tl = require('azure-pipelines-task-lib/task');

async function run() {
    try {
        const inputString: string | undefined = tl.getInput('samplestring', true);
        if (inputString == 'bad') {
            tl.setResult(tl.TaskResult.Failed, 'Bad input was given');
            return;
        }
        console.log('Hello', inputString);
    }
    catch (err) {
        tl.setResult(tl.TaskResult.Failed, err.message);
    }
}

run();

Compilar

Insira "tsc" da pasta buildandreleasetask para compilar um index.js arquivo de index.ts.

Executar a tarefa

Um agente pode executar a tarefa com node index.js o PowerShell.

No exemplo a seguir, a tarefa falha porque as entradas não foram fornecidas (samplestring é uma entrada necessária).

node index.js
##vso[task.debug]agent.workFolder=undefined
##vso[task.debug]loading inputs and endpoints
##vso[task.debug]loaded 0
##vso[task.debug]task result: Failed
##vso[task.issue type=error;]Input required: samplestring
##vso[task.complete result=Failed;]Input required: samplestring

Como correção, podemos definir a samplestring entrada e executar a tarefa novamente.

$env:INPUT_SAMPLESTRING="Human"
node index.js
##vso[task.debug]agent.workFolder=undefined
##vso[task.debug]loading inputs and endpoints
##vso[task.debug]loading INPUT_SAMPLESTRING
##vso[task.debug]loaded 1
##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]samplestring=Human
Hello Human

Desta vez, a tarefa foi bem-sucedida porque samplestring foi fornecida e saiu corretamente "Olá, Humano"!

Etapa 2: Teste de unidade seus scripts de tarefa

Nós testamos a unidade para testar rapidamente o script de tarefa e não as ferramentas externas que ele está chamando. Queremos testar todos os aspectos dos caminhos de sucesso e falha.

Instalar ferramentas de teste

Usamos Mocha como o driver de teste nesta caminhada.

npm install mocha --save-dev -g
npm install sync-request --save-dev
npm install @types/mocha --save-dev

Criar pacote de testes

Crie uma tests pasta contendo um _suite.ts arquivo com o seguinte conteúdo:

import * as path from 'path';
import * as assert from 'assert';
import * as ttm from 'azure-pipelines-task-lib/mock-test';

describe('Sample task tests', function () {

    before( function() {

    });

    after(() => {

    });

    it('should succeed with simple inputs', function(done: Mocha.Done) {
        // Add success test here
    });

    it('it should fail if tool returns 1', function(done: Mocha.Done) {
        // Add failure test here
    });    
});

Dica

Sua pasta de teste deve estar localizada na pasta buildandreleasetask. Se você receber um erro de solicitação de sincronização, poderá contorná-lo adicionando a solicitação de sincronização à pasta buildandreleasetask com o comando npm i --save-dev sync-request.

Criar teste de êxito

O teste de êxito valida que, com as entradas apropriadas, ele é bem-sucedido sem erros ou avisos e retorna a saída correta.

Crie um arquivo que contenha seu executor de simulação de tarefa. Essa criação de arquivo simula a execução da tarefa e zomba de todas as chamadas para métodos externos.

Crie um success.ts arquivo no diretório de teste com o seguinte conteúdo:

import ma = require('azure-pipelines-task-lib/mock-answer');
import tmrm = require('azure-pipelines-task-lib/mock-run');
import path = require('path');

let taskPath = path.join(__dirname, '..', 'index.js');
let tmr: tmrm.TaskMockRunner = new tmrm.TaskMockRunner(taskPath);

tmr.setInput('samplestring', 'human');

tmr.run();

Em seguida, adicione o seguinte exemplo de teste de êxito ao arquivo _suite.ts para executar o executor de simulação de tarefa:

it('should succeed with simple inputs', function(done: Mocha.Done) {
    this.timeout(1000);

    let tp = path.join(__dirname, 'success.js');
    let tr: ttm.MockTestRunner = new ttm.MockTestRunner(tp);

    tr.run();
    console.log(tr.succeeded);
    assert.equal(tr.succeeded, true, 'should have succeeded');
    assert.equal(tr.warningIssues.length, 0, "should have no warnings");
    assert.equal(tr.errorIssues.length, 0, "should have no errors");
    console.log(tr.stdout);
    assert.equal(tr.stdout.indexOf('Hello human') >= 0, true, "should display Hello human");
    done();
});

Criar teste de falha

O teste de falha valida que, quando a ferramenta obtém entrada incompleta ou incompleta, ela falha da maneira esperada com uma saída útil.

Primeiro, criamos nosso executor de simulação de tarefa. Para fazer isso, crie um failure.ts arquivo no diretório de teste com o seguinte conteúdo:

import ma = require('azure-pipelines-task-lib/mock-answer');
import tmrm = require('azure-pipelines-task-lib/mock-run');
import path = require('path');

let taskPath = path.join(__dirname, '..', 'index.js');
let tmr: tmrm.TaskMockRunner = new tmrm.TaskMockRunner(taskPath);

tmr.setInput('samplestring', 'bad');

tmr.run();

Em seguida, adicione o seguinte ao arquivo _suite.ts para executar o executor de simulação de tarefa:

it('it should fail if tool returns 1', function(done: Mocha.Done) {
    this.timeout(1000);

    let tp = path.join(__dirname, 'failure.js');
    let tr: ttm.MockTestRunner = new ttm.MockTestRunner(tp);

    tr.run();
    console.log(tr.succeeded);
    assert.equal(tr.succeeded, false, 'should have failed');
    assert.equal(tr.warningIssues.length, 0, "should have no warnings");
    assert.equal(tr.errorIssues.length, 1, "should have 1 error issue");
    assert.equal(tr.errorIssues[0], 'Bad input was given', 'error issue output');
    assert.equal(tr.stdout.indexOf('Hello bad'), -1, "Should not display Hello bad");

    done();
});

Executar os testes

Para executar os testes, execute os seguintes comandos:

tsc
mocha tests/_suite.js

Ambos os testes devem ser aprovados. Se você quiser executar os testes com uma saída mais detalhada (o que você veria no console de build), defina a variável de ambiente: TASK_TEST_TRACE=1.

$env:TASK_TEST_TRACE=1

Etapa 3: Criar o arquivo de manifesto de extensão

O manifesto da extensão contém todas as informações sobre sua extensão. Ele inclui links para seus arquivos, incluindo pastas de tarefas e pastas de imagens. Verifique se você criou uma pasta de imagens com extension-icon.png. O exemplo a seguir é um manifesto de extensão que contém a tarefa de build ou versão.

Copie o código .json a seguir e salve-o como seu vss-extension.json arquivo em seu home diretório. Não crie esse arquivo na pasta buildandreleasetask.

{
    "manifestVersion": 1,
    "id": "build-release-task",
    "name": "Fabrikam Build and Release Tools",
    "version": "0.0.1",
    "publisher": "fabrikam",
    "targets": [
        {
            "id": "Microsoft.VisualStudio.Services"
        }
    ],    
    "description": "Tools for building/releasing with Fabrikam. Includes one build/release task.",
    "categories": [
        "Azure Pipelines"
    ],
    "icons": {
        "default": "images/extension-icon.png"        
    },
    "files": [
        {
            "path": "buildandreleasetask"
        }
    ],
    "contributions": [
        {
            "id": "custom-build-release-task",
            "type": "ms.vss-distributed-task.task",
            "targets": [
                "ms.vss-distributed-task.tasks"
            ],
            "properties": {
                "name": "buildandreleasetask"
            }
        }
    ]
}

Observação

O publicador aqui deve ser alterado para o nome do publicador. Se você quiser criar um editor agora, vá para criar seu editor para obter instruções.

Contribuições

Propriedade Descrição
id Identificador da contribuição. Deve ser exclusivo dentro da extensão. Não precisa corresponder ao nome da tarefa de build ou versão. Normalmente, o nome da tarefa de build ou versão está na ID da contribuição.
type Tipo de contribuição. Deve ser ms.vss-distributed-task.task.
targets Contribuições "direcionadas" por essa contribuição. Deve ser ms.vss-distributed-task.tasks.
properties.name Nome da tarefa. Esse nome deve corresponder ao nome da pasta do pipeline de tarefas de lançamento ou build autocontido correspondente.

Arquivos

Propriedade Descrição
path Caminho do arquivo ou pasta em relação ao home diretório.

Observação

Para obter mais informações sobre o arquivo de manifesto de extensão, como suas propriedades e o que eles fazem, confira a referência de manifesto da extensão.

Etapa 4: Empacotar sua extensão

Depois de escrever sua extensão, a próxima etapa para que ela seja colocada no Visual Studio Marketplace é empacotar todos os arquivos juntos. Todas as extensões são empacotadas como arquivos .vsix compatíveis com VSIX 2.0. A Microsoft fornece uma CLI (interface de linha de comando) multiplataforma para empacotar sua extensão.

Empacotar sua extensão em um arquivo .vsix é fácil depois que você tiver o tfx-cli, ir para o diretório inicial da sua extensão e executar o seguinte comando:

tfx extension create --manifest-globs vss-extension.json

Observação

A versão de uma extensão ou integração deve ser incrementada em cada atualização. Quando você estiver atualizando uma extensão existente, atualize a versão no manifesto ou passe a opção --rev-version de linha de comando. Isso incrementa o número de versão do patch da extensão e salva a nova versão no manifesto. Você deve revisar a versão da tarefa e a versão da extensão para que uma atualização ocorra. tfx extension create --manifest-globs vss-extension.json --rev-version atualiza apenas a versão da extensão e não a versão da tarefa. Para obter mais informações, consulte Build Task no GitHub.

Depois de ter sua extensão empacotada em um arquivo .vsix, você estará pronto para publicar sua extensão no Marketplace.

Etapa 5: Publicar sua extensão

Criar seu publicador

Todas as extensões, incluindo extensões da Microsoft, são identificadas como sendo fornecidas por um editor. Se você ainda não for membro de um publicador existente, criará um.

  1. Entre no Portal de Publicação do Visual Studio Marketplace.
  2. Se você ainda não for membro de um publicador existente, será solicitado que você crie um publicador. Se você não for solicitado a criar um editor, role para baixo até a parte inferior da página e selecione Publicar extensões em Sites Relacionados.
    • Especifique um identificador para seu publicador, por exemplo: mycompany-myteam.
      • Esse identificador é usado como o valor do publisher atributo no arquivo de manifesto de suas extensões.
    • Especifique um nome de exibição para seu publicador, por exemplo: My Team.
  3. Examine o Contrato de Editor do Marketplace e selecione Criar.

Seu publicador está definido. Em uma versão futura, você pode conceder permissões para exibir e gerenciar as extensões do publicador. É mais fácil e seguro publicar extensões em um publicador comum, sem a necessidade de compartilhar um conjunto de credenciais entre os usuários.

Carregar sua extensão

Depois de criar um publicador, você pode carregar sua extensão no Marketplace.

  • Localize o botão Carregar nova extensão , vá para o arquivo .vsix empacotado e selecione Carregar.

Você também pode carregar sua extensão por meio da linha de comando usando o tfx extension publish comando em vez de tfx extension create empacotar e publicar sua extensão em uma etapa. Opcionalmente, você pode usar --share-with para compartilhar sua extensão com uma ou mais contas após a publicação. Você também precisará de um token de acesso pessoal. Para obter mais informações, consulte Adquirir um token de acesso pessoal.

tfx extension publish --manifest-globs your-manifest.json --share-with yourOrganization

Compartilhar sua extensão

Agora que você carregou sua extensão, ela está no Marketplace, mas ninguém pode vê-la. Compartilhe-o com sua organização para que você possa instalá-lo e testá-lo.

  • Clique com o botão direito do mouse na extensão, selecione Compartilhar e insira as informações da organização. Você também pode compartilhá-lo com outras contas que deseja ter acesso à sua extensão.

Importante

Os editores devem ser verificados para compartilhar extensões publicamente. Para saber mais, consulte Pacote/Publicação/Instalação.

Agora que sua extensão está no Marketplace e compartilhada, quem quiser usá-la deve instalá-la.

Etapa 6: Criar um pipeline de build e lançamento para publicar a extensão no Marketplace

Crie um pipeline de build e lançamento no Azure DevOps para ajudar a manter a tarefa personalizada no Marketplace.

Pré-requisitos

Crie um grupo de variáveis de biblioteca de pipeline para manter as variáveis usadas pelo pipeline. Para obter mais informações sobre como criar um grupo de variáveis, consulte Adicionar e usar grupos de variáveis. Tenha em mente que você pode criar grupos de variáveis na guia Biblioteca do Azure DevOps ou por meio da CLI. Depois que um grupo de variáveis for feito, use todas as variáveis dentro desse grupo em seu pipeline. Leia mais sobre como usar um grupo de variáveis.

Declare as seguintes variáveis no grupo de variáveis:

  • publisherId: ID do seu publicador do marketplace.
  • extensionId: ID da sua extensão, conforme declarado no arquivo vss-extension.json.
  • extensionName: nome da extensão, conforme declarado no arquivo vss-extension.json.
  • artifactName: nome do artefato que está sendo criado para o arquivo VSIX.

Crie uma nova conexão de serviço do Visual Studio Marketplace e conceda permissões de acesso para todos os pipelines. Para obter mais informações sobre como criar uma conexão de serviço, consulte as conexões de serviço.

Captura de tela que mostra o novo painel de conexão de serviço.

Captura de tela que mostra o novo painel de conexão de serviço do Visual Studio Marketplace.

Use o exemplo a seguir para criar um novo pipeline com YAML. Saiba mais sobre como criar seu primeiro pipeline e esquema YAML.

trigger: 
- master

pool:
  vmImage: "ubuntu-latest"

variables:
  - group: variable-group # Rename to whatever you named your variable group in the prerequisite stage of step 6

stages:
  - stage: Run_and_publish_unit_tests
    jobs:
      - job:
        steps:
          - task: TfxInstaller@3
            inputs:
              version: "v0.7.x"
          - task: Npm@1
            inputs:
              command: 'install'
              workingDir: '/TaskDirectory' # Update to the name of the directory of your task
          - task: Bash@3
            displayName: Compile Javascript
            inputs:
              targetType: "inline"
              script: |
                cd TaskDirectory # Update to the name of the directory of your task
                tsc
          - task: Npm@1
            inputs:
              command: 'custom'
              workingDir: '/TestsDirectory' # Update to the name of the directory of your task's tests
              customCommand: 'testScript' # See the definition in the explanation section below - it may be called test
          - task: PublishTestResults@2
            inputs:
              testResultsFormat: 'JUnit'
              testResultsFiles: '**/ResultsFile.xml'
  - stage: Package_extension_and_publish_build_artifacts
    jobs:
      - job:
        steps:
          - task: TfxInstaller@3
            inputs:
              version: "v0.7.x"
          - task: Npm@1
            inputs:
              command: 'install'
              workingDir: '/TaskDirectory' # Update to the name of the directory of your task
          - task: Bash@3
            displayName: Compile Javascript
            inputs:
              targetType: "inline"
              script: |
                cd TaskDirectory # Update to the name of the directory of your task
                tsc
          - task: QueryAzureDevOpsExtensionVersion@3
            inputs:
              connectTo: 'VsTeam'
              connectedServiceName: 'ServiceConnection' # Change to whatever you named the service connection
              publisherId: '$(PublisherID)'
              extensionId: '$(ExtensionID)'
              versionAction: 'Patch'
              outputVariable: 'Task.Extension.Version'
          - task: PackageAzureDevOpsExtension@3
            inputs:
              rootFolder: '$(System.DefaultWorkingDirectory)'
              publisherId: '$(PublisherID)'
              extensionId: '$(ExtensionID)'
              extensionName: '$(ExtensionName)'
              extensionVersion: '$(Task.Extension.Version)'
              updateTasksVersion: true
              updateTasksVersionType: 'patch'
              extensionVisibility: 'private' # Change to public if you're publishing to the marketplace
              extensionPricing: 'free'
          - task: CopyFiles@2
            displayName: "Copy Files to: $(Build.ArtifactStagingDirectory)"
            inputs:
              Contents: "**/*.vsix"
              TargetFolder: "$(Build.ArtifactStagingDirectory)"
          - task: PublishBuildArtifacts@1
            inputs:
              PathtoPublish: '$(Build.ArtifactStagingDirectory)'
              ArtifactName: '$(ArtifactName)'
              publishLocation: 'Container'
  - stage: Download_build_artifacts_and_publish_the_extension
    jobs:
      - job:
        steps:
          - task: TfxInstaller@3
            inputs:
              version: "v0.7.x"
          - task: DownloadBuildArtifacts@0
            inputs:
              buildType: "current"
              downloadType: "single"
              artifactName: "$(ArtifactName)"
              downloadPath: "$(System.DefaultWorkingDirectory)"
          - task: PublishAzureDevOpsExtension@3
            inputs:
              connectTo: 'VsTeam'
              connectedServiceName: 'ServiceConnection' # Change to whatever you named the service connection
              fileType: 'vsix'
              vsixFile: '$(PublisherID).$(ExtensionName)/$(PublisherID)..vsix'
              publisherId: '$(PublisherID)'
              extensionId: '$(ExtensionID)'
              extensionName: '$(ExtensionName)'
              updateTasksVersion: false
              extensionVisibility: 'private' # Change to public if you're publishing to the marketplace
              extensionPricing: 'free'

Para obter mais ajuda com gatilhos, como gatilhos de CI e PR, consulte Especificar eventos que disparam pipelines.

Observação

Cada trabalho usa um novo agente de usuário e requer que as dependências sejam instaladas.

Estágios do pipeline

Esta seção ajuda você a entender como funcionam os estágios do pipeline.

Estágio: executar e publicar testes de unidade

Esta fase executa testes de unidade e publica resultados de teste no Azure DevOps.

Para executar testes de unidade, adicione um script personalizado ao arquivo package.json. Por exemplo:

"scripts": {
    "testScript": "mocha ./TestFile --reporter xunit --reporter-option output=ResultsFile.xml"
},
  1. Adicione "Usar a CLI do Nó para o Azure DevOps (tfx-cli)" para instalar o tfx-cli em seu agente de build.

  2. Adicione a tarefa "npm" com o comando "install" e direcione a pasta com o arquivo package.json.

  3. Adicione a tarefa "Bash" para compilar o TypeScript em JavaScript.

  4. Adicione a tarefa "npm" com o comando "personalizado", direcione a pasta que contém os testes de unidade e a entrada testScript como o comando. Use as seguintes entradas:

    • Comando: personalizado
    • Pasta de trabalho que contém package.json: /TestsDirectory
    • Comando e argumentos: testScript
  5. Adicione a tarefa "Publicar Resultados do Teste". Se você estiver usando o repórter do Mocha XUnit, verifique se o formato de resultado é "JUnit" e não "XUnit". Defina a pasta de pesquisa para o diretório raiz. Use as seguintes entradas:

    • Formato de resultado do teste: JUnit
    • Arquivos de resultados de teste: **/ResultsFile.xml
    • Pasta de pesquisa: $(System.DefaultWorkingDirectory)

Depois que os resultados do teste tiverem sido publicados, a saída na guia testes deverá ter esta aparência:

Captura de tela do exemplo de resultado do teste.

Estágio: empacotar a extensão e publicar artefatos de build

  1. Adicione "Usar a CLI do Nó para o Azure DevOps (tfx-cli)" para instalar o tfx-cli em seu agente de build.

  2. Adicione a tarefa "npm" com o comando "install" e direcione a pasta com o arquivo package.json.

  3. Adicione a tarefa "Bash" para compilar o TypeScript em JavaScript.

  4. Adicione a tarefa "Versão da Extensão de Consulta" para consultar a versão da extensão existente. Use as seguintes entradas:

    • Conectar-se a: Visual Studio Marketplace
    • Visual Studio Marketplace (conexão de serviço): Conexão de Serviço
    • ID do Publicador: ID do publicador do Visual Studio Marketplace
    • ID da extensão: ID da extensão no arquivo vss-extension.json
    • Aumentar versão: Patch
    • Variável de saída: Task.Extension.Version
  5. Adicione a tarefa "Extensão de Pacote" para empacotar as extensões com base no manifesto Json. Use as seguintes entradas:

    • Pasta de manifestos raiz: aponta para o diretório raiz que contém o arquivo de manifesto. Por exemplo, $(System.DefaultWorkingDirectory) é o diretório raiz.
    • Arquivo de manifesto(s): vss-extension.json.
    • ID do Publicador: ID do seu publicador do Visual Studio Marketplace.
    • ID da extensão: ID da extensão no arquivo vss-extension.json.
    • Nome da extensão: nome da extensão no arquivo vss-extension.json.
    • Versão da extensão: $(Task.Extension.Version).
    • Substituir a versão das tarefas: marcada (true).
    • Tipo de substituição: substituir somente patch (1.0.r).
    • Visibilidade da extensão: se a extensão ainda estiver em desenvolvimento, defina o valor como privado. Para liberar a extensão para o público, defina o valor como público.
  6. Adicione a tarefa "Copiar arquivos" para copiar arquivos publicados. Use as seguintes entradas:

    • Conteúdo: todos os arquivos a serem copiados para publicá-los como um artefato
    • Pasta de destino: a pasta para a qual os arquivos são copiados
      • Por exemplo: $(Build.ArtifactStagingDirectory)
  7. Adicione "Publicar artefatos de build" para publicar os artefatos para uso em outros trabalhos ou pipelines. Use as seguintes entradas:

    • Caminho a ser publicado: o caminho para a pasta que contém os arquivos que estão sendo publicados.
      • Por exemplo: $(Build.ArtifactStagingDirectory).
    • Nome do artefato: o nome fornecido ao artefato.
    • Localização de publicação de artefatos: escolha "Azure Pipelines" para usar o artefato em trabalhos futuros.

Estágio: baixar artefatos de build e publicar a extensão

  1. Adicione "Usar a CLI do Nó para o Azure DevOps (tfx-cli)" para instalar o tfx-cli em seu agente de build.

  2. Adicione a tarefa "Baixar artefatos de build" para baixar os artefatos em um novo trabalho. Use as seguintes entradas:

    • Baixe artefatos produzidos por: Se você estiver baixando o artefato em um novo trabalho no mesmo pipeline, selecione "Build atual". Se você estiver baixando em um novo pipeline, selecione "Build específico".
    • Tipo de download: escolha "Artefato específico" para baixar todos os arquivos que foram publicados.
    • Nome do artefato: o nome do artefato publicado.
    • Diretório de destino: a pasta em que os arquivos devem ser baixados.
  3. A última tarefa de que você precisa é a tarefa "Publicar Extensão". Use as seguintes entradas:

    • Conectar-se a: Visual Studio Marketplace
    • Conexão do Visual Studio Marketplace: ServiceConnection
    • Tipo de arquivo de entrada: arquivo VSIX
    • Arquivo VSIX: /Publisher.*.vsix
    • ID do Publicador: ID do publicador do Visual Studio Marketplace
    • ID da extensão: ID da extensão no arquivo vss-extension.json
    • Nome da extensão: nome da extensão no arquivo vss-extension.json
    • Visibilidade da extensão: privada ou pública

Opcional: instalar e testar sua extensão

Instale uma extensão que é compartilhada com você em apenas algumas etapas:

  1. No painel de controle da organização (https://dev.azure.com/{organization}/_admin), vá para a página de administração da coleção de projetos.
  2. Na guia Extensões , localize sua extensão no grupo "Extensões Compartilhadas Comigo" e selecione o link de extensão.
  3. Instalar a extensão.

Se você não conseguir ver a guia Extensões , verifique se está no painel de controle (a página de administração no nível https://dev.azure.com/{organization}/_adminda coleção do projeto) e não a página de administração de um projeto.

Se você não vir a guia Extensões , as extensões não estarão habilitadas para sua organização. Você pode obter acesso antecipado ao recurso de extensões ingressando no Visual Studio Partner Program.

Para empacotar e publicar extensões do Azure DevOps no Visual Studio Marketplace, você pode baixar as Tarefas de Extensão do Azure DevOps.

Perguntas frequentes

Como posso restringir o uso de comandos do Visual Studio Codespaces para tarefa?

Você pode restringir o uso de comandos e variáveis do Visual Studio Codespaces, que podem ser definidos por tarefa. Essa ação pode ser útil para impedir o acesso irrestrito a comandos variáveis/vso para scripts personalizados que a tarefa executa. É recomendável configurá-lo para novas tarefas. Para aplicar - talvez seja necessário adicionar a seguinte instrução ao arquivo task.json:

  "restrictions": {
    "commands": {
      "mode": "restricted"
    },
    "settableVariables": {
      "allowed": ["variable1", "test*"]
    }
}

Se o valor "restrito" for especificado para "modo" - você só poderá executar os seguintes comandos pela tarefa:

  • logdetail
  • logissue
  • complete
  • setprogress
  • setsecret
  • setvariable
  • debug
  • settaskvariable
  • prependpath
  • publish

As restrições "settableVariables" permitem que você passe uma lista de permissões de variáveis, que pode ser definida por setvariable ou prependpath comandos. Ele também permite expressões regulares básicas. Portanto, por exemplo, se sua lista de permissões fosse: ['abc', 'test*'], definindo abc, teste ou test1 como variáveis com qualquer valor ou pré-endending para o caminho teria êxito, mas se você tentar definir um proxy variável, ele avisaria. Lista vazia significa que nenhuma variável pode ser alterada por tarefa.

"commands" e "settableVariables" são ortogonais - se a chave de comandos ou settableVariables for omitida - a restrição relevante não será aplicada.

O recurso de restrição está disponível na versão do agente 2.182.1 .

Como o sinal de cancelamento está sendo tratado por uma tarefa?

O agente de pipeline envia sinais SIGINT e SIGTERM para o processo filho relevante. Não há meios explícitos na biblioteca de tarefas a serem processados . Você pode encontrar mais informações aqui.

Como posso remover a tarefa da coleção de projetos?

Não damos suporte à exclusão automática de tarefas. A exclusão automática não é segura e interrompe pipelines existentes que já usam essas tarefas. Mas, você pode marcar tarefas como preteridas. Para fazer isso, pressione a versão da tarefa conforme descrito aqui e siga as etapas descritas nos documentos.

Como posso migrar a tarefa para o Nó 10?

Você pode encontrar diretrizes aqui.