api(config): ?apply=staged|live gates SSE push on PUT /apps/{slug}/config
When apply=staged, saves to DB only — no CONFIG_UPDATE dispatched to agents. When apply=live (default, back-compat), preserves today's immediate-push behavior. Unknown apply values return 400. Audit action is stage_app_config vs update_app_config. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -108,13 +108,20 @@ public class ApplicationConfigController {
|
||||
|
||||
@PutMapping("/apps/{appSlug}/config")
|
||||
@Operation(summary = "Update application config for this environment",
|
||||
description = "Saves config and pushes CONFIG_UPDATE to LIVE agents of this application in the given environment")
|
||||
@ApiResponse(responseCode = "200", description = "Config saved and pushed")
|
||||
description = "Saves config. When apply=live (default), also pushes CONFIG_UPDATE to LIVE agents. "
|
||||
+ "When apply=staged, persists without a live push — the next successful deploy applies it.")
|
||||
@ApiResponse(responseCode = "200", description = "Config saved (and pushed if apply=live)")
|
||||
@ApiResponse(responseCode = "400", description = "Unknown apply value (must be 'staged' or 'live')")
|
||||
public ResponseEntity<ConfigUpdateResponse> updateConfig(@EnvPath Environment env,
|
||||
@PathVariable String appSlug,
|
||||
@RequestParam(name = "apply", defaultValue = "live") String apply,
|
||||
@RequestBody ApplicationConfig config,
|
||||
Authentication auth,
|
||||
HttpServletRequest httpRequest) {
|
||||
if (!"staged".equalsIgnoreCase(apply) && !"live".equalsIgnoreCase(apply)) {
|
||||
return ResponseEntity.status(HttpStatus.BAD_REQUEST).build();
|
||||
}
|
||||
|
||||
String updatedBy = auth != null ? auth.getName() : "system";
|
||||
|
||||
config.setApplication(appSlug);
|
||||
@@ -126,14 +133,24 @@ public class ApplicationConfigController {
|
||||
List<String> perAppKeys = extractSensitiveKeys(saved);
|
||||
List<String> mergedKeys = SensitiveKeysMerger.merge(globalKeys, perAppKeys);
|
||||
|
||||
CommandGroupResponse pushResult = pushConfigToAgentsWithMergedKeys(appSlug, env.slug(), saved, mergedKeys);
|
||||
log.info("Config v{} saved for '{}', pushed to {} agent(s), {} responded",
|
||||
saved.getVersion(), appSlug, pushResult.total(), pushResult.responded());
|
||||
CommandGroupResponse pushResult;
|
||||
if ("staged".equalsIgnoreCase(apply)) {
|
||||
pushResult = new CommandGroupResponse(true, 0, 0, List.of(), List.of());
|
||||
log.info("Config v{} staged for '{}' (no live push)", saved.getVersion(), appSlug);
|
||||
} else {
|
||||
pushResult = pushConfigToAgentsWithMergedKeys(appSlug, env.slug(), saved, mergedKeys);
|
||||
log.info("Config v{} saved for '{}', pushed to {} agent(s), {} responded",
|
||||
saved.getVersion(), appSlug, pushResult.total(), pushResult.responded());
|
||||
}
|
||||
|
||||
auditService.log("update_app_config", AuditCategory.CONFIG, appSlug,
|
||||
auditService.log(
|
||||
"staged".equalsIgnoreCase(apply) ? "stage_app_config" : "update_app_config",
|
||||
AuditCategory.CONFIG, appSlug,
|
||||
Map.of("environment", env.slug(), "version", saved.getVersion(),
|
||||
"apply", apply.toLowerCase(),
|
||||
"agentsPushed", pushResult.total(),
|
||||
"responded", pushResult.responded(), "timedOut", pushResult.timedOut().size()),
|
||||
"responded", pushResult.responded(),
|
||||
"timedOut", pushResult.timedOut().size()),
|
||||
AuditResult.SUCCESS, httpRequest);
|
||||
|
||||
return ResponseEntity.ok(new ConfigUpdateResponse(saved, pushResult));
|
||||
|
||||
Reference in New Issue
Block a user