e63d2ffe9b
Clicking "Update" on a stack member (and the native auto-update daemon updating one) redeployed the whole compose stack instead of updating just that container. Match Watchtower behaviour: always recreate the single container with a re-pull. The recreate endpoint preserves config + compose labels, so the container stays part of its project. Collapse all update surfaces to a single-container recreate and drop the now-dead stack-aware routing: - frontend: "Update now" button, list badge and bulk "Update selected" now recreate each container individually; remove standalone/stack/external routing, the external refusal, the PortainerStackUpdate gate and the stack-update confirm dialog. - daemon: route every outdated candidate through updateStandalone; remove updateStack, the stack/external grouping and the stackDeployer dependency. - add a regression test asserting a Portainer-managed compose-stack member is recreated individually, not stack-redeployed. Behavioural notes: git/external compose containers are now auto-updated too (were detect-only), and updating a stack member no longer requires PortainerStackUpdate (same auth as the normal Recreate action). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
24 lines
1019 B
TypeScript
24 lines
1019 B
TypeScript
import { recreateContainer } from '../containers.service';
|
|
|
|
import { ContainerUpdateContext } from './types';
|
|
|
|
/**
|
|
* Shared "apply an image update" primitive. Recreates the single container with
|
|
* a fresh image pull via the Portainer `containers/{id}/recreate` endpoint. This
|
|
* is the single frontend code path behind the "Update now" button and the bulk
|
|
* "Update selected" action, guaranteeing both manual flows behave identically.
|
|
*
|
|
* The recreate endpoint preserves the container's configuration and its compose
|
|
* labels, so a recreated stack member stays part of its project — Watchtower-style:
|
|
* only this one container is updated, the owning stack is never redeployed and an
|
|
* externally-managed compose container is never refused.
|
|
*/
|
|
export async function applyContainerUpdate(
|
|
context: ContainerUpdateContext,
|
|
{ pullImage = true }: { pullImage?: boolean } = {}
|
|
): Promise<void> {
|
|
await recreateContainer(context.environmentId, context.id, pullImage, {
|
|
nodeName: context.nodeName,
|
|
});
|
|
}
|