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

Azure Repos | Azure DevOps Server 2020 | Azure DevOps Server 2019 | TFS 2018

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

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

Предварительные условия

организация в Azure DevOps с репозиторием Git. Если у вас нет организации, Зарегистрируйтесь для отправки и совместно используйте код в бесплатных неограниченных частных репозиториях Git.

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

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

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

    Get function url

    Copy function url

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

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

    Choose Service hooks from the admin menu

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

    Select Create a new subscription from the toolbar

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

    Select the green plus to create a new service hook subscription.

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

    Select web hooks from the list of services

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

    Select pull request created from the list of event triggers

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

    Enter the URL and select Test to test the service hook

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

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

    В окне Тестовое уведомление перейдите на вкладку ответ, чтобы просмотреть подробные сведения о ответе сервера. Вы должны увидеть ответ сервера.

    Select the response tab to see the results of the test

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

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

Важно!

Выполните предыдущие шаги дважды и создайте перехватчики событий для запросов на включение внесенных изменений и обновления запросов на вытягивание .

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

Опубликовать состояние в вытягивание

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

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

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

Важно!

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

В этом образце проверяется заголовок запроса на вытягивание, чтобы узнать, указывает ли пользователь на то, что назначением запроса на вытягивание является невыполненная работа, добавив в заголовок WIP . В этом примере код изменяет состояние, отправленное обратно на запрос на вытягивание. Замените код в функции Azure следующим кодом, чтобы реализовать обновление состояния, отправленного обратно в запрос на вытягивание.

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"
            }
        });
}

Создание нового запроса на вытягивание для проверки сервера состояния

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

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

    Select Edit from the context menu

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

    Edit the file and select Commit from the toolbar

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

    Enter a new branch name and select Commit

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

    Select Create a pull request from the suggestion bar

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

    Add WIP to the default PR title

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

    Status section with Work in progress entry.

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

Next Steps