Partager via


Ajouter une extension de tâche de pipelines personnalisée

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

Cet article explique comment installer des extensions à votre organisation pour des tâches de génération ou de mise en production personnalisées dans Azure DevOps. Pour plus d’informations, consultez Qu’est-ce qu’Azure Pipelines ?

Remarque

Cet article traite des tâches d’agent dans les extensions basées sur l’agent. Pour plus d’informations sur les tâches serveur et les extensions basées sur le serveur, consultez la section Création de tâches du serveur.

Prérequis

  • Une organisation dans Azure DevOps. Créez une organisation.

  • Un éditeur de texte Pour de nombreux didacticiels, nous utilisons Visual Studio Code, qui fournit une prise en charge d'IntelliSense et de débogage.

  • La dernière version de Node.js.

  • npmjs.com 4.0.2 ou version ultérieure. Installez la dernière version de ce compilateur TypeScript.

  • CLI multiplateforme pour Azure DevOps (tfx-cli) pour empaqueter vos extensions.

    • tfx-cli peut être installé à l’aide npmd’un composant de Node.js, en exécutant npm i -g tfx-cli.
  • Kit de développement logiciel (SDK) d’extension Azure DevOps. Installez le package azure-devops-extension-sdk .

  • Un répertoire home pour votre projet. Le home répertoire d’une extension de tâche de génération ou de mise en production doit avoir la structure suivante après avoir effectué les étapes décrites dans cet article :

    |--- README.md    
    |--- images                        
        |--- extension-icon.png  
    |--- buildandreleasetask            // where your task scripts are placed
    |--- vss-extension.json             // extension's manifest
    

Importante

La machine de développement doit exécuter la dernière version de Node pour s’assurer que le code écrit est compatible avec l’environnement de production sur l’agent et la dernière version non préliminaire de azure-pipelines-task-lib. Mettez à jour votre task.json fichier conformément à la commande suivante :

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

1. Créer une tâche personnalisée

Effectuez toutes les parties de cette procédure dans le dossier buildandreleasetask à l'intérieur de votre répertoire home.

Remarque

Cet exemple de procédure pas à pas utilise Windows avec PowerShell. Les étapes sont génériques pour toutes les plateformes, mais la syntaxe pour obtenir des variables d’environnement est différente. Si vous utilisez un Mac ou Linux, remplacez toutes les instances de $env:<var>=<val>export <var>=<val>.

Créer une structure de tâches

  1. Créez la structure de dossiers pour la tâche et installez les bibliothèques et dépendances requises.

  2. Ouvrez une fenêtre de commande PowerShell, accédez à votre buildandreleasetask dossier et exécutez la commande suivante.

    npm init --yes
    

    npm init crée le package.json fichier. Nous avons ajouté le --yes paramètre pour accepter toutes les options par défaut npm init .

    Conseil

    L’agent n’installe pas automatiquement les modules requis, car il s’attend à ce que votre dossier de tâches inclue les modules de nœud. Pour atténuer, copiez la valeur node_modules vers buildandreleasetask. À mesure que votre tâche augmente, il est facile de dépasser la limite de taille (50 Mo) d’un fichier VSIX. Avant de copier le dossier du nœud, vous souhaiterez peut-être exécuter npm install --production ou npm prune --production, ou vous pouvez écrire un script pour générer et packer tout.

  3. Ajouter azure-pipelines-task-lib à votre bibliothèque.

    npm install azure-pipelines-task-lib --save
    
  4. Assurez-vous que les typages TypeScript sont installés pour les dépendances externes.

    npm install @types/node --save-dev
    npm install @types/q --save-dev
    
  5. Créez un .gitignore fichier et ajoutez-y node_modules. Votre processus de build doit effectuer une action npm install et une autre action typings install de façon à ce que node_modules soit construit chaque fois et n'ait pas besoin d'être inclus dans le contrôle de version.

    echo node_modules > .gitignore
    
  6. Installez Mocha comme dépendance de développement.

    npm install mocha --save-dev -g
    npm install sync-request --save-dev
    npm install @types/mocha --save-dev
    
  7. Choisissez TypeScript version 2.3.4 ou 4.6.3.

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

    Remarque

    Assurez-vous que TypeScript est installé globalement avec npm dans votre environnement de développement. Par conséquent, la tsc commande est disponible. Si vous ignorez cette étape, TypeScript version 2.3.4 est utilisée par défaut et vous devez toujours installer le package globalement pour que la tsc commande soit disponible.

  8. Créez des tsconfig.json options de compilateur. Ce fichier garantit que vos fichiers TypeScript sont compilés en fichiers JavaScript.

    tsc --init --target es2022
    

Créer une tâche

Maintenant que l'échafaudage est terminé, vous pouvez créer votre tâche personnalisée.

  1. Créez un task.json fichier dans le buildandreleasetask dossier. Le task.json fichier décrit la tâche de génération/mise en production et correspond à ce que le système de génération/mise en production utilise pour afficher les options de configuration à l’utilisateur et pour connaître les scripts à exécuter au moment de la génération/mise en production.

  2. Copiez le code suivant et remplacez {{placeholders}} par les informations de votre tâche. L’espace réservé le plus important est le taskguid, et il doit être unique.

    {
     "$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. Créez un index.ts fichier à l’aide du code suivant comme référence. Ce code s’exécute lorsque la tâche est appelée.

    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. Pour compiler un index.js fichier à partir de index.ts, entrez tsc à partir du buildandreleasetask dossier.

composants de task.json

Consultez les descriptions suivantes de certains composants du task.json fichier.

Propriété Descriptif
id Un GUID unique pour votre tâche.
name Nom sans espace.
friendlyName Nom descriptif (espaces autorisés).
description Description détaillée de ce que fait votre tâche.
author Chaîne courte décrivant l’entité qui développe la tâche de génération ou de mise en production, par exemple : Microsoft Corporation
instanceNameFormat Comment la tâche s’affiche dans la liste d’étapes de génération/mise en production. Vous pouvez utiliser des valeurs de variable à l’aide de $(nom_variable).
groups Décrit le regroupement logique des propriétés de tâche dans l’interface utilisateur.
inputs Entrées à utiliser lorsque votre tâche de génération ou de mise en production s’exécute. Cette tâche attend une entrée avec le nom samplestring.
execution Il existe plusieurs options d’exécution pour cette tâche, notamment les scripts, tels que Node, PowerShell, PowerShell3, ou Process.
restrictions Restrictions appliquées à la tâche concernant les commandes GitHub Codespaces que la tâche peut appeler et les variables que la tâche peut définir. Nous vous recommandons de spécifier le mode de restriction pour les nouvelles tâches.

Remarque

Créez une id commande avec la commande suivante dans PowerShell :

(New-Guid).Guid

Pour plus d’informations, consultez la référence de tâche de compilation/déploiement.

Exécuter la tâche

Exécutez la tâche à l’aide node index.js de PowerShell.

Dans l’exemple suivant, la tâche échoue, car les entrées n’ont pas été fournies (samplestring est une entrée obligatoire).

 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

En guise de correctif, définissez l’entrée samplestring et réexécutez la tâche.

$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

Cette fois, la tâche réussit parce que samplestring a été fourni, et elle génère correctement Bonjour Humain !

Conseil

Pour plus d’informations sur les différents exécuteurs de tâches et sur la façon d’inclure la dernière version du nœud dans le task.json, consultez les instructions de mise à jour de l’exécuteur de nœuds pour les auteurs de tâches Azure Pipelines.

2. Test unitaire de vos scripts de tâche

Effectuez des tests unitaires pour tester rapidement le script de tâche, et non les outils externes qu’il appelle. Testez tous les aspects des chemins de réussite et d’échec.

  1. Installez les outils de test. Nous utilisons Mocha comme pilote de test dans cette procédure.

    npm install mocha --save-dev -g
    npm install sync-request --save-dev
    npm install @types/mocha --save-dev
    
  2. Créez un tests dossier contenant un _suite.ts fichier avec le contenu suivant :

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

    Conseil

    Votre dossier de test doit se trouver dans le buildandreleasetask dossier. Si vous obtenez une erreur de requête de synchronisation, vous pouvez la contourner en ajoutant la requête de synchronisation au buildandreleasetask dossier avec la commande npm i --save-dev sync-request.

  3. Créez un success.ts fichier dans votre répertoire de test avec le contenu suivant. Cette création de fichier simule l’exécution de la tâche et simule tous les appels à des méthodes externes.

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

    Le test de réussite valide que, avec les entrées appropriées, il réussit sans erreurs ni avertissements et retourne la sortie correcte.

  4. Pour exécuter l’exécuteur fictif de tâche, ajoutez l’exemple de test de réussite suivant à votre _suite.ts fichier.

         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. Créez un failure.ts fichier dans votre répertoire de test en tant qu’exécuteur fictif de tâche avec le contenu suivant :

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

    Le test d’échec valide que, lorsque l’outil obtient une entrée incorrecte ou incomplète, il échoue de la manière attendue avec une sortie utile.

  6. Pour exécuter l’exécuteur fictif de tâche, ajoutez le code suivant à votre _suite.ts fichier.

    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. Exécutez les tests.

    tsc
    mocha tests/_suite.js
    

    Les deux tests doivent réussir. Si vous souhaitez exécuter les tests avec une sortie plus détaillée (ce que vous verrez dans la console de build), définissez la variable d’environnement : TASK_TEST_TRACE=1.

    $env:TASK_TEST_TRACE=1
    

3. Créer le fichier manifeste d’extension

Le manifeste d’extension contient toutes les informations relatives à votre extension. Il inclut des liens vers vos fichiers, y compris vos dossiers de tâches et dossiers d’images. Vérifiez que vous avez créé un dossier d’images avec extension-icon.png. L’exemple suivant est un manifeste d’extension qui contient la tâche de génération ou de mise en production.

Copiez le code .json suivant et enregistrez-le sous forme vss-extension.json de fichier dans votre home répertoire.

Ne créez pas ce fichier dans le dossier 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"
            }
        }
    ]
}

Remarque

Remplacez l’éditeur par le nom de votre éditeur. Pour plus d’informations, consultez Créer un éditeur.

Contributions

Propriété Descriptif
id Identificateur de la contribution. Doit être unique dans l'extension. Ne doit pas nécessairement correspondre au nom de la tâche de génération ou de mise en production. En règle générale, le nom de la tâche de génération ou de mise en production se trouve dans l’ID de la contribution.
type Type de contribution. doit être ms.vss-distributed-task.task.
targets Contributions ciblées par cette contribution. doit être ms.vss-distributed-task.tasks.
properties.name Nom de la tâche. Ce nom doit correspondre au nom du dossier de la tâche de build autonome ou de la tâche de pipeline de mise en production correspondante.

Fichiers

Propriété Descriptif
path Chemin d’accès du fichier ou du dossier par rapport au home répertoire.

Pour plus d’informations sur le fichier manifeste d’extension, telles que ses propriétés et ce qu’elles font, consultez la référence du manifeste d’extension.

4. Empaqueter votre extension

Empaqueter tous vos fichiers ensemble pour obtenir votre extension dans Visual Studio Marketplace. Toutes les extensions sont empaquetées en tant que fichiers .vsix compatibles VSIX 2.0. Microsoft fournit une interface de ligne de commande multiplateforme (CLI) pour empaqueter votre extension.

Une fois que vous disposez de tfx-cli, accédez au répertoire de base de votre extension, puis exécutez la commande suivante :

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

Remarque

Une version d’extension ou d’intégration doit être incrémentée sur chaque mise à jour. Lorsque vous mettez à jour une extension existante, mettez à jour la version dans le manifeste ou passez l'option de ligne de commande --rev-version. Cela incrémente le numéro de version de correctif de votre extension et enregistre la nouvelle version dans votre manifeste. Vous devez mettre à jour à la fois la version de la tâche et la version de l’extension pour qu’une mise à jour se produise. tfx extension create --manifest-globs vss-extension.json --rev-version met uniquement à jour la version de l’extension et non la version de la tâche. Pour plus d’informations, consultez Build Task sur GitHub.

Une fois que votre extension empaquetée se trouve dans un fichier .vsix, vous êtes prêt à publier votre extension sur la Place de marché.

5. Publier votre extension

Pour publier votre extension, commencez par créer votre éditeur, puis chargez votre extension, puis partagez-la.

Créer votre éditeur

Toutes les extensions, y compris les extensions de Microsoft, sont identifiées comme étant fournies par un éditeur. Si vous n’êtes pas déjà membre d’un éditeur existant, vous en créez un.

  1. Connectez-vous au Visual Studio Marketplace Publishing Portal.

  2. Si vous n’êtes pas déjà membre d’un éditeur existant, vous êtes invité à créer un éditeur. Si vous n’êtes pas invité à créer un éditeur, faites défiler vers le bas de la page et sélectionnez Publier des extensions sous Sites connexes.

    • Spécifiez un identificateur pour votre éditeur, par exemple : mycompany-myteam.
      • Cet identificateur est utilisé comme valeur de l’attribut dans le publisher fichier manifeste de vos extensions.
    • Spécifiez un nom d'affichage pour votre éditeur, par exemple : My Team.
  3. Passez en revue le Contrat d’éditeur de la Place de marché, puis sélectionnez Créer.

Votre éditeur est défini. Dans une version ultérieure, vous pouvez accorder des autorisations pour afficher et gérer les extensions de votre éditeur. Il est plus facile et plus sécurisé de publier des extensions sous un éditeur commun, sans avoir à partager un ensemble d’informations d’identification entre les utilisateurs.

Charger votre extension

Recherchez le bouton Charger une nouvelle extension , accédez à votre fichier .vsix empaqueté, puis sélectionnez Charger.

Vous pouvez également charger votre extension via l’interface de ligne de commande (CLI) à l’aide de la tfx extension publish commande au lieu de tfx extension create empaqueter et de publier votre extension en une seule étape. Vous pouvez éventuellement utiliser --share-with pour partager votre extension avec un ou plusieurs comptes après sa publication.

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

Partager votre extension

Maintenant que vous avez chargé votre extension, elle se trouve sur la Place de marché, mais personne ne peut la voir. Partagez-le avec votre organisation pour pouvoir l’installer et le tester.

Sélectionnez avec le bouton droit votre extension, puis sélectionnez Partager, puis entrez les informations de votre organisation. Vous pouvez également le partager avec d’autres comptes à qui vous souhaitez donner accès à votre extension.

Importante

Les éditeurs doivent être vérifiés pour partager des extensions publiquement. Pour plus d’informations, consultez Package/Publish/Install.

Une fois que votre extension est partagée dans la Place de marché, toute personne qui souhaite l’utiliser doit l’installer.

6. Créer un pipeline de build et de mise en production pour publier l’extension sur La Place de marché

Pour gérer la tâche personnalisée sur la Place de marché, créez un pipeline de build et de mise en production sur Azure DevOps.

Conditions préalables à la publication

  • Un projet Azure DevOps. Créer un projet.

  • Extension de tâches pour Azure DevOps. Installez-le gratuitement dans votre organisation.

  • Groupe de variables de bibliothèque de pipelines. Créez un groupe de variables de bibliothèque du pipeline pour contenir les variables utilisées par le pipeline. Pour plus d’informations, consultez Ajouter et utiliser des groupes de variables. Vous pouvez créer des groupes de variables à partir de l’onglet Bibliothèque Azure DevOps ou via l’interface CLI. Utilisez les variables de ce groupe dans votre pipeline. Déclarez également les variables suivantes dans le groupe de variables :

    • publisherId : D de votre éditeur de marché
    • extensionId: ID de votre extension, comme déclaré dans le fichier vss-extension.json
    • extensionName: Nom de votre extension, comme déclaré dans le fichier vss-extension.json
    • artifactName: nom de l’artefact créé pour le fichier VSIX
  • Connexion de service. Créez une nouvelle connexion de service Marketplace et accordez les autorisations d'accès pour tous les pipelines.

  • Pipeline YAML. Utilisez l’exemple suivant pour créer un pipeline avec YAML. Pour plus d’informations, consultez Créer votre premier pipeline et schéma 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'
    

Pour plus d’informations, consultez Spécifier des événements qui déclenchent des pipelines.

Remarque

Chaque travail utilise un nouvel agent utilisateur et nécessite l’installation de dépendances.

Étapes de canalisation

La section suivante vous aide à comprendre le fonctionnement des étapes du pipeline.

Étape 1 : Exécuter et publier des tests unitaires

Cette étape exécute des tests unitaires et publie les résultats des tests dans Azure DevOps.

Pour exécuter des tests unitaires, ajoutez un script personnalisé au fichier comme dans l’exemple package.json suivant.

"scripts": {
    "testScript": "mocha ./TestFile --reporter xunit --reporter-option output=ResultsFile.xml"
},
  1. Ajoutez Utiliser l’interface CLI Node pour Azure DevOps (tfx-cli) pour installer tfx-cli sur votre agent de build.

  2. Ajoutez la tâche avec la commande npminstall et ciblez le dossier contenant le fichier package.json.

  3. Ajoutez la Bash tâche pour compiler le TypeScript en JavaScript.

  4. Ajoutez la tâche npm avec la commande custom, ciblez le dossier qui contient les tests unitaires et entrez la commande testScript. Utilisez les entrées suivantes :

    • Commande : custom
    • Dossier de travail qui contient package.json: /TestsDirectory
    • Commande et arguments : testScript
  5. Ajoutez la tâche Publier les résultats des tests . Si vous utilisez le reporter Mocha XUnit, assurez-vous que le format de résultat est JUnit et non XUnit. Définissez le dossier de recherche sur le répertoire racine. Utilisez les entrées suivantes :

    • Format de résultat du test : JUnit
    • Fichiers de résultats des tests : **/ResultsFile.xml
    • Dossiers de recherche : $(System.DefaultWorkingDirectory)

    Une fois les résultats de test publiés, la sortie sous l’onglet tests doit ressembler à l’exemple suivant.

    Capture d’écran de l’exemple de résultat de test.

Étape 2 : Empaqueter l’extension et publier des artefacts de build

  1. Ajoutez Utiliser l’interface CLI Node pour Azure DevOps (tfx-cli) pour installer tfx-cli sur votre agent de build.

  2. Ajoutez la tâche avec la commande npminstall et ciblez le dossier contenant le fichier package.json.

  3. Ajoutez la Bash tâche pour compiler le TypeScript en JavaScript.

  4. Pour interroger la version existante, ajoutez la tâche version de l’extension de requête à l’aide des entrées suivantes :

    • Se connecter à : Visual Studio Marketplace
    • Visual Studio Marketplace (connexion de service) : connexion de service
    • ID de l’éditeur : ID de votre éditeur visual Studio Marketplace
    • ID d’extension : ID de votre extension dans le vss-extension.json fichier
    • Augmenter la version : Correctif
    • Variable de sortie : Task.Extension.Version
  5. Pour empaqueter les extensions en fonction du manifeste Json, ajoutez la tâche d’extension de package à l’aide des entrées suivantes :

    • Dossier racine des manifestes : fait référence au répertoire racine qui contient le fichier manifeste. Par exemple, $(System.DefaultWorkingDirectory) est le répertoire racine
    • Fichier manifeste : vss-extension.json
    • ID de l’éditeur : ID de votre éditeur visual Studio Marketplace
    • ID d’extension : ID de votre extension dans le vss-extension.json fichier
    • Nom de l’extension : nom de votre extension dans le vss-extension.json fichier
    • Version de l’extension : $(Task.Extension.Version)
    • Remplacer la version des tâches : cochée (true)
    • Type de remplacement : remplacer uniquement le correctif (1.0.r)
    • Visibilité de l’extension : si l’extension est toujours en cours de développement, définissez la valeur sur privée. Pour rendre l'extension publique, définissez la valeur à public.
  6. Pour copier des fichiers publiés, ajoutez la tâche Copier des fichiers à l’aide des entrées suivantes :

    • Contenu : tous les fichiers à copier pour les publier en tant qu’artefact
    • Dossier cible : dossier dans lequel les fichiers sont copiés
      • Par exemple : $(Build.ArtifactStagingDirectory)
  7. Ajoutez Publier les artefacts de build pour qu'ils puissent être utilisés dans d'autres tâches ou pipelines. Utilisez les entrées suivantes :

    • Chemin d’accès à la publication : chemin d’accès au dossier qui contient les fichiers en cours de publication
      • Par exemple : $(Build.ArtifactStagingDirectory)
    • Nom de l’artefact : nom donné à l’artefact
    • Emplacement de publication des artefacts : choisissez Azure Pipelines pour utiliser les artefacts dans les travaux futurs.

Étape 3 : Télécharger les artefacts de build et publier l’extension

  1. Pour installer tfx-cli sur votre agent de build, ajoutez Use Node CLI for Azure DevOps (tfx-cli).

  2. Pour télécharger les artefacts vers une nouvelle tâche, veuillez ajouter la tâche Télécharger les artefacts de build en utilisant les informations suivantes :

    • Télécharger les artefacts produits par : si vous téléchargez l'artefact sur une nouvelle tâche à partir du même pipeline, sélectionnez Compilation actuelle. Si vous effectuez le téléchargement sur un nouveau pipeline, veuillez sélectionner « Version spécifique ».
    • Type de téléchargement : choisissez un artefact spécifique pour télécharger tous les fichiers publiés.
    • Nom de l’artefact : nom de l’artefact publié
    • Répertoire de destination : dossier dans lequel les fichiers doivent être téléchargés
  3. Pour obtenir la tâche Publier l’extension , utilisez les entrées suivantes :

    • Se connecter à : Visual Studio Marketplace
    • Connexion Visual Studio Marketplace : ServiceConnection
    • Type de fichier d’entrée : fichier VSIX
    • Fichier VSIX : /Publisher.*.vsix
    • ID de l’éditeur : ID de votre éditeur visual Studio Marketplace
    • ID d’extension : ID de votre extension dans le vss-extension.json fichier
    • Nom de l’extension : nom de votre extension dans le vss-extension.json fichier
    • Visibilité de l’extension : privé ou public

Facultatif : Installer et tester votre extension

Installez une extension partagée avec vous en quelques étapes :

  1. À partir du panneau de configuration de votre organisation (https://dev.azure.com/{organization}/_admin), accédez à la page d’administration de collection de projets.
  2. Sous l’onglet Extensions , recherchez votre extension dans le groupe Extensions partagés avec moi , puis sélectionnez le lien d’extension.
  3. Installez l’extension.

Si vous ne voyez pas l’onglet Extensions , vérifiez que vous êtes dans le panneau de configuration (la page d’administration au niveau https://dev.azure.com/{organization}/_adminde la collection de projets) et non la page d’administration d’un projet.

Si vous ne voyez pas l’onglet Extensions , les extensions ne sont pas activées pour votre organisation. Vous pouvez obtenir un accès anticipé à la fonctionnalité d’extensions en joignant le programme partenaire Visual Studio.

Pour empaqueter et publier des extensions Azure DevOps sur Visual Studio Marketplace, vous pouvez télécharger les tâches d’extension Azure DevOps.

Questions fréquentes (FAQ)

Consultez les questions fréquemment posées suivantes sur l’ajout de tâches de build ou de mise en production personnalisées dans les extensions pour Azure DevOps.

Q : Comment puis-je restreindre l’utilisation des commandes Azure Pipelines pour la tâche ?

Vous pouvez restreindre l’utilisation et les variables des commandes Azure Pipelines, qui sont définies par tâche. Cette action peut être utile pour empêcher l’accès illimité aux variables ou aux commandes vso pour les scripts personnalisés exécutés par la tâche. Nous vous recommandons de le configurer pour les nouvelles tâches. Pour appliquer, vous devrez peut-être ajouter l’instruction suivante à votre task.json fichier :

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

Si une valeur restricted est spécifiée pour mode, vous ne pouvez exécuter les commandes suivantes que par la tâche :

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

Les restrictions settableVariables vous permettent de passer une liste blanche de variables, qui sont définies par les commandes setvariable ou prependpath. Il permet également des expressions régulières de base. Par exemple, si votre liste d’autorisation était : ['abc', 'test*'], définir abc, test ou test1 en tant que variables avec n’importe quelle valeur ou les ajoutant au chemin d’accès fonctionnerait, mais si vous essayez de définir une variable proxy, vous recevrez un avertissement. La liste vide signifie qu’aucune variable n’est modifiée par tâche.

Si soit la clé settableVariables, soit la clé commands est omise, la restriction pertinente n'est pas appliquée.

La fonctionnalité de restriction est disponible à partir de l’agent version 2.182.1.

Q : Comment le signal d’annulation est-il géré par une tâche ?

L'agent de pipeline envoie les signaux SIGINT et SIGTERM au processus enfant approprié. Il n'existe aucun moyen explicite dans la bibliothèque de tâches pour traiter. Pour plus d'informations, consultez l'annulation des tâches de l'agent.

Q : Comment puis-je supprimer la tâche de la collection de projets ?

Nous ne prenons pas en charge la suppression automatique des tâches. La suppression automatique n’est pas sécurisée et interrompt les pipelines existants qui utilisent déjà ces tâches. Toutefois, vous pouvez marquer les tâches comme déconseillées. Pour ce faire, augmentez la version de la tâche et marquez la tâche comme obsolète.

Q : Comment puis-je mettre à niveau ma tâche personnalisée vers la dernière version de Node.js ?

Nous vous recommandons de procéder à la mise à niveau vers la dernière version de Node. Pour obtenir des exemples d’informations, consultez Mise à niveau des tâches vers le nœud 20.

Les agents hébergés par Microsoft et les différentes versions d’Azure DevOps Server ont des cycles de vie différents, ce qui entraîne l’installation de différentes versions de l’exécuteur de nœuds en fonction de l’emplacement d’exécution d’une tâche. Pour garantir la compatibilité entre les agents avec différentes versions de l’exécuteur de nœud, le task.json fichier peut inclure plusieurs sections d’exécution. Dans l’exemple suivant, les agents Azure Pipeline avec le moteur Node 20 l’utilisent par défaut, tandis que les agents sans celui-ci reviennent à l’implémentation Node 10.

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

Pour mettre à niveau vos tâches :

  • Pour vous assurer que votre code se comporte comme prévu, testez vos tâches sur les différentes versions de Node Runner.

  • Dans la section d’exécution de votre tâche, mettez à jour depuis Node ou Node10 vers Node16 ou Node20.

  • Pour prendre en charge les versions antérieures du serveur, vous devez laisser la Node/Node10 cible. Les versions antérieures d’Azure DevOps Server peuvent ne pas avoir la dernière version de Node Runner incluse.

  • Vous pouvez choisir de partager le point d’entrée défini dans la cible ou d’avoir des cibles optimisées pour la version du nœud utilisée.

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

Importante

Si vous n’ajoutez pas la prise en charge de l’exécuteur Node 20 à vos tâches personnalisées, elles échouent sur les agents installés à partir du flux de mise en production pipelines-agent-*.