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


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

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

Узнайте, как установить расширения в вашу организацию для пользовательских задач, связанных со сборкой или выпуском, в Azure DevOps. Дополнительные сведения см. в статье "Что такое Azure Pipelines"?

Примечание.

В этой статье рассматриваются задачи агента в агентно-ориентированных расширениях. Дополнительные сведения о задачах сервера и расширениях на основе сервера см. в документации по GitHub по задачам сервера.

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

Программное обеспечение или средство Информация
Организация Azure DevOps Создайте организации.
Текстовый редактор Для многих процедур мы используем Visual Studio Code, который обеспечивает поддержку intellisense и отладки. Скачайте последнюю версию.
Node.js Скачайте последнюю версию.
npmjs.com 4.0.2 или более поздней версии Компилятор TypeScript. Скачайте последнюю версию.
tfx-cli Упаковайте расширение с помощью кроссплатформенного интерфейса командной строки для Azure DevOps. Используя npm, компонент Node.js, выполните npm i -g tfx-cli.
Пакет SDK для расширения Azure DevOps Установите пакет azure-devops-extension-sdk.
home Каталог для проекта Каталог home расширения задачи сборки или релиза должен быть похож на следующий пример после выполнения действий, описанных в этой статье.
|--- README.md    
|--- images                        
    |--- extension-icon.png  
|--- buildandreleasetask            // where your task scripts are placed
|--- vss-extension.json             // extension's manifest

Внимание

Компьютер разработки должен запускать последнюю версию Node, чтобы убедиться, что написанный код совместим с производственной средой на агенте и последней стабильной не-предварительной версией azure-pipelines-task-lib. Обновите файл task.json следующим образом:

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

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

Выполните каждую часть этой процедуры в папке buildandreleasetask .

Примечание.

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

Создание шаблонов задач

  1. Создайте структуру папок для задачи и установите необходимые библиотеки и зависимости.

  2. Откройте командное окно PowerShell, перейдите в buildandreleasetask папку и выполните следующую команду.

    npm init --yes
    

    npm init создает файл package.json. Мы добавили --yes параметр для принятия всех параметров по умолчанию npm init .

    Совет

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

  3. Добавьте azure-pipelines-task-lib в библиотеку.

    npm install azure-pipelines-task-lib --save
    
  4. Убедитесь, что для внешних зависимостей установлена типизация TypeScript.

    npm install @types/node --save-dev
    npm install @types/q --save-dev
    
  5. .gitignore Создайте файл и добавьте в него node_modules. Процесс сборки должен выполнять npm install и typings install, чтобы node_modules создавались каждый раз и не требовали добавления в систему управления версиями.

    echo node_modules > .gitignore
    
  6. Установите Mocha как зависимость для разработки.

    npm install mocha --save-dev -g
    npm install sync-request --save-dev
    npm install @types/mocha --save-dev
    
  7. Выберите TypeScript версии 2.3.4 или 4.6.3.

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

    Примечание.

    Убедитесь, что TypeScript установлен глобально с помощью npm в вашей среде разработки так, чтобы команда tsc была доступна. Если пропустить этот шаг, версия TypeScript 2.3.4 используется по умолчанию, и вам всё равно нужно глобально установить пакет, чтобы команда tsc была доступна.

  8. Создание tsconfig.json параметров компилятора. Этот файл гарантирует, что файлы TypeScript компилируются в файлы JavaScript.

    tsc --init --target es2022
    

Создать задачу

Теперь, когда формирование шаблонов завершено, мы можем создать настраиваемую задачу.

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

  2. Скопируйте следующий код и замените {{placeholders}} информацией о вашей задаче. Наиболее важным является заполнитель taskguid, и он должен быть уникальным.

    {
     "$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. 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();
    
  4. Чтобы скомпилировать файл index.js из index.ts, введите tsc из папки buildandreleasetask.

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

См. следующие описания некоторых компонентов task.json файла.

Имущество Описание
id Уникальный идентификатор GUID для вашей задачи.
name Имя без пробелов.
friendlyName Описательное имя (разрешён пробел).
description Подробное описание того, что делает ваша задача.
author Короткая строка, описывающая сущность, разрабатывающую задачу сборки или выпуска, например "Корпорация Майкрософт".
instanceNameFormat Как задача отображается в списке шагов сборки и выпуска. Значения переменных можно использовать с помощью $(variablename).
groups Описывает логическую группирование свойств задач в пользовательском интерфейсе.
inputs Входные данные, которые используются при запуске вашей задачи по сборке или выпуску. Эта задача ожидает ввод с именем samplestring.
execution Для этой задачи существует несколько вариантов выполнения, включая скрипты, такие как Node, PowerShell, PowerShell3или Process.
restrictions Ограничения применяются к командам GitHub Codespaces, которые задачи могут вызывать, и переменным, которые задачи могут устанавливать. Рекомендуется указать режим ограничения для новых задач.

Примечание.

Создайте id с помощью следующей команды в PowerShell:

(New-Guid).Guid

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

Выполнение задачи

Запустите задачу из PowerShell с помощью node index.js.

В следующем примере задача завершается сбоем, так как входные данные не были предоставлены (samplestring это обязательные входные данные).

 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

В качестве исправления можно задать входные samplestring данные и снова запустить задачу.

$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

На этот раз задача завершилась успешно, так как samplestring был предоставлен и корректно вывел сообщение "Hello Human!".

Совет

Сведения о различных средствах выполнения задач и о том, как включить последнюю версию Node.js в task.json, см. в руководстве по обновлению средств выполнения Node.js для авторов задач Azure Pipelines.

2. Модульное тестирование скриптов задач

Выполните модульные тесты, чтобы быстро протестировать скрипт задачи, а не внешние средства, которые он вызывает. Проверьте все элементы возможных успешного и неуспешного исхода.

  1. Установите средства тестирования. В этой процедуре мы используем Mocha в качестве тестового драйвера.

    npm install mocha --save-dev -g
    npm install sync-request --save-dev
    npm install @types/mocha --save-dev
    
  2. Создайте папку 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() {
    
        });
    
        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
        });    
    });
    

    Совет

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

  3. Создайте файл в тестовом 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);
    
    tmr.setInput('samplestring', 'human');
    
    tmr.run();
    

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

  4. Чтобы запустить эмулятор выполнения задачи, добавьте следующий пример успешно пройденного теста в файл _suite.ts.

         it('should succeed with simple inputs', function(done: Mocha.Done) {
         this.timeout(1000);
    
         let tp: string = path.join(__dirname, 'success.js');
         let tr: ttm.MockTestRunner = new ttm.MockTestRunner(tp);
    
         // tr.run(); //current, old function.
         tr.runAsync().then(() => {
             console.log(tr.succeeded);
             assert.equal(tr.succeeded, true, 'should have succeeded');
             assert.equal(tr.warningIssues.length, 0, "should have no warnings");
             assert.equal(tr.errorIssues.length, 0, "should have no errors");
             console.log(tr.stdout);
             assert.equal(tr.stdout.indexOf('Hello human') >= 0, true, "should display Hello human");
             done();
         }).catch((error) => {
             done(error); // Ensure the test case fails if there's an error
         });
     });
    
  5. Создайте файл 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);
    
    tmr.setInput('samplestring', 'bad');
    
    tmr.run();
    

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

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

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

    tsc
    mocha tests/_suite.js
    

    Оба теста должны пройти. Если вы хотите выполнить тесты с более подробными выходными данными (то, что вы увидите в консоли сборки), задайте переменную среды: TASK_TEST_TRACE=1

    $env:TASK_TEST_TRACE=1
    

3. Создание файла манифеста расширения

Манифест расширения содержит все сведения о расширении. Он содержит ссылки на файлы, включая папки задач и папки изображений. Убедитесь, что вы создали папку изображений с extension-icon.png. В следующем примере представлен манифест расширения, содержащий задачу сборки или выпуска.

Скопируйте следующий .json код и сохраните его в качестве vss-extension.json файла в каталоге home .

Не создавайте этот файл в папке 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"
            }
        }
    ]
}

Примечание.

Измените издателя на название вашего издательства. Дополнительные сведения см. в статье "Создание издателя".

Участие в проекте

Свойство Описание
id Идентификатор вклада. Должен быть уникальным в пределах расширения. Непременно не должно совпадать с именем задачи сборки или выпуска. Обычно имя задачи сборки или релиза находится в идентификаторе компонента.
type Тип вклада. Должен быть ms.vss-distributed-task.task.
targets Взносы ,предназначенные для этого вклада. Должно быть ms.vss-distributed-task.tasks.
properties.name Имя задачи. Это имя должно соответствовать имени папки соответствующей автономной задачи сборки или конвейера выпуска.

Файлы

Собственность Описание
path Путь к файлу или папке относительно каталога home.

Дополнительные сведения о файле манифеста расширения, например его свойствах и возможностях, см. в справочнике по манифесту расширения.

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

Упаковайте все файлы вместе, чтобы получить расширение в Visual Studio Marketplace. Все расширения упаковываются в виде VSIX 2.0-совместимых vsix-файлов. Корпорация Майкрософт предоставляет кроссплатформенный интерфейс командной строки (CLI) для упаковки расширения.

После получения tfx-cli перейдите в корневой каталог расширения и выполните следующую команду:

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

Примечание.

При каждом обновлении необходимо увеличить расширение или версию интеграции. При обновлении существующего расширения обновите версию в манифесте или передайте параметр командной строки --rev-version. Это увеличивает номер версии исправления расширения и сохраняет новую версию в манифесте. Для обновления необходимо обновить версию задачи и версию расширения. tfx extension create --manifest-globs vss-extension.json --rev-version обновляет только версию расширения, а не версию задачи. Дополнительные сведения см. в разделе "Задача сборки" в GitHub.

После того как упакованое расширение находится в VSIX-файле, вы готовы опубликовать расширение в Marketplace.

5. Опубликуйте расширение

Чтобы опубликовать расширение, сначала создайте издателя, а затем отправьте расширение и, наконец , поделитесь им.

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

Все расширения, включая расширения от Корпорации Майкрософт, определяются как предоставляемые издателем. Если вы еще не являетесь членом существующего издателя, создайте его.

  1. Войдите на Visual Studio Marketplace Publishing Portal.
  2. Если вы еще не являетесь членом существующего издателя, вам будет предложено создать издателя. Если вам не будет предложено создать издателя, прокрутите вниз до нижней части страницы и выберите "Опубликовать расширения" в разделе "Связанные сайты".
    • Укажите идентификатор издателя, например: mycompany-myteam
      • Этот идентификатор используется в качестве значения атрибута publisher в файле манифеста расширений.
    • Укажите отображаемое имя издателя, например: My Team
  3. Просмотрите соглашение издателя Marketplace и нажмите кнопку "Создать".

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

Загрузите ваше расширение

Найдите кнопку "Отправить новое расширение", перейдите в упакованный VSIX-файл и нажмите кнопку "Отправить".

  1. Вы также можете загрузить ваше расширение с помощью интерфейса командной строки (CLI), используя команду tfx extension publish вместо tfx extension create, чтобы упаковать и опубликовать расширение единым шагом. Вы можете при желании использовать --share-with для совместного использования расширения с одной или несколькими учетными записями после его публикации.

    tfx extension publish --manifest-globs your-manifest.json --share-with yourOrganization
    
  2. Создайте личный маркер доступа (PAT).

    • Выберите область "Marketplace (публикация)". Эта область действия ограничивает маркер только возможностью публикации расширений в Маркетплейс.

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

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

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

Внимание

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

Теперь, когда расширение предоставлено в Marketplace, любой пользователь, желающий использовать его, должен установить его.

6. Создание конвейера сборки и выпуска для публикации расширения в Marketplace

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

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

Программное обеспечение или средство

Информация

Проект Azure DevOps

Расширение задач для Azure DevOps

Установите бесплатно задачи расширения Azure DevOps в организации.

Группа переменных библиотеки конвейера

Создайте группу переменных библиотеки конвейера для хранения переменных, используемых конвейером. Дополнительные сведения см. в разделе "Добавление и использование групп переменных". Группы переменных можно сделать на вкладке библиотеки Azure DevOps или с помощью интерфейса командной строки. Используйте переменные в этой группе в конвейере. Кроме того, объявите следующие переменные в группе переменных:

  • publisherId: идентификатор издателя Marketplace
  • extensionId: идентификатор расширения, объявленный в файле vss-extension.json
  • extensionName: имя расширения, объявленное в файле vss-extension.json
  • artifactName: имя создаваемого артефакта для VSIX-файла

Подключение службы

Создайте новое подключение службы Marketplace и предоставьте разрешения доступа для всех конвейеров.

Конвейер YAML

Используйте следующий пример, чтобы создать новый конвейер с помощью YAML. Дополнительные сведения см. в статье "Создание первого конвейера и схемы 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'

Дополнительные сведения см. в разделе "Указание событий, которые активируют конвейеры".

Примечание.

Каждое задание использует новый агент пользователя и требует установки зависимостей.

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

В следующем разделе показано, как работают этапы конвейера.

Этап 1. Запуск и публикация модульных тестов

На этом этапе выполняются модульные тесты и публикуются результаты теста в Azure DevOps.

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

"scripts": {
    "testScript": "mocha ./TestFile --reporter xunit --reporter-option output=ResultsFile.xml"
},
  1. Используйте Node CLI для Azure DevOps (tfx-cli) для установки tfx-cli на агент сборки.

  2. Добавьте задачу npm с помощью команды "install" и нацельте папку с помощью файла package.json.

  3. Добавьте задачу "Bash", чтобы скомпилировать TypeScript в JavaScript.

  4. Добавьте задачу "npm" с командой "custom", укажите папку, содержащую модульные тесты, и используйте testScript в качестве команды. Используйте следующие входные данные:

    • Команда: настраиваемая
    • Рабочая папка, содержащая package.json: /TestDirectory
    • Команды и аргументы: testScript
  5. Добавьте задачу "Опубликовать результаты теста". Если вы используете репортер Mocha XUnit, убедитесь, что формат результата — JUnit, а не XUnit. Установите корневой каталог в качестве папки поиска. Используйте следующие входные данные:

    • Формат результатов теста: JUnit
    • Файлы результатов теста: **/ResultsFile.xml
    • Папка поиска: $(System.DefaultWorkingDirectory)

    После публикации результатов теста выходные данные на вкладке тестов должны выглядеть следующим образом.

    Снимок экрана: пример результата теста.

Этап 2. Упаковка расширения и публикация артефактов сборки

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

  2. Добавьте задачу npm с помощью команды "install" и нацельте папку с помощью файла package.json.

  3. Добавьте задачу "Bash", чтобы скомпилировать TypeScript в JavaScript.

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

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

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

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

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

Этап 3. Скачивание артефактов сборки и публикация расширения

  1. Чтобы установить tfx-cli на ваш агент сборки, добавьте "Use Node CLI for Azure DevOps (tfx-cli)".

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

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

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

Необязательно. Установка и проверка расширения

Установите расширение, к которому вы предоставили общий доступ, всего за несколько шагов:

  1. На панели управления вашей организации (https://dev.azure.com/{organization}/_admin) перейдите на страницу администрирования коллекции проектов.
  2. На вкладке "Расширения" найдите расширение в группе "Расширения, к которым предоставлен доступ ко мне", и выберите ссылку расширения.
  3. Установите расширение.

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

Если вкладка "Расширения" не отображается, расширения не включены для вашей организации. Вы можете получить ранний доступ к функции расширений, присоединившись к программе партнеров Visual Studio.

Чтобы упаковать и опубликовать расширения Azure DevOps в Visual Studio Marketplace, можно скачать задачи расширения Azure DevOps.

Вопросы и ответы

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

Вопрос. Как ограничить использование команд Azure Pipelines для задачи?

Вы можете ограничить использование и переменные команд Azure Pipelines, которые задаются задачей. Это действие может быть полезно, чтобы предотвратить неограниченный доступ к переменным или командам vso для пользовательских скриптов, которые выполняются задачей. Рекомендуется настроить его для новых задач. Чтобы применить, может потребоваться добавить следующую инструкцию в файл task.json:

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

Если для restricted задано значение mode, вы можете выполнить только следующие команды задачей:

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

Ограничения settableVariables позволяют передавать список разрешенных переменных, которые задаются командами setvariable или prependpath. Он также позволяет использовать основные регулярные выражения. Например, если ваш список разрешений: ['abc', 'test*'], установка abc, test или test1 как переменных с любым значением или добавление их в начало пути будет выполнено успешно, но при попытке задать прокси-сервер для переменной вы получите предупреждение. Пустой список означает, что переменные не изменяются задачей.

Если опущен любой из ключей settableVariables или commands, соответствующее ограничение не применяется.

Функция ограничения доступна с версии агента 2.182.1 .

Вопрос: Как задача обрабатывает сигнал о прекращении работы?

Агент конвейера отправляет сигналы SIGINT и SIGTERM соответствующему дочернему процессу. В библиотеке задач нет явных средств для обработки. Дополнительные сведения см. в разделе об отмене заданий агента.

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

Ответ. Мы не поддерживаем автоматическое удаление задач. Автоматическое удаление не является безопасным и нарушает существующие конвейеры, которые уже используют такие задачи. Но вы можете пометить задачи как устаревшие. Для этого обновите версию задачи и пометьте задачу как устаревшую.

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

Ответ. Рекомендуется обновить до последней версии Node.js. Примеры см. в разделе "Обновление задач до узла 20".

Агенты, размещённые на платформе Microsoft, и различные версии сервера Azure DevOps имеют разные жизненные циклы, что приводит к установке различных версий Node runner в зависимости от того, где выполняется задача. Чтобы обеспечить совместимость между агентами с различными версиями запуска узла, файл task.json может включать несколько разделов выполнения. В следующем примере агенты Azure Pipeline с средством выполнения Node 20 используют его по умолчанию, а агент без него возвращается в реализацию Node 10.

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

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

  • Чтобы убедиться, что код работает должным образом, протестируйте задачи в различных версиях 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-*.