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


Использование Функций Azure для создания пользовательских политик ветвей

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

Рабочий процесс пулл-реквестов (PR) позволяет разработчикам получать отзывы о своем коде от коллег и автоматизированных инструментов. Немайкрософтовские инструменты и службы также могут участвовать в рабочем процессе PR с помощью API состояния PR. В этой статье описано, как создать настраиваемую политику ветви с помощью функций Azure для проверки PR в репозитории Azure DevOps Git. Функции Azure устраняют необходимость подготовки и обслуживания серверов, даже при росте рабочей нагрузки. Они предоставляют полностью управляемую платформу вычислений с высокой надежностью и безопасностью.

Дополнительные сведения о состоянии pull request см. в разделе Настройка и расширение рабочих процессов pull request со статусом.

Предпосылки

Категория Требования
Предприятие Организация в Azure DevOps с репозиторием Git.
Функция Azure Функция Azure, которая реализует бессерверное решение, управляемое событиями, которое интегрируется с Azure DevOps для создания настраиваемых политик ветви и автоматизации проверки PR.
Хуки сервисов Настройте веб-хуки службы для событий запроса на вытягивание (PR), чтобы уведомить функцию Azure при изменении запроса на вытягивание.
Личный маркер доступа (PAT) Создайте PAT с областью кода (статуса), чтобы иметь разрешение на изменение статуса PR. Дополнительные сведения см. в разделе "Использование PATs для проверки подлинности".

Создание базовой функции Azure для прослушивания событий Azure Repos

Создайте первую функцию 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 уведомляется при изменении запроса на вытягивание. Чтобы получать POST запросы при изменении запросов на вытягивание, укажите перехватчик службы URL-адресом функции Azure.

В этом примере настройте два перехвата службы. Первое — для события создания запроса на вытягивание, а второе — для события обновления запроса на вытягивание.

  1. Получите URL-адрес функции на портале Azure, щелкнув Получить URL-адрес функции в представлении вашей функции Azure и скопируйте URL-адрес.

    Получить URL-адрес функции

    Url-адрес функции копирования

  2. Перейдите к проекту в Azure DevOps, например https://dev.azure.com/<your organization>/<your project name>

  3. В меню навигации наведите курсор на шестерёнку и выберите хуки службы.

    Выбор перехватчиков служб в меню администрирования

  4. Если это ваш первый сервисный хук, выберите + Создать подписку.

    Выберите

    Если у вас уже настроены другие веб-хуки, выберите значок зеленого плюса (+), чтобы создать новую подписку на веб-хук.

    Выберите зелёный плюс, чтобы создать подписку на service hook.

  5. В диалоговом окне "Новая подписка перехватчиков служб" выберите веб-перехватчики из списка служб, а затем выберите Далее.

    Выберите вебхуки из списка служб

  6. Выберите запрос на вытягивание, созданный из списка триггеров событий, а затем выберите Далее.

    Выберите pull request из списка триггеров событий

  7. На странице действия введите URL-адрес, скопированный на шаге 1 в поле URL-адреса . Выберите Test, чтобы отправить тестовое событие на сервер.

    Введите URL-адрес и выберите

    В окне журнала функций Azure отображается входящий POST, который вернул статус 200 OK, указывая, что ваша функция получила событие перехватчика службы.

    HTTP Requests
    -------------
    
    POST /                         200 OK
    

    В окне "Уведомление о тестировании" выберите вкладку "Ответ", чтобы просмотреть сведения об ответе с сервера. Вы увидите ответ с сервера.

    Выберите вкладку ответа, чтобы просмотреть результаты теста

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

Повторите шаги 2-8, но на этот раз настройте обновленное событие запроса на вытягивание .

Это важно

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

Создайте pull request, чтобы убедиться, что ваша функция Azure получает уведомления.

Состояние публикации в PR

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

Обновите код функции Azure, как показано в следующем примере.

Обязательно обновите код с именем организации, именем проекта, именем репозитория и маркером PAT. Чтобы иметь разрешение на изменение состояния PR, ПАТ требует область vso.code_status, которую можно предоставить, выбрав область Код (состояние) на странице Создать личный маркер доступа.

Это важно

Этот пример кода хранит PAT в коде, упрощая пример. Рекомендуется хранить секреты в KeyVault и извлекать их из него.

В этом примере проверяется заголовок PR, чтобы узнать, указал ли пользователь, находится ли PR в разработке, добавив WIP в заголовок. В этом случае пример кода изменяет состояние, переданное обратно в 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 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"
            }
        });
}

Создайте новый PR и проверьте статус сервера

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

  1. Начните с просмотра файлов. Измените файл readme.md в репозитории (или любой другой файл, если у вас нет readme.md).

    Выберите

  2. Внесите изменения и зафиксируйте изменения в репозитории.

    Измените файл и выберите

  3. Обязательно зафиксируйте изменения в новой ветви, чтобы создать PR на следующем шаге.

    Введите новое имя ветви и нажмите кнопку

  4. Выберите ссылку Создать пулл-реквест.

    Выберите

  5. Добавьте WIP в заголовке, чтобы проверить функциональные возможности приложения. Выберите Создать, чтобы создать PR.

    Добавить

  6. После создания PR отображается раздел состояния с записью «В работе», которая ссылается на URL-адрес, указанный в пакете данных.

    Раздел состояния с записью

  7. Обновите заголовок PR и удалите текст WIP и заметьте, что статус изменяется с В работе на Готово для проверки.

Дальнейшие действия