fix: close release preflight gaps
CI and Deploy / test (pull_request) Failing after 1m22s
CI and Deploy / deploy (pull_request) Has been skipped

Route public health checks to the API, backfill and synchronize job opportunities, stabilize SPA smoke tests, and document operator-only production steps.
This commit is contained in:
cesnimda
2026-07-31 20:18:30 +02:00
parent ce76046a29
commit 955182b7c2
18 changed files with 350 additions and 52 deletions
+4 -1
View File
@@ -567,6 +567,7 @@ public sealed class GmailController : ControllerBase
if (string.IsNullOrWhiteSpace(company.RecruiterEmail) && !string.IsNullOrWhiteSpace(request.RecruiterEmail)) company.RecruiterEmail = request.RecruiterEmail.Trim();
}
var savedAt = DateTime.UtcNow;
var job = new JobApplication
{
OwnerUserId = ownerUserId,
@@ -574,8 +575,10 @@ public sealed class GmailController : ControllerBase
JobTitle = jobTitle,
Status = string.IsNullOrWhiteSpace(request.Status) ? "Applied" : request.Status.Trim(),
Notes = string.IsNullOrWhiteSpace(request.Notes) ? null : request.Notes.Trim(),
DateApplied = DateTime.UtcNow,
DateApplied = savedAt,
SavedAt = savedAt,
};
job.Job = JobOpportunitySync.Create(job, "gmail");
_db.JobApplications.Add(job);
await _db.SaveChangesAsync(cancellationToken);
@@ -702,27 +702,6 @@ Canonical profile:
return Ok(dtos);
}
private static void SyncOpportunity(JobApplication application, Job opportunity)
{
opportunity.OwnerUserId = application.OwnerUserId;
opportunity.CompanyId = application.CompanyId;
opportunity.JobTitle = application.JobTitle;
opportunity.Location = application.Location;
opportunity.JobUrl = application.JobUrl;
opportunity.Description = application.Description;
opportunity.TranslatedDescription = application.TranslatedDescription;
opportunity.DescriptionLanguage = application.DescriptionLanguage;
opportunity.ShortSummary = application.ShortSummary;
opportunity.Tags = application.Tags;
opportunity.Deadline = application.Deadline;
opportunity.Salary = application.Salary;
opportunity.SalaryMin = application.SalaryMin;
opportunity.SalaryMax = application.SalaryMax;
opportunity.SalaryCurrency = application.SalaryCurrency;
opportunity.SalaryPeriod = application.SalaryPeriod;
opportunity.SavedAt = application.SavedAt;
}
private static (decimal? Min, decimal? Max, string? Currency, string? Period) NormalizeSalary(
decimal? min, decimal? max, string? currency, string? period)
{
@@ -782,7 +761,7 @@ Canonical profile:
if (source?.Length > 32) source = source[..32];
var countryCode = string.IsNullOrWhiteSpace(request.CountryCode) ? null : request.CountryCode.Trim().ToUpperInvariant();
if (countryCode?.Length != 2) countryCode = null;
job.Job = new Job { Source = source, CountryCode = countryCode };
job.Job = JobOpportunitySync.Create(job, source, countryCode);
// A job created straight into a pre-application stage has not been applied to, so it
// must not carry an applied date. SyncAppliedDate also covers the reverse: a create
@@ -803,7 +782,7 @@ Canonical profile:
// ignore summarizer failures at create time
}
SyncOpportunity(job, job.Job);
JobOpportunitySync.Apply(job, job.Job);
_db.JobApplications.Add(job);
await _db.SaveChangesAsync(cancellationToken);
@@ -879,7 +858,7 @@ Canonical profile:
// Records StatusChanged plus any lifecycle event the transition implies.
JobLifecycleEvents.RecordStatusChange(_db, job, oldStatus, request.StatusChangedAt ?? DateTime.Now);
if (job.Job is not null) SyncOpportunity(job, job.Job);
if (job.Job is not null) JobOpportunitySync.Apply(job, job.Job);
await _db.SaveChangesAsync(cancellationToken);
return NoContent();
}