Skip to content
This repository was archived by the owner on Nov 1, 2023. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
155 changes: 3 additions & 152 deletions src/ApiService/ApiService/Functions/Migrations/JinjaToScriban.cs
Original file line number Diff line number Diff line change
Expand Up @@ -39,11 +39,11 @@ private async Async.Task<HttpResponseData> Post(HttpRequestData req) {
_log.Info($"Finding notifications to migrate");

var notifications = _context.NotificationOperations.SearchAll()
.Select(notification => {
.SelectAwait(async notification => {
var (didModify, config) = notification.Config switch {
TeamsTemplate => (false, notification.Config),
AdoTemplate adoTemplate => ConvertToScriban(adoTemplate),
GithubIssuesTemplate githubIssuesTemplate => ConvertToScriban(githubIssuesTemplate),
AdoTemplate adoTemplate => await JinjaTemplateAdapter.ConvertToScriban(adoTemplate),
GithubIssuesTemplate githubIssuesTemplate => await JinjaTemplateAdapter.ConvertToScriban(githubIssuesTemplate),
_ => throw new NotImplementedException("Unexpected notification configuration type")
};

Expand Down Expand Up @@ -82,153 +82,4 @@ await notifications.Select(notification => notification.NotificationId).ToListAs

return await RequestHandling.Ok(req, new JinjaToScribanMigrationResponse(updatedNotificationsIds, failedNotificationIds));
}

private static (bool didModify, AdoTemplate template) ConvertToScriban(AdoTemplate template) {
var didModify = false;

if (JinjaTemplateAdapter.IsJinjaTemplate(template.Project)) {
didModify = true;
template = template with {
Project = JinjaTemplateAdapter.AdaptForScriban(template.Project)
};
}

foreach (var item in template.AdoFields) {
if (JinjaTemplateAdapter.IsJinjaTemplate(item.Value)) {
template.AdoFields[item.Key] = JinjaTemplateAdapter.AdaptForScriban(item.Value);
didModify = true;
}
}

if (JinjaTemplateAdapter.IsJinjaTemplate(template.Type)) {
didModify = true;
template = template with {
Type = JinjaTemplateAdapter.AdaptForScriban(template.Type)
};
}

if (template.Comment != null && JinjaTemplateAdapter.IsJinjaTemplate(template.Comment)) {
didModify = true;
template = template with {
Comment = JinjaTemplateAdapter.AdaptForScriban(template.Comment)
};
}

foreach (var item in template.OnDuplicate.AdoFields) {
if (JinjaTemplateAdapter.IsJinjaTemplate(item.Value)) {
template.OnDuplicate.AdoFields[item.Key] = JinjaTemplateAdapter.AdaptForScriban(item.Value);
didModify = true;
}
}

if (template.OnDuplicate.Comment != null && JinjaTemplateAdapter.IsJinjaTemplate(template.OnDuplicate.Comment)) {
didModify = true;
template = template with {
OnDuplicate = template.OnDuplicate with {
Comment = JinjaTemplateAdapter.AdaptForScriban(template.OnDuplicate.Comment)
}
};
}

return (didModify, template);
}

private static (bool didModify, GithubIssuesTemplate template) ConvertToScriban(GithubIssuesTemplate template) {
var didModify = false;

if (JinjaTemplateAdapter.IsJinjaTemplate(template.UniqueSearch.str)) {
didModify = true;
template = template with {
UniqueSearch = template.UniqueSearch with {
str = JinjaTemplateAdapter.AdaptForScriban(template.UniqueSearch.str)
}
};
}

if (!string.IsNullOrEmpty(template.UniqueSearch.Author) && JinjaTemplateAdapter.IsJinjaTemplate(template.UniqueSearch.Author)) {
didModify = true;
template = template with {
UniqueSearch = template.UniqueSearch with {
Author = JinjaTemplateAdapter.AdaptForScriban(template.UniqueSearch.Author)
}
};
}

if (JinjaTemplateAdapter.IsJinjaTemplate(template.Title)) {
didModify = true;
template = template with {
Title = JinjaTemplateAdapter.AdaptForScriban(template.Title)
};
}

if (JinjaTemplateAdapter.IsJinjaTemplate(template.Body)) {
didModify = true;
template = template with {
Body = JinjaTemplateAdapter.AdaptForScriban(template.Body)
};
}

if (!string.IsNullOrEmpty(template.OnDuplicate.Comment) && JinjaTemplateAdapter.IsJinjaTemplate(template.OnDuplicate.Comment)) {
didModify = true;
template = template with {
OnDuplicate = template.OnDuplicate with {
Comment = JinjaTemplateAdapter.AdaptForScriban(template.OnDuplicate.Comment)
}
};
}

if (template.OnDuplicate.Labels.Any()) {
template = template with {
OnDuplicate = template.OnDuplicate with {
Labels = template.OnDuplicate.Labels.Select(label => {
if (JinjaTemplateAdapter.IsJinjaTemplate(label)) {
didModify = true;
return JinjaTemplateAdapter.AdaptForScriban(label);
}
return label;
}).ToList()
}
};
}

if (template.Assignees.Any()) {
template = template with {
Assignees = template.Assignees.Select(assignee => {
if (JinjaTemplateAdapter.IsJinjaTemplate(assignee)) {
didModify = true;
return JinjaTemplateAdapter.AdaptForScriban(assignee);
}
return assignee;
}).ToList()
};
}

if (template.Labels.Any()) {
template = template with {
Labels = template.Labels.Select(label => {
if (JinjaTemplateAdapter.IsJinjaTemplate(label)) {
didModify = true;
return JinjaTemplateAdapter.AdaptForScriban(label);
}
return label;
}).ToList()
};
}

if (JinjaTemplateAdapter.IsJinjaTemplate(template.Organization)) {
didModify = true;
template = template with {
Organization = JinjaTemplateAdapter.AdaptForScriban(template.Organization)
};
}

if (JinjaTemplateAdapter.IsJinjaTemplate(template.Repository)) {
didModify = true;
template = template with {
Repository = JinjaTemplateAdapter.AdaptForScriban(template.Repository)
};
}

return (didModify, template);
}
}
127 changes: 1 addition & 126 deletions src/ApiService/ApiService/Functions/ValidateScriban.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,19 +17,9 @@ private async Async.Task<HttpResponseData> Post(HttpRequestData req) {
return await _context.RequestHandling.NotOk(req, request.ErrorV, "ValidateTemplate");
}

var instanceUrl = _context.ServiceConfiguration.OneFuzzInstance!;

try {
var (renderer, templateRenderContext) = await GenerateTemplateRenderContext(request.OkV.Context);

var renderedTemaplate = await renderer.Render(request.OkV.Template, new Uri(instanceUrl), strictRendering: true);
return await RequestHandling.Ok(req, await JinjaTemplateAdapter.ValidateScribanTemplate(_context, _log, request.OkV.Context, request.OkV.Template));

var response = new TemplateValidationResponse(
renderedTemaplate,
templateRenderContext
);

return await RequestHandling.Ok(req, response);
} catch (Exception e) {
return await new RequestHandling(_log).NotOk(
req,
Expand All @@ -47,119 +37,4 @@ public Async.Task<HttpResponseData> Run([HttpTrigger(AuthorizationLevel.Anonymou
_ => throw new InvalidOperationException("Unsupported HTTP method"),
};
}

private async Async.Task<(NotificationsBase.Renderer, TemplateRenderContext)> GenerateTemplateRenderContext(TemplateRenderContext? templateRenderContext) {
if (templateRenderContext != null) {
_log.Info($"Using the request's TemplateRenderContext");
} else {
_log.Info($"Generating TemplateRenderContext");
}

var targetUrl = templateRenderContext?.TargetUrl ?? new Uri("https://example.com/targetUrl");
var inputUrl = templateRenderContext?.InputUrl ?? new Uri("https://example.com/inputUrl");
var reportUrl = templateRenderContext?.ReportUrl ?? new Uri("https://example.com/reportUrl");
var executable = "target.exe";
var crashType = "some crash type";
var crashSite = "some crash site";
var callStack = new List<string>()
{
"stack frame 0",
"stack frame 1"
};
var callStackSha = "call stack sha";
var inputSha = "input sha";
var taskId = Guid.NewGuid();
var jobId = Guid.NewGuid();
var taskState = TaskState.Running;
var jobState = JobState.Enabled;
var os = Os.Linux;
var taskType = TaskType.LibfuzzerFuzz;
var duration = 100;
var project = "some project";
var jobName = "job name";
var buildName = "build name";
var reportContainer = templateRenderContext?.ReportContainer ?? Container.Parse("example-container-name");
var reportFileName = templateRenderContext?.ReportFilename ?? "example file name";
var reproCmd = templateRenderContext?.ReproCmd ?? "onefuzz command to create a repro";
var report = templateRenderContext?.Report ?? new Report(
inputUrl.ToString(),
null,
executable,
crashType,
crashSite,
callStack,
callStackSha,
inputSha,
null,
taskId,
jobId,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null
);

var task = new Task(
jobId,
taskId,
taskState,
os,
templateRenderContext?.Task ?? new TaskConfig(
jobId,
null,
new TaskDetails(
taskType,
duration
)
)
);

var job = new Job(
jobId,
jobState,
templateRenderContext?.Job ?? new JobConfig(
project,
jobName,
buildName,
duration,
null
)
);

var renderer = await NotificationsBase.Renderer.ConstructRenderer(
_context,
reportContainer,
reportFileName,
report,
_log,
task,
job,
targetUrl,
inputUrl,
reportUrl,
scribanOnlyOverride: true
);

templateRenderContext ??= new TemplateRenderContext(
report,
task.Config,
job.Config,
reportUrl,
inputUrl,
targetUrl,
reportContainer,
reportFileName,
reproCmd
);

return (renderer, templateRenderContext);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,11 @@ public async Async.Task<OneFuzzResult<Notification>> Create(Container container,
return OneFuzzResult<Notification>.Error(ErrorCode.INVALID_REQUEST, "invalid container");
}

if (await _context.FeatureManagerSnapshot.IsEnabledAsync(FeatureFlagConstants.EnableScribanOnly) &&
!await JinjaTemplateAdapter.IsValidScribanNotificationTemplate(_context, _logTracer, config)) {
return OneFuzzResult<Notification>.Error(ErrorCode.INVALID_REQUEST, "The notification config is not a valid scriban template");
}

if (replaceExisting) {
var existing = this.SearchByRowKeys(new[] { container.String });
await foreach (var existingEntry in existing) {
Expand Down
Loading