Skip to content
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
4 changes: 2 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@ packages/
*/appSettings.json
api_referece/*
.sonarqube/
*.html
*.cobertura.xml
integration-test-report_*.html
*.zip
.trx
.trx
*.html
Original file line number Diff line number Diff line change
Expand Up @@ -193,7 +193,7 @@ public void Test008_Should_Fetch_Created_Branch()
Assert.Inconclusive("Test004 did not create branch — skipping.");
try
{
ContentstackResponse response = _stack.Branch(_createdBranchUid).Fetch();
ContentstackResponse response = RetryOnBranchProvisioning(() => _stack.Branch(_createdBranchUid).Fetch());
var json = response.OpenJsonObjectResponse();
AssertLogger.IsNotNull(json, "response");
}
Expand All @@ -212,7 +212,7 @@ public async Task Test009_Should_Fetch_Created_Branch_Async()
Assert.Inconclusive("Test005 did not create branch — skipping.");
try
{
ContentstackResponse response = await _stack.Branch(_createdBranchUidAsync).FetchAsync();
ContentstackResponse response = await RetryOnBranchProvisioningAsync(() => _stack.Branch(_createdBranchUidAsync).FetchAsync());
var json = response.OpenJsonObjectResponse();
AssertLogger.IsNotNull(json, "response");
}
Expand All @@ -235,7 +235,7 @@ public void Test010_Should_Delete_Branch()
{
var force = new ParameterCollection();
force.Add("force", true);
ContentstackResponse response = _stack.Branch(_createdBranchUid).Delete(force);
ContentstackResponse response = RetryOnBranchProvisioning(() => _stack.Branch(_createdBranchUid).Delete(force));
var json = response.OpenJsonObjectResponse();
AssertLogger.IsNotNull(json, "response");
_createdBranchUid = null;
Expand All @@ -257,7 +257,7 @@ public async Task Test011_Should_Delete_Branch_Async()
{
var force = new ParameterCollection();
force.Add("force", true);
ContentstackResponse response = await _stack.Branch(_createdBranchUidAsync).DeleteAsync(force);
ContentstackResponse response = await RetryOnBranchProvisioningAsync(() => _stack.Branch(_createdBranchUidAsync).DeleteAsync(force));
var json = response.OpenJsonObjectResponse();
AssertLogger.IsNotNull(json, "response");
_createdBranchUidAsync = null;
Expand All @@ -268,6 +268,51 @@ public async Task Test011_Should_Delete_Branch_Async()
}
}

// ---- Branch provisioning retry helpers ---------------------------------
// Branch creation is async server-side: POST /branches returns 201 immediately
// with `"deleted_at": "in-progress"` while the branch is still being provisioned.
// Fetch/Delete against a branch in that state returns a 422 "branch is not valid"
// error until the provisioning job completes, so retry with backoff instead of
// failing on the first attempt.

private static bool IsBranchProvisioningError(ContentstackErrorException ex)
{
return ex.StatusCode == (HttpStatusCode)422 && ex.Message != null &&
(ex.Message.Contains("Failed to fetch Branch") || ex.Message.Contains("Branch delete failed") || ex.Message.Contains("is not valid"));
}

private static ContentstackResponse RetryOnBranchProvisioning(Func<ContentstackResponse> action, int maxAttempts = 6, int delayMs = 1000)
{
for (int attempt = 1; attempt < maxAttempts; attempt++)
{
try
{
return action();
}
catch (ContentstackErrorException ex) when (IsBranchProvisioningError(ex))
{
Task.Delay(delayMs).Wait();
}
}
return action();
}

private static async Task<ContentstackResponse> RetryOnBranchProvisioningAsync(Func<Task<ContentstackResponse>> action, int maxAttempts = 6, int delayMs = 1000)
{
for (int attempt = 1; attempt < maxAttempts; attempt++)
{
try
{
return await action();
}
catch (ContentstackErrorException ex) when (IsBranchProvisioningError(ex))
{
await Task.Delay(delayMs);
}
}
return await action();
}

// ---- SDK validation tests (no API call) --------------------------------

[TestMethod]
Expand Down
27 changes: 27 additions & 0 deletions Contentstack.Management.Core.Tests/Mock/extension.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<script
src="https://unpkg.com/@contentstack/ui-extensions-sdk@2.2.3/dist/ui-extension-sdk.js"
integrity="sha512-LMktiFAj7j/AUFctMlgY8qmLrLIQVctwwCsnCXIWnvgF9JlanilvFbZxOCtPNB5eO3vp2Nhw9ED1UsWa+ltSvQ=="
crossorigin="anonymous"
></script>
<link
rel="stylesheet"
type="text/css"
href="https://unpkg.com/@contentstack/ui-extensions-sdk/dist/ui-extension-sdk.css"
integrity="sha512-yPPI/jWiqPr0HIh+1A2QPP5p58sSYqbPoBykxIuBckT1vzGwNbrOmwYM03qGI4ffnxd7q4kkoDys0kdZzxYn9A=="
crossorigin="anonymous"
/>
</head>
<body>
<div id="extension-container"></div>
<script>
ContentstackUIExtension.init().then(function(extension) {
extension.window.updateHeight(200);
}).catch(function(error) {
console.log(error);
});
</script>
</body>
</html>
Loading