Freigeben über


Hinzufügen einer benutzerdefinierten Aufgabenerweiterung für Pipelines

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

Dieser Leitfaden führt Sie durch das Erstellen, Testen und Veröffentlichen von benutzerdefinierten Build- oder Freigabeaufgaben als Azure DevOps-Erweiterungen. Mit benutzerdefinierten Pipelineaufgaben können Sie Azure DevOps mit speziellen Funktionen erweitern, die auf die Workflows Ihres Teams zugeschnitten sind, von einfachen Hilfsprogrammen bis hin zu komplexen Integrationen mit externen Systemen.

Erfahren Sie, wie Sie die folgenden Aufgaben ausführen:

  • Einrichten der Entwicklungsumgebung und Projektstruktur
  • Erstellen von Aufgabenlogik mithilfe von TypeScript und der Azure Pipelines-Aufgabenbibliothek
  • Implementieren von umfassenden Komponententests mit Mock-Frameworks
  • Verpacken Sie Ihre Erweiterung für die Verteilung
  • Veröffentlichen im Visual Studio Marketplace
  • Einrichten automatisierter CI/CD-Pipelines für die Erweiterungswartung

Weitere Informationen zu Azure-Pipelines finden Sie unter Was ist Azure-Pipelines?

Hinweis

In diesem Artikel werden Agentaufgaben in agentbasierten Erweiterungen behandelt. Informationen zu Serveraufgaben und serverbasierten Erweiterungen finden Sie unter Serveraufgabenerstellung.

Voraussetzungen

Bevor Sie beginnen, stellen Sie sicher, dass Die folgenden Anforderungen erfüllt sind:

Komponente Anforderung Beschreibung
Azure DevOps Organisation Erforderlich Erstellen Sie eine Organisation, wenn Sie keine haben
Texteditor Empfohlen Visual Studio Code für IntelliSense und Debuggingunterstützung
Node.js Erforderlich Installieren der neuesten Version (Node.js 20 oder höher empfohlen)
TypeScript-Compiler Erforderlich Installieren der neuesten Version (Version 4.6.3 oder höher)
Azure DevOps CLI (tfx-cli) Erforderlich Installation mithilfe von npm i -g tfx-cli für Erweiterungen paketieren
Azure DevOps-Erweiterungs-SDK Erforderlich Installieren des Azure-devops-extension-sdk-Pakets
Testframework Erforderlich Mocha für Komponententests (während des Setups installiert)

Projektstruktur

Erstellen Sie ein home Verzeichnis für Ihr Projekt. Nachdem Sie diese Anleitung abgeschlossen haben, sollte Ihre Erweiterung die folgende Struktur aufweisen:

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

Wichtig

Ihr Entwicklungscomputer muss die neueste Version von Node.js ausführen, um die Kompatibilität mit der Produktionsumgebung sicherzustellen. Aktualisieren Sie Ihre task.json Datei für die Verwendung von Node 20:

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

Erstellen einer benutzerdefinierten Aufgabe

Dieser Abschnitt führt Sie durch das Erstellen der grundlegenden Struktur und Implementierung Ihrer benutzerdefinierten Aufgabe. Alle Dateien in diesem Schritt sollten innerhalb des buildandreleasetask Ordners home im Verzeichnis Ihres Projekts erstellt werden.

Hinweis

In dieser exemplarischen Vorgehensweise wird Windows mit PowerShell verwendet. Die Schritte funktionieren auf allen Plattformen, die Umgebungsvariablensyntax unterscheidet sich jedoch. Ersetzen Sie auf einem Mac oder Linux $env:<var>=<val> durch export <var>=<val>.

Aufgabengerüst einrichten

Erstellen Sie die grundlegende Projektstruktur, und installieren Sie erforderliche Abhängigkeiten:

  1. Um das Node.js Projekt zu initialisieren, öffnen Sie PowerShell, wechseln Sie zu Ihrem buildandreleasetask Ordner, und führen Sie Folgendes aus:

    npm init --yes
    

    Die package.json Datei wird mit Standardeinstellungen erstellt. Das --yes Kennzeichen akzeptiert automatisch alle Standardoptionen.

    Tipp

    Azure Pipelines-Agents erwarten, dass Aufgabenordner Knotenmodule enthalten. Kopieren Sie node_modules in den buildandreleasetask Ordner. Zum Verwalten der VSIX-Dateigröße (Grenzwert von 50 MB) sollten Sie die Ausführung npm install --production oder npm prune --production vor dem Verpacken in Betracht ziehen.

  2. Installieren Sie die Azure Pipelines-Aufgabenbibliothek:

    npm install azure-pipelines-task-lib --save
    
  3. TypeScript-Typdefinitionen installieren:

    npm install @types/node --save-dev
    npm install @types/q --save-dev
    
  4. Einrichten von Versionssteuerungsausschlüssen

    echo node_modules > .gitignore
    

    Ihr Buildprozess sollte npm install jedes Mal ausführen, um node_modules neu zu erstellen.

  5. Installieren von Testabhängigkeiten:

    npm install mocha --save-dev -g
    npm install sync-request --save-dev
    npm install @types/mocha --save-dev
    
  6. TypeScript-Compiler installieren:

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

    Hinweis

    Installieren Sie TypeScript global, um sicherzustellen, dass der tsc Befehl verfügbar ist. Ohne dies wird TypeScript 2.3.4 standardmäßig verwendet.

  7. Konfigurieren der TypeScript-Kompilierung:

    tsc --init --target es2022
    

    Die tsconfig.json Datei wird mit ES2022-Zieleinstellungen erstellt.

Implementieren der Aufgabenlogik

Erstellen Sie nach Abschluss des Gerüsts die Kernaufgabendateien, die Funktionen und Metadaten definieren:

  1. Erstellen Sie die Aufgabendefinitionsdatei: task.json im Ordner buildandreleasetask. Diese Datei beschreibt Ihre Aufgabe im Azure Pipelines-System, definieren Eingaben, Ausführungseinstellungen und UI-Präsentationen.

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

    Hinweis

    Ersetzen Sie {{placeholders}} mit den tatsächlichen Informationen Ihrer Aufgabe. Die taskguid muss eindeutig sein. Generieren Sie eins mithilfe von PowerShell: (New-Guid).Guid

  2. Um die Aufgabenlogik zu implementieren, erstellen Sie index.ts mit der Hauptfunktionalität Ihrer Aufgabe:

    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. Kompilieren von TypeScript in JavaScript:

    tsc
    

    Die index.js Datei wird aus Ihrer TypeScript-Quelle erstellt.

task.json-Komponenten

Die task.json Datei ist das Herzstück Ihrer Aufgabendefinition. Hier sind die wichtigsten Eigenschaften:

Eigenschaft Beschreibung Beispiel
id Eindeutiger GUID-Bezeichner für Ihre Aufgabe Generiert mit (New-Guid).Guid
name Vorgangsname ohne Leerzeichen (intern verwendet) MyCustomTask
friendlyName Anzeigename, der in der Benutzeroberfläche angezeigt wird My Custom Task
description Detaillierte Beschreibung der Aufgabenfunktionalität Performs custom operations on files
author Herausgeber- oder Autorname My Company
instanceNameFormat Wie die Aufgabe in Pipeline-Schritten dargestellt wird Process $(inputFile)
inputs Feld von Eingabeparametern Siehe die folgenden Eingabetypen
execution Spezifikation der Ausführungsumgebung Node20_1, PowerShell3 usw.
restrictions Sicherheitseinschränkungen für Befehle und Variablen Empfohlen für neue Aufgaben

Sicherheitsbeschränkungen

Fügen Sie für Produktionsaufgaben Sicherheitseinschränkungen hinzu, um die Verwendung von Befehlen und den variablen Zugriff einzuschränken:

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

Der eingeschränkte Modus lässt nur die folgenden Befehle zu:

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

Die Variable-Zulassungsliste bestimmt, welche Variablen über setvariable oder prependpath festgelegt werden können. Unterstützt grundlegende regex-Muster.

Hinweis

Für dieses Feature ist agent Version 2.182.1 oder höher erforderlich.

Eingabetypen und Beispiele

Allgemeine Eingabetypen für Vorgangsparameter:

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

Testen Sie Ihre Aufgabe lokal

Testen Sie vor dem Verpacken Ihre Aufgabe, um sicherzustellen, dass sie ordnungsgemäß funktioniert:

  1. Testen mit fehlender Eingabe (sollte fehlschlagen):

    node index.js
    

    Erwartete Ausgabe:

    ##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. Testen mit gültiger Eingabe (sollte erfolgreich sein):

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

    Erwartete Ausgabe:

    ##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. Testen der Fehlerbehandlung:

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

    Diese Aktion sollte den Fehlerbehandlungspfad in Ihrem Code auslösen.

    Tipp

    Informationen zu Aufgabenläufern und Node.js Versionen finden Sie unter Node runner update guidance.

Weitere Informationen finden Sie in der Build-/Release-Aufgabenreferenz.

Implementieren von Komponententests

Durch das gründliche Testen Ihrer Aufgabe wird die Zuverlässigkeit sichergestellt und hilft, Probleme vor der Bereitstellung in Produktionspipelinen abzufangen.

Installieren von Testabhängigkeiten

Installieren Sie die erforderlichen Testtools:

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

Erstellen von Tests

  1. Erstellen Sie einen tests Ordner in Ihrem Aufgabenverzeichnis, der eine _suite.ts Datei enthält:

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

    Tipp

    Ihr Testordner sollte sich im Aufgabenordner befinden (z. B buildandreleasetask. ). Wenn ein Synchronisierungsanforderungsfehler auftritt, installieren Sie ihn im Aufgabenordner: npm i --save-dev sync-request.

  2. Erstellen Sie success.ts in Ihrem Testverzeichnis, um eine erfolgreiche Aufgabenausführung zu simulieren:

     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. Fügen Sie den Erfolgstest zu Ihrer _suite.ts Datei hinzu:

     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. Erstellen Sie failure.ts in Ihrem Testverzeichnis, um die Fehlerbehandlung zu testen:

    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. Fügen Sie den Fehlertest Ihrer _suite.ts Datei hinzu.

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

Ausführung Ihrer Tests

Führen Sie die Testsuite aus:

# Compile TypeScript
tsc

# Run tests
mocha tests/_suite.js

Beide Tests sollten bestehen. Legen Sie die Umgebungsvariable für die Ablaufverfolgung fest, um eine ausführliche Ausgabe zu erhalten (ähnlich wie bei der Buildkonsolenausgabe).

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

Testabdeckungsrichtlinien

  • Testen Sie alle Eingabekombinationen: Gültige Eingaben, ungültige Eingaben, fehlende erforderliche Eingaben
  • Testfehlerszenarien: Netzwerkfehler, Dateisystemfehler, Berechtigungsprobleme
  • Simulierte externe Abhängigkeiten: Verlassen Sie sich nicht auf externe Dienste in Komponententests
  • Überprüfen von Ausgaben: Überprüfen der Konsolenausgabe, Aufgabenergebnisse und generierter Artefakte
  • Leistungstests: Erwägen Sie das Hinzufügen von Tests für Aufgaben, die große Dateien verarbeiten

Sicherheitsrichtlinien

  • Eingabeüberprüfung: Eingaben immer überprüfen und bereinigungen
  • Umgang mit geheimen Schlüsseln: Verwendung setSecret für vertrauliche Daten
  • Befehlseinschränkungen: Implementieren von Befehlseinschränkungen für Produktionsaufgaben
  • Minimale Berechtigungen: Nur erforderliche Berechtigungen anfordern
  • Regelmäßige Updates: Beibehalten von Abhängigkeiten und Node.js Versionen auf dem aktuellen Stand

Nachdem Sie Ihre Aufgabe lokal getestet und umfassende Komponententests implementiert haben, packen Sie sie in eine Erweiterung für Azure DevOps.

Installieren von Verpackungstools

Installieren Sie die plattformübergreifende Befehlszeilenschnittstelle (tfx-cli):

npm install -g tfx-cli

Erstellen des Erweiterungsmanifests

Das Erweiterungsmanifest (vss-extension.json) enthält alle Informationen zu Ihrer Erweiterung, einschließlich Verweise auf Ihre Aufgabenordner und Bilder.

  1. Erstellen eines Bilderordners mit einer extension-icon.png Datei

  2. Erstellen Sie vss-extension.json im Stammverzeichnis Ihrer Erweiterung (nicht im Aufgabenordner):

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

Wichtige Manifest-Eigenschaften

Eigenschaft Beschreibung
publisher Ihr Marktplatz-Publisher-ID
contributions.id Eindeutiger Bezeichner innerhalb der Erweiterung
contributions.properties.name Muss dem Namen des Aufgabenordners entsprechen
files.path Pfad zum Aufgabenordner relativ zum Manifest

Hinweis

Ändern Sie den Wert für den Herausgeber in Ihren Herausgebernamen. Informationen zum Erstellen eines Herausgebers finden Sie unter Erstellen Ihres Herausgebers.

Verpacken Sie Ihre Erweiterung

Packen Sie Ihre Erweiterung in eine .vsix-Datei.

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

Versionsverwaltung

  • Erweiterungsversion: Erhöhen Sie die Versionsnummer in vss-extension.json für jedes Update
  • Aufgabenversion: Erhöhen der Version task.json für jede Aktualisierung der Aufgabe
  • Auto-Inkrement: Verwenden Sie --rev-version, um die Patchversion automatisch zu erhöhen.
tfx extension create --manifest-globs vss-extension.json --rev-version

Wichtig

Sowohl die Aufgabenversion als auch die Erweiterungsversion müssen aktualisiert werden, damit Änderungen in Azure DevOps wirksam werden.

Versionsverwaltungsstrategie

Folgen Sie den Prinzipien der semantischen Versionsverwaltung für Ihre Aufgabenaktualisierungen:

  • Hauptversion: Grundlegende Änderungen an Eingaben/Ausgaben
  • Nebenversion: Neue Features, abwärtskompatibel
  • Patchversion: Nur Fehlerbehebungen

Aktualisierungsprozess:

  1. Update task.json Version
  2. Update vss-extension.json Version
  3. Gründliches Testen in einer Testorganisation
  4. Veröffentlichen und Probleme überwachen

Veröffentlichen auf Visual Studio Marketplace

Erstellen eines Herausgebers

  1. Melden Sie sich beim Visual Studio Marketplace-Veröffentlichungsportal an.
  2. Erstellen Sie einen neuen Herausgeber, wenn Sie dazu aufgefordert werden:
    • Herausgeberbezeichner: Wird in Ihrem Erweiterungsmanifest verwendet (z. B mycompany-myteam. )
    • Anzeigename: Öffentlicher Name, der auf dem Marketplace angezeigt wird (z. B My Team. )
  3. Überprüfen und Akzeptieren der Marketplace-Herausgebervereinbarung

Hochladen der Erweiterung

Webschnittstellenmethode:

  1. Wählen Sie "Neue Erweiterung hochladen" aus.
  2. Wählen Sie Ihre .vsix verpackte Datei aus.
  3. Wählen Sie Hochladen aus.

Befehlszeilenmethode:

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

Erweiterung teilen

  1. Klicken Sie mit der rechten Maustaste auf Ihre Erweiterung auf dem Marketplace.
  2. Wählen Sie Freigeben aus
  3. Geben Sie den Namen Ihrer Organisation ein.
  4. Hinzufügen weiterer Organisationen nach Bedarf

Wichtig

Herausgeber müssen überprüft werden, um Erweiterungen öffentlich freizugeben. Weitere Informationen finden Sie unter "Package/Publish/Install".

Installieren in Ihrer Organisation

Installieren Sie die Erweiterung nach der Freigabe in Ihrer Azure DevOps-Organisation.

  1. Navigieren Sie zu Organisationseinstellungen>Erweiterungen
  2. Durchsuchen Sie nach Ihrer Erweiterung
  3. Wählen Sie "Kostenlos abrufen " und "Installieren" aus.

Paketieren und veröffentlichen Sie die Erweiterung

Überprüfen Sie Ihre Erweiterung

Überprüfen Sie nach der Installation, ob die Aufgabe ordnungsgemäß funktioniert:

  1. Erstellen oder Bearbeiten einer Pipeline
  2. Fügen Sie Ihre benutzerdefinierte Aufgabe hinzu:
    • Wählen Sie im Pipeline-Editor "Aufgabe hinzufügen" aus.
    • Suchen Sie nach Ihrer benutzerdefinierten Aufgabe anhand des Namens
    • Fügen Sie es Ihrer Pipeline hinzu
  3. Aufgabenparameter konfigurieren:
    • Festlegen erforderlicher Eingaben
    • Konfigurieren optionaler Einstellungen
  4. Führen Sie die Pipeline aus, um die Funktionalität zu testen.
  5. Überwachen der Ausführung:
    • Überprüfen von Aufgabenprotokollen auf ordnungsgemäße Ausführung
    • Überprüfen der erwarteten Ausgaben
    • Sicherstellen, dass keine Fehler oder Warnungen auftreten

Automatisierung der Veröffentlichung mit CI/CD

Um Ihre benutzerdefinierte Aufgabe effektiv zu verwalten, erstellen Sie automatisierte Build- und Freigabepipelinen, die Tests, Verpackungen und Veröffentlichungen verarbeiten.

CI/CD-Voraussetzungen

  • Azure DevOps-Erweiterungsaufgaben: Installieren Der Erweiterung kostenlos
  • Variablengruppe: Erstellen Sie eine Pipelinebibliotheksvariablengruppe mit diesen Variablen:
    • publisherId: Ihre Marketplace-Herausgeber-ID
    • extensionId: Erweiterungs-ID von vss-extension.json
    • extensionName: Erweiterungsname aus vss-extension.json
    • artifactName: Name für das VSIX-Artefakt
  • Dienstverbindung: Erstellen einer Marketplace-Dienstverbindung mit Pipelinezugriffsberechtigungen

CI/CD-Pipelinebeispiel

Erstellen Sie eine YAML-Pipeline mit umfassenden Phasen für Tests, Verpackungen und Veröffentlichungen:

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'

Konfigurieren von package.json zu Testzwecken

Fügen Sie Testskripte zu Ihrem package.json hinzu:

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

Pipelinephasen

Testen und Überprüfen

  • Zweck: Sicherstellen der Codequalität und -funktionalität
  • Aktionen: Installieren von Abhängigkeiten, Kompilieren von TypeScript, Ausführen von Komponententests, Veröffentlichen von Ergebnissen
  • Überprüfung: Alle Tests müssen bestehen, um fortzufahren.

Erweiterung verpacken

  • Zweck: Erstellen eines bereitstellenden VSIX-Pakets
  • Aktionen: Aktuelle Version abfragen, Version inkrementieren, Erweiterung verpacken, Artefakte veröffentlichen
  • Versionsverwaltung: Behandelt automatisch Versionserhöhungen

Auf Marketplace veröffentlichen

  • Zweck: Bereitstellen auf Visual Studio Marketplace
  • Bedingungen: Läuft nur nach erfolgreicher Verpackung auf dem Master-Branch
  • Umgebung: Verwendet die Bereitstellungsumgebung für die Freigabeprozesse.

CI/CD-Richtlinien

  • Branch-Schutz: Nur aus Haupt-/Release-Branches veröffentlichen
  • Umgebungsgates: Verwenden von Bereitstellungsumgebungen für Produktionsversionen
  • Versionsverwaltung: Automatisieren von Versionsinkrementierungen, um Konflikte zu vermeiden
  • Testabdeckung: Sicherstellen einer umfassenden Testabdeckung vor dem Verpacken
  • Sicherheit: Verwenden von Dienstverbindungen anstelle hartcodierter Anmeldeinformationen
  • Überwachung: Einrichten von Warnungen für fehlgeschlagene Bereitstellungen

Führen Sie für klassische Build-Pipelines die folgenden Schritte aus, um das Verpacken und Veröffentlichen von Erweiterungen einzurichten:

  1. Fügen Sie die Bash Aufgabe hinzu, um typeScript in JavaScript zu kompilieren.

  2. Um die vorhandene Version abzufragen, fügen Sie die Abfrageerweiterungsversion-Aufgabe mithilfe der folgenden Eingaben hinzu:

    • Herstellen einer Verbindung mit: Visual Studio Marketplace
    • Visual Studio Marketplace (Dienst-Verbindung): Dienst-Verbindung
    • Herausgeber-ID: ID Ihres Visual Studio Marketplace-Herausgebers
    • Erweiterungs-ID: ID Ihrer Erweiterung in der vss-extension.json Datei
    • Version erhöhen: Patch
    • Ausgabevariable: Task.Extension.Version
  3. Um die Erweiterungen basierend auf manifest json zu packen, fügen Sie die Paketerweiterungsaufgabe mithilfe der folgenden Eingaben hinzu:

    • Stammmanifestordner: Verweist auf das Stammverzeichnis, das die Manifestdatei enthält. Zum Beispiel ist $(System.DefaultWorkingDirectory) das Stammverzeichnis.
    • Manifestdatei: vss-extension.json
    • Herausgeber-ID: ID Ihres Visual Studio Marketplace-Herausgebers
    • Erweiterungs-ID: ID Ihrer Erweiterung in der vss-extension.json Datei
    • Erweiterungsname: Name der Erweiterung in der vss-extension.json Datei
    • Erweiterungsversion: $(Task.Extension.Version)
    • Aufgaben Version überschreiben: markiert (true)
    • Typ überschreiben: Nur Patch ersetzen (1.0.r)
    • Sichtbarkeit der Erweiterung: Wenn sich die Erweiterung noch in der Entwicklung befindet, legen Sie den Wert auf "Privat" fest. Um die Erweiterung für die Öffentlichkeit freizugeben, legen Sie den Wert auf "öffentlich" fest.
  4. Um in veröffentlichte Dateien zu kopieren, fügen Sie die Aufgabe " Dateien kopieren " mithilfe der folgenden Eingaben hinzu:

    • Inhalt: Alle Dateien, die zum Veröffentlichen als Artefakt kopiert werden sollen
    • Zielordner: Der Ordner, in den die Dateien kopiert werden
      • Beispiel: $(Build.ArtifactStagingDirectory)
  5. Fügen Sie Bauartefakte veröffentlichen hinzu, um die Artefakte zur Verwendung in anderen Aufträgen oder Pipelines zu veröffentlichen. Verwenden Sie die folgenden Eingaben:

    • Pfad zur Veröffentlichung: Der Pfad zum Ordner, der die dateien enthält, die veröffentlicht werden
      • Beispiel: $(Build.ArtifactStagingDirectory)
    • Artefaktname: Der dem Artefakt zugewiesene Name
    • Artefakt-Veröffentlichungsort: Wählen Sie Azure Pipelines aus, um das Artefakt in zukünftigen Aufträgen zu verwenden.

Herunterladen und Veröffentlichen von Artefakten

  1. Um die tfx-cli auf Ihrem Build-Agent zu installieren, fügen Sie den Befehl Node CLI für Azure DevOps verwenden (tfx-cli) hinzu.

  2. Um die Artefakte auf einen neuen Auftrag herunterzuladen, fügen Sie die Aufgabe Download build artifacts mit den folgenden Eingaben hinzu:

    • Downloads von Artefakten erstellt von: Wenn Sie das Artefakt mit einem neuen Auftrag aus derselben Pipeline herunterladen, wählen Sie Aktueller Build. Wenn Sie mit einer neuen Pipeline herunterladen, wählen Sie Spezifischer Build
    • Downloadtyp: Wählen Sie "Spezifisches Artefakt " aus, um alle veröffentlichten Dateien herunterzuladen.
    • Artefaktname: Der Name des veröffentlichten Artefakts
    • Zielverzeichnis: Der Ordner, in den die Dateien heruntergeladen werden sollen
  3. Verwenden Sie die folgenden Eingaben, um die Aufgabe "Erweiterung veröffentlichen " abzurufen:

    • Herstellen einer Verbindung mit: Visual Studio Marketplace
    • Visual Studio Marketplace-Verbindung: ServiceConnection
    • Eingabedateityp: VSIX-Datei
    • VSIX-Datei: /Publisher.*.vsix
    • Herausgeber-ID: ID Ihres Visual Studio Marketplace-Herausgebers
    • Erweiterungs-ID: ID Ihrer Erweiterung in der vss-extension.json Datei
    • Erweiterungsname: Name der Erweiterung in der vss-extension.json Datei
    • Sichtbarkeit der Erweiterung: Entweder privat oder öffentlich

Installieren und Testen der Erweiterung

Nachdem Sie Ihre Erweiterung veröffentlicht haben, muss sie in Azure DevOps-Organisationen installiert werden.

In einer Organisation installieren

Installieren Sie Ihre freigegebene Erweiterung in einigen Schritten:

  1. Wechseln Sie zu "Organisationseinstellungen" , und wählen Sie "Erweiterungen" aus.

  2. Suchen Sie Ihre Erweiterung im Abschnitt "Für mich freigegebene Erweiterungen ":

    • Wählen Sie den Erweiterungslink aus.
    • Wählen Sie "Kostenlos abrufen" oder "Installieren" aus.
  3. Überprüfen Sie, ob die Erweiterung in der Liste der installierten Erweiterungen angezeigt wird:

    • Vergewissern Sie sich, dass sie in Ihrer Pipelineaufgabenbibliothek verfügbar ist.

Hinweis

Wenn die Registerkarte "Erweiterungen " nicht angezeigt wird, stellen Sie sicher, dass Sie sich auf der Verwaltungsebene (https://dev.azure.com/{organization}/_admin) der Organisation befinden und nicht auf Projektebene.

End-to-End-Tests

Führen Sie nach der Installation umfassende Tests durch:

  1. Erstellen einer Testpipeline:

    • Fügen Sie Ihre benutzerdefinierte Aufgabe zu einer neuen Pipeline hinzu
    • Konfigurieren aller Eingabeparameter
    • Testen mit verschiedenen Eingabekombinationen
  2. Überprüfen der Funktionalität:

    • Ausführen der Pipeline und Überwachen der Ausführung
    • Überprüfen von Aufgabenausgängen und Protokollen
    • Überprüfen der Fehlerbehandlung mit ungültigen Eingaben
  3. Testleistung:

    • Testen mit großen Eingabedateien (falls zutreffend)
    • Überwachen der Ressourcennutzung
    • Validieren des Timeout-Verhaltens

Häufig gestellte Fragen

F: Wie wird der Vorgangsabbruch verarbeitet?

A: Der Pipeline-Agent sendet SIGINT- und SIGTERM-Signale an die Aufgabenprozesse. Während die Aufgabenbibliothek keine explizite Abbruchbehandlung bereitstellt, kann Ihre Aufgabe Signalhandler implementieren. Ausführliche Informationen finden Sie unter Kündigung von Agentaufträgen.

F: Wie kann ich eine Aufgabe aus meiner Organisation entfernen?

A: Das automatische Löschen wird nicht unterstützt , da vorhandene Pipelines abgebrochen werden. Stattdessen:

  1. Aufgabe als veraltet markieren: Aufgabe als veraltet kennzeichnen
  2. Versionsverwaltung: Aktualisiere die Aufgabenversion
  3. Kommunikation: Benutzer über den Zeitplan zur Abkündigung informieren.

F: Wie kann ich meine Aufgabe auf die neueste Node.js Version aktualisieren?

A: Aktualisieren Sie auf die neueste Node-Version , um eine bessere Leistung und Sicherheit zu erzielen. Anleitungen zur Migration finden Sie unter Aktualisieren von Aufgaben auf Node 20.

Mehrere Node-Versionen unterstützen, indem Sie mehrere Ausführungsabschnitte in task.json einfügen:

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

Agents mit Node 20 verwenden die bevorzugte Version, während ältere Agents auf Node 10 zurückgreifen.

So aktualisieren Sie Ihre Aufgaben:

  • Um sicherzustellen, dass sich Ihr Code wie erwartet verhält, testen Sie Ihre Aufgaben in den verschiedenen Node-Läuferversionen.

  • Aktualisieren Sie im Ausführungsbereich Ihrer Aufgabe von Node oder Node10 zu Node16 oder Node20.

  • Um ältere Serverversionen zu unterstützen, sollten Sie das Node/Node10 Ziel beibehalten. Ältere Azure DevOps Server-Versionen verfügen möglicherweise nicht über die neueste Node-Runner-Version.

  • Sie können den im Ziel definierten Einstiegspunkt teilen oder die Ziele auf die verwendete Node-Version optimieren lassen.

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

Wichtig

Wenn Sie ihren benutzerdefinierten Aufgaben keine Unterstützung für den Node 20-Läufer hinzufügen, schlagen sie bei Agents fehl, die aus dem pipelines-agent-*Releasefeed installiert wurden.