Azure DevOps 서비스 | Azure DevOps 서버 2022 - Azure DevOps Server 2019
PR(끌어오기 요청) 워크플로를 사용하면 개발자가 피어 및 자동화된 도구에서 코드에 대한 피드백을 받을 수 있습니다. Microsoft 이외의 도구 및 서비스는 PR 상태 API를 사용하여 PR 워크플로에 참여할 수도 있습니다. 이 문서에서는 Azure Functions를 사용하여 Azure DevOps Git 리포지토리에서 PR의 유효성을 검사하는 사용자 지정 분기 정책을 만드는 방법을 안내합니다. Azure Functions는 워크로드가 증가함에 따라 서버를 프로비전하고 유지 관리할 필요가 없습니다. 높은 안정성과 보안을 갖춘 완전 관리형 컴퓨팅 플랫폼을 제공합니다.
PR 상태에 대한 더 많은 정보는 끌어오기 요청 워크플로 사용자 지정 및 확장 및 끌어오기 요청 상태을 참조하세요.
필수 조건
카테고리 | 요구 사항 |
---|---|
조직 | Azure DevOps의 조직에는 Git 리포지토리가 있습니다. |
Azure 함수 | Azure Function은 Azure DevOps와 통합되어 사용자 지정 분기 정책을 만들고 PR 유효성 검사를 자동화하는 서버리스 이벤트 기반 솔루션을 구현합니다. |
서비스 연결점 | 끌어오기 요청이 변경되면 Azure 함수에 알리도록 PR 이벤트에 대한 서비스 후크를 구성합니다. |
인증 | Microsoft Entra ID 토큰은 PR 상태를 변경할 수 있는 권한을 가지기 위해 코드(상태) 범위가 있어야 합니다. 자세한 내용은 Microsoft Entra 인증을 참조하세요. |
Azure Repos 이벤트를 수신 대기하는 기본 Azure Function 만들기
첫 번째 Azure 함수를 만듭니다. 그런 다음 샘플의 코드를 다음 코드와 같이 수정합니다.
using System;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using Newtonsoft.Json;
public static async Task<HttpResponseMessage> Run(HttpRequestMessage req, TraceWriter log)
{
try
{
log.Info("Service Hook Received.");
// Get request body
dynamic data = await req.Content.ReadAsAsync<object>();
log.Info("Data Received: " + data.ToString());
// Get the pull request object from the service hooks payload
dynamic jObject = JsonConvert.DeserializeObject(data.ToString());
// Get the pull request id
int pullRequestId;
if (!Int32.TryParse(jObject.resource.pullRequestId.ToString(), out pullRequestId))
{
log.Info("Failed to parse the pull request id from the service hooks payload.");
};
// Get the pull request title
string pullRequestTitle = jObject.resource.title;
log.Info("Service Hook Received for PR: " + pullRequestId + " " + pullRequestTitle);
return req.CreateResponse(HttpStatusCode.OK);
}
catch (Exception ex)
{
log.Info(ex.ToString());
return req.CreateResponse(HttpStatusCode.InternalServerError);
}
}
PR 이벤트에 대한 서비스 후크 구성
서비스 후크는 특정 이벤트가 발생할 때 외부 서비스에 경고할 수 있는 Azure DevOps 기능입니다. 이 샘플의 경우 PR 이벤트에 대한 서비스 후크를 설정하면 끌어오기 요청이 변경되면 Azure 함수에 알림이 표시됩니다. 끌어오기 요청이 변경될 때 요청을 받으려면 Azure 함수 URL을 서비스 후크에 제공합니다.
이 샘플에서는 두 개의 서비스 후크를 구성합니다. 첫 번째는 이벤트를 만든 끌어오기 요청에 대한 것이고, 두 번째는 업데이트된 이벤트에 대한 끌어오기 요청입니다.
Azure 함수 보기에서 함수 URL 가져오기 를 클릭하고 URL을 복사하여 Azure Portal에서 함수 URL을 가져옵니다.
Azure DevOps에서 프로젝트로 이동합니다(예:
https://dev.azure.com/<your organization>/<your project name>
탐색 메뉴에서 기어에 마우스를 올려놓고 서비스 후크를 선택합니다.
첫 번째 서비스 후크인 경우 + 구독 만들기를 선택합니다.
다른 서비스 후크를 이미 구성한 경우 녹색 플러스
(+)
를 선택하여 새로운 서비스 후크 구독을 생성합니다.새 서비스 후크 구독 대화 상자의 서비스 목록에서 웹 후크를 선택한 다음, 다음을 선택합니다.
이벤트 트리거 목록에서 에서 생성된 끌어오기 요청을 선택한 다음, 다음을 선택합니다.
작업 페이지에서 URL 상자에 1단계에서 복사한 URL 을 입력합니다. 테스트 선택하여 테스트 이벤트를 서버에 보냅니다.
Azure 함수 로그 창에는 함수가 서비스 후크 이벤트를 수신했음을 나타내는 들어오는
POST
항목이 있고, 이는200 OK
을 반환했음을 보여줍니다.HTTP Requests ------------- POST / 200 OK
테스트 알림 창에서 응답 탭을 선택하여 서버의 응답 세부 정보를 확인합니다. 서버로부터 응답을 확인해야 합니다.
테스트 알림 창을 닫고 마침 선택하여 서비스 후크를 만듭니다.
2-8단계를 다시 진행하지만 이번에는 끌어오기 요청 업데이트 이벤트를 구성합니다.
중요합니다
이전 단계를 두 번 검토하고 끌어오기 요청 생성 및 끌어오기 요청 업데이트 이벤트에 대한 서비스 후크를 각각 만들어야 합니다.
끌어오기 요청을 만들어 Azure 함수가 알림을 받고 있는지 확인합니다.
PR에 상태 게시
이제 서버가 새 PR을 만들 때 서비스 후크 이벤트를 받을 수 있으므로 PR에 상태를 게시할 수 있도록 업데이트하세요. 서비스 훅에서 게시한 JSON 페이로드를 사용하여 PR에 어떤 상태를 설정할지 결정할 수 있습니다.
다음 예제와 마찬가지로 Azure 함수의 코드를 업데이트합니다.
조직 이름, 프로젝트 이름, 리포지토리 이름 및 Microsoft Entra ID 토큰으로 코드를 업데이트해야 합니다. PR 상태를 변경할 수 있는 권한을 갖기 위해 토큰에는 microsoft Entra 인증을 통해 가져올 수 있는 vso.code_status 범위가 필요합니다.
중요합니다
이 샘플 코드는 토큰을 코드에 저장하여 샘플을 간소화합니다. 보안 강화를 위해 관리 ID를 사용하여 Azure Key Vault에 비밀을 저장하고 검색하는 것이 좋습니다.
이 샘플은 PR 제목을 검사하여 사용자가 제목에 WIP를 추가하여 PR이 진행 중인 상태인지 확인합니다. 이 경우 샘플 코드는 PR에 다시 게시된 상태를 변경합니다. Azure 함수의 코드를 PR에 다시 게시된 상태를 업데이트하는 다음 코드로 바꿉니다.
using System;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using Newtonsoft.Json;
private static string organizationName = "[Organization Name]"; // Organization name
private static string projectName = "[Project Name]"; // Project name
private static string repositoryName = "[Repo Name]"; // Repository name
/*
This is here just to simplify the sample, it is recommended to store
secrets in Azure Key Vault and retrieve them using managed identity.
*/
private static string accessToken = "[MICROSOFT_ENTRA_TOKEN]";
public static async Task<HttpResponseMessage> Run(HttpRequestMessage req, TraceWriter log)
{
try
{
log.Info("Service Hook Received.");
// Get request body
dynamic data = await req.Content.ReadAsAsync<object>();
log.Info("Data Received: " + data.ToString());
// Get the pull request object from the service hooks payload
dynamic jObject = JsonConvert.DeserializeObject(data.ToString());
// Get the pull request id
int pullRequestId;
if (!Int32.TryParse(jObject.resource.pullRequestId.ToString(), out pullRequestId))
{
log.Info("Failed to parse the pull request id from the service hooks payload.");
};
// Get the pull request title
string pullRequestTitle = jObject.resource.title;
log.Info("Service Hook Received for PR: " + pullRequestId + " " + pullRequestTitle);
PostStatusOnPullRequest(pullRequestId, ComputeStatus(pullRequestTitle));
return req.CreateResponse(HttpStatusCode.OK);
}
catch (Exception ex)
{
log.Info(ex.ToString());
return req.CreateResponse(HttpStatusCode.InternalServerError);
}
}
private static void PostStatusOnPullRequest(int pullRequestId, string status)
{
string Url = string.Format(
@"https://dev.azure.com/{0}/{1}/_apis/git/repositories/{2}/pullrequests/{3}/statuses?api-version=4.1",
organizationName,
projectName,
repositoryName,
pullRequestId);
using (HttpClient client = new HttpClient())
{
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);
var method = new HttpMethod("POST");
var request = new HttpRequestMessage(method, Url)
{
Content = new StringContent(status, Encoding.UTF8, "application/json")
};
using (HttpResponseMessage response = client.SendAsync(request).Result)
{
response.EnsureSuccessStatusCode();
}
}
}
private static string ComputeStatus(string pullRequestTitle)
{
string state = "succeeded";
string description = "Ready for review";
if (pullRequestTitle.ToLower().Contains("wip"))
{
state = "pending";
description = "Work in progress";
}
return JsonConvert.SerializeObject(
new
{
State = state,
Description = description,
TargetUrl = "https://visualstudio.microsoft.com",
Context = new
{
Name = "PullRequest-WIT-App",
Genre = "pr-azure-function-ci"
}
});
}
새 PR 만들기 및 상태 서버 테스트
서버가 실행 중이고 서비스 후크 알림을 수신 대기했으므로 끌어오기 요청을 만들어 테스트합니다.
파일 보기에서 시작합니다. 리포지토리에서 readme.md 파일을 편집합니다(또는 readme.md 없는 경우 다른 파일).
편집하고 변경 내용을 리포지토리에 커밋합니다.
다음 단계에서 PR을 만들 수 있도록 변경 내용을 새 분기에 커밋해야 합니다.
끌어오기 요청 만들기 링크를 선택합니다.
타이틀에 WIP 추가하여 앱의 기능을 테스트합니다. 만들기 선택하여 PR을 만듭니다.
PR이 만들어지면 상태 섹션이 표시되고 페이로드에 지정된 URL에 연결되는 진행 중인 작업 항목이 표시됩니다.
PR 제목을 업데이트하고 WIP 텍스트를 제거한 다음, 상태가 진행 중에서 검토 준비로 변경되었음을 명심하세요.