Condividi tramite


Aggiungere un'estensione personalizzata dell'attività pipeline

Azure DevOps Services | Azure DevOps Server | Azure DevOps Server 2022 | Azure DevOps Server 2020

Questa guida illustra come creare, testare e pubblicare attività di compilazione o versione personalizzate come estensioni di Azure DevOps. Le attività della pipeline personalizzate consentono di estendere Azure DevOps con funzionalità specializzate personalizzate per i flussi di lavoro del team, da utilità semplici a integrazioni complesse con sistemi esterni.

Informazioni su come eseguire le attività seguenti:

  • Configurare l'ambiente di sviluppo e la struttura del progetto
  • Creare la logica delle attività usando TypeScript e la libreria di attività di Azure Pipelines
  • Implementare unit test completi con framework fittizi
  • Creare un pacchetto dell'estensione per la distribuzione
  • Pubblicare in Visual Studio Marketplace
  • Configurare pipeline CI/CD automatizzate per la manutenzione dell'estensione

Per altre informazioni su Azure Pipelines, vedere Che cos'è Azure Pipelines?

Nota

Questo articolo illustra le attività degli agenti nelle estensioni basate su agenti. Per informazioni sulle attività del server e sulle estensioni basate su server, vedere Creazione di attività server.

Prerequisiti

Prima di iniziare, assicurarsi di avere i requisiti seguenti:

Componente Requisito Descrizione
Organizzazione DevOps di Azure Obbligatorio Creare un'organizzazione se non si dispone di un'organizzazione
Editor di testo Consigliato Supporto di Visual Studio Code per IntelliSense e debug
Node.js Obbligatorio Installare la versione più recente (Node.js 20 o versione successiva consigliata)
Compilatore TypeScript Obbligatorio Installare la versione più recente (versione 4.6.3 o successiva)
Interfaccia della riga di comando di Azure DevOps (tfx-cli) Obbligatorio Eseguire l'installazione usando npm i -g tfx-cli per le estensioni del pacchetto
Azure DevOps Extension SDK Obbligatorio Installare il pacchetto azure-devops-extension-sdk
Framework di test Obbligatorio Mocha per unit test (installato durante l'installazione)

Struttura progetto

Creare una home directory per il progetto. Dopo aver completato questa esercitazione, l'estensione deve avere la struttura seguente:

|--- README.md    
|--- images                        
    |--- extension-icon.png  
|--- buildandreleasetask            // Task scripts location
    |--- task.json                  // Task definition
    |--- index.ts                   // Main task logic
    |--- package.json               // Node.js dependencies
    |--- tests/                     // Unit tests
        |--- _suite.ts
        |--- success.ts
        |--- failure.ts
|--- vss-extension.json             // Extension manifest

Importante

Il computer di sviluppo deve eseguire la versione più recente di Node.js per garantire la compatibilità con l'ambiente di produzione. Aggiornare il task.json file per usare Node 20:

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

1. Creare un'attività personalizzata

Questa sezione illustra come creare la struttura di base e l'implementazione dell'attività personalizzata. Tutti i file in questo passaggio devono essere creati all'interno della buildandreleasetask cartella all'interno della directory del home progetto.

Nota

Questa procedura dettagliata usa Windows con PowerShell. I passaggi funzionano su tutte le piattaforme, ma la sintassi delle variabili di ambiente è diversa. In Mac o Linux sostituire $env:<var>=<val> con export <var>=<val>.

Configurare lo scaffolding delle attività

Creare la struttura di progetto di base e installare le dipendenze necessarie:

  1. Per inizializzare il progetto Node.js, aprire PowerShell, passare alla buildandreleasetask cartella ed eseguire:

    npm init --yes
    

    Il package.json file viene creato con le impostazioni predefinite. Il --yes flag accetta automaticamente tutte le opzioni predefinite.

    Suggerimento

    Gli agenti di Azure Pipelines prevedono che le cartelle attività includano moduli nodo. Copiare node_modules nella buildandreleasetask cartella. Per gestire le dimensioni del file VSIX (limite di 50 MB), prendere in considerazione l'esecuzione npm install --production o npm prune --production prima della creazione di pacchetti.

  2. Installare la libreria di attività di Azure Pipelines:

    npm install azure-pipelines-task-lib --save
    
  3. Installare le definizioni dei tipi TypeScript:

    npm install @types/node --save-dev
    npm install @types/q --save-dev
    
  4. Configurare le esclusioni del controllo della versione

    echo node_modules > .gitignore
    

    Il processo di compilazione deve essere eseguito npm install per ricompilare node_modules ogni volta.

  5. Installare le dipendenze di test:

    npm install mocha --save-dev -g
    npm install sync-request --save-dev
    npm install @types/mocha --save-dev
    
  6. Installare il compilatore TypeScript:

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

    Nota

    Installare TypeScript a livello globale per assicurarsi che il tsc comando sia disponibile. Senza di esso, TypeScript 2.3.4 viene usato per impostazione predefinita.

  7. Configurare la compilazione TypeScript:

    tsc --init --target es2022
    

    Il tsconfig.json file viene creato con le impostazioni di destinazione ES2022.

Implementare la logica delle attività

Dopo aver completato lo scaffolding, creare i file di attività principali che definiscono funzionalità e metadati:

  1. Creare il file di definizione dell'attività: creare task.json nella buildandreleasetask cartella . Questo file descrive l'attività nel sistema Azure Pipelines, definendo input, impostazioni di esecuzione e presentazione dell'interfaccia utente.

    {
     "$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"
         }
     }
     }
    

    Nota

    Sostituire {{placeholders}} con le informazioni effettive dell'attività. Il valore per taskguid deve essere univoco. Generarne uno usando PowerShell: (New-Guid).Guid

  2. Per implementare la logica delle attività, creare index.ts con la funzionalità principale dell'attività:

    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();
    
  3. Compilare TypeScript in JavaScript:

    tsc
    

    Il index.js file viene creato dall'origine TypeScript.

Informazioni sui componenti di task.json

Il task.json file è il cuore della definizione dell'attività. Ecco le proprietà principali:

Proprietà Descrizione Esempio
id Identificatore GUID univoco per l'attività Generato con (New-Guid).Guid
name Nome attività senza spazi (usato internamente) MyCustomTask
friendlyName Nome visualizzato visualizzato nell'interfaccia utente My Custom Task
description Descrizione dettagliata delle funzionalità delle attività Performs custom operations on files
author Nome autore o autore My Company
instanceNameFormat Modalità di visualizzazione dell'attività nei passaggi della pipeline Process $(inputFile)
inputs Matrice di parametri di input Vedere i tipi di input seguenti
execution Specifica dell'ambiente di esecuzione Node20_1, PowerShell3e così via.
restrictions Restrizioni di sicurezza per comandi e variabili Consigliato per le nuove attività

Restrizioni di sicurezza

Per le attività di produzione, aggiungere restrizioni di sicurezza per limitare l'utilizzo dei comandi e l'accesso alle variabili:

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

La modalità con restrizioni consente solo questi comandi:

  • logdetail, logissue, completesetprogress
  • setsecret, setvariable, debugsettaskvariable
  • prependpath, publish

Variabile allowlist controlla quali variabili possono essere impostate tramite setvariable o prependpath. Supporta modelli regex di base.

Nota

Questa funzionalità richiede l'agente versione 2.182.1 o successiva.

Tipi di input ed esempi

Tipi di input comuni per i parametri dell'attività:

"inputs": [
    {
        "name": "stringInput",
        "type": "string",
        "label": "Text Input",
        "defaultValue": "",
        "required": true,
        "helpMarkDown": "Enter a text value"
    },
    {
        "name": "boolInput",
        "type": "boolean",
        "label": "Enable Feature",
        "defaultValue": "false",
        "required": false
    },
    {
        "name": "picklistInput",
        "type": "pickList",
        "label": "Select Option",
        "options": {
            "option1": "First Option",
            "option2": "Second Option"
        },
        "defaultValue": "option1"
    },
    {
        "name": "fileInput",
        "type": "filePath",
        "label": "Input File",
        "required": true,
        "helpMarkDown": "Path to the input file"
    }
]

Testare l'attività in locale

Prima di creare pacchetti, testare l'attività per assicurarsi che funzioni correttamente:

  1. Test con input mancante (errore):

    node index.js
    

    Output previsto:

    ##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
    
  2. Test con input valido (dovrebbe avere esito positivo):

    $env:INPUT_SAMPLESTRING="World"
    node index.js
    

    Output previsto:

    ##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]samplestring=World
    Hello World
    
  3. Testare la gestione degli errori:

    $env:INPUT_SAMPLESTRING="bad"
    node index.js
    

    Questa azione deve attivare il percorso di gestione degli errori nel codice.

    Suggerimento

    Per informazioni sugli strumenti di esecuzione delle attività e sulle versioni di Node.js, vedere Indicazioni per l'aggiornamento di Node Runner.

Per altre informazioni, vedere le informazioni di riferimento sulle attività di compilazione/rilascio.

2. Implementare unit test completi

Il test dell'attività garantisce accuratamente l'affidabilità e consente di intercettare i problemi prima della distribuzione nelle pipeline di produzione.

Installare le dipendenze di test

Installare gli strumenti di test necessari:

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

Creare test

  1. Creare una tests cartella nella directory attività contenente un _suite.ts file:

     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() {
             // Setup before tests
         });
    
         after(() => {
             // Cleanup after tests
         });
    
         it('should succeed with simple inputs', function(done: Mocha.Done) {
             // Success test implementation
         });
    
         it('should fail if tool returns 1', function(done: Mocha.Done) {
             // Failure test implementation
         });    
       });
    

    Suggerimento

    La cartella di test deve trovarsi nella cartella dell'attività , ad esempio buildandreleasetask. Se si verifica un errore di richiesta di sincronizzazione, installarlo nella cartella dell'attività: npm i --save-dev sync-request.

  2. Creare success.ts nella directory di test per simulare l'esecuzione dell'attività riuscita:

     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);
    
     // Set valid input for success scenario
     tmr.setInput('samplestring', 'human');
    
     tmr.run();
    
  3. Aggiungere il test di esito positivo al _suite.ts file:

     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.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
         });
     });
    
  4. Creare failure.ts nella directory di test per testare la gestione degli errori:

    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);
    
    // Set invalid input to trigger failure
    tmr.setInput('samplestring', 'bad');
    
    tmr.run();
    
  5. Aggiungere il test di errore al _suite.ts file:

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

Esecuzione dei test

Eseguire il gruppo di test:

# Compile TypeScript
tsc

# Run tests
mocha tests/_suite.js

Entrambi i test devono essere superati. Per l'output dettagliato (simile all'output della console di compilazione), impostare la variabile di ambiente di traccia:

$env:TASK_TEST_TRACE=1
mocha tests/_suite.js

Procedure consigliate per la copertura dei test

  • Testare tutte le combinazioni di input: input validi, input non validi, input necessari mancanti
  • Scenari di errore di test: errori di rete, errori del file system, problemi di autorizzazione
  • Simulare le dipendenze esterne: non basarsi su servizi esterni negli unit test
  • Convalidare gli output: controllare l'output della console, i risultati delle attività e gli artefatti generati
  • Test delle prestazioni: prendere in considerazione l'aggiunta di test per attività che elaborano file di grandi dimensioni

Procedure consigliate per la sicurezza

  • Convalida dell'input: convalidare e sanificare sempre gli input
  • Gestione dei segreti: usare setSecret per i dati sensibili
  • Restrizioni dei comandi: implementare le restrizioni dei comandi per le attività di produzione
  • Autorizzazioni minime: richiedere solo le autorizzazioni necessarie
  • Aggiornamenti regolari: mantenere aggiornate le dipendenze e le versioni Node.js

Dopo aver testato l'attività in locale e implementato unit test completi, crearne il pacchetto in un'estensione per Azure DevOps.

Installare gli strumenti di creazione pacchetti

Installare l'interfaccia della riga di comando multipiattaforma (tfx-cli):

npm install -g tfx-cli

Creare il manifesto dell'estensione

Il manifesto dell'estensione (vss-extension.json) contiene tutte le informazioni sull'estensione, inclusi i riferimenti alle cartelle e alle immagini delle attività.

  1. Creare una cartella images con un extension-icon.png file

  2. Creare vss-extension.json nella directory radice dell'estensione (non nella cartella attività):

    {
     "manifestVersion": 1,
     "id": "my-custom-tasks",
     "name": "My Custom Tasks",
     "version": "1.0.0",
     "publisher": "your-publisher-id",
     "targets": [
         {
             "id": "Microsoft.VisualStudio.Services"
         }
     ],
     "description": "Custom build and release tasks for Azure DevOps",
     "categories": [
         "Azure Pipelines"
     ],
     "icons": {
         "default": "images/extension-icon.png"
     },
     "files": [
         {
             "path": "MyCustomTask"
         }
     ],
     "contributions": [
         {
             "id": "my-custom-task",
             "type": "ms.vss-distributed-task.task",
             "targets": [
                 "ms.vss-distributed-task.tasks"
             ],
             "properties": {
                 "name": "MyCustomTask"
             }
         }
     ]
    }
    

Proprietà del manifesto della chiave

Proprietà Descrizione
publisher Identificatore dell'editore del Marketplace
contributions.id Identificatore univoco all'interno dell'estensione
contributions.properties.name Deve corrispondere al nome della cartella attività
files.path Percorso della cartella attività relativa al manifesto

Nota

Modificare il valore dell'editore impostando il nome dell'editore. Per informazioni sulla creazione di un server di pubblicazione, vedere Creare il server di pubblicazione.

Confeziona la tua estensione

Creare un pacchetto dell'estensione in un file con estensione vsix:

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

Gestione delle versioni

  • Versione dell'estensione: incrementare la versione in vss-extension.json per ogni aggiornamento
  • Versione attività: incrementare la versione in task.json per ogni aggiornamento dell'attività
  • Incremento automatico: usare --rev-version per incrementare automaticamente la versione della patch
tfx extension create --manifest-globs vss-extension.json --rev-version

Importante

Sia la versione dell'attività che la versione dell'estensione devono essere aggiornate per rendere effettive le modifiche in Azure DevOps.

Strategia di controllo delle versioni

Seguire i principi di controllo delle versioni semantici per gli aggiornamenti delle attività:

  • Versione principale: modifiche di rilievo apportate a input/output
  • Versione secondaria: nuove funzionalità, compatibili con le versioni precedenti
  • Versione patch: solo correzioni di bug

Processo di aggiornamento:

  1. Aggiornare la versione di task.json
  2. Aggiornare la versione di vss-extension.json
  3. Testare accuratamente in un'organizzazione di test
  4. Pubblicare e monitorare i problemi

Pubblicare in Visual Studio Marketplace

1. Creare l'editore

  1. Accedere al portale di pubblicazione di Visual Studio Marketplace
  2. Se richiesto, creare un nuovo server di pubblicazione:
    • Identificatore del server di pubblicazione: usato nel manifesto dell'estensione (ad esempio, mycompany-myteam)
    • Nome visualizzato: nome pubblico visualizzato nel marketplace (ad esempio, My Team)
  3. Esaminare e accettare il Contratto di pubblicazione del Marketplace

2. Caricare l'estensione

Metodo dell'interfaccia Web:

  1. Selezionare Carica nuova estensione
  2. Scegliere il file in .vsix pacchetto
  3. Selezionare Carica

Metodo della riga di comando:

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

3. Condividere l'estensione

  1. Fare clic con il pulsante destro del mouse sull'estensione nel marketplace
  2. Seleziona Condividi
  3. Immettere il nome dell'organizzazione
  4. Aggiungere altre organizzazioni in base alle esigenze

Importante

Gli editori devono essere verificati per condividere le estensioni pubblicamente. Per altre informazioni, vedere Package/Publish/Install.For more information, see Package/Publish/Install.

4. Installare nell'organizzazione

Dopo la condivisione, installare l'estensione nell'organizzazione Azure DevOps:

  1. Passare a Estensioni delle impostazioni> dell'organizzazione
  2. Cercare l'estensione
  3. Selezionare Scarica gratuitamente e installa

3. Creare un pacchetto e pubblicare l'estensione

Verificare l'estensione

Dopo l'installazione, verificare che l'attività funzioni correttamente:

  1. Creare o modificare una pipeline.
  2. Aggiungere l'attività personalizzata:
    • Selezionare Aggiungi attività nell'editor della pipeline
    • Cercare l'attività personalizzata in base al nome
    • Aggiungerlo alla pipeline
  3. Configurare i parametri dell'attività:
    • Impostare gli input necessari
    • Configurare impostazioni facoltative
  4. Eseguire la pipeline per testare la funzionalità
  5. Monitorare l'esecuzione:
    • Controllare i log attività per l'esecuzione corretta
    • Verificare gli output previsti
    • Assicurarsi che non vengano visualizzati errori o avvisi

4. Automatizzare la pubblicazione dell'estensione con CI/CD

Per mantenere l'attività personalizzata in modo efficace, creare pipeline di compilazione e versione automatizzate che gestiscono test, creazione di pacchetti e pubblicazione.

Prerequisiti per l'automazione

  • Attività dell'estensione Azure DevOps: installare gratuitamente l'estensione
  • Gruppo di variabili: creare un gruppo di variabili della libreria della pipeline con queste variabili:
    • publisherId: ID editore del Marketplace
    • extensionId: ID di estensione da vss-extension.json
    • extensionName: nome dell'estensione da vss-extension.json
    • artifactName: nome per l'artefatto VSIX
  • Connessione al servizio: creare una connessione al servizio Marketplace con autorizzazioni di accesso alla pipeline

Completare la pipeline CI/CD

Creare una pipeline YAML con fasi complete per test, creazione di pacchetti e pubblicazione:

trigger: 
- main

pool:
  vmImage: "ubuntu-latest"

variables:
  - group: extension-variables # Your variable group name

stages:
  - stage: Test_and_validate
    displayName: 'Run Tests and Validate Code'
    jobs:
      - job: RunTests
        displayName: 'Execute unit tests'
        steps:
          - task: TfxInstaller@4
            displayName: 'Install TFX CLI'
            inputs:
              version: "v0.x"
          
          - task: Npm@1
            displayName: 'Install task dependencies'
            inputs:
              command: 'install'
              workingDir: '/MyCustomTask' # Update to your task directory
          
          - task: Bash@3
            displayName: 'Compile TypeScript'
            inputs:
              targetType: "inline"
              script: |
                cd MyCustomTask # Update to your task directory
                tsc
          
          - task: Npm@1
            displayName: 'Run unit tests'
            inputs:
              command: 'custom'
              workingDir: '/MyCustomTask' # Update to your task directory
              customCommand: 'test' # Ensure this script exists in package.json
          
          - task: PublishTestResults@2
            displayName: 'Publish test results'
            inputs:
              testResultsFormat: 'JUnit'
              testResultsFiles: '**/test-results.xml'
              searchFolder: '$(System.DefaultWorkingDirectory)'

  - stage: Package_extension
    displayName: 'Package Extension'
    dependsOn: Test_and_validate
    condition: succeeded()
    jobs:
      - job: PackageExtension
        displayName: 'Create VSIX package'
        steps:
          - task: TfxInstaller@4
            displayName: 'Install TFX CLI'
            inputs:
              version: "v0.x"
          
          - task: Npm@1
            displayName: 'Install dependencies'
            inputs:
              command: 'install'
              workingDir: '/MyCustomTask'
          
          - task: Bash@3
            displayName: 'Compile TypeScript'
            inputs:
              targetType: "inline"
              script: |
                cd MyCustomTask
                tsc
          
          - task: QueryAzureDevOpsExtensionVersion@4
            name: QueryVersion
            displayName: 'Query current extension version'
            inputs:
              connectTo: 'VsTeam'
              connectedServiceName: 'marketplace-connection'
              publisherId: '$(publisherId)'
              extensionId: '$(extensionId)'
              versionAction: 'Patch'
          
          - task: PackageAzureDevOpsExtension@4
            displayName: 'Package extension'
            inputs:
              rootFolder: '$(System.DefaultWorkingDirectory)'
              publisherId: '$(publisherId)'
              extensionId: '$(extensionId)'
              extensionName: '$(extensionName)'
              extensionVersion: '$(QueryVersion.Extension.Version)'
              updateTasksVersion: true
              updateTasksVersionType: 'patch'
              extensionVisibility: 'private'
              extensionPricing: 'free'
          
          - task: PublishBuildArtifacts@1
            displayName: 'Publish VSIX artifact'
            inputs:
              PathtoPublish: '$(System.DefaultWorkingDirectory)/*.vsix'
              ArtifactName: '$(artifactName)'
              publishLocation: 'Container'

  - stage: Publish_to_marketplace
    displayName: 'Publish to Marketplace'
    dependsOn: Package_extension
    condition: and(succeeded(), eq(variables['Build.SourceBranch'], 'refs/heads/main'))
    jobs:
      - deployment: PublishExtension
        displayName: 'Deploy to marketplace'
        environment: 'marketplace-production'
        strategy:
          runOnce:
            deploy:
              steps:
                - task: TfxInstaller@4
                  displayName: 'Install TFX CLI'
                  inputs:
                    version: "v0.x"
                
                - task: PublishAzureDevOpsExtension@4
                  displayName: 'Publish to marketplace'
                  inputs:
                    connectTo: 'VsTeam'
                    connectedServiceName: 'marketplace-connection'
                    fileType: 'vsix'
                    vsixFile: '$(Pipeline.Workspace)/$(artifactName)/*.vsix'
                    publisherId: '$(publisherId)'
                    extensionId: '$(extensionId)'
                    extensionName: '$(extensionName)'
                    updateTasksVersion: false
                    extensionVisibility: 'private'
                    extensionPricing: 'free'

Configurare package.json per i test

Aggiungere script di test a package.json:

{
  "scripts": {
    "test": "mocha tests/_suite.js --reporter xunit --reporter-option output=test-results.xml",
    "test-verbose": "cross-env TASK_TEST_TRACE=1 npm test"
  }
}

Suddivisione della fase della pipeline

Fase 1: Testare e convalidare

  • Scopo: garantire la qualità e la funzionalità del codice
  • Azioni: installare le dipendenze, compilare TypeScript, eseguire unit test, pubblicare i risultati
  • Convalida: tutti i test devono essere superati per procedere

Fase 2: Estensione pacchetto

  • Scopo: Creare un pacchetto VSIX distribuibile
  • Azioni: eseguire query sulla versione corrente, incrementare la versione, l'estensione del pacchetto, pubblicare gli artefatti
  • Controllo delle versioni: gestisce automaticamente gli incrementi di versione

Fase 3: Pubblicare nel marketplace

  • Scopo: eseguire la distribuzione in Visual Studio Marketplace
  • Condizioni: viene eseguito solo nel ramo principale dopo la corretta creazione del pacchetto
  • Ambiente: usa l'ambiente di distribuzione per i controlli di approvazione

Procedure consigliate per la pipeline CI/CD

  • Protezione dei rami: pubblica solo dai rami main/release
  • Controlli di ambiente: usare gli ambienti di distribuzione per le versioni di produzione
  • Gestione delle versioni: automatizzare gli incrementi di versione per evitare conflitti
  • Copertura dei test: verificare la copertura completa dei test prima della creazione del pacchetto
  • Sicurezza: usare le connessioni al servizio anziché le credenziali hardcoded
  • Monitoraggio: configurare gli avvisi per le distribuzioni non riuscite

Per le pipeline di compilazione classiche, seguire questa procedura per configurare la creazione di pacchetti e la pubblicazione dell'estensione:

  1. Aggiungi il compito Bash per compilare TypeScript in JavaScript.

  2. Per eseguire una query sulla versione esistente, aggiungere l'attività Query Estensione Versione utilizzando i seguenti input:

    • Connettersi a: Visual Studio Marketplace
    • Visual Studio Marketplace (Connessione al Servizio): Connessione al Servizio
    • ID editore: ID dell'editore di Visual Studio Marketplace
    • ID dell'estensione: ID della tua estensione nel file vss-extension.json
    • Aggiorna versione: Patch
    • Variabile di output: Task.Extension.Version
  3. Per creare un pacchetto delle estensioni in base al file JSON del manifesto, aggiungere l'attività Estensione pacchetto usando gli input seguenti:

    • Cartella manifest principale: indica la directory root che contiene il file manifest. Ad esempio, $(System.DefaultWorkingDirectory) è la directory principale
    • File di manifesto: vss-extension.json
    • ID editore: ID dell'editore di Visual Studio Marketplace
    • ID dell'estensione: ID della tua estensione nel file vss-extension.json
    • Nome estensione: nome dell'estensione vss-extension.json nel file
    • La versione dell'estensione: $(Task.Extension.Version)
    • Sovrascrivere le versioni delle attività: selezionato (true)
    • Tipo di override: Sostituisci solo la patch (1.0.r)
    • Visibilità estensione: se l'estensione è ancora in fase di sviluppo, impostare il valore privato. Per rilasciare l'estensione al pubblico, impostare il valore su pubblico.
  4. Per copiare nei file pubblicati, aggiungere l'attività Copia file usando gli input seguenti:

    • Contenuto: tutti i file da copiare per pubblicarli come artefatto
    • Cartella di destinazione: cartella in cui vengono copiati i file
      • Ad esempio: $(Build.ArtifactStagingDirectory)
  5. Aggiungere Pubblicare gli artefatti di compilazione per pubblicare gli artefatti da usare in altri processi o pipeline. Usare gli input seguenti:

    • Percorso di pubblicazione: percorso della cartella che contiene i file da pubblicare
      • Ad esempio: $(Build.ArtifactStagingDirectory)
    • Nome artefatto: nome assegnato all'artefatto
    • Percorso di pubblicazione degli artefatti: scegliere Azure Pipelines per usare l'artefatto nei job futuri

Fase 3: Scaricare gli artefatti di compilazione e pubblicare l'estensione

  1. Per installare tfx-cli nell'agente di compilazione, aggiungere Usare l'interfaccia della riga di comando del nodo per Azure DevOps (tfx-cli).

  2. Per scaricare gli artefatti in un nuovo processo, aggiungere l'attività Scarica artefatti di compilazione usando gli input seguenti:

    • Scarica gli artefatti prodotti da: se stai scaricando l'artefatto in un nuovo compito dalla stessa pipeline, seleziona Compilazione corrente. Se si esegue il download in una nuova pipeline, selezionare Compilazione specifica
    • Tipo di download: scegliere Artefatto specifico per scaricare tutti i file pubblicati.
    • Nome artefatto: nome dell'artefatto pubblicato
    • Directory di destinazione: cartella in cui scaricare i file
  3. Per ottenere l'attività Pubblica estensione, usare gli input seguenti:

    • Connettersi a: Visual Studio Marketplace
    • Connessione a Visual Studio Marketplace: ServiceConnection
    • Tipo di file di input: file VSIX
    • File VSIX: /Publisher.*.vsix
    • ID editore: ID dell'editore di Visual Studio Marketplace
    • ID dell'estensione: ID della tua estensione nel file vss-extension.json
    • Nome estensione: nome dell'estensione vss-extension.json nel file
    • Visibilità dell'estensione: privata o pubblica

Facoltativo: installare e testare l'estensione

Dopo aver pubblicato l'estensione, deve essere installata nelle organizzazioni di Azure DevOps.

Installare l'estensione per l'organizzazione

Installare l'estensione condivisa in pochi passaggi:

  1. Passare a Impostazioni organizzazione e selezionare Estensioni.

  2. Individuare l'estensione nella sezione Estensioni condivise con l'utente corrente :

    • Selezionare il collegamento dell'estensione
    • Selezionare Scarica gratuitamente o Installa
  3. Verificare che l'estensione venga visualizzata nell'elenco Estensioni installate :

    • Verificare che sia disponibile nella libreria di attività della pipeline

Nota

Se non viene visualizzata la scheda Estensioni , assicurarsi di essere a livello di amministrazione dell'organizzazione (https://dev.azure.com/{organization}/_admin) e non a livello di progetto.

Test end-to-end

Dopo l'installazione, eseguire test completi:

  1. Creare una pipeline di test:

    • Aggiungere l'attività personalizzata a una nuova pipeline
    • Configurare tutti i parametri di input
    • Testare con varie combinazioni di input
  2. Convalidare la funzionalità:

    • Eseguire la pipeline e monitorare l'esecuzione
    • Controllare gli output e i log delle attività
    • Verificare la gestione degli errori con input non validi
  3. Prestazioni dei test:

    • Eseguire il test con file di input di grandi dimensioni (se applicabile)
    • Monitorare l'utilizzo delle risorse
    • Convalidare il comportamento di timeout

Domande frequenti

D: Come viene gestito l'annullamento delle attività?

R: L'agente della pipeline invia SIGINT e SIGTERM segnala i processi delle attività. Anche se la libreria di attività non fornisce una gestione esplicita dell'annullamento, l'attività può implementare gestori di segnali. Per informazioni dettagliate, vedere Annullamento dei processi di Agent.

D: Come è possibile rimuovere un'attività dall'organizzazione?

R: L'eliminazione automatica non è supportata perché interrompe le pipeline esistenti. Invece:

  1. Deprecare l'attività: contrassegnare l'attività come deprecata
  2. Gestione delle versioni: aggiornare la versione dell'attività
  3. Comunicazione: notificare agli utenti la sequenza temporale di deprecazione

D: Come è possibile aggiornare l'attività alla versione Node.js più recente?

R: Eseguire l'aggiornamento alla versione più recente del nodo per migliorare le prestazioni e la sicurezza. Per indicazioni sulla migrazione, vedere Aggiornamento delle attività al nodo 20.

Supportare più versioni di Node includendo più sezioni di esecuzione in task.json:

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

Gli agenti con Node 20 usano la versione preferita, mentre gli agenti meno recenti eseguono il fallback al nodo 10.

Per migliorare le tue attività:

  • Per assicurarsi che il codice si comporti come previsto, testare le attività nelle varie versioni di Node Runner.

  • Nella sezione esecuzione dell'attività aggiornare da Node o Node10 a Node16 o Node20.

  • Per supportare le versioni precedenti del server, è necessario lasciare il Node/Node10 target. Le versioni precedenti di Azure DevOps Server potrebbero non includere la versione più recente dello strumento di esecuzione dei nodi.

  • È possibile scegliere di condividere il punto di ingresso definito nella destinazione o avere destinazioni ottimizzate per la versione del nodo usata.

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

Importante

Se non si aggiunge il supporto per il runner Node 20 alle attività personalizzate, queste falliranno sugli agenti installati dal feed di rilascio delle versioni pipelines-agent-*.