Select Git revision
Reporting.cs

Sirieam Marie Hunke authored
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
Reporting.cs 7.31 KiB
using Coscine.Configuration;
using Coscine.Metadata;
using GitLabApiClient;
using GitLabApiClient.Models.Commits.Requests.CreateCommitRequest;
using KPIGenerator.Utils;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System.Text;
using VDS.RDF;
using VDS.RDF.Query;
using static KPIGenerator.Utils.CommandLineOptions;
namespace KPIGenerator;
public abstract class Reporting<O> where O : class
{
public O Options { get; init; }
public GitLabClient GitLabClient { get; set; }
public List<Organization> Organizations { get; set; }
public RdfStoreConnector RdfStoreConnector { get; init; }
public SparqlRemoteEndpoint QueryEndpoint { get; init; }
public ConsulConfiguration Configuration { get; }
private static string HostUrl { get; } = "https://git.rwth-aachen.de/";
private static string InstanceName { get; set; } = null!;
public virtual string ReportingFileName { get; init; } = null!;
public readonly Organization _otherOrganization = new()
{
Name = "Other",
RorUrl = "https://ror.org/_other",
};
/// <summary>
/// Reporting Database GitLab Project URL
/// </summary>
/// <remarks>https://git.rwth-aachen.de/coscine/reporting/reporting-database</remarks>
private static readonly int ReportingDatabaseProjectId = 75304;
public Reporting(O options)
{
InstanceName = this.GetType().Name;
Options = options;
Configuration = new ConsulConfiguration();
RdfStoreConnector = new RdfStoreConnector(Configuration.GetStringAndWait("coscine/local/virtuoso/additional/url"));
QueryEndpoint = new SparqlRemoteEndpoint(new Uri(Configuration.GetStringAndWait("coscine/local/virtuoso/additional/url")));
GitLabClient = new GitLabClient(HostUrl, Configuration.GetStringAndWait("coscine/global/gitlabtoken"));
Organizations = new List<Organization>() { _otherOrganization };
}
public abstract IEnumerable<ReportingFileObject> GenerateReporting();
public bool Run()
{
// Console text output
Console.Write($"{new string('=', 60)}\n{InstanceName}");
var baseOptions = Options as BaseOptions;
if (baseOptions is not null && baseOptions.DummyMode)
{
Console.Write(" : DUMMY MODE");
}
Console.WriteLine($"\n{new string('-', 60)}");
// Generate Reporting based on CLI input
var reportingFiles = GenerateReporting();
Console.WriteLine($"\n{new string('=', 60)}");
Console.WriteLine("Reporting generated successfully. Publishing...");
// Publish Report
var success = PublishAsync(reportingFiles).Result;
Console.WriteLine(success ? "Published successfully." : "Publishing FAILED!");
return success;
}
private async Task<bool> PublishAsync(IEnumerable<ReportingFileObject> files)
{
try
{
// Retrieve Reporting Database project
var reportingDatabaseProject = await GitLabClient.Projects.GetAsync(ReportingDatabaseProjectId);
var commitBranch = reportingDatabaseProject.DefaultBranch;
var commitMessage = $"{InstanceName} Generated - {DateTime.Now:dd.MM.yyyy HH:mm}"; // CompleteReporting Generated - 31.08.2022 10:25
var projectTree = await GitLabClient.Trees.GetAsync(reportingDatabaseProject, o =>
{
o.Recursive = true;
o.Reference = commitBranch;
});
// Define commit actions
var actions = new List<CreateCommitRequestAction>();
// Delete files or organizations that are not valid anymore
foreach (var fileInProject in projectTree.Where(file => file.Type.Equals("blob")))
{
if (!files.Any(f => f.Path.Equals(fileInProject.Path)) && !fileInProject.Path.Equals("README.md"))
{
// Add Action
actions.Add(new CreateCommitRequestAction(CreateCommitRequestActionType.Delete, fileInProject.Path));
}
}
// Create a commit per file with its contents
foreach (var file in files)
{
// Write file contents to bytes
byte[] bytes;
using (var ms = new MemoryStream())
{
file.Content.CopyTo(ms);
bytes = ms.ToArray();
}
// Distinguish between Creating or Updating a file
var actionType = CreateCommitRequestActionType.Create;
if (projectTree.Any(f => f.Path.Equals(file.Path)))
{
actionType = CreateCommitRequestActionType.Update;
}
// Add Action
actions.Add(new CreateCommitRequestAction(actionType, file.Path)
{
Content = Convert.ToBase64String(bytes),
Encoding = CreateCommitRequestActionEncoding.Base64
});
}
// Push Commit
var baseOptions = Options as BaseOptions;
if (baseOptions is not null && !baseOptions.DummyMode)
{
await GitLabClient.Commits.CreateAsync(reportingDatabaseProject, new CreateCommitRequest(commitBranch, commitMessage, actions));
}
return true;
}
catch (Exception e)
{
Console.WriteLine(e.Message);
return false;
}
}
public Organization FetchOrganizationByRor(string rorUrl)
{
var result = new Organization();
var organizationFound = Organizations.Find(o => o.RorUrl.Equals(rorUrl));
if (organizationFound is not null)
{
result = new Organization
{
Name = organizationFound.Name,
RorUrl = organizationFound.RorUrl,
};
}
else
{
var organizationTriples = RdfStoreConnector.GetLabelForSubject(new Uri(Uri.UnescapeDataString(rorUrl))).ToList();
if (organizationTriples.Any())
{
result = new Organization
{
// Only one entry possible per organization, take 0th element
Name = organizationTriples[0].Object.ToString(),
RorUrl = organizationTriples[0].Subject.ToString(),
};
Organizations.Add(result); // Cache the fetched organization
}
else
{
result = _otherOrganization;
Console.ForegroundColor = ConsoleColor.Yellow;
Console.WriteLine($"WARNING!: Organization with ROR \"{rorUrl}\" could not be correctly identified. Will use \"{result.RorUrl}\" and \"{result.Name}\".");
Console.ResetColor();
}
}
return result;
}
public static string GetReportingPathGeneral(string fileName)
{
return string.Format("General/{0}", fileName);
}
public static string GetReportingPathOrganization(string organizationRor, string fileName)
{
return string.Format("Organizations/{0}/{1}", organizationRor, fileName);
}
public static Stream ConvertStringContentsToStream(string contents)
{
byte[] byteArray = Encoding.UTF8.GetBytes(contents);
return new MemoryStream(byteArray);
}
}