다음을 통해 공유


사용자 지정 파이프라인 작업 확장 추가

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

Azure DevOps에서 사용자 지정 빌드 또는 릴리스 작업을 위해 조직에 확장을 설치하는 방법을 알아봅니다. 자세한 내용은 Azure Pipelines란?을 참조하세요.

참고 항목

이 문서에서는 에이전트 기반 확장의 에이전트 작업을 다룹니다. 서버 작업 및 서버 기반 확장에 대한 자세한 내용은 서버 작업 GitHub 설명서를 참조 하세요.

필수 조건

Azure DevOps에 대한 확장을 만들려면 다음 소프트웨어 및 도구가 필요합니다.

소프트웨어/도구 정보
Azure DevOps 조직 조직을 만듭니다.
텍스트 편집기 많은 절차에서 Intellisense 및 디버깅 지원을 제공하는 Visual Studio Code를 사용합니다. 최신 버전 다운로드 .
Node.js 최신 버전 다운로드 .
npmjs.com 4.0.2 이상 TypeScript 컴파일러입니다. 최신 버전 다운로드 .
tfx-cli Azure DevOps용 플랫폼 간 CLI를 사용하여 확장을 패키지합니다. 를 사용하여 npmNode.js 구성 요소를 실행 npm i -g tfx-cli합니다.
Azure DevOps 확장 SDK 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

Important

개발 컴퓨터는 최신 버전의 Node실행하여 작성 코드가 에이전트의 프로덕션 환경 및 최신 비 미리 보기 버전의 azure-pipelines-task-lib프로덕션 환경과 호환되도록 해야 합니다. 다음 명령에 따라 task.json 파일을 업데이트합니다.

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

1. 사용자 지정 작업 만들기

폴더 내에서 이 절차의 모든 부분을 수행합니다 buildandreleasetask .

참고 항목

이 연습 예제에서는 PowerShell에서 Windows를 사용합니다. 모든 플랫폼에 대해 제네릭으로 만들었지만 환경 변수를 가져오기 위한 구문은 다릅니다. Mac 또는 Linux를 사용하는 경우 인스턴스를 .로 대체합니다 $env:<var>=<val> export <var>=<val>.

작업 스캐폴딩 만들기

  1. 작업에 대한 폴더 구조를 만들고 필요한 라이브러리 및 종속성을 설치합니다.

  2. PowerShell 명령 창을 열고 폴더로 buildandreleasetask 이동하여 다음 명령을 실행합니다.

    npm init --yes
    

    npm init 는 파일을 만듭니다 package.json . 모든 기본 npm init 옵션을 허용하는 매개 변수를 추가 --yes 했습니다.

    에이전트는 작업 폴더에 노드 모듈을 포함해야 하므로 필요한 모듈을 자동으로 설치하지 않습니다. 이를 완화하려면 다음을 복사합니다 node_modules buildandreleasetask. 작업이 커지면 VSIX 파일의 크기 제한(50MB)을 쉽게 초과할 수 있습니다. 노드 폴더를 복사하기 전에 실행 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. 폴더에서 "tsc"를 buildandreleasetask 입력하여 파일을 index.ts컴파일 index.js 합니다.

task.json 구성 요소

파일의 일부 구성 요소에 대한 다음 설명을 참조하세요 task.json .

속성 설명
id 작업에 대한 고유한 GUID입니다.
name 공백이 없는 이름입니다.
friendlyName 설명이 포함된 이름(허용된 공백)입니다.
description 작업이 수행하는 작업에 대한 자세한 설명입니다.
author 빌드 또는 릴리스 작업을 개발하는 엔터티를 설명하는 짧은 문자열입니다(예: "Microsoft Corporation").
instanceNameFormat 빌드/릴리스 단계 목록 내에 태스크가 표시되는 방식 $(variablename)를 사용하여 변수 값을 사용할 수 있습니다.
groups UI에서 작업 속성의 논리적 그룹화에 대해 설명합니다.
inputs 빌드 또는 릴리스 작업이 실행될 때 사용할 입력입니다. 이 작업에는 이름 샘플링이 포함된 입력이 예상됩니다.
execution 스크립트를 포함하여 이 작업에 대한 실행 옵션입니다.
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!" 출력이 올바르게 출력되었습니다.

다양한 작업 실행기와 task.json 최신 노드 버전을 포함하는 방법에 대한 자세한 내용은 Azure Pipelines 작업 작성자의 Node Runner 업데이트 지침을 참조하세요.

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 폴더에 있어야 합니다. 동기화 요청 오류가 발생하면 명령을 npm i --save-dev sync-request사용하여 buildandreleasetask 폴더에 동기화 요청을 추가하여 해결할 수 있습니다.

  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('it should fail if tool returns 1', function(done: Mocha.Done) {
        this.timeout(1000);
    
        let tp = path.join(__dirname, 'failure.js');
        let tr: ttm.MockTestRunner = new ttm.MockTestRunner(tp);
    
        tr.run();
        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 코드를 복사하여 디렉터리에 파일 homevss-extension.json 저장합니다.

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 기여의 식별자입니다. 확장 내에서 고유해야 합니다. 빌드 또는 릴리스 작업의 이름과 일치시킬 필요가 없습니다. 일반적으로 빌드 또는 릴리스 작업 이름은 기여의 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 파일로 패키지됩니다. Microsoft는 확장을 패키지하는 플랫폼 간 CLI(명령줄 인터페이스)를 제공합니다.

tfx-cli있으면 확장의 홈 디렉터리로 이동하여 다음 명령을 실행합니다.

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

참고 항목

확장 또는 통합의 버전은 모든 업데이트에서 증가해야 합니다. 기존 확장을 업데이트하는 경우 매니페스트에서 버전을 업데이트하거나 명령줄 스위치를 --rev-version 전달합니다. 이렇게 하면 확장의 패치 버전 번호가 증가하고 새 버전이 매니페스트에 저장됩니다. 업데이트가 수행되려면 작업 버전과 확장 버전을 모두 rev해야 합니다. tfx extension create --manifest-globs vss-extension.json --rev-version 는 작업 버전이 아닌 확장 버전만 업데이트합니다. 자세한 내용은 GitHub의 빌드 작업을 참조하세요.

패키지된 확장 프로그램이 .vsix 파일에 있으면 Marketplace에 확장을 게시할 준비가 된 것입니다.

5. 확장 게시

확장을 게시하려면 먼저 게시자를 만든 다음 확장을 업로드하고 마지막으로 공유합니다.

게시자 만들기

Microsoft의 확장을 포함한 모든 확장은 게시자가 제공하는 것으로 식별됩니다. 기존 게시자의 멤버가 아닌 경우 새로 만듭니다.

  1. Visual Studio Marketplace 게시 포털에 로그인합니다.
  2. 기존 게시자의 구성원이 아닌 경우 게시자를 만들라는 메시지가 표시됩니다. 게시자를 만들라는 메시지가 표시되지 않으면 페이지 아래쪽으로 스크롤하여 관련 사이트에서 확장 게시를 선택합니다.
    • 게시자에 대한 식별자를 지정합니다. 예를 들면 다음과 mycompany-myteam같습니다.
      • 이 식별자는 확장명 매니페스트 파일의 publisher 특성 값으로 사용됩니다.
    • 게시자의 표시 이름을 지정합니다. 예를 들면 다음과 My Team같습니다.
  3. Marketplace 게시자 계약을 검토하고 만들기를 선택합니다.

게시자가 정의됩니다. 이후 릴리스에서는 게시자의 확장을 보고 관리할 수 있는 권한을 부여할 수 있습니다. 사용자 간에 자격 증명 집합을 공유할 필요 없이 일반 게시자에서 확장을 게시하는 것이 더 쉽고 안전합니다.

확장 업로드

새 확장 업로드 단추를 찾아 패키지된 .vsix 파일로 이동한 다음 업로드를 선택합니다.

  1. 한 단계에서 확장을 패키지하고 게시하는 대신 tfx extension create 명령을 사용하여 tfx extension publish CLI(명령줄 인터페이스)를 통해 확장을 업로드할 수도 있습니다. 필요에 따라 확장을 게시한 후 하나 이상의 계정과 공유하는 데 사용할 --share-with 수 있습니다.

    tfx extension publish --manifest-globs your-manifest.json --share-with yourOrganization
    
  2. PAT(개인용 액세스 토큰)를 만듭니다.

    • "Marketplace(게시)" 범위를 선택합니다. 이 범위는 토큰을 Marketplace에 확장만 게시할 수 있도록 제한합니다.

확장 공유

이제 확장을 업로드했으므로 Marketplace에 있지만 아무도 볼 수 없습니다. 설치하고 테스트할 수 있도록 조직과 공유합니다.

확장을 마우스 오른쪽 으로 선택하고 공유를 선택하고 조직 정보를 입력합니다. 확장에 액세스하려는 다른 계정과 공유할 수도 있습니다.

Important

퍼블리셔는 공개적으로 확장을 공유하도록 확인해야 합니다. 자세한 내용은 패키지/게시/설치를 참조 하세요.

이제 Marketplace에서 확장이 공유되었으므로 확장을 사용하려는 모든 사용자가 확장을 설치해야 합니다.

6. 빌드 및 릴리스 파이프라인을 만들어 Marketplace에 확장 게시

Marketplace에서 사용자 지정 작업을 유지 관리하는 데 도움이 되는 빌드 및 릴리스 파이프라인을 Azure DevOps에 만듭니다.

필수 조건

소프트웨어/도구

정보

Azure DevOps 프로젝트

Azure DevOps 확장 작업 확장

조직에 Azure DevOps 확장 작업을 무료로 설치합니다.

파이프라인 라이브러리 변수 그룹

파이프라인에서 사용하는 변수를 저장할 파이프라인 라이브러리 변수 그룹을 만듭니다. 자세한 내용은 변수 그룹 추가 및 사용을 참조 하세요. Azure DevOps 라이브러리 탭 또는 CLI를 통해 변수 그룹을 만들 수 있습니다. 파이프라인에서 이 그룹 내의 변수 를 사용합니다. 또한 변수 그룹에서 다음 변수를 선언합니다.

  • publisherId: 마켓플레이스 게시자의 ID
  • extensionId: vss-extension.json 파일에 선언된 확장의 ID입니다.
  • 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. "Azure DevOps(tfx-cli)에 노드 CLI 사용"을 추가하여 빌드 에이전트에 tfx-cli를 설치합니다.

  2. "install" 명령을 사용하여 "npm" 작업을 추가하고 package.json 파일을 사용하여 폴더를 대상으로 지정합니다.

  3. "Bash" 작업을 추가하여 TypeScript를 JavaScript로 컴파일합니다.

  4. "사용자 지정" 명령을 사용하여 "npm" 작업을 추가하고 단위 테스트가 포함된 폴더를 대상으로 지정하고 입력 testScript 을 명령으로 입력합니다. 다음 입력을 사용합니다.

    • 명령: 사용자 지정
    • package.json 포함하는 작업 폴더: /TestsDirectory
    • 명령 및 인수: testScript
  5. "테스트 결과 게시" 작업을 추가합니다. Mocha XUnit 기자를 사용하는 경우 결과 형식이 "XUnit"이 아닌 "JUnit"인지 확인합니다. 검색 폴더를 루트 디렉터리로 설정합니다. 다음 입력을 사용합니다.

    • 테스트 결과 형식: JUnit
    • 테스트 결과 파일: **/ResultsFile.xml
    • 검색 폴더: $(System.DefaultWorkingDirectory)

    테스트 결과가 게시되면 테스트 탭 아래의 출력은 다음 예제와 같이 표시됩니다.

    테스트 결과 예제의 스크린샷.

2단계: 확장 패키지 및 빌드 아티팩트 게시

  1. "Azure DevOps(tfx-cli)에 노드 CLI 사용"을 추가하여 빌드 에이전트에 tfx-cli를 설치합니다.

  2. "install" 명령을 사용하여 "npm" 작업을 추가하고 package.json 파일을 사용하여 폴더를 대상으로 지정합니다.

  3. "Bash" 작업을 추가하여 TypeScript를 JavaScript로 컴파일합니다.

  4. "확장 버전 쿼리" 작업을 추가하여 기존 확장 버전을 쿼리합니다. 다음 입력을 사용합니다.

    • 연결: Visual Studio Marketplace
    • Visual Studio Marketplace(서비스 연결): 서비스 연결
    • 게시자 ID: Visual Studio Marketplace 게시자의 ID
    • 확장 ID: vss-extension.json 파일의 확장 ID
    • 버전 늘리기: 패치
    • 출력 변수: Task.Extension.Version
  5. 매니페스트 Json을 기반으로 확장을 패키지하는 "패키지 확장" 작업을 추가합니다. 다음 입력을 사용합니다.

    • 루트 매니페스트 폴더: 매니페스트 파일이 포함된 루트 디렉터리를 가리킵니다. 예를 들어 $(System.DefaultWorkingDirectory)는 루트 디렉터리입니다.
    • 매니페스트 파일: vss-extension.json
    • 게시자 ID: Visual Studio Marketplace 게시자의 ID
    • 확장 ID: vss-extension.json 파일의 확장 ID
    • 확장명: vss-extension.json 파일의 확장명
    • 확장 버전: $(Task.Extension.Version)
    • 작업 버전 재정의: 선택됨(true)
    • 재정의 유형: 패치만 바꾸기(1.0.r)
    • 확장 표시 유형: 확장이 아직 개발 중인 경우 값을 프라이빗으로 설정합니다. 확장을 공용으로 해제하려면 값을 public으로 설정합니다.
  6. "파일 복사" 작업을 추가하여 게시된 파일을 복사합니다. 다음 입력을 사용합니다.

    • 내용: 아티팩트로 게시하기 위해 복사할 모든 파일
    • 대상 폴더: 파일이 복사되는 폴더
      • 예: $(Build.ArtifactStagingDirectory)
  7. 다른 작업 또는 파이프라인에서 사용할 아티팩트 게시를 위해 "빌드 아티팩트 게시"를 추가합니다. 다음 입력을 사용합니다.

    • 게시할 경로: 게시 중인 파일이 포함된 폴더의 경로입니다.
      • 예: $(Build.ArtifactStagingDirectory)
    • 아티팩트 이름: 아티팩트에 지정된 이름
    • 아티팩트 게시 위치: "Azure Pipelines"를 선택하여 향후 작업에서 아티팩트 사용

3단계: 빌드 아티팩트 다운로드 및 확장 게시

  1. "Azure DevOps(tfx-cli)에 노드 CLI 사용"을 추가하여 빌드 에이전트에 tfx-cli를 설치합니다.

  2. "빌드 아티팩트 다운로드" 작업을 추가하여 아티팩트를 새 작업에 다운로드합니다. 다음 입력을 사용합니다.

    • 생성된 아티팩트 다운로드: 동일한 파이프라인에서 새 작업에서 아티팩트를 다운로드하는 경우 "현재 빌드"를 선택합니다. 새 파이프라인에서 다운로드하는 경우 "특정 빌드"를 선택합니다.
    • 다운로드 유형: "특정 아티팩트"를 선택하여 게시된 모든 파일을 다운로드합니다.
    • 아티팩트 이름: 게시된 아티팩트의 이름입니다.
    • 대상 디렉터리: 파일을 다운로드해야 하는 폴더입니다.
  3. 필요한 마지막 작업은 "확장 게시" 작업입니다. 다음 입력을 사용합니다.

    • 연결: Visual Studio Marketplace
    • Visual Studio Marketplace 연결: ServiceConnection
    • 입력 파일 형식: VSIX 파일
    • VSIX 파일: /Publisher.*.vsix
    • 게시자 ID: Visual Studio Marketplace 게시자의 ID
    • 확장 ID: vss-extension.json 파일의 확장 ID
    • 확장명: vss-extension.json 파일의 확장명
    • 확장 표시 유형: 프라이빗 또는 퍼블릭

선택 사항: 확장 설치 및 테스트

몇 단계만 수행하여 사용자와 공유되는 확장을 설치합니다.

  1. 조직 제어판(https://dev.azure.com/{organization}/_admin)에서 프로젝트 컬렉션 관리 페이지로 이동합니다.
  2. 확장 탭의 "나와 공유한 확장" 그룹에서 확장을 찾고 확장 링크를 선택합니다.
  3. 익스텐션을 설치합니다.

확장 탭을 볼 수 없는 경우 프로젝트의 관리 페이지가 아닌 제어판(프로젝트 컬렉션 수준의 https://dev.azure.com/{organization}/_admin관리 페이지)에 있는지 확인합니다.

확장 탭이 표시되지 않으면 조직에서 확장을 사용할 수 없습니다. Visual Studio 파트너 프로그램에 조인하여 확장 기능에 대한 초기 액세스를 얻을 수 있습니다.

Visual Studio Marketplace에 Azure DevOps 확장을 패키지하고 게시하려면 Azure DevOps 확장 작업을 다운로드할 수 있습니다.

FAQ

Azure DevOps용 확장에서 사용자 지정 빌드 또는 릴리스 작업을 추가하는 방법에 대한 다음 FAQ(질문과 대답)를 참조하세요.

Q: 작업에 대한 Azure Pipelines 명령 사용을 제한하려면 어떻게 해야 하나요?

작업별로 설정되는 Azure Pipelines 명령 사용량 및 변수를 제한할 수 있습니다. 이 작업은 태스크가 실행되는 사용자 지정 스크립트에 대한 변수/vso 명령에 대한 무제한 액세스를 방지하는 데 유용할 수 있습니다. 새 작업에 대해 설정하는 것이 좋습니다. 적용하려면 task.json 파일에 다음 문을 추가해야 할 수 있습니다.

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

값이 지정된 mode 경우 restricted 작업에서 다음 명령만 실행할 수 있습니다.

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

settableVariables 제한을 사용하면 변수의 허용 목록을 전달할 수 있습니다. 이 목록은 명령으로 setvariable prependpath 설정됩니다. 또한 기본 정규식을 허용합니다. 예를 들어 허용 목록이 다음과 ['abc', 'test*']같은 경우, 값이 있는 변수로 설정abctest하거나 test1 경로 앞에 추가하면 성공하지만 변수 프록시를 설정하려고 하면 경고가 표시됩니다. 빈 목록은 태스크에 의해 변수가 변경되지 않음을 의미합니다.

settableVariables 키 또는 commands 키를 생략하면 관련 제한이 적용되지 않습니다.

제한 기능은 2.182.1 에이전트 버전에서 사용할 수 있습니다.

Q: 취소 신호는 태스크에서 어떻게 처리합니까?

A: 파이프라인 에이전트가 SIGINT SIGTERM 관련 자식 프로세스에 보내고 신호를 보냅니다. 작업 라이브러리에서 처리할 명시적 수단은 없습니다. 자세한 내용은 에이전트 작업 취소를 참조하세요.

Q: 프로젝트 컬렉션에서 작업을 제거하려면 어떻게 해야 하나요?

A: 작업의 자동 삭제는 지원되지 않습니다. 자동 삭제는 안전하지 않으며 이러한 작업을 이미 사용하는 기존 파이프라인을 중단합니다. 그러나 작업을 더 이상 사용되지 않는 것으로 표시할 수 있습니다. 이렇게 하려면 작업 버전을 범프하고 작업을 더 이상 사용되지 않는 것으로 표시합니다.

Q: 사용자 지정 작업을 최신 노드로 업그레이드하려면 어떻게 해야 하나요?

A: 최신 노드 버전으로 업그레이드하는 것이 좋습니다. 예제 정보는 작업을 노드 20으로 업그레이드하는 방법을 참조 하세요.

Microsoft Hosted 에이전트 및 다양한 Azure DevOps Server 버전에 수명 주기가 다르기 때문에 작업이 실행되는 위치에 따라 다른 노드 실행기 버전이 설치될 수 있습니다. 노드 실행기 버전 이 다른 에이전트에서 동일한 작업을 실행할 수 있도록 task.json 파일에는 여러 실행 섹션이 포함될 수 있습니다. 다음 예제에서는 노드 20 실행기를 포함하는 Azure Pipeline 에이전트가 기본적으로 이를 선택하고 노드 10 구현으로 대체되지 않는 에이전트를 선택합니다.

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

작업을 업그레이드하려면 다음을 수행합니다.

  • 다양한 노드 실행기 버전에서 태스크를 테스트하여 코드가 예상대로 작동하는지 확인합니다.

  • 작업의 실행 섹션에서 다음으로 또는 그 다음으로 Node Node16 업데이트합니다Node20.Node10

  • 이전 서버 버전을 지원하려면 대상을 Node/Node10 그대로 두어야 합니다. 이전 Azure DevOps Server 버전에는 최신 Node Runner 버전이 포함되지 않을 수 있습니다.

  • 대상에 정의된 진입점을 공유하거나 대상을 노드 버전에 맞게 최적화하도록 선택할 수 있습니다.

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

Important

사용자 지정 작업에서 Node 20 Runner에 대한 지원을 추가하지 않으면 릴리스 피드에서 설치된 에이전트에서 태스크가 pipelines-agent-* 실패합니다.