Usar o Azure Functions para criar políticas de ramificação personalizadas
Serviços de DevOps do Azure | Azure DevOps Server 2022 - Azure DevOps Server 2019
O fluxo de trabalho de pull request (PR) permite que os desenvolvedores recebam feedback sobre seu código de colegas e ferramentas automatizadas. Ferramentas e serviços que não sejam da Microsoft também podem participar no fluxo de trabalho de PR usando a API de Status PR . Este artigo orienta você na criação de uma política de ramificação personalizada usando do Azure Functions para validar PRs em um repositório Git do Azure DevOps. O Azure Functions elimina a necessidade de provisionar e manter servidores, mesmo quando sua carga de trabalho aumenta. Eles fornecem uma plataforma de computação totalmente gerenciada com alta confiabilidade e segurança.
Para mais informações sobre o estado da solicitação pull, consulte Personalizar e expandir fluxos de trabalho de solicitação pull com status de solicitação pull.
Pré-requisitos
Categoria | Requerimentos |
---|---|
Organização | Uma organização no Azure DevOps com um repositório Git. |
Função do Azure | Um Azure Function, que implementa uma solução sem servidor e orientada a eventos, integrando-se com o Azure DevOps para criar políticas de ramificação personalizadas e automatizar a validação de PR. |
Service Hooks | Configurar ganchos de serviço para eventos de RP para notificar sua função do Azure quando uma solicitação pull for alterada. |
Token de Acesso Pessoal (PAT) | Crie uma PAT com o Código (estado) no âmbito para ter permissão para alterar o estado do PR. Para obter mais informações, veja Use PATs para autenticar. |
Criar uma Função do Azure básica para ouvir eventos do Azure Repos
Crie sua primeira função do Azure. Em seguida, modifique o código no exemplo para se parecer com o código a seguir:
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);
}
}
Configurar um webhook para eventos de PR
Os ganchos de serviço são um recurso do Azure DevOps que pode alertar serviços externos quando determinados eventos ocorrem. Para este exemplo, configure um gancho de serviço para eventos de RP, sua função do Azure é notificada quando uma solicitação pull é alterada. Para receber solicitações POST
quando as solicitações pull forem alteradas, forneça o gancho de serviço com a URL da função do Azure.
Para este exemplo, configure dois ganchos de serviço. A primeira é para o evento de criação da solicitação de pull request , e a segunda é para o evento de atualização da solicitação de pull request .
Obtenha a URL da função do portal do Azure clicando no Obter URL da função em sua exibição de função do Azure e copie a URL.
Navegue até seu projeto no Azure DevOps, por exemplo,
https://dev.azure.com/<your organization>/<your project name>
No menu de navegação, passe o rato sobre o ícone de engrenagem e selecione Ganchos de Serviço.
Se for seu primeiro gancho de serviço, selecione + Criar assinatura.
Se já tiveres outros ganchos de serviço configurados, seleciona o botão verde com o símbolo de mais
(+)
para criar uma nova subscrição de gancho de serviço.Na caixa de diálogo Nova Subscrição de Ganchos de Serviço, selecione Ganchos da Web na lista de serviços e, em seguida, selecione Seguinte.
Selecione solicitação pull criada na lista de gatilhos de evento e, em seguida, selecione Avançar.
Na página Ação, introduza o URL que copiou no passo 1 na caixa URL. Selecione Teste para enviar um evento de teste ao servidor.
Na janela de log de funções do Azure, você verá um
POST
de entrada que retornou um200 OK
, indicando que sua função recebeu o evento de gancho de serviço.HTTP Requests ------------- POST / 200 OK
Na janela Notificação de teste, selecione a guia Resposta para ver os detalhes da resposta do servidor. Você deve ver a resposta do seu servidor.
Feche a janela Notificação de teste e selecione Concluir para criar o gancho de serviço.
Passe pelas etapas 2 a 8 novamente, mas desta vez configure o evento Pull request atualizado.
Importante
Certifique-se de passar pelas etapas anteriores duas vezes e de criar ganchos de serviço para os eventos de o pull request criado e o pull request atualizado.
Crie uma solicitação pull para verificar se sua função do Azure está recebendo notificações.
Postar status para RPs
Agora que seu servidor pode receber eventos de gancho de serviço quando novos PRs são criados, atualize-o para postar de volta o status para o PR. Você pode usar a carga JSON postada pelo gancho de serviço para determinar qual status definir em seu PR.
Atualize o código da sua função do Azure, semelhante ao exemplo a seguir.
Certifique-se de atualizar o código com o nome da organização, o nome do projeto, o nome do repositório e token PAT. Para ter permissão para alterar o status de PR, a PAT requer vso.code_status âmbito, que pode ser concedido selecionando o Code (status) âmbito na página Criar um token de acesso pessoal.
Importante
Este código de exemplo armazena a PAT em código, simplificando o exemplo. Recomenda-se armazenar segredos no KeyVault e recuperá-los de lá.
Este exemplo inspeciona o título de PR para ver se o utilizador indicou se o PR é um trabalho em andamento, adicionando WIP ao título. Em caso afirmativo, o código de exemplo altera o estado enviado de volta para o PR. Substitua o código em sua função do Azure pelo código a seguir, que atualiza o status postado de volta para a RP.
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 KeyVault and retrieve them from there.
*/
private static string pat = "[PAT 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("Basic", Convert.ToBase64String(
ASCIIEncoding.ASCII.GetBytes(
string.Format("{0}:{1}", "", pat))));
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"
}
});
}
Criar um novo PR e testar o servidor de status
Agora que seu servidor está em execução e ouvindo notificações de gancho de serviço, crie uma solicitação pull para testá-la.
Comece na visualização de arquivos. Edite o arquivo readme.md em seu repositório (ou qualquer outro arquivo se você não tiver um readme.md).
Faça uma edição e confirme as alterações no repositório.
Certifique-se de confirmar as alterações num novo ramo para criar um PR na próxima etapa.
Selecione o link Criar uma solicitação pull.
Adicione WIP no título para testar a funcionalidade do aplicativo. Selecione Criar para criar a PR.
Depois que o PR é criado, a seção de status é exibida, com a entrada Work in progress que vincula à URL especificada na carga útil.
Atualize o título de RP e remova o texto do WIP e observe que o status muda de Work in progress para Ready for review.