Поделиться через


Добавить расширение задачи для пользовательских конвейеров

Сервисы Azure DevOps | Azure DevOps Server | Azure DevOps Server 2022

В этом руководстве описывается создание, тестирование и публикация пользовательских задач сборки или выпуска в виде расширений Azure DevOps. Пользовательские задачи конвейера позволяют расширить Azure DevOps с помощью специализированных функций, адаптированных к рабочим процессам вашей команды, от простых служебных программ до сложных интеграций с внешними системами.

Узнайте, как выполнять следующие задачи:

  • Настройка среды разработки и структуры проекта
  • Создание логики задач с помощью TypeScript и библиотеки задач Azure Pipelines
  • Реализация комплексного модульного тестирования с помощью макетных платформ
  • Упакуйте расширение для распространения
  • Публикация в Visual Studio Marketplace
  • Настройте автоматизированные конвейеры CI/CD для поддержки расширений.

Дополнительные сведения о Azure Pipelines см. в статье "Что такое Azure Pipelines?

Примечание.

В этой статье рассматриваются задачи агента в агентно-ориентированных расширениях. Сведения о задачах сервера и расширениях на основе сервера см. в разделе "Разработка задач сервера".

Предварительные условия

Прежде чем начать, убедитесь, что у вас есть следующие требования:

Компонент Требование Описание
Организация Azure DevOps Обязательно Создайте организацию, если у вас её ещё нет
Текстовый редактор Рекомендуется Visual Studio Code для поддержки IntelliSense и отладки
Node.js Обязательно Установите последнюю версию (рекомендуетсяNode.js 20 или более поздней версии)
Компилятор TypeScript Обязательно Установите последнюю версию (версия 4.6.3 или более поздняя)
Интерфейс командной строки Azure DevOps (tfx-cli) Обязательно Установка расширений пакетов с помощью npm i -g tfx-cli
Пакет SDK для расширения Azure DevOps Обязательно Установка пакета azure-devops-extension-sdk
Платформа тестирования Обязательно Mocha для модульного тестирования (устанавливается при установке)

Структура проекта

home Создайте каталог для проекта. После завершения работы с этим руководством расширение должно иметь следующую структуру:

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

Внимание

Компьютер разработки должен запускать последнюю версию Node.js , чтобы обеспечить совместимость с рабочей средой. Обновите task.json файл, чтобы использовать Node 20:

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

Создание настраиваемой задачи

В этом разделе описано, как создать базовую структуру и реализацию пользовательской задачи. Все файлы на этом шаге должны быть созданы в папке buildandreleasetask в каталоге home проекта.

Примечание.

В этом пошаговом руководстве используется Windows с PowerShell. Действия работают на всех платформах, но синтаксис переменных среды отличается. В Mac или Linux замените $env:<var>=<val> на export <var>=<val>.

Создайте структуру задач

Создайте базовую структуру проекта и установите необходимые зависимости:

  1. Чтобы инициализировать проект Node.js, откройте PowerShell, перейдите в buildandreleasetask папку и выполните следующую команду:

    npm init --yes
    

    Файл package.json создается с параметрами по умолчанию. Флаг --yes принимает все параметры по умолчанию автоматически.

    Совет

    Агенты Azure Pipelines ожидают, что папки задач будут включать модули узлов. Скопируйте node_modules в buildandreleasetask папку. Чтобы управлять размером файла VSIX (ограничение в 50 МБ), рассмотрите возможность выполнения npm install --production или npm prune --production перед упаковкой.

  2. Установите библиотеку задач Azure Pipelines:

    npm install azure-pipelines-task-lib --save
    
  3. Установка определений типов TypeScript:

    npm install @types/node --save-dev
    npm install @types/q --save-dev
    
  4. Настройка исключений управления версиями

    echo node_modules > .gitignore
    

    Процесс сборки должен выполняться npm install для восстановления node_modules каждый раз.

  5. Установите зависимости тестирования:

    npm install mocha --save-dev -g
    npm install sync-request --save-dev
    npm install @types/mocha --save-dev
    
  6. Установите компилятор TypeScript:

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

    Примечание.

    Установите TypeScript глобально, чтобы команда tsc была доступна. Без него TypeScript 2.3.4 используется по умолчанию.

  7. Настройка компиляции TypeScript:

    tsc --init --target es2022
    

    Файл tsconfig.json создается с параметрами целевого объекта ES2022.

Реализация логики задачи

После завершения формирования шаблонов создайте основные файлы задач, определяющие функциональные возможности и метаданные:

  1. Создайте файл определения задачи: создайте task.json в папке buildandreleasetask . Этот файл описывает задачу в системе Azure Pipelines, определяя входные данные, параметры выполнения и презентацию пользовательского интерфейса.

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

    Примечание.

    Замените {{placeholders}} на фактическую информацию о вашей задаче. Значение taskguid должно быть уникальным. Создайте его с помощью PowerShell: (New-Guid).Guid

  2. Чтобы реализовать логику задачи, создайте index.ts с помощью основных функциональных возможностей задачи:

    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. Компиляция TypeScript в JavaScript:

    tsc
    

    Файл index.js создается из источника TypeScript.

компоненты task.json

Файл task.json является сердцем определения задачи. Ниже приведены ключевые свойства:

Имущество Описание Пример
id Уникальный идентификатор GUID для задачи Создано с помощью (New-Guid).Guid
name Имя задачи без пробелов (используется внутренне) MyCustomTask
friendlyName Имя, отображаемое в пользовательском интерфейсе My Custom Task
description Подробное описание функциональных возможностей задач Performs custom operations on files
author Имя издателя или автора My Company
instanceNameFormat Как задача отображается в шагах конвейера Process $(inputFile)
inputs Массив входных параметров См. следующие типы входных данных
execution Спецификация среды выполнения Node20_1, PowerShell3и т. д.
restrictions Ограничения безопасности для команд и переменных Рекомендуется для новых задач

Ограничения безопасности

Для рабочих задач добавьте ограничения безопасности, чтобы ограничить использование команд и доступ к переменным:

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

Ограниченный режим позволяет выполнять только следующие команды:

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

Список разрешенных переменных контролирует, какие переменные можно задать через setvariable или prependpath. Поддерживает базовые шаблоны регулярных выражений.

Примечание.

Для этой функции требуется агент версии 2.182.1 или более поздней.

Типы входных данных и примеры

Распространенные типы входных данных для параметров задачи:

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

Локальное тестирование задачи

Перед упаковкой проверьте задачу, чтобы убедиться, что она работает правильно:

  1. Проверка с отсутствующими входными данными (должна завершиться ошибкой):

    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
    
  2. Проверка с допустимыми входными данными (должна выполнена успешно):

    $env:INPUT_SAMPLESTRING="World"
    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]samplestring=World
    Hello World
    
  3. Проверка обработки ошибок:

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

    Это действие должно активировать путь обработки ошибок в коде.

    Совет

    Для получения информации о таск-раннерах и версиях Node.js см. в руководстве по обновлению Node runner.

Дополнительные сведения см. в справочнике по задаче сборки и выпуска.

Реализация модульного тестирования

Тщательное тестирование задачи гарантирует надежность и помогает перехватывать проблемы перед развертыванием в рабочих конвейерах.

Установка зависимостей тестирования

Установите необходимые средства тестирования:

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

Создание тестов

  1. Создайте папку tests в вашем каталоге задач, содержащую файл _suite.ts.

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

    Совет

    Тестовая папка должна находиться в папке задач (например, buildandreleasetask). При возникновении ошибки запроса на синхронизацию установите его в папку задач: npm i --save-dev sync-request

  2. Создайте success.ts в тестовом каталоге, чтобы имитировать успешное выполнение задачи:

     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. Добавьте тест успешности в _suite.ts файл:

     it('should succeed with simple inputs', function(done: Mocha.Done) {
         this.timeout(1000);
    
         let tp: string = path.join(__dirname, 'success.js');
         let tr: ttm.MockTestRunner = new ttm.MockTestRunner(tp);
    
         tr.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. Создайте failure.ts в тестовом каталоге для проверки обработки ошибок:

    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. Добавьте тест сбоя в _suite.ts файл:

     it('should fail if tool returns 1', function(done: Mocha.Done) {
         this.timeout(1000);
    
         const tp = path.join(__dirname, 'failure.js');
         const tr: ttm.MockTestRunner = new ttm.MockTestRunner(tp);
    
         tr.runAsync().then(() => {
             console.log(tr.succeeded);
             assert.equal(tr.succeeded, false, 'should have failed');
             assert.equal(tr.warningIssues.length, 0, 'should have no warnings');
             assert.equal(tr.errorIssues.length, 1, 'should have 1 error issue');
             assert.equal(tr.errorIssues[0], 'Bad input was given', 'error issue output');
             assert.equal(tr.stdout.indexOf('Hello bad'), -1, 'Should not display Hello bad');
             done();
         });
     });
    

Запуск тестов

Выполните набор тестов:

# Compile TypeScript
tsc

# Run tests
mocha tests/_suite.js

Оба теста должны быть пройдены. Для подробных выходных данных (аналогично выходным данным консоли сборки) задайте переменную среды трассировки:

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

Рекомендации по тестированию покрытия

  • Проверьте все сочетания входных данных: допустимые входные данные, недопустимые входные данные, отсутствующие необходимые входные данные
  • Сценарии тестирования ошибок: сбои сети, ошибки файловой системы, проблемы с разрешениями
  • Макет внешних зависимостей: не полагаться на внешние службы в модульных тестах
  • Проверка выходных данных: проверка выходных данных консоли, результатов задач и созданных артефактов
  • Тестирование производительности. Рассмотрите возможность добавления тестов для задач, обрабатывающих большие файлы

Рекомендации по безопасности

  • Проверка входных данных: всегда проверяйте и очищайте входные данные
  • Обработка секретов: использование setSecret конфиденциальных данных
  • Ограничения команд. Реализация ограничений команд для рабочих задач
  • Минимальные разрешения: запрашивать только необходимые разрешения
  • Регулярные обновления: сохранение зависимостей и Node.js версий в актуальном состоянии

После локального тестирования задачи и реализации комплексных модульных тестов упаковайте его в расширение для Azure DevOps.

Установка средств упаковки

Установите кроссплатформенный интерфейс командной строки (tfx-cli):

npm install -g tfx-cli

Создание манифеста расширения

Манифест расширения (vss-extension.json) содержит все сведения о расширении, включая ссылки на папки задач и изображения.

  1. Создание папки изображений с файлом extension-icon.png

  2. Создайте vss-extension.json в корневом каталоге расширения (не в папке задач):

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

Ключевые свойства манифеста

Имущество Описание
publisher Идентификатор издателя торговой платформы
contributions.id Уникальный идентификатор в рамках расширения
contributions.properties.name Должно соответствовать имени папки задачи
files.path Путь к папке задачи относительно манифеста

Примечание.

Измените значение издателя на имя издателя. Сведения о создании издателя см. в разделе "Создание издателя".

Упакуйте своё расширение

Упаковайте расширение в VSIX-файл:

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

Управление версиями

  • Версия расширения: увеличение версии vss-extension.json для каждого обновления
  • Версия задачи: увеличение версии task.json для каждого обновления задачи
  • Автоматическое увеличение: используйте --rev-version для автоматического увеличения версии исправления
tfx extension create --manifest-globs vss-extension.json --rev-version

Внимание

Чтобы изменения вступили в силу в Azure DevOps, необходимо обновить версию задачи и версию расширения.

Стратегия управления версиями

Следуйте принципам семантического управления версиями для обновлений задачи:

  • Основная версия: существенные изменения входных и выходных данных
  • Минорная версия: новые функции, обратная совместимость
  • Патч-версия: только исправление ошибок

Процесс обновления:

  1. Обновление версии task.json
  2. Обновление vss-extension.json версии
  3. Тщательное тестирование в тестовой организации
  4. Публикация и мониторинг проблем

Публикация в Visual Studio Marketplace

Создание издателя

  1. Вход на портал публикации Visual Studio Marketplace
  2. При появлении запроса создайте нового издателя:
    • Идентификатор издателя: используется в манифесте расширения (например, mycompany-myteam)
    • Отображаемое имя: общедоступное имя, отображаемое в Marketplace (например, My Team)
  3. Просмотр и принятие соглашения издателя Marketplace

Отправка расширения

Метод веб-интерфейса:

  1. Выберите " Отправить новое расширение"
  2. Выберите упакованный .vsix файл
  3. Щелкните Отправить.

Метод командной строки:

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

Поделитесь расширением

  1. Нажмите правой кнопкой мыши на ваше расширение в маркетплейсе
  2. Выберите Поделиться
  3. Введите имя организации
  4. Добавление дополнительных организаций по мере необходимости

Внимание

Издатели должны быть проверены для публичного распространения расширений. Дополнительные сведения см. в разделе "Package/Publish/Install".

Установить для вашей организации

После обмена установите расширение в организацию Azure DevOps:

  1. Перейдите к Параметры Организации>Расширения
  2. Выберите своё расширение
  3. Выберите "Получить бесплатно " и установите

Упаковка и публикация расширения

Проверьте ваше расширение

После установки убедитесь, что задача работает правильно:

  1. Создание или изменение конвейера.
  2. Добавьте настраиваемую задачу:
    • Выберите Добавить задачу в редакторе конвейера
    • Поиск настраиваемой задачи по имени
    • Добавьте его в ваш поток
  3. Настройка параметров задачи:
    • Установка необходимых входных данных
    • Настройка необязательных параметров
  4. Запуск конвейера для тестирования функциональных возможностей
  5. Мониторинг выполнения:
    • Проверка журналов задач для правильного выполнения
    • Проверка ожидаемых выходных данных
    • Убедитесь, что ошибки или предупреждения отсутствуют

Автоматизация публикации с помощью CI/CD

Чтобы эффективно поддерживать настраиваемую задачу, создайте автоматизированные конвейеры сборки и выпуска, обрабатывающие тестирование, упаковку и публикацию.

Предварительные требования CI/CD

  • Задачи расширения Azure DevOps. Установка расширения бесплатно
  • Группа переменных: создайте группу переменных библиотеки конвейера с этими переменными:
    • publisherId: ваш идентификатор издателя маркетплейса
    • extensionId: идентификатор расширения из vss-extension.json
    • extensionName: имя расширения из vss-extension.json
    • artifactName: имя артефакта VSIX
  • Подключение к службе: Создайте соединение с сервисом Marketplace с правами доступа к конвейеру.

Пример конвейера CI/CD

Создайте конвейер YAML с комплексными этапами тестирования, упаковки и публикации:

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'

Настройка package.json для тестирования

Добавьте тестовые скрипты в 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"
  }
}

Этапы конвейера

Тестирование и проверка

  • Назначение. Обеспечение качества и функциональности кода
  • Действия. Установка зависимостей, компиляция TypeScript, запуск модульных тестов, публикация результатов
  • Проверка: все тесты должны пройти, чтобы продолжить

Упакуйте расширение

  • Назначение. Создание развертываемого пакета VSIX
  • Действия: запрос текущей версии, добавочная версия, расширение пакета, публикация артефактов
  • Управление версиями: автоматически обрабатывает добавочные версии

Публикация в Marketplace

  • Назначение. Развертывание в Visual Studio Marketplace
  • Условия: запускается только в главной ветке после успешной упаковки
  • Среда: использует среду развертывания для шлюзов утверждения

Рекомендации по CI/CD

  • Защита ветки: публиковать только из веток main/release
  • Шлюзы среды: Используйте среды развертывания для выпуска в производство
  • Управление версиями: автоматизация добавок версий для предотвращения конфликтов
  • Покрытие тестов: обеспечение комплексного покрытия тестов перед упаковкой
  • Безопасность: используйте подключения служб вместо жестко закодированных учетных данных
  • Мониторинг: Настройте оповещения для неудачных развертываний

Для классических сборочных конвейеров выполните следующие действия, чтобы настроить создание пакетов расширений и их публикацию:

  1. Добавьте задачу для компиляции Bash TypeScript в JavaScript.

  2. Чтобы запросить существующую версию, добавьте задачу расширения запроса с помощью следующих входных данных:

    • Подключение к: Visual Studio Marketplace
    • Visual Studio Marketplace (Сервисное соединение): Сервисное соединение
    • Идентификатор издателя: идентификатор издателя Visual Studio Marketplace
    • Идентификатор расширения: идентификатор расширения в vss-extension.json файле
    • Повышение версии: патч
    • Выходная переменная: Task.Extension.Version
  3. Чтобы упаковать расширения на основе json-манифеста, добавьте задачу Package Extension с помощью следующих входных данных:

    • Папка корневых манифестов: указывает на корневой каталог, содержащий файл манифеста. Например, $(System.DefaultWorkingDirectory) корневой каталог
    • Файл манифеста: vss-extension.json
    • Идентификатор издателя: идентификатор издателя Visual Studio Marketplace
    • Идентификатор расширения: идентификатор расширения в vss-extension.json файле
    • Имя расширения: Название вашего расширения в vss-extension.json файле
    • Версия расширения: $(Task.Extension.Version)
    • Переопределение версии задачи: отмечено (true)
    • Переопределение типа: только замена исправления (1.0.r)
    • Видимость расширения: если расширение по-прежнему находится в разработке, задайте для параметра private значение. Чтобы сделать расширение общедоступным, установите значение в public.
  4. Чтобы скопировать в опубликованные файлы, добавьте задачу копирования файлов с помощью следующих входных данных:

    • Содержимое: все файлы, которые необходимо копировать для публикации в качестве артефакта
    • Целевая папка: папка, в которую копируются файлы
      • Например: $(Build.ArtifactStagingDirectory)
  5. Добавьте Опубликовать артефакты сборки, чтобы разместить артефакты для использования в других заданиях и конвейерах. Используйте следующие входные данные:

    • Путь к публикации: путь к папке, содержащей опубликованные файлы
      • Например: $(Build.ArtifactStagingDirectory)
    • Имя артефакта: имя, заданное артефакту
    • Расположение публикации артефактов: выберите Azure Pipelines для использования артефакта в будущих заданиях

Скачивание и публикация артефактов

  1. Чтобы установить tfx-cli на ваш агент сборки, добавьте используйте Node CLI для Azure DevOps (tfx-cli).

  2. Чтобы скачать артефакты в новое задание, добавьте задачу download build artifacts с помощью следующих входных данных:

    • Скачайте артефакты, созданные: если вы скачиваете артефакт на новом задании из того же конвейера, выберите текущую сборку. Если вы скачиваете на новом конвейере, выберите конкретную сборку
    • Тип скачивания: выберите конкретный артефакт , чтобы скачать все опубликованные файлы.
    • Имя артефакта: имя опубликованного артефакта
    • Каталог назначения: папка, в которой должны быть скачаны файлы
  3. Чтобы получить задачу "Опубликовать расширение" , используйте следующие входные данные:

    • Подключение к: Visual Studio Marketplace
    • Подключение к Visual Studio Marketplace: ServiceConnection
    • Тип входного файла: VSIX-файл
    • VSIX-файл: /Publisher.*.vsix
    • Идентификатор издателя: идентификатор издателя Visual Studio Marketplace
    • Идентификатор расширения: идентификатор расширения в vss-extension.json файле
    • Имя расширения: Название вашего расширения в vss-extension.json файле
    • Видимость расширения: частная или общедоступная

Установка и проверка расширения

После публикации расширения его необходимо установить в организациях Azure DevOps.

Установка в организацию

Установите общее расширение в нескольких шагах:

  1. Перейдите в параметры организации и выберите "Расширения".

  2. Найдите расширение в разделе "Расширения, к которым предоставлен доступ ко мне ":

    • Выберите ссылку расширения
    • Выберите "Получить бесплатно" или "Установить"
  3. Убедитесь, что расширение отображается в списке установленных расширений:

    • Убедитесь, что он доступен в библиотеке задач конвейера

Примечание.

Если вкладка "Расширения" не отображается, убедитесь, что вы находитесь на уровне администрирования организации (https://dev.azure.com/{organization}/_admin) и не на уровне проекта.

Сквозное тестирование

После установки выполните комплексное тестирование:

  1. Создание тестового конвейера:

    • Добавление настраиваемой задачи в новый конвейер
    • Настройка всех входных параметров
    • Тестирование с различными сочетаниями входных данных
  2. Проверка функциональности:

    • Запуск конвейера и мониторинг выполнения
    • Проверка выходных данных и журналов задач
    • Проверка обработки ошибок при недопустимых входных данных
  3. Производительность теста:

    • Тестирование с большими входными файлами (если применимо)
    • Мониторинг использования ресурсов
    • Валидация режима работы времени ожидания

Часто задаваемые вопросы

Вопрос. Как обрабатывается отмена задачи?

Ответ. Агент конвейера отправляет SIGINT и SIGTERM передает сигналы процессам задач. Хотя библиотека задач не предоставляет явной обработки отмены, ваша задача может реализовать обработчики сигналов. Дополнительные сведения см. в разделе "Отмена заданий агента".

Вопрос. Как удалить задачу из моей организации?

Ответ. Автоматическое удаление не поддерживается , так как это приведет к разрыву существующих конвейеров. Вместо:

  1. Нерекомендуемая задача: пометить задачу как нерекомендуемую
  2. Управление версиями: обновить версию задачи
  3. Коммуникация: уведомление пользователей о сроках прекращения поддержки

Вопрос. Как обновить задачу до последней версии Node.js?

Ответ. Обновление до последней версии узла для повышения производительности и безопасности. Инструкции по миграции см. в разделе "Обновление задач до узла 20".

Поддержка нескольких версий узлов путем включения нескольких разделов выполнения в task.json:

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

Агенты с Node.js 20 используют предпочтительную версию, а более старые агенты переходят на Node.js 10.

Чтобы обновить задачи, выполните следующие действия.

  • Чтобы убедиться, что код работает должным образом, протестируйте задачи в различных версиях runner node.

  • В разделе выполнения задачи обновите с Node или Node10 на Node16 или Node20.

  • Чтобы поддерживать более старые версии сервера, следует оставить целевой элемент Node/Node10. Более старые версии Azure DevOps Server могут не включать последнюю версию Node.js раннера.

  • Вы можете предоставить общий доступ к точке входа, определенной в целевом объекте, или иметь целевые объекты, оптимизированные для используемой версии узла.

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

Внимание

Если вы не добавите поддержку среды выполнения Node 20 в пользовательские задачи, они завершаются сбоем на агентах, установленных из канала релизов pipelines-agent-*.