80 Commits

Author SHA1 Message Date
agent_coder 7b5dfeac3f fix(#30 review): clamp the base-file delete + test the crash-recovery adopt branch (F1/F2)
F2 (security): the base-file removal in materializeStackVersion used the unclamped
filepath.Join while the read (GetFileContent) and write
(StoreStackFileFromBytesByVersion) in the same function are clamped. An
attacker-influenceable fileName (stack.EntryPoint/AdditionalFiles via DB
restore/import) could escape basePath in this file-deleting path. Use the clamped
filesystem.JoinPaths, consistent with the read/write.
F1 (test): the adopt branch (complete v{N} on disk but stale DB metadata -> repoint
ProjectPath + set StackFileVersion + seed Versions) is exactly the post-crash state
the crash-safety guarantee relies on (crash between materialize and DB persist), but
no test hit it — existing complete-v-dir tests have consistent metadata and take the
no-op short-circuit. Add TestMigrateStackFileVersions_2_44_0_AdoptCompleteVDirStaleMetadata:
seed a complete v1 on disk, stack with stale flat ProjectPath + empty Versions, no
base copies; assert the migration repoints ProjectPath to v1, sets StackFileVersion=1,
seeds Versions, and leaves the v1 files intact.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-03 01:02:49 +03:00
agent_coder 54854f263f fix(migrator): heal 2.44.0 stacks with StackFileVersion>0 but no on-disk v{N} dir (#30)
The 2.44.0 stack-file-version migration skipped any stack with StackFileVersion>0,
assuming the versioned on-disk layout (compose/{id}/v{N}) already existed. That is
false for stacks whose files still live only at the flat base path (from EE<->CE
edition juggling, DB restores, older builds): they were skipped and left broken —
GET /stacks/{id}/file?version=N returns 500 (the v{N} dir doesn't exist), while the
stack keeps running.

Replace the blanket StackFileVersion>0 skip with a check on the ACTUAL on-disk state
of the current version: complete v-dir -> adopt (idempotent no-op when already
repointed); missing/incomplete -> heal by materializing v{N} from the flat base
files. Factor the fresh (v==0->v1) and heal (v>0-but-missing) paths into one shared
materializeStackVersion helper, and generalize seedStackVersionMetadata to an
arbitrary version v (heals a StackFileVersion=3 stack into v3, not v1; seeds Versions
only when empty so a real history is never clobbered).

Preserves the all-or-nothing guarantee (read every file before writing any; never
write a partial v{N}) and the base-copy-removal ordering (base files are removed only
after ProjectPath is repointed to the v-dir, so a deploy mid-migration or a crash
never finds a missing file — a re-run completes the repoint from the full v{N}).

closes #30

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-03 00:30:35 +03:00
agent_coder d0d3c068ba feat(stacks): file-based stack versioning with full history + rollback (#27)
Adds append-only version history on disk (compose/{id}/v{N}/<files>) for
file-based (WorkflowID==0) Compose/Swarm stacks, with rollback to any past
version. Git stacks (versioned by commit) and Kubernetes are untouched.

Backend:
- Stack model: StackFileVersion, PreviousDeploymentInfo, Versions[]; new
  StackFileVersionInfo type. APIVersion 2.43.0 -> 2.44.0.
- Versioned multi-file snapshot (entrypoint + AdditionalFiles) into v{N}/;
  ProjectPath repointed via GetStackProjectPathByVersion each deploy. Retention
  cap (20): Versions[] trimmed in-tx, old dirs deleted only AFTER the tx commits.
- Update handlers: RollbackTo (content read server-side from the target version,
  never trusted from the client; validated 1..current & present in Versions).
- Create paths seed v1. stackFile reads ?version= (validated; negative -> 400).
- New GET /stacks/{id}/versions endpoint.
- Migration 2.44.0: move existing file-based stacks' files into v1/ (idempotent,
  atomic pre-read of the full file set, skips git/kube/orphans).

Frontend:
- useStackVersions query + stackVersions key; StackEditorTab builds the full
  history list; StackVersionSelector shows 'v{N} · date · author'; file/versions
  caches invalidated (by prefix) after deploy/rollback.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-02 16:07:26 +03:00
claude code agent 32a2b7a9ae feat(automation): health-gated rollback + per-endpoint + notify hook (#12, epic #3 M5)
P0 Health-gated rollback (standalone auto-update path): capture the previous
image id + reference + healthcheck before the recreate, then poll the new
container's health over a configurable window. On healthy proceed (and only
then clean up the old image); on unhealthy/exit/timeout re-tag the old image
back onto the original reference and Recreate (no pull) to restore it, reusing
Recreate's config preservation. The decision is a pure decideRollback() helper.

P1 Per-endpoint enable: ContainerAutomationDisabled flag on Endpoint (zero value
participates, no migration churn), checked by both daemons; settable via the
endpoint update API. UI control deferred (see report).

P2 Notifier seam: minimal Notifier interface + logNotifier, emitting structured
updated/rollback/update-failed/heal-restarted events from the daemon.

Settings: RollbackOnFailure + RollbackTimeout (default 120s) added to
ContainerAutomation.AutoUpdate, wired through defaults/migration/golden,
settings_update validation, the AutoUpdatePanel and the TS types.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-29 10:41:55 +03:00
claude code agent b3ae5f3659 feat(automation): native auto-update daemon (#11, epic #3 M4)
Add an optional periodic auto-update daemon that detects outdated container
images and applies updates, replacing the containrrr/watchtower sidecar. It
extends M1's containerautomation service/scheduler/labels infrastructure and
reuses the existing zlib image-detection engine, the standalone Recreate path
and the stack deployer.

Backend:
- api/containerautomation/autoupdate.go: scheduler job iterating Docker
  (non-edge) endpoints -> in-scope running containers -> ContainerImageStatus;
  for Outdated: standalone -> ContainerService.Recreate(pull); stack-managed ->
  one stack redeploy-with-pull per stack per tick (git via RedeployWhenChanged,
  file via the deployer directly); external compose -> detect only. Monitor-only
  containers are status-checked (warms the badge cache) but never applied.
  Overlap guard (atomic), pull/registry-auth failure -> leave running container
  untouched, conservative cleanup of the dangling old image on the Cleanup flag
  (non-forced ImageRemove only succeeds when truly unused).
- labels.go: update enable / monitor-only labels with watchtower aliases,
  InUpdateScope, IsMonitorOnly, and pure resolveContainerUpdateRouting /
  groupContainersForUpdate (Go analogue of M3's TS routing + grouping).
- service.go: run both jobs, Reload restarts/stops each per settings; NewService
  also takes ContainerService, StackDeployer and GitService.
- Settings.ContainerAutomation.AutoUpdate {Enabled, PollInterval, Scope,
  Cleanup} with fresh-install defaults and a 2.43.0 backfill (extends M1's
  migration; golden test data updated). settings handler validates + reloads.

Frontend:
- Global AutoUpdatePanel in SettingsView (enable / poll interval / scope /
  cleanup) via useUpdateSettingsMutation, plus settings TS types.
- Read-only per-container Auto-update row in the container details view
  (Docker labels are immutable at runtime), surfacing monitor-only.

Tests: Go unit tests for the update label aliases, scope, monitor-only, the
routing decision and the one-redeploy-per-stack grouping; vitest for the panel
and the per-container row.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-29 10:04:09 +03:00
claude code agent 51957d2f98 feat(automation): native auto-heal daemon (#8, epic #3 M1)
Add a native, CE-only auto-heal daemon that restarts Docker containers whose
healthcheck reports "unhealthy", replacing the willfarrell/autoheal sidecar.

Backend:
- New package api/containerautomation (service lifecycle + scheduler job,
  per-endpoint heal pass, label/scope parsing, in-memory cooldown/retry state).
- Settings.ContainerAutomation.AutoHeal {Enabled, CheckInterval, Scope} with
  fresh-install defaults and a 2.43.0 migration backfilling existing installs.
- Settings update handler reloads/stops the job via a small Reloader interface
  (no import cycle); service bootstrapped from main.go after stack schedules.

Frontend:
- Global AutoHealPanel in SettingsView (enable / interval / scope) via
  useUpdateSettingsMutation, plus settings TS types.
- Read-only per-container Auto-heal row in the container details view (Docker
  labels are immutable at runtime; opt-in is set via Create/Edit form labels).

Tests: Go unit tests for label/scope resolution and the cooldown/retry decision;
vitest for the panel and the per-container row.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-29 08:22:46 +03:00
andres-portainer 0da42c01b6 feat(gitcredential): remove GitCredential BE-12919 (#2838) 2026-06-11 18:53:24 -03:00
andres-portainer df7a4b5d6f feat(gitops): improve the data model BE-12919 (#2819) 2026-06-08 15:01:55 -03:00
andres-portainer 8daf0bb2a9 feat(customtemplates): use Sources for CustomTemplates BE-12919 (#2759) 2026-06-05 01:51:18 -03:00
andres-portainer ab4626e7de feat(workflows): introduce Artifacts BE-12919 (#2740) 2026-05-26 16:17:32 -03:00
andres-portainer 3d09c70e13 feat(sources): add sources and workflows to the backend BE-12919 (#2666) 2026-05-20 20:42:10 -03:00
andres-portainer 1298fc629e chore(tests): allow for the tests to run in parallel BE-12801 (#2231) 2026-04-07 17:38:22 -03:00
Ali f84e657707 feat(registries): support service accounts with registry secrets for cluster level [C9S 37] (#2120) 2026-03-25 11:00:13 +13:00
andres-portainer da6544e981 fix(semver): consolidate dependencies BE-12695 (#2014) 2026-03-09 15:33:45 -03:00
Josiah Clumont e0c22ea3eb fix(copy): Fixed an issue with the downgrade links [R8S-832] (#1907) 2026-02-19 09:38:04 +13:00
andres-portainer 71c000756b chore(linters): enforce error checking in CE BE-12527 (#1723) 2026-01-26 14:37:55 -03:00
Chaim Lev-Ari aef27f475d feat(analytics): remove setting for collection analytics [BE-12402] (#1559) 2025-12-22 15:59:08 +02:00
andres-portainer 30e70b6327 chore(version): bump to v2.34.0 (#1216) 2025-09-15 22:13:51 -03:00
andres-portainer ec0e98a64b chore(linters): enable testifylint BE-12183 (#1091) 2025-08-22 15:31:10 -03:00
andres-portainer 2035c42c3c fix(migrator): rewrite a migration so it is idempotent BE-12053 (#1042) 2025-08-15 09:26:10 -03:00
andres-portainer 2c08becf6c feat(openai): remove OpenAI BE-12018 (#873) 2025-08-14 10:42:21 -03:00
Andrew Amesbury 3ade5cdf19 bump version to 2.33.0-rc1 (#1019) 2025-08-13 14:40:34 +12:00
andres-portainer 937456596a fix(edgegroups): convert the related endpoint IDs to roaring bitmaps to increase performance BE-12053 (#903) 2025-07-21 21:31:13 -03:00
Oscar Zhou b6f3682a62 refactor(edge): init endpoint relation when endpoint is created [BE-11928] (#814) 2025-06-30 15:15:56 -03:00
andres-portainer 75f165d1ff feat(edgestackstatus): optimize the Edge Stack structures BE-11740 (#756) 2025-06-05 19:46:10 -03:00
andres-portainer e319a7a5ae fix(linter): enable ineffassign BE-10204 (#669) 2025-04-21 19:27:14 -03:00
andres-portainer e1f9b69cd5 feat(edgestack): improve the structure to make JSON operations faster BE-11668 (#475) 2025-03-15 10:10:17 -03:00
Oscar Zhou ee0dbf2d22 feat(init): allow to customize kubectl-shell image by cli flag [BE-11419] (#162) 2024-11-26 10:17:46 +13:00
andres-portainer f0d43f941f chore(code): replace interface{} with any EE-6513 (#11986) 2024-06-28 14:59:28 -03:00
andres-portainer 19fa40286a chore(fdo): remove FDO code EE-7235 (#11981) 2024-06-28 08:42:16 -03:00
andres-portainer 9ee092aa5e chore(code): reduce the code duplication EE-7278 (#11969) 2024-06-26 18:14:22 -03:00
andres-portainer 90a19cec5c chore(code): remove unnecessary type conversions EE-7191 (#11908) 2024-06-10 09:32:52 -03:00
Matt Hook 5a5a10821d fix(pendingactions): refactor pending actions [EE-7011] (#11780) 2024-05-09 08:10:10 +12:00
Dakota Walsh 439f13af19 fix(migration): improper version EE-7048 (#11712) 2024-04-30 21:30:40 -04:00
Prabhat Khera d9df58e93a fix(pending-actions): clean pending actions for deleted environment [EE-6545] (#11598) 2024-04-16 15:09:10 +12:00
Matt Hook bdeedb4018 fix(namespace): fix default namespace quota [EE-6700] (#11185) 2024-02-16 08:20:24 +13:00
Ali e84dd27e88 feat(cache): default to off [EE-6293] (#10867)
Co-authored-by: testa113 <testa113>
2023-12-19 12:13:44 +13:00
Ali 4096bb562d feat(cache): introduce cache option [EE-6293] (#10672)
Co-authored-by: testa113 <testa113>
2023-11-22 14:21:07 +13:00
Ali ecce501cf3 Revert "feat(cache): introduce cache option [EE-6293] (#10641)" (#10658)
This reverts commit 2c032f1739.
2023-11-20 15:08:19 +13:00
Ali 2c032f1739 feat(cache): introduce cache option [EE-6293] (#10641) 2023-11-20 10:22:48 +13:00
Chaim Lev-Ari e1e90c9c1d feat(edge/templates): introduce edge app templates [EE-6209] (#10480) 2023-11-14 14:54:44 +02:00
Matt Hook 8ee718f808 chore(binaries): upgrade binaries [EE-6253] (#10529) 2023-10-27 15:40:06 +13:00
cmeng 6fde4195f8 fix(migrator): prevent duplicated migration EE-5777 (#10077) 2023-08-18 21:40:48 +12:00
Chaim Lev-Ari fd7e8a629e feat(edge/stacks): info for old agent status [EE-5792] (#10013) 2023-08-14 16:04:24 +03:00
Chaim Lev-Ari 0bcb57568c feat(edge/stacks): increase status transparency [EE-5554] (#9094) 2023-07-13 23:55:52 +03:00
cmeng b93624fa1f fix(chisel): convert seed to private key file EE-5099 (#9149) 2023-07-13 15:19:40 +12:00
andres-portainer 64b227b2e1 chore(code): clean up the code EE-5719 (#9183) 2023-07-10 23:26:54 -03:00
andres-portainer 4cc96b4b30 feat(dataservices): unify access methods and abstract away redundant code [EE-5628] (#9115) 2023-06-22 18:28:07 -03:00
Prabhat Khera 14fa60f6e6 fix(docker): fix extension spelling EE-5277 (#8956) 2023-05-18 10:21:07 +12:00
Prabhat Khera 83551201fb fix(docker): add docker desktop extension flag in settings and add migration EE-5277 (#8948) 2023-05-17 14:31:46 +12:00