Partilhar via


Adicionar uma extensão de tarefa personalizada para pipelines

Serviços de DevOps do Azure | Azure DevOps Server 2022 - Azure DevOps Server 2019

Este artigo explica como instalar extensões na sua organização para tarefas personalizadas de compilação ou lançamento no Azure DevOps. Para obter mais informações, consulte O que é o Azure Pipelines?

Nota

Este artigo aborda as tarefas de agentes em extensões baseadas em agentes. Para obter mais informações sobre tarefas de servidor e extensões baseadas em servidor, consulte Criação de tarefas de servidor.

Pré-requisitos

  • Uma organização no Azure DevOps. Crie uma organização.

  • Um editor de texto. Para muitos tutoriais, usamos o Visual Studio Code, que fornece suporte a intellisense e depuração.

  • A última versão do Node.js.

  • npmjs.com 4.0.2 ou mais recente. Instale a versão mais recente deste compilador TypeScript.

  • CLI de plataforma cruzada para Azure DevOps (tfx-cli) para empacotar suas extensões.

    • tfx-cli pode ser instalado usando npm, um componente de Node.js, executando npm i -g tfx-cli.
  • SDK da extensão 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 compilação ou liberação deve ter a seguinte estrutura 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 com a versão mais recente não visualizada do azure-pipelines-task-lib. Atualize seu task.json arquivo de acordo com o seguinte comando:

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

1. Crie uma tarefa personalizada

Faça cada parte deste procedimento dentro da pasta dentro do buildandreleasetask seu home diretório.

Nota

Este exemplo passo a passo usa o Windows com PowerShell. As etapas são genéricas 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 de $env:<var>=<val> por export <var>=<val>.

Criar andaimes 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 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 .

    Gorjeta

    O agente não instala automaticamente os módulos necessários porque espera que a sua pasta de tarefas inclua os módulos de node. Para atenuar, 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ó, poderá querer 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. Certifique-se de que os tipos TypeScript estejam instalados para as 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 compilação deve fazer um npm install e um typings install para que node_modules sejam construídos 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
    

    Nota

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

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

    tsc --init --target es2022
    

Criar tarefa

Agora que o andaime está concluído, pode criar a sua tarefa personalizada.

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

  2. Copie o código a seguir e substitua o {{placeholders}} pelas informações específicas da sua tarefa. O marcador de posição 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": {
         "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. Para compilar um ficheiro index.js a partir de index.ts, execute tsc a partir da pasta buildandreleasetask.

componentes de task.json

Consulte as descrições a seguir de alguns dos componentes do task.json arquivo.

Propriedade Descrição
id Um GUID exclusivo para a sua tarefa.
name Nome sem espaços.
friendlyName Nome descritivo (espaços permitidos).
description Descrição detalhada do que esta tarefa faz.
author Cadeia de caracteres curta que descreve a entidade que está desenvolvendo a tarefa de compilação ou versão, por exemplo: Microsoft Corporation
instanceNameFormat Como a tarefa é exibida na lista de etapas de compilação/liberação. Você pode usar valores de variáveis usando $(variablename).
groups Descreve o agrupamento lógico das propriedades da tarefa na interface do usuário.
inputs Entradas a serem usadas quando sua tarefa de compilação ou liberação for executada. Esta tarefa espera uma entrada com o nome samplestring.
execution Há várias opções de execução para essa tarefa, incluindo scripts, como Node, PowerShell, PowerShell3ou Process.
restrictions Restrições sendo aplicadas à tarefa sobre os comandos Codespaces do GitHub 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.

Nota

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 usando o node index.js do 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, defina a samplestring entrada e execute 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 é bem-sucedida porque samplestring foi fornecida, e produz corretamente Hello Human!

Gorjeta

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.

Faça testes unitários aos seus scripts de tarefas

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

  1. Instale ferramentas de teste. Usamos 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
        });    
    });
    

    Gorjeta

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

  3. Crie um success.ts arquivo em seu diretório de teste com o seguinte conteúdo. 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. Para executar o simulador de execução de tarefas, adicione o seguinte exemplo de teste de sucesso ao seu arquivo _suite.ts.

         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 ruim ou incompleta, ela falha da maneira esperada com saída útil.

  6. Para executar o executante simulado de tarefa, adicione o seguinte código ao seu ficheiro _suite.ts.

    it('should fail if tool returns 1', function(done: Mocha.Done) {
        this.timeout(1000);
    
        const tp = path.join(__dirname, 'failure.js');
        const tr: ttm.MockTestRunner = new ttm.MockTestRunner(tp);
    
        tr.runAsync().then(() => {
            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 de extensão contém todas as informações sobre sua extensão. Inclui links para os seus ficheiros, incluindo as suas pastas de tarefas e pastas de imagens. Certifique-se de criar uma pasta extension-icon.png de imagens. O exemplo a seguir é um manifesto de extensão que contém a tarefa de compilação ou versão.

Copie o seguinte código .json e salve-o como seu vss-extension.json arquivo no diretório home .

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"
            }
        }
    ]
}

Nota

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

Contribuições

Propriedade Descrição
id Identificador da contribuição. Deve ser único dentro da extensão. Não precisa corresponder ao nome da tarefa de compilação ou versão. Normalmente, o nome da tarefa de compilação ou liberação está no ID da contribuição.
type Tipo de contribuição. deverá ser ms.vss-distributed-task.task.
targets Contribuições visadas por esta contribuição. deverá ser ms.vss-distributed-task.tasks.
properties.name Nome da tarefa. Esse nome deve corresponder ao nome da pasta da tarefa de pipeline de compilação ou liberação independente correspondente.

Ficheiros

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

Para obter mais informações sobre o ficheiro de manifesto de extensão, como as suas propriedades e o que elas 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 interface de linha de comando (CLI) entre plataformas 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

Nota

Uma extensão ou versão de integração deve ser incrementada em cada atualização. Quando estiver a atualizar uma extensão existente, atualize a versão no manifesto ou utilize a opção da linha de comando --rev-version. Isso incrementa o número da versão do patch da sua extensão e salva a nova versão no seu manifesto. Você deve rever 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 apenas atualiza a versão da extensão e não a versão da tarefa. Para obter mais informações, consulte Criar tarefa no GitHub.

Quando a 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 o seu publicador

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

  1. Entre no Portal de Publicação do Visual Studio Marketplace.

  2. Se ainda não for membro de um editor existente, ser-lhe-á pedido para 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 o editor, por exemplo: mycompany-myteam.
      • Esse identificador é usado como o valor para o atributo publisher no arquivo de manifesto das suas extensões.
    • Especifique um nome para exibição para seu editor, por exemplo: My Team.
  3. Reveja o Contrato de Editor do Marketplace e selecione Criar.

Seu editor está definido. Numa versão futura, poderá conceder permissões para ver e gerir as extensões do seu publicador. É 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.

Carregue a sua extensão

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

Você também pode submeter a sua extensão através da interface de linha de comando (CLI) usando o comando tfx extension publish em vez de tfx extension create para empacotar e publicar a extensão num único passo. 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

Partilhe a sua extensão

Agora que você carregou sua extensão, ela está no Marketplace, mas ninguém pode vê-la. Partilhe-o com a sua organização para que 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 partilhá-la com outras contas às quais pretende dar acesso à sua extensão.

Importante

Os publicadores devem ser verificados para partilhar extensões publicamente. Para obter mais informações, consulte Package/Publish/Install.

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

6. Crie um pipeline de compilação e lançamento para publicar a extensão no Marketplace

Para manter a tarefa personalizada no Marketplace, crie um pipeline de compilação e lançamento no Azure DevOps.

Pré-requisitos para publicar

  • Um projeto de DevOps do Azure. Crie um projeto.

  • Extensão de Tarefas do Azure DevOps. Instale-o gratuitamente na sua organização.

  • Grupo de variáveis da biblioteca de pipeline. Crie um grupo de variáveis da biblioteca de pipeline para armazenar 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 Biblioteca de DevOps do Azure 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 seu 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 o 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 acionam pipelines.

Nota

Cada trabalho usa um novo agente de usuário e requer dependências para ser instalado.

Estágios do pipeline

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

Etapa 1: Executar e publicar testes de unidade

Este 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 package.json arquivo, como o exemplo a seguir.

"scripts": {
    "testScript": "mocha ./TestFile --reporter xunit --reporter-option output=ResultsFile.xml"
},
  1. Adicione Use Node CLI for Azure DevOps (tfx-cli) para instalar o tfx-cli em seu agente de compilação.

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

  3. Adicione a tarefa Bash para a compilação do TypeScript para JavaScript.

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

    • Comando: custom
    • 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 Mocha XUnit reporter, certifique-se de que o formato do resultado é 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
    • Ficheiros de resultados do teste: **/ResultsFile.xml
    • Pasta de pesquisa: $(System.DefaultWorkingDirectory)

    Depois que os resultados do teste forem publicados, a saída na guia testes deve se parecer com o exemplo a seguir.

    Captura de tela do exemplo de resultado do teste.

Etapa 2: Empacotar a extensão e publicar artefatos de compilação

  1. Adicione Use Node CLI for Azure DevOps (tfx-cli) para instalar o tfx-cli em seu agente de compilação.

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

  3. Adicione a tarefa Bash para a compilação do TypeScript para JavaScript.

  4. Para consultar a versão existente, adicione a tarefa Versão de Extensão de Consulta usando 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 seu editor do Visual Studio Marketplace
    • ID da extensão: ID da sua extensão no vss-extension.json arquivo
    • Atualizar versão: Patch
    • Variável de saída: Task.Extension.Version
  5. Para empacotar as extensões com base no manifesto Json, adicione a tarefa Extensão de pacote usando 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: vss-extension.json
    • ID do editor: ID do seu editor do Visual Studio Marketplace
    • ID da extensão: ID da sua extensão no vss-extension.json arquivo
    • Nome da extensão: Nome da sua extensão no vss-extension.json arquivo
    • Versão da extensão: $(Task.Extension.Version)
    • Substituir versão de tarefas: verificada (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 privado. Para liberar a extensão para o público, defina o valor como público.
  6. Para copiar para arquivos publicados, adicione a tarefa Copiar arquivos usando 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 compilação para disponibilizar os artefatos para uso em outras tarefas ou pipelines. Use as seguintes entradas:

    • Caminho para publicação: 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 o Azure Pipelines para usar o artefato em trabalhos futuros

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

  1. Para instalar o tfx-cli no seu agente de compilação, adicione Use Node CLI for Azure DevOps (tfx-cli).

  2. Para baixar os artefatos em um novo trabalho, adicione a tarefa Baixar artefatos de compilação usando as seguintes entradas:

    • Baixar artefatos produzidos por: Se estiveres a baixar o artefato num novo trabalho da mesma linha de montagem, seleciona Compilação atual. Se estiver a baixar num novo pipeline, selecione Compilação específica
    • 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. Para obter a tarefa Publicar extensão, use as seguintes informações:

    • 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 seu editor do Visual Studio Marketplace
    • ID da extensão: ID da sua extensão no vss-extension.json arquivo
    • Nome da extensão: Nome da sua extensão no vss-extension.json arquivo
    • Visibilidade da extensão: privada ou pública

Opcional: Instale e teste sua extensão

Instale uma extensão 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 , localize sua extensão no grupo Extensões compartilhadas comigo e selecione o link da extensão.
  3. Instale a extensão.

Se não conseguir ver o separador 'Extensões', certifique-se de estar no painel de controlo (página de administração no nível da coleção de projetos) e não na página de administração de projeto específico.

Se não vir a aba Extensões, as extensões não estão ativadas para a 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 as Extensões de DevOps do Azure no Visual Studio Marketplace, você pode baixar as Tarefas de Extensão do Azure DevOps.

Perguntas Frequentes

Consulte as seguintes perguntas frequentes sobre como adicionar tarefas de compilação ou versão personalizadas em extensões para o Azure DevOps.

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

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

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

Se o valor restricted 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 o utilizador forneça uma lista de aprovação de variáveis, que são definidas por comandos setvariable ou prependpath. Ele também permite expressões regulares básicas. Por exemplo, se a sua lista de permissões fosse: ['abc', 'test*'], definir abc, test, ou test1 como variáveis com qualquer valor ou adicioná-las ao caminho teria êxito, mas se tentar definir uma variável de proxy, surgirá um aviso. Lista vazia significa que nenhuma variável é alterada por tarefa.

Se as chaves settableVariables ou commands forem omitidas, a restrição relevante não será aplicada.

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

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

O agente do pipeline envia os sinais SIGINT e SIGTERM 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 de agente.

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

Não suportamos a eliminação automática de tarefas. A eliminação automática não é segura e interrompe os processos existentes que já utilizam essas tarefas. Mas, você pode marcar tarefas como obsoletas. Para fazer isso, aumente a versão da tarefa e marque a tarefa como obsoleta.

P: Como posso atualizar a minha tarefa personalizada para o Node.js mais recente?

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

Os agentes hospedados pela Microsoft e várias versões do Azure DevOps Server têm ciclos de vida diferentes, levando à instalação de diferentes versões do Node runner, dependendo de onde uma tarefa está a ser executada. Para garantir a compatibilidade entre agentes com diferentes versões do Node runner, o task.json arquivo pode incluir várias seções de execução. No exemplo a seguir, os agentes do Azure Pipeline com o executor do Nó 20 o usam por padrão, enquanto os agentes sem ele retornam à implementação do Nó 10.

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

Para atualizar suas tarefas:

  • Para garantir que seu código se comporte conforme o esperado, teste suas tarefas nas várias versões do Node runner.

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

  • Para suportar versões mais antigas do servidor, deve-se deixar o Node/Node10 alvo. As versões mais antigas do Azure DevOps Server podem não incluir a versão mais recente do executor de Node.

  • Você pode optar por compartilhar o ponto de entrada definido no alvo ou ter alvos otimizados para a versão do Node.js usada.

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

Importante

Se não adicionar suporte para o executor do Node 20 às suas tarefas personalizadas, elas falharão nos agentes instalados a partir do feed release.