Adicionar uma extensão de tarefa de pipelines personalizados

Azure DevOps Services | Azure DevOps Server 2022 - Azure DevOps Server 2019

Saiba como instalar extensões em sua organização para tarefas personalizadas de build ou versão no Azure DevOps. Para obter mais informações, confira O que são os pipelines do Azure?

Observação

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

Pré-requisitos

Para criar extensões para o Azure DevOps, você precisa do software e das ferramentas a seguir.

Software/ferramenta Informações
Organização do Azure DevOps Crie uma organização.
Um editor de texto Para muitos procedimentos, usamos o Visual Studio Code, que fornece suporte ao intellisense e à depuração. Faça o download da versão mais recente.
Node.js Faça o download da versão mais recente.
npmjs.com 4.0.2 ou mais recente Compilador TypeScript. Faça o download da versão mais recente.
tfx-cli Empacote sua extensão com a CLI multiplataforma para Azure DevOps. usando npm, um componente do Node.js, executando npm i -g tfx-cli.
SDK da extensão do Azure DevOps Instale o pacote azure-devops-extension-sdk.
Um home diretório para o seu projeto O home diretório de uma extensão de tarefa de build ou versão deve ser semelhante ao exemplo a seguir depois de concluir as etapas neste artigo.
|--- README.md    
|--- images                        
    |--- extension-icon.png  
|--- buildandreleasetask            // where your task scripts are placed
|--- vss-extension.json             // extension's manifest

Importante

A máquina de desenvolvimento deve executar a versão mais recente do Node para garantir que o código escrito 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. Atualize seu arquivo task.json de acordo com o seguinte comando:

"execution": {
   "Node20_1": {
     "target": "index.js"
   }
 }

1. Crie uma tarefa personalizada

Faça todas as partes deste procedimento dentro da buildandreleasetask pasta.

Observação

Este exemplo passo a passo usa Windows com o PowerShell. Nós o tornamos 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>.

Criar scaffolding de tarefas

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

  2. Abra uma janela de comando do PowerShell, vá para sua buildandreleasetask pasta e execute o comando a seguir.

    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 do nó. Para atenuar isso, copie o node_modules arquivo para buildandreleasetask. À medida que sua tarefa fica maior, é fácil exceder o limite de tamanho (50 MB) de um arquivo VSIX. Antes de copiar a pasta do nó, você pode executar npm install --production ou npm prune --production, ou pode escrever um script para compilar e empacotar tudo.

  3. Adicione azure-pipelines-task-lib à sua biblioteca.

    npm install azure-pipelines-task-lib --save
    
  4. Verifique se as tipificações do TypeScript estão instaladas para dependências externas.

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

    echo node_modules > .gitignore
    
  6. Instale 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
    
  7. Escolha TypeScript versão 2.3.4 ou 4.6.3.

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

    Observação

    Verifique se o TypeScript está instalado globalmente com o npm em seu ambiente de desenvolvimento, para que o tsc comando esteja disponível. Se você ignorar esta etapa, o TypeScript versão 2.3.4 será usado por padrão e você ainda precisará instalar o pacote globalmente para ter o tsc comando disponível.

  8. Crie tsconfig.json opções do compilador. Esse arquivo garante que seus arquivos TypeScript sejam compilados em arquivos JavaScript.

    tsc --init --target es2022
    

Criar tarefa

Agora que o andaime está completo, podemos criar nossa tarefa personalizada.

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

  2. Copie o código a seguir e substitua o {{placeholders}} pelas informações da tarefa. O espaço reservado mais importante é o taskguid, e 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": {
         "Node20_1": {
             "target": "index.js"
         }
     }
     }
    
  3. 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:any) {
             tl.setResult(tl.TaskResult.Failed, err.message);
         }
     }
    
     run();
    
  4. Digite "tsc" na buildandreleasetask pasta para compilar um index.js arquivo de index.ts.

task.json componentes

Veja as seguintes 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 desenvolve a tarefa de build ou versão, por exemplo: "Microsoft Corporation".
instanceNameFormat Como a tarefa é exibida na lista de etapas de compilação/versão. Você pode usar valores de variáveis usando $(variablename).
groups Descreve o agrupamento lógico de propriedades de tarefa 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 esta tarefa, incluindo scripts.
restrictions As restrições que estão sendo aplicadas à tarefa sobre comandos do GitHub Codespaces que a tarefa pode chamar e as variáveis que a tarefa pode definir. Recomendamos que você especifique o modo de restrição para novas tarefas.

Observação

Crie um id com o seguinte comando no PowerShell:

(New-Guid).Guid

Para obter mais informações, consulte a referência da tarefa Compilar/liberar.

Executar a tarefa

Execute 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 gerou corretamente "Hello Human!"

Dica

Para obter informações sobre vários executores de tarefas e como incluir a versão mais recente do nó no task.json, consulte Diretrizes de atualização do executor de nó para autores de tarefas do Azure Pipelines.

2. Teste a unidade de seus scripts de tarefa

Faça testes de unidade para testar rapidamente o script de tarefa e não as ferramentas externas que ele chama. Teste todos os aspectos dos caminhos de sucesso e falha.

  1. Instale ferramentas de teste. Usamos o Mocha como o driver de teste neste procedimento.

    npm install mocha --save-dev -g
    npm install sync-request --save-dev
    npm install @types/mocha --save-dev
    
  2. 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 sync-request à pasta buildandreleasetask com o comando npm i --save-dev sync-request.

  3. Crie um success.ts arquivo em seu diretório de teste com o conteúdo a seguir. Essa criação de arquivo simula a execução da tarefa e simula todas as chamadas para métodos externos.

    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();
    

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

  4. Adicione o exemplo de teste de sucesso a seguir ao arquivo _suite.ts para executar o executor simulado de tarefas.

        it('should succeed with simple inputs', function(done: Mocha.Done) {
        this.timeout(1000);
    
        let tp: string = path.join(__dirname, 'success.js');
        let tr: ttm.MockTestRunner = new ttm.MockTestRunner(tp);
    
        // tr.run(); //current, old function.
        tr.runAsync().then(() => {
            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();
        }).catch((error) => {
            done(error); // Ensure the test case fails if there's an error
        });
    });
    
  5. Crie um failure.ts arquivo em seu diretório de teste como seu executor simulado de tarefas 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();
    

    O teste de falha valida que, quando a ferramenta recebe entrada inválida ou incompleta, ela falha da maneira esperada com saída útil.

  6. Adicione o código a seguir ao arquivo _suite.ts para executar o executor simulado de tarefas.

    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();
    });
    
  7. Execute os testes.

    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 compilação), defina a variável de ambiente: TASK_TEST_TRACE=1.

    $env:TASK_TEST_TRACE=1
    

3. Crie o arquivo de manifesto de extensão

O manifesto da extensão contém todas as informações sobre sua extensão. Inclui links para seus arquivos, incluindo suas pastas de tarefas e pastas de imagens. Certifique-se de ter criado 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

Altere o editor para o nome do editor. Para obter mais informações, consulte Criar um editor.

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 esta contribuição. Deve ser ms.vss-distributed-task.tasks.
properties.name Nome da tarefa. Esse nome deve corresponder ao nome da pasta da tarefa de build ou pipeline de lançamento independente 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, consulte a referência de manifesto de extensão.

4. Empacote sua extensão

Empacote todos os seus arquivos juntos para colocar sua extensão no Visual Studio Marketplace. 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.

Depois de ter o tfx-cli, vá para o diretório inicial da sua extensão e execute 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. Ao atualizar uma extensão existente, atualize a versão no manifesto ou passe a opção de --rev-version linha de comando. Isso incrementa o número da 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 ocorra uma atualização. 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 Tarefa de build no GitHub.

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

5. Publique sua extensão

Para publicar sua extensão, primeiro crie seu editor, depois carregue sua extensão e, finalmente , compartilhe-a.

Crie seu editor

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 editor existente, crie um.

  1. Entre no Portal de Publicação do Visual Studio Marketplace.
  2. Se você ainda não for membro de um editor existente, será solicitado a criar um editor. 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 editor, por exemplo: mycompany-myteam.
      • Esse identificador é usado como o valor do atributo no arquivo de manifesto publisher de suas extensões.
    • Especifique um nome de exibição para seu editor, por exemplo: My Team.
  3. Examine o Contrato de Editor do Marketplace e selecione Criar.

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

Carregar sua extensão

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

  1. Você também pode carregar sua extensão por meio da interface de linha de comando (CLI) usando o tfx extension publish comando em vez de tfx extension create empacotar e publicar sua extensão em uma única etapa. Opcionalmente, você pode usar --share-with para compartilhar sua extensão com uma ou mais contas depois que ela for publicada.

    tfx extension publish --manifest-globs your-manifest.json --share-with yourOrganization
    
  2. Crie um PAT (token de acesso pessoal).

    • Selecione o escopo "Marketplace (publicar)". Esse escopo limita o token a apenas poder publicar extensões no Marketplace.

Compartilhe 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.

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

Importante

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

Agora que sua extensão é compartilhada no Marketplace, qualquer pessoa que queira usá-la deve instalá-la.

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

Software/ferramenta

Informações

Projeto do Azure DevOps

Extensão de tarefas de extensão do Azure DevOps

Instale gratuitamente as Tarefas de Extensão do Azure DevOps em sua organização.

Grupo de variáveis da biblioteca de pipeline

Crie um grupo de variáveis de biblioteca de pipeline para manter as variáveis usadas pelo pipeline. Para obter mais informações, consulte Adicionar e usar grupos de variáveis. Você pode criar grupos de variáveis na guia Azure DevOps Library ou por meio da CLI. Use as variáveis dentro desse grupo em seu pipeline. Além disso, declare as seguintes variáveis no grupo de variáveis:

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

Conexão de serviço

Crie uma nova conexão de serviço do Marketplace e conceda permissões de acesso para todos os pipelines.

Pipeline YAML

Use o exemplo a seguir para criar um novo pipeline com YAML. Para obter mais informações, consulte Criar seu primeiro pipeline e esquema YAML.

trigger: 
- main
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@4
inputs:
version: "v0.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@4
inputs:
version: "0.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@4
name: QueryVersion
inputs:
connectTo: 'VsTeam'
connectedServiceName: 'ServiceConnection' # Change to whatever you named the service connection
publisherId: '$(PublisherID)'
extensionId: '$(ExtensionID)'
versionAction: 'Patch'
- task: PackageAzureDevOpsExtension@4
inputs:
rootFolder: '$(System.DefaultWorkingDirectory)'
publisherId: '$(PublisherID)'
extensionId: '$(ExtensionID)'
extensionName: '$(ExtensionName)'
extensionVersion: '$(QueryVersion.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@4
inputs:
version: "v0.x"
- task: DownloadBuildArtifacts@0
inputs:
buildType: "current"
downloadType: "single"
artifactName: "$(ArtifactName)"
downloadPath: "$(System.DefaultWorkingDirectory)"
- task: PublishAzureDevOpsExtension@4
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 informações, consulte Especificar eventos que disparam pipelines.

Observação

Cada trabalho usa um novo agente de usuário e requer a instalação de dependências.

Estágios do pipeline

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

Estágio 1: Executar e publicar testes de unidade

Esse estágio executa testes de unidade e publica os resultados do teste no Azure DevOps.

Para executar testes de unidade, adicione um script personalizado ao arquivo package.json, como no exemplo a seguir.

"scripts": {
    "testScript": "mocha ./TestFile --reporter xunit --reporter-option output=ResultsFile.xml"
},
  1. Adicione "Usar CLI do Nó para 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 "custom", direcione a pasta que contém os testes de unidade e insira 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 Mocha XUnit, certifique-se de que o formato do resultado seja "JUnit" e não "XUnit". Defina a pasta de pesquisa para o diretório raiz. Use as seguintes entradas:

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

    Depois que os resultados do teste forem publicados, a saída na guia testes deverá ser semelhante ao exemplo a seguir.

    Captura de tela do exemplo de resultado do teste.

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

  1. Adicione "Usar CLI do Nó para 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 "Consultar Versão da Extensão" 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 editor: ID do editor do Visual Studio Marketplace
    • ID da extensão: ID da sua 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 do 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(s) de manifesto: vss-extension.json
    • ID do editor: ID do editor do Visual Studio Marketplace
    • ID da extensão: ID da sua extensão no arquivo vss-extension.json
    • Nome da extensão: Nome da sua extensão no arquivo vss-extension.json
    • Versão da extensão: $(Task.Extension.Version)
    • Substituir versão das tarefas: marcada (true)
    • Tipo de substituição: Substituir apenas patch (1.0.r)
    • Visibilidade da extensão: se a extensão ainda estiver em desenvolvimento, defina o valor como private. 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 para publicar: o caminho para a pasta que contém os arquivos que estão sendo publicados
      • Por exemplo: $(Build.ArtifactStagingDirectory)
    • Nome do artefato: O nome dado ao artefato
    • Local de publicação de artefatos: escolha "Azure Pipelines" para usar o artefato em trabalhos futuros

Etapa 3: Baixar artefatos de build e publicar a extensão

  1. Adicione "Usar CLI do Nó para 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:

    • Baixar artefatos produzidos por: se você estiver baixando o artefato em um novo trabalho do 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 onde os arquivos devem ser baixados.
  3. A última tarefa 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 editor: ID do editor do Visual Studio Marketplace
    • ID da extensão: ID da sua extensão no arquivo vss-extension.json
    • Nome da extensão: Nome da sua extensão no arquivo vss-extension.json
    • Visibilidade da extensão: privada ou pública

Opcional: Instale e teste sua extensão

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

  1. No painel de controle da sua 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, encontre sua extensão no grupo "Extensões compartilhadas comigo" e selecione o link da 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 da coleção de projetos) https://dev.azure.com/{organization}/_admine não na página de administração de um projeto.

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

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

Perguntas Frequentes

Consulte as perguntas frequentes a seguir sobre como adicionar tarefas personalizadas de build ou versão em extensões para Azure DevOps.

P: Como posso restringir o uso de comandos do Azure Pipelines para a tarefa?

Você pode restringir o uso e as variáveis de comandos do Azure Pipelines, que são definidos por tarefa. Essa ação pode ser útil para impedir o acesso irrestrito a comandos variables/vso para scripts personalizados cuja tarefa é executada. Recomendamos que você o configure para novas tarefas. Para se inscrever, talvez seja necessário adicionar a seguinte instrução ao arquivo task.json:

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

Se restricted value for especificado para mode - você só poderá executar os seguintes comandos pela tarefa:

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

As settableVariables restrições permitem que você passe uma lista de permissões de variáveis, que são definidas por setvariable comandos or prependpath . Ele também permite expressões regulares básicas. Por exemplo, se sua lista de permissões fosse: ['abc', 'test*'], definindo abc, test, ou test1 como variáveis com qualquer valor ou anexando-as ao caminho seria bem-sucedido, mas se você tentar definir um proxy de variável, ele avisaria. Lista vazia significa que nenhuma variável é alterada por tarefa.

Se a chave ou commands for omitida, a settableVariables restrição relevante não será aplicada.

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

P: Como o sinal de cancelamento é tratado por uma tarefa?

R: O agente de pipeline envia SIGINT e SIGTERM sinaliza para o processo filho relevante. Não há meios explícitos na biblioteca de tarefas para processar. Para obter mais informações, consulte Cancelamento de trabalhos do agente.

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

R: Não oferecemos suporte à exclusão automática de tarefas. A exclusão automática não é segura e interrompe os pipelines existentes que já usam essas tarefas. No entanto, você pode marcar tarefas como obsoletas. Para fazer isso, aumente a versão da tarefa e marque a tarefa como preterida.

P: Como posso atualizar minha tarefa personalizada para o nó mais recente?

R: Recomendamos atualizar para a versão mais recente do Node. Para obter informações de exemplo, consulte Atualizando tarefas para o Nó 20.

Como os agentes hospedados pela Microsoft e várias versões do Azure DevOps Server têm ciclos de vida diferentes, pode haver diferentes versões do executor do nó instaladas, dependendo de onde uma tarefa está sendo executada. Para poder executar a mesma tarefa em agentes com diferentes versões do executor do Node, o arquivo task.json pode conter várias seções de execução. No exemplo a seguir, os agentes do Azure Pipeline que incluem o executor do Nó 20 o escolherão por padrão e aqueles que não o fizerem retornarão à implementação do Nó 10.

  "execution": {
    "Node10": {
      "target": "bash.js",
      "argumentFormat": ""
    },
    "Node20_1": {
      "target": "bash.js",
      "argumentFormat": ""
    }

Para atualizar suas tarefas:

  • Teste suas tarefas nas várias versões do executor do Node para garantir que seu código se comporte conforme o esperado.

  • Na seção de execução da tarefa, atualize de Node ou Node10 para Node16 ou Node20.

  • Para oferecer suporte a versões mais antigas do servidor, você deve deixar o Node/Node10 destino. Azure DevOps Server versões mais antigas podem não ter a versão mais recente do executor do nó incluída.

  • Você pode optar por compartilhar o ponto de entrada definido no destino ou ter destinos otimizados para a versão do nó usada.

    "execution": {
       "Node10": {
         "target": "bash10.js",
         "argumentFormat": ""
    },
    "Node16": {
       "target": "bash16.js",
       "argumentFormat": ""
    },
    "Node20_1": {
       "target": "bash20.js",
       "argumentFormat": ""
    }
    

Importante

Não adicionar suporte para o executor do Nó 20 em suas tarefas personalizadas fará com que as tarefas falhem nos agentes instalados a pipelines-agent-* partir do feed de lançamento.