Utilizar Funções do Azure 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) oferece aos desenvolvedores a oportunidade de obter feedback sobre seu código de pares, bem como de ferramentas automatizadas. Ferramentas e serviços de terceiros podem participar do fluxo de trabalho de RP usando a API de status de RP. Este artigo orienta você pelo processo de criação de uma política de ramificação personalizada usando o Azure Functions para validar PRs em um repositório Git dos Serviços de DevOps do Azure. Com o Azure Functions, você não precisa se preocupar com o provisionamento e a manutenção de servidores, especialmente quando sua carga de trabalho aumenta. O Azure Functions fornece uma plataforma de computação totalmente gerenciada com alta confiabilidade e segurança.
Para obter mais informações sobre o status de RP, consulte Personalizar e estender fluxos de trabalho de solicitação pull com status de solicitação pull.
Pré-requisitos
Uma organização no Azure DevOps com um repositório Git. Se você não tiver uma organização, inscreva-se para carregar e compartilhar código em repositórios Git privados ilimitados e gratuitos.
Criar uma função básica do Azure para ouvir eventos do Azure Repos
Siga a documentação de criar sua primeira função do Azure para criar uma função simples. Modifique o código no exemplo para ter esta aparência:
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 gancho de serviço para eventos de RP
Os ganchos de serviço são um recurso dos Serviços de DevOps do Azure que pode alertar serviços externos quando determinados eventos ocorrem. Para este exemplo, você desejará configurar um gancho de serviço para eventos de RP, sua função do Azure será notificada quando uma solicitação pull for alterada. Para receber POST
solicitações quando as solicitações pull forem alteradas, você precisará fornecer o gancho de serviço com a URL da função do Azure.
Para este exemplo, você precisará configurar 2 ganchos de serviço. O primeiro será para o evento Pull request created e o segundo será para o evento Pull request atualizado .
Obtenha a URL da função no portal do Azure clicando em 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 mouse sobre a engrenagem e selecione Ganchos de serviço.
Se este for o seu primeiro gancho de serviço, selecione + Criar assinatura.
Se você já tiver outros ganchos de serviço configurados, selecione o sinal verde mais
(+)
para criar uma nova assinatura de gancho de serviço.Na caixa de diálogo Nova Assinatura de Ganchos de Serviço, selecione Web Hooks na lista de serviços e selecione Avançar.
Selecione Pull request created na lista de acionadores de evento e, em seguida, selecione Next.
Na página Ação, introduza o URL que copiou no passo 1 na caixa URL . Selecione Testar para enviar um evento de teste para o servidor.
Na janela de log de funções do Azure, você verá uma entrada
POST
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 criar ganchos de serviço para os eventos Pull request created e Pull request atualizados .
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 para se parecer com o exemplo a seguir.
Certifique-se de atualizar o código com o nome da sua organização, nome do projeto, nome do repositório e token PAT. Para ter permissão para alterar o status de RP, a PAT requer vso.code_status escopo, que você pode conceder selecionando o escopo Código (status) na página Criar um token de acesso pessoal.
Importante
Este código de exemplo armazena a PAT em código para simplificar o exemplo. Recomenda-se armazenar segredos no KeyVault e recuperá-los de lá.
Este exemplo inspeciona o título PR para ver se o usuário indicou se o PR é um trabalho em andamento, adicionando WIP ao título. Em caso afirmativo, o código de exemplo altera o status postado de volta para o PR. Substitua o código em sua função do Azure pelo código a seguir para implementar a atualização do 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 uma nova RP para 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 em uma nova ramificação para que você possa criar uma RP 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 RP.
Uma vez que o PR tenha sido criado, você verá a seção de status, com a entrada Trabalho em andamento que vincula à URL especificada na carga útil.
Atualize o título PR e remova o texto WIP e observe que o status muda de Trabalho em andamento para Pronto para revisão.
Passos Seguintes
- Neste artigo, você aprendeu as noções básicas de como criar uma função do Azure sem servidor que escuta eventos de RP por meio de ganchos de serviço e pode postar mensagens de status usando a API de status. Para obter mais informações sobre a API de status de solicitação pull, consulte a documentação da API REST.
- Configure uma política de filial para um serviço externo.