Author SHA1 Message Date
vadimenovikau 09a9e68847 ci: retry transient QuickStack rollouts
vadimenovikau/Platform-CI: Immutable QuickStack OCI deployment / Build once and deploy exact digest (pull_request) Canceled after 0s
vadimenovikau/Platform-CI: Immutable QuickStack OCI deployment / Build once and deploy exact digest (push) Canceled after 0s
2026-08-18 19:30:57 +02:00
3 changed files with 2 additions and 67 deletions
+2 -15
View File
@@ -101,10 +101,7 @@ export function createQuickStackClient({ baseUrl, token, fetchImpl = fetch }) {
});
const parsed = await readBody(response);
if (!response.ok) {
throw Object.assign(
new Error(`${method} ${pathname} failed with HTTP ${response.status}: ${parsed?.detail ?? response.statusText}`),
{ statusCode: response.status },
);
throw new Error(`${method} ${pathname} failed with HTTP ${response.status}: ${parsed?.detail ?? response.statusText}`);
}
return parsed;
}
@@ -121,17 +118,7 @@ export function createQuickStackClient({ baseUrl, token, fetchImpl = fetch }) {
async function waitForDeployment(client, appId, deploymentId, sleep) {
for (let attempt = 1; attempt <= 180; attempt += 1) {
let deployment;
try {
deployment = await client.getDeployment(appId, deploymentId);
} catch (error) {
if (error?.statusCode === 404) {
console.log(`QuickStack deployment ${deploymentId}: NOT_VISIBLE_YET (${attempt}/180)`);
await sleep(5_000);
continue;
}
throw error;
}
const deployment = await client.getDeployment(appId, deploymentId);
const status = String(deployment?.status ?? "UNKNOWN").toUpperCase();
console.log(`QuickStack deployment ${deploymentId}: ${status} (${attempt}/180)`);
if (SUCCESS.has(status)) return deployment;
@@ -147,35 +147,3 @@ test("transient QuickStack deployment failures retry the desired immutable image
assert.equal(current.sourceType, "CONTAINER");
assert.equal(current.containerImageSource, image);
});
test("a newly created deployment may be briefly unavailable without triggering rollback", async () => {
let current = app();
let deployments = 0;
let lookups = 0;
const image = `gitea.example/owner/app@sha256:${"c".repeat(64)}`;
const client = {
getApp: async () => current,
saveApp: async (payload) => { current = { ...current, ...payload }; },
deployApp: async () => ({ deploymentId: `deployment-${++deployments}` }),
getDeployment: async (_appId, deploymentId) => {
lookups += 1;
if (lookups === 1) throw Object.assign(new Error("not visible"), { statusCode: 404 });
return { deploymentId, status: "DEPLOYED" };
},
};
const result = await deployExactImage({
client,
appId: "app-one",
image,
registryUsername: "deploy",
registryToken: "token",
sha: "3".repeat(40),
sleep: async () => {},
});
assert.equal(deployments, 1);
assert.equal(lookups, 2);
assert.equal(result.image, image);
assert.equal(current.sourceType, "CONTAINER");
});
-20
View File
@@ -1,20 +0,0 @@
name: Platform CI tests
on:
push:
branches:
- main
pull_request:
branches:
- main
jobs:
test:
name: QuickStack deploy action tests
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Run action tests
run: node --test .gitea/actions/quickstack-oci/deploy.test.mjs