Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
078adc9
[316] Serve published dashboards behind a customer path prefix
CarsonDavis Aug 27, 2026
305feed
[316] Apply review fixes and prune test slop on the dashboard-subpath PR
CarsonDavis Sep 1, 2026
738e1dc
[316] Correct the CloudFront Function ES5 note (arrow fns and templat…
CarsonDavis Sep 1, 2026
46cd878
[316] Converge a dashboard's CloudFormation stack on republish
CarsonDavis Aug 27, 2026
967c416
[316] Rework republish stack convergence and prune test slop
CarsonDavis Sep 1, 2026
3600864
[316] Trim convergeStackUpdate comments (drop the duplicated prior ra…
CarsonDavis Sep 1, 2026
0e5af20
Merge 316-dashboard-subpath into 316-republish-stack-convergence
CarsonDavis Sep 3, 2026
c1700ac
Merge 316-dashboard-subpath into 316-republish-stack-convergence
CarsonDavis Sep 3, 2026
182c131
[316] Return the settled stack on a no-op converge and let publish co…
CarsonDavis Sep 3, 2026
7d70ca5
[316] Name the OAC grants as headroom and fix the update route's order
CarsonDavis Sep 3, 2026
b96e9ad
Merge remote-tracking branch 'origin/316-dashboard-subpath' into 316-…
CarsonDavis Sep 3, 2026
6aa1396
[316] Re-check the stack after every wait-out and pace the busy retry
CarsonDavis Sep 3, 2026
d8d54bf
[316] Refuse an update on an in-flight or deleted deployment and desc…
CarsonDavis Sep 3, 2026
8a9e192
[316] Re-read the stack on every attempt and bound the converge by a …
CarsonDavis Sep 3, 2026
465f5c5
[316] Refuse an update only while the live stack is mid-operation
CarsonDavis Sep 3, 2026
fdbed57
Merge remote-tracking branch 'origin/316-dashboard-subpath' into 316-…
CarsonDavis Sep 3, 2026
c7f10b4
Merge remote-tracking branch 'origin/316-dashboard-subpath' into 316-…
CarsonDavis Sep 3, 2026
7c7b0c7
[316] Treat a vanished stack as gone, name the busy status, and pin A…
CarsonDavis Sep 3, 2026
3e90b4a
[316] Decide update refusals in one testable helper and always refuse…
CarsonDavis Sep 3, 2026
4e1fd73
Merge remote-tracking branch 'origin/316-dashboard-subpath' into 316-…
CarsonDavis Sep 3, 2026
02537e6
[316] Decide the publish flow in pure helpers and stop a Delete from …
CarsonDavis Sep 3, 2026
11ce50a
[316] Name the missing-stack refusal and record the 409 contract in t…
CarsonDavis Sep 3, 2026
aa2bdbf
Merge remote-tracking branch 'origin/316-dashboard-subpath' into 316-…
CarsonDavis Sep 3, 2026
7ca7ddc
[316] Guard every bucket write behind a live row and keep the stalene…
CarsonDavis Sep 4, 2026
c7184e3
[316] Refuse a recent in-flight update, recover a stack-less row, and…
CarsonDavis Sep 4, 2026
28bf90a
Merge remote-tracking branch 'origin/316-dashboard-subpath' into 316-…
CarsonDavis Sep 4, 2026
d1883a9
[316] Render the template before the build and share the unusable-sta…
CarsonDavis Sep 4, 2026
cc3e10e
[316] Claim the row atomically, refuse settled wedged stacks up front…
CarsonDavis Sep 4, 2026
5323413
[316] Heartbeat the row between steps and give every wedged-stack mes…
CarsonDavis Sep 4, 2026
975deed
[316] Claim on status and timestamp, refuse any readable wedged stack…
CarsonDavis Sep 4, 2026
07865b2
Merge remote-tracking branch 'origin/316-dashboard-subpath' into 316-…
CarsonDavis Sep 4, 2026
5e29ccd
[316] Heartbeat the row through the copy and uploads and return one s…
CarsonDavis Sep 4, 2026
6c7b42a
[316] Refuse an unreadable stack for every row status and start both …
CarsonDavis Sep 4, 2026
528330b
[316] Keep only the audited fixes: fresh read before each UpdateStack…
CarsonDavis Sep 4, 2026
e7b49ea
Merge remote-tracking branch 'origin/316-dashboard-subpath' into 316-…
CarsonDavis Sep 4, 2026
2bf514e
[316] Drop the duplicated function-behaviour block the merge left in …
CarsonDavis Sep 4, 2026
07ede2b
[316] Match the unusable-stack guidance to the stack's state
CarsonDavis Sep 8, 2026
a2178d0
[316] Lock the admin's publish actions on ECS task liveness
CarsonDavis Sep 8, 2026
a809ff3
Merge remote-tracking branch 'origin/316-dashboard-subpath' into 316-…
CarsonDavis Sep 9, 2026
d792a83
Merge remote-tracking branch 'origin/316-dashboard-subpath' into 316-…
CarsonDavis Sep 9, 2026
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
53 changes: 53 additions & 0 deletions API/Backend/Deployments/models/deployment.js
Original file line number Diff line number Diff line change
Expand Up @@ -74,5 +74,58 @@ var Deployments = sequelize.define(

Deployments.STATUS = STATUS;

// Statuses under which a publish task may be running for the row.
const IN_FLIGHT_STATUSES = Object.freeze([STATUS.PROVISIONING, STATUS.UPDATING]);
Deployments.IN_FLIGHT_STATUSES = IN_FLIGHT_STATUSES;

// Records the ECS task ARN of the row's publish task under
// `settings.publish_task_arn`, so a read can ask ECS whether the task is
// still alive. Both the route that starts the task and the task itself call
// this. `settings` is a plain JSON column (last writer wins), so the write
// spreads the latest read; it is conditional on the row still being in
// flight, so a Delete that landed in between never regains a task ARN on
// its `deleting` row. The write is silent so `updatedAt` stays the moment
// the row was claimed for this run, which is what the reads measure the
// task's age from. Resolves the number of rows written (0 or 1).
Deployments.recordPublishTaskArn = async function (deploymentId, taskArn) {
const latest = await Deployments.findByPk(deploymentId);
if (latest == null) return 0;
const [written] = await Deployments.update(
{ settings: { ...(latest.settings || {}), publish_task_arn: taskArn } },
{
where: {
id: deploymentId,
status: { [Sequelize.Op.in]: IN_FLIGHT_STATUSES },
},
silent: true,
}
);
return written;
};

// Marks the row `failed` because ECS reported the publish task recorded on
// it as stopped or missing. The write is pinned to the row still being in
// flight and still carrying that very ARN (a JSON path on `settings`), so
// it can neither overwrite a terminal status the task wrote in the meantime
// nor land on a row an Update has since re-claimed for a new task.
// Resolves the number of rows written (0 or 1).
Deployments.markPublishTaskExited = async function (
deploymentId,
taskArn,
lastError
) {
const [flipped] = await Deployments.update(
{ status: STATUS.FAILED, last_error: lastError },
{
where: {
id: deploymentId,
status: { [Sequelize.Op.in]: IN_FLIGHT_STATUSES },
"settings.publish_task_arn": taskArn,
},
}
);
return flipped;
};

// export Deployments model for use in other files.
module.exports = Deployments;
Loading
Loading