Skip to content

Commit

Permalink
Merge pull request #2354 from DataDog/pierre/labelling
Browse files Browse the repository at this point in the history
[Automation] Add automatic labelling
  • Loading branch information
pierotibou authored Nov 30, 2023
2 parents 23ed6b2 + 1d9a14e commit 9ebc339
Show file tree
Hide file tree
Showing 4 changed files with 165 additions and 1 deletion.
24 changes: 24 additions & 0 deletions .github/labeller.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
labels:
- name: "area:asm"
title: "^\\[?(?i)ASM"

- name: "area:asm"
allFilesIn: "(appsec\/.*|docker-compose.yml|.*\/.circleci\/.*)"

- name: "profiling"
title: "^*(profiler)"

- name: "profiling"
title: "^*(profiling)"

- name: "profiling"
allFilesIn: "(profiling\/.*|docker-compose.yml|.*\/.circleci\/.*)"

- name: "tracing"
title: "^\\[?(?i)tracer"

- name: "tracing"
title: "^\\[?(?i)tracing"

- name: "tracing"
allFilesIn: "(.*\/ext\/.*|.*\/src\/.*|.*\/tests\/.*|.*\/zend_abstract_interface\/.*|docker-compose.yml|.*\/.circleci\/.*)"
23 changes: 23 additions & 0 deletions .github/workflows/auto_label_prs.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
name: Label PRs

on:
- pull_request

jobs:
add-labels:

runs-on: ubuntu-latest

steps:
- name: Checkout
uses: actions/checkout@v2

- uses: actions/setup-dotnet@v1
with:
dotnet-version: '7.0.101'

- name: "Add labels"
run: ./github-actions-helpers/build.sh AssignLabelsToPullRequest
env:
GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
PullRequestNumber: "${{ github.event.pull_request.number }}"
2 changes: 2 additions & 0 deletions github-actions-helpers/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
bin/
obj/
117 changes: 116 additions & 1 deletion github-actions-helpers/Build.Github.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using Nuke.Common;
using Nuke.Common.IO;
Expand All @@ -14,9 +16,14 @@
using Target = Nuke.Common.Target;
using Logger = Serilog.Log;
using System.Net.Http;
using System.Text;
using Octokit.GraphQL.Model;
using System.Net.Http.Json;
using YamlDotNet.Serialization.NamingConventions;
using ProductHeaderValue = Octokit.ProductHeaderValue;
using static Octokit.GraphQL.Variable;
using Milestone = Octokit.Milestone;
using Release = Octokit.Release;
using Nuke.Common.Utilities.Collections;

partial class Build
{
Expand Down Expand Up @@ -223,4 +230,112 @@ async Task HideCommentsInPullRequest(int prNumber, string prefix)
Logger.Warning($"There was an error trying to minimise old comments with prefix '{prefix}': {ex}");
}
}

Target AssignLabelsToPullRequest => _ => _
.Unlisted()
.Requires(() => GitHubRepositoryName)
.Requires(() => GitHubToken)
.Requires(() => PullRequestNumber)
.Executes(async() =>
{
var client = GetGitHubClient();

var pr = await client.PullRequest.Get(
owner: GitHubRepositoryOwner,
name: GitHubRepositoryName,
number: PullRequestNumber.Value);

// Fixes an issue (ambiguous argument) when we do git diff in the Action.
GitTasks.Git("fetch origin master:master", logOutput: false);
var changedFiles = GitTasks.Git("diff --name-only master").Select(f => f.Text);
var config = GetLabellerConfiguration();
Console.WriteLine($"Checking labels for PR {PullRequestNumber}");

var updatedLabels = ComputeLabels(config, pr.Title, pr.Labels.Select(l => l.Name), changedFiles);
var issueUpdate = new IssueUpdate();
updatedLabels.ForEach(l => issueUpdate.AddLabel(l));

try
{
await client.Issue.Update(
owner: GitHubRepositoryOwner,
name: GitHubRepositoryName,
number: PullRequestNumber.Value,
issueUpdate);
}
catch(Exception ex)
{
Logger.Warning($"An error happened while updating the labels on the PR: {ex}");
}

Console.WriteLine($"PR labels updated");

HashSet<String> ComputeLabels(LabbelerConfiguration config, string prTitle, IEnumerable<string> labels, IEnumerable<string> changedFiles)
{
var updatedLabels = new HashSet<string>(labels);

foreach(var label in config.Labels)
{
try
{
if (!string.IsNullOrEmpty(label.Title))
{
Console.WriteLine("Checking if pr title matches: " + label.Title);
var regex = new Regex(label.Title, RegexOptions.Compiled);
if (regex.IsMatch(prTitle))
{
Console.WriteLine("Yes it does. Adding label " + label.Name);
updatedLabels.Add(label.Name);
}
}
else if (!string.IsNullOrEmpty(label.AllFilesIn))
{
Console.WriteLine("Checking if changed files are all located in:" + label.AllFilesIn);
var regex = new Regex(label.AllFilesIn, RegexOptions.Compiled);
if(!changedFiles.Any(x => !regex.IsMatch(x)))
{
Console.WriteLine("Yes they do. Adding label " + label.Name);
updatedLabels.Add(label.Name);
}
}
}
catch(Exception ex)
{
Logger.Warning($"There was an error trying to check labels: {ex}");
}
}
return updatedLabels;
}

LabbelerConfiguration GetLabellerConfiguration()
{
var labellerConfigYaml = RootDirectory / ".github" / "labeller.yml";
Logger.Information($"Reading {labellerConfigYaml} YAML file");
var deserializer = new YamlDotNet.Serialization.DeserializerBuilder()
.WithNamingConvention(CamelCaseNamingConvention.Instance)
.IgnoreUnmatchedProperties()
.Build();

using var sr = new StreamReader(labellerConfigYaml);
return deserializer.Deserialize<LabbelerConfiguration>(sr);
}
});

GitHubClient GetGitHubClient() =>
new(new ProductHeaderValue("nuke-ci-client"))
{
Credentials = new Credentials(GitHubToken)
};

class LabbelerConfiguration
{
public Label[] Labels { get; set; }

public class Label
{
public string Name { get; set; }
public string Title { get; set; }
public string AllFilesIn { get; set; }
}
}
}

0 comments on commit 9ebc339

Please sign in to comment.