in tools/code/publisher/WorkspaceApi.cs [348:433]
private static CorrectWorkspaceApimRevisionNumber GetCorrectWorkspaceApimRevisionNumber(IServiceProvider provider)
{
var getPreviousCommitDtos = provider.GetRequiredService<GetWorkspaceApiDtosInPreviousCommit>();
var putApiInApim = provider.GetRequiredService<PutWorkspaceApiInApim>();
var makeApiRevisionCurrent = provider.GetRequiredService<MakeWorkspaceApiRevisionCurrent>();
var isNameInSourceControl = provider.GetRequiredService<IsWorkspaceApiNameInSourceControl>();
var deleteApiFromApim = provider.GetRequiredService<DeleteWorkspaceApiFromApim>();
var logger = provider.GetRequiredService<ILogger>();
return async (name, dto, workspaceName, cancellationToken) =>
{
if (ApiName.IsRevisioned(name))
{
return;
}
var previousRevisionNumberOption = await tryGetPreviousRevisionNumber(name, workspaceName, cancellationToken);
await previousRevisionNumberOption.IterTask(async previousRevisionNumber =>
{
var currentRevisionNumber = Common.GetRevisionNumber(dto);
await setApimCurrentRevisionNumber(name, currentRevisionNumber, previousRevisionNumber, workspaceName, cancellationToken);
});
};
async ValueTask<Option<ApiRevisionNumber>> tryGetPreviousRevisionNumber(ApiName name, WorkspaceName workspaceName, CancellationToken cancellationToken) =>
await getPreviousCommitDtos()
.Find((name, workspaceName))
.BindTask(async getDto =>
{
var dtoOption = await getDto(cancellationToken);
return from dto in dtoOption
select Common.GetRevisionNumber(dto);
});
async ValueTask setApimCurrentRevisionNumber(ApiName name, ApiRevisionNumber newRevisionNumber, ApiRevisionNumber existingRevisionNumber, WorkspaceName workspaceName, CancellationToken cancellationToken)
{
if (newRevisionNumber == existingRevisionNumber)
{
return;
}
logger.LogInformation("Changing current revision on {ApiName} in workspace {WorkspaceName} from {RevisionNumber} to {RevisionNumber}...", name, workspaceName, existingRevisionNumber, newRevisionNumber);
await putRevision(name, newRevisionNumber, existingRevisionNumber, workspaceName, cancellationToken);
await makeApiRevisionCurrent(name, newRevisionNumber, workspaceName, cancellationToken);
await deleteOldRevision(name, existingRevisionNumber, workspaceName, cancellationToken);
}
async ValueTask putRevision(ApiName name, ApiRevisionNumber revisionNumber, ApiRevisionNumber existingRevisionNumber, WorkspaceName workspaceName, CancellationToken cancellationToken)
{
var dto = new WorkspaceApiDto
{
Properties = new WorkspaceApiDto.ApiCreateOrUpdateProperties
{
ApiRevision = revisionNumber.ToString(),
SourceApiId = $"/apis/{ApiName.GetRevisionedName(name, existingRevisionNumber)}"
}
};
await putApiInApim(name, dto, Option<(ApiSpecification.GraphQl, BinaryData)>.None, workspaceName, cancellationToken);
}
/// <summary>
/// If the old revision is no longer in source control, delete it from APIM. Handles this scenario:
/// 1. Dev and prod APIM both have apiA with current revision 1. Artifacts folder has /apis/apiA/apiInformation.json with revision 1.
/// 2. User changes the current revision in dev APIM from 1 to 2.
/// 3. User deletes revision 1 from dev APIM, as it's no longer needed.
/// 4. User runs extractor for dev APIM. Artifacts folder has /apis/apiA/apiInformation.json with revision 2.
/// 5. User runs publisher to prod APIM. The only changed artifact will be an update in apiInformation.json to revision 2, so we will create revision 2 in prod and make it current.
///
/// If we do nothing else, dev and prod will be inconsistent as prod will still have the revision 1 API. There was nothing in Git that told the publisher to delete revision 1.
/// </summary>
async ValueTask deleteOldRevision(ApiName name, ApiRevisionNumber oldRevisionNumber, WorkspaceName workspaceName, CancellationToken cancellationToken)
{
var revisionedName = ApiName.GetRevisionedName(name, oldRevisionNumber);
if (isNameInSourceControl(revisionedName, workspaceName))
{
return;
}
logger.LogInformation("Deleting old revision {RevisionNumber} of {ApiName} in workspace {WorkspaceName}...", oldRevisionNumber, name, workspaceName);
await deleteApiFromApim(revisionedName, workspaceName, cancellationToken);
}
}