gitops 1.11.0__tar.gz → 1.12.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (97) hide show
  1. gitops-1.12.0/.release-please-manifest.json +5 -0
  2. {gitops-1.11.0 → gitops-1.12.0}/CHANGELOG.md +15 -0
  3. {gitops-1.11.0 → gitops-1.12.0}/PKG-INFO +1 -1
  4. {gitops-1.11.0 → gitops-1.12.0}/charts/gitops/CHANGELOG.md +8 -0
  5. {gitops-1.11.0 → gitops-1.12.0}/charts/gitops/Chart.yaml +1 -1
  6. {gitops-1.11.0 → gitops-1.12.0}/charts/gitops/templates/deployment.yml +2 -0
  7. {gitops-1.11.0 → gitops-1.12.0}/charts/gitops/values.yaml +2 -0
  8. {gitops-1.11.0 → gitops-1.12.0}/gitops/__init__.py +1 -1
  9. {gitops-1.11.0 → gitops-1.12.0}/gitops_server/app.py +15 -8
  10. {gitops-1.11.0 → gitops-1.12.0}/gitops_server/settings.py +8 -0
  11. gitops-1.12.0/gitops_server/version.py +1 -0
  12. {gitops-1.11.0 → gitops-1.12.0}/gitops_server/workers/deployer/deploy.py +14 -0
  13. {gitops-1.11.0 → gitops-1.12.0}/gitops_server/workers/deployer/worker.py +17 -1
  14. {gitops-1.11.0 → gitops-1.12.0}/pyproject.toml +1 -1
  15. gitops-1.12.0/tests/test_shutdown.py +78 -0
  16. {gitops-1.11.0 → gitops-1.12.0}/uv.lock +10 -10
  17. gitops-1.11.0/.release-please-manifest.json +0 -5
  18. gitops-1.11.0/gitops_server/version.py +0 -1
  19. {gitops-1.11.0 → gitops-1.12.0}/.dockerignore +0 -0
  20. {gitops-1.11.0 → gitops-1.12.0}/.github/CODEOWNERS +0 -0
  21. {gitops-1.11.0 → gitops-1.12.0}/.github/workflows/release-please.yaml +0 -0
  22. {gitops-1.11.0 → gitops-1.12.0}/.github/workflows/test.yml +0 -0
  23. {gitops-1.11.0 → gitops-1.12.0}/.gitignore +0 -0
  24. {gitops-1.11.0 → gitops-1.12.0}/.mise.toml +0 -0
  25. {gitops-1.11.0 → gitops-1.12.0}/.pre-commit-config.yaml +0 -0
  26. {gitops-1.11.0 → gitops-1.12.0}/CLAUDE.md +0 -0
  27. {gitops-1.11.0 → gitops-1.12.0}/Dockerfile +0 -0
  28. {gitops-1.11.0 → gitops-1.12.0}/LICENSE +0 -0
  29. {gitops-1.11.0 → gitops-1.12.0}/README.md +0 -0
  30. {gitops-1.11.0 → gitops-1.12.0}/charts/gitops/.helmignore +0 -0
  31. {gitops-1.11.0 → gitops-1.12.0}/charts/gitops/README.md +0 -0
  32. {gitops-1.11.0 → gitops-1.12.0}/charts/gitops/templates/_helpers.tpl +0 -0
  33. {gitops-1.11.0 → gitops-1.12.0}/charts/gitops/templates/certificate.yml +0 -0
  34. {gitops-1.11.0 → gitops-1.12.0}/charts/gitops/templates/environment.yml +0 -0
  35. {gitops-1.11.0 → gitops-1.12.0}/charts/gitops/templates/ingress.yml +0 -0
  36. {gitops-1.11.0 → gitops-1.12.0}/charts/gitops/templates/issuer.yml +0 -0
  37. {gitops-1.11.0 → gitops-1.12.0}/charts/gitops/templates/pdb.yml +0 -0
  38. {gitops-1.11.0 → gitops-1.12.0}/charts/gitops/templates/secrets.yml +0 -0
  39. {gitops-1.11.0 → gitops-1.12.0}/charts/gitops/templates/service.yml +0 -0
  40. {gitops-1.11.0 → gitops-1.12.0}/charts/gitops/templates/serviceaccount.yaml +0 -0
  41. {gitops-1.11.0 → gitops-1.12.0}/docker-compose.yml +0 -0
  42. {gitops-1.11.0 → gitops-1.12.0}/docs/plans/2026-03-13-kms-encryption-design.md +0 -0
  43. {gitops-1.11.0 → gitops-1.12.0}/gitops/common/__init__.py +0 -0
  44. {gitops-1.11.0 → gitops-1.12.0}/gitops/common/app.py +0 -0
  45. {gitops-1.11.0 → gitops-1.12.0}/gitops/common/utils.py +0 -0
  46. {gitops-1.11.0 → gitops-1.12.0}/gitops/core.py +0 -0
  47. {gitops-1.11.0 → gitops-1.12.0}/gitops/main.py +0 -0
  48. {gitops-1.11.0 → gitops-1.12.0}/gitops/py.typed +0 -0
  49. {gitops-1.11.0 → gitops-1.12.0}/gitops/settings.py +0 -0
  50. {gitops-1.11.0 → gitops-1.12.0}/gitops/shorthands.py +0 -0
  51. {gitops-1.11.0 → gitops-1.12.0}/gitops/utils/__init__.py +0 -0
  52. {gitops-1.11.0 → gitops-1.12.0}/gitops/utils/apps.py +0 -0
  53. {gitops-1.11.0 → gitops-1.12.0}/gitops/utils/async_runner.py +0 -0
  54. {gitops-1.11.0 → gitops-1.12.0}/gitops/utils/cli.py +0 -0
  55. {gitops-1.11.0 → gitops-1.12.0}/gitops/utils/exceptions.py +0 -0
  56. {gitops-1.11.0 → gitops-1.12.0}/gitops/utils/images.py +0 -0
  57. {gitops-1.11.0 → gitops-1.12.0}/gitops/utils/kube.py +0 -0
  58. {gitops-1.11.0 → gitops-1.12.0}/gitops/utils/tags.py +0 -0
  59. {gitops-1.11.0 → gitops-1.12.0}/gitops/utils/yaml.py +0 -0
  60. {gitops-1.11.0 → gitops-1.12.0}/gitops_server/CHANGELOG.md +0 -0
  61. {gitops-1.11.0 → gitops-1.12.0}/gitops_server/README.md +0 -0
  62. {gitops-1.11.0 → gitops-1.12.0}/gitops_server/__init__.py +0 -0
  63. {gitops-1.11.0 → gitops-1.12.0}/gitops_server/main.py +0 -0
  64. {gitops-1.11.0 → gitops-1.12.0}/gitops_server/types.py +0 -0
  65. {gitops-1.11.0 → gitops-1.12.0}/gitops_server/utils/__init__.py +0 -0
  66. {gitops-1.11.0 → gitops-1.12.0}/gitops_server/utils/git.py +0 -0
  67. {gitops-1.11.0 → gitops-1.12.0}/gitops_server/utils/github.py +0 -0
  68. {gitops-1.11.0 → gitops-1.12.0}/gitops_server/utils/github_auth.py +0 -0
  69. {gitops-1.11.0 → gitops-1.12.0}/gitops_server/utils/slack.py +0 -0
  70. {gitops-1.11.0 → gitops-1.12.0}/gitops_server/workers/__init__.py +0 -0
  71. {gitops-1.11.0 → gitops-1.12.0}/gitops_server/workers/deployer/__init__.py +0 -0
  72. {gitops-1.11.0 → gitops-1.12.0}/gitops_server/workers/deployer/disruption.py +0 -0
  73. {gitops-1.11.0 → gitops-1.12.0}/gitops_server/workers/deployer/hooks.py +0 -0
  74. {gitops-1.11.0 → gitops-1.12.0}/gitops_server/workers/deployer/semaphore_manager.py +0 -0
  75. {gitops-1.11.0 → gitops-1.12.0}/release-please-config.json +0 -0
  76. {gitops-1.11.0 → gitops-1.12.0}/release.py +0 -0
  77. {gitops-1.11.0 → gitops-1.12.0}/renovate.json +0 -0
  78. {gitops-1.11.0 → gitops-1.12.0}/ruff.toml +0 -0
  79. {gitops-1.11.0 → gitops-1.12.0}/secrets.example.env +0 -0
  80. {gitops-1.11.0 → gitops-1.12.0}/setup.cfg +0 -0
  81. {gitops-1.11.0 → gitops-1.12.0}/tests/__init__.py +0 -0
  82. {gitops-1.11.0 → gitops-1.12.0}/tests/conftest.py +0 -0
  83. {gitops-1.11.0 → gitops-1.12.0}/tests/sample_data.py +0 -0
  84. {gitops-1.11.0 → gitops-1.12.0}/tests/test_app.py +0 -0
  85. {gitops-1.11.0 → gitops-1.12.0}/tests/test_clone_credentials.py +0 -0
  86. {gitops-1.11.0 → gitops-1.12.0}/tests/test_core.py +0 -0
  87. {gitops-1.11.0 → gitops-1.12.0}/tests/test_deploy.py +0 -0
  88. {gitops-1.11.0 → gitops-1.12.0}/tests/test_deploy_concurrent.py +0 -0
  89. {gitops-1.11.0 → gitops-1.12.0}/tests/test_disruption_guard.py +0 -0
  90. {gitops-1.11.0 → gitops-1.12.0}/tests/test_git.py +0 -0
  91. {gitops-1.11.0 → gitops-1.12.0}/tests/test_github_auth.py +0 -0
  92. {gitops-1.11.0 → gitops-1.12.0}/tests/test_gitops_server.py +0 -0
  93. {gitops-1.11.0 → gitops-1.12.0}/tests/test_load_app_definitions.py +0 -0
  94. {gitops-1.11.0 → gitops-1.12.0}/tests/test_utils.py +0 -0
  95. {gitops-1.11.0 → gitops-1.12.0}/tests/test_worker_concurrency.py +0 -0
  96. {gitops-1.11.0 → gitops-1.12.0}/tests/utils.py +0 -0
  97. {gitops-1.11.0 → gitops-1.12.0}/tests/webhook_sample_data.py +0 -0
@@ -0,0 +1,5 @@
1
+ {
2
+ ".": "1.12.0",
3
+ "gitops_server": "0.15.1",
4
+ "charts/gitops": "1.6.0"
5
+ }
@@ -1,5 +1,20 @@
1
1
  # Changelog
2
2
 
3
+ ## [1.12.0](https://github.com/uptick/gitops/compare/gitops-v1.11.0...gitops-v1.12.0) (2026-11-02)
4
+
5
+
6
+ ### Features
7
+
8
+ * **server:** finish running helm upgrades on shutdown ([92a7952](https://github.com/uptick/gitops/commit/92a7952f91b90543ed573d8c96d8853ff8f7caf5))
9
+ * **server:** finish running helm upgrades on shutdown ([ef16fd2](https://github.com/uptick/gitops/commit/ef16fd21ae53cba6987aecc4455ffdf6b254f4e1))
10
+ * **server:** report work dropped at shutdown, at ERROR by default ([eb2717b](https://github.com/uptick/gitops/commit/eb2717b3ead89abdcffe37e0b14cfd9688ed9994))
11
+
12
+
13
+ ### Bug Fixes
14
+
15
+ * **deps:** upgrade botocore to 1.43.117 ([7d1e151](https://github.com/uptick/gitops/commit/7d1e1517770c5f7ffa66a883a6e860852405c011))
16
+ * **deps:** upgrade botocore to 1.43.117 ([77e7bcf](https://github.com/uptick/gitops/commit/77e7bcfbc1d7f46124d486f67cb35a9d3ac18467))
17
+
3
18
  ## [1.11.0](https://github.com/uptick/gitops/compare/gitops-v1.10.2...gitops-v1.11.0) (2026-10-27)
4
19
 
5
20
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: gitops
3
- Version: 1.11.0
3
+ Version: 1.12.0
4
4
  Summary: Manage multiple apps across one or more k8s clusters.
5
5
  Author-email: Jarek Głowacki <jarekwg@gmail.com>
6
6
  License-File: LICENSE
@@ -1,5 +1,13 @@
1
1
  # Changelog
2
2
 
3
+ ## [1.6.0](https://github.com/uptick/gitops/compare/helm-v1.5.0...helm-v1.6.0) (2026-11-02)
4
+
5
+
6
+ ### Features
7
+
8
+ * **server:** finish running helm upgrades on shutdown ([92a7952](https://github.com/uptick/gitops/commit/92a7952f91b90543ed573d8c96d8853ff8f7caf5))
9
+ * **server:** finish running helm upgrades on shutdown ([ef16fd2](https://github.com/uptick/gitops/commit/ef16fd21ae53cba6987aecc4455ffdf6b254f4e1))
10
+
3
11
  ## [1.5.0](https://github.com/uptick/gitops/compare/helm-v1.4.1...helm-v1.5.0) (2026-10-27)
4
12
 
5
13
 
@@ -2,4 +2,4 @@ apiVersion: v1
2
2
  appVersion: "1.0"
3
3
  description: GitOps Server Helm chart.
4
4
  name: gitops
5
- version: 1.5.0
5
+ version: 1.6.0
@@ -24,6 +24,8 @@ spec:
24
24
  spec:
25
25
  serviceAccountName: {{ include "uptick.serviceAccountName" . }}
26
26
  priorityClassName: system-node-critical
27
+ # Must exceed GITOPS_SHUTDOWN_TIMEOUT_SECONDS, or running helm upgrades are killed.
28
+ terminationGracePeriodSeconds: {{ .Values.terminationGracePeriodSeconds }}
27
29
  containers:
28
30
  - name: gitops
29
31
  image: {{ .Values.image }}
@@ -44,6 +44,8 @@ podDisruptionBudget: {}
44
44
  resources:
45
45
  requests:
46
46
  memory: 750Mi
47
+
48
+ terminationGracePeriodSeconds: 720
47
49
  serviceAccount:
48
50
  # Specifies whether a service account should be created
49
51
  create: true
@@ -6,7 +6,7 @@ from gitops.utils.apps import App, get_app_details, get_apps # type: ignore[att
6
6
 
7
7
  from .utils.cli import success, warning
8
8
 
9
- __version__ = "1.11.0"
9
+ __version__ = "1.12.0"
10
10
 
11
11
 
12
12
  # Checking gitops version matches cluster repo version.
@@ -26,17 +26,24 @@ async def lifespan(app: FastAPI) -> AsyncIterator[None]:
26
26
 
27
27
  loop = asyncio.get_running_loop()
28
28
  deploy_queue_worker = DeployQueueWorker.get_worker()
29
- tasks = [asyncio.ensure_future(deploy_queue_worker.run(), loop=loop)]
29
+ worker_task = asyncio.ensure_future(deploy_queue_worker.run(), loop=loop)
30
+ guard_task = None
30
31
  if guard := build_disruption_guard(deploy_queue_worker.is_busy):
31
32
  deploy_queue_worker.on_activity = guard.poke
32
- tasks.append(asyncio.ensure_future(guard.run(), loop=loop))
33
+ guard_task = asyncio.ensure_future(guard.run(), loop=loop)
33
34
  yield
34
- for task in tasks:
35
- task.cancel()
36
- try:
37
- await task
38
- except asyncio.CancelledError:
39
- pass
35
+ await _cancel(worker_task)
36
+ await deploy_queue_worker.drain(float(settings.GITOPS_SHUTDOWN_TIMEOUT_SECONDS))
37
+ if guard_task:
38
+ await _cancel(guard_task)
39
+
40
+
41
+ async def _cancel(task: asyncio.Future[None]) -> None:
42
+ task.cancel()
43
+ try:
44
+ await task
45
+ except asyncio.CancelledError:
46
+ pass
40
47
 
41
48
 
42
49
  app = FastAPI(lifespan=lifespan)
@@ -30,6 +30,14 @@ POD_NAMESPACE = os.environ.get("POD_NAMESPACE", "")
30
30
  # Report to Sentry once karpenter.sh/do-not-disrupt has been held this long without a break.
31
31
  GITOPS_DO_NOT_DISRUPT_WARN_SECONDS = os.environ.get("GITOPS_DO_NOT_DISRUPT_WARN_SECONDS", "10800")
32
32
 
33
+ # How long shutdown waits for running helm upgrades. Covers helm's 600s --timeout;
34
+ # keep it below the chart's terminationGracePeriodSeconds.
35
+ GITOPS_SHUTDOWN_TIMEOUT_SECONDS = os.environ.get("GITOPS_SHUTDOWN_TIMEOUT_SECONDS", "660")
36
+
37
+ # Log level for work shutdown drops: skipped apps, queued pushes, upgrades still running.
38
+ # ERROR and above reach Sentry.
39
+ GITOPS_SHUTDOWN_DROPPED_LOG_LEVEL = os.environ.get("GITOPS_SHUTDOWN_DROPPED_LOG_LEVEL", "ERROR")
40
+
33
41
  # Pass --disable-openapi-validation to helm. Off by default: helm keeps checking
34
42
  # manifests against the cluster schema before applying them, which costs each
35
43
  # helm process a download and parse of that schema. The API server still
@@ -0,0 +1 @@
1
+ __version__ = "1.12.0"
@@ -33,6 +33,11 @@ MAX_HELM_HISTORY = 3
33
33
  # Kube api may rate limit otherwise
34
34
  helm_parallel_semaphore = asyncio.Semaphore(int(settings.GITOPS_MAX_PARALLEL_DEPLOYS))
35
35
 
36
+ # Set on SIGTERM. Apps that haven't started their helm upgrade are skipped, so the
37
+ # drain waits for at most one upgrade rather than a whole push.
38
+ shutting_down = asyncio.Event()
39
+ DROPPED_LOG_LEVEL = logging.getLevelNamesMapping()[settings.GITOPS_SHUTDOWN_DROPPED_LOG_LEVEL.upper()]
40
+
36
41
 
37
42
  @tracer.start_as_current_span("post_result_summary")
38
43
  async def post_result_summary(source: str, results: list[UpdateAppResult]) -> None:
@@ -138,6 +143,7 @@ class Deployer:
138
143
  # Track which ones we've deployed and which ones failed
139
144
  self.successful_apps: set[str] = set()
140
145
  self.failed_apps: set[str] = set()
146
+ self.skipped_on_shutdown: list[str] = []
141
147
 
142
148
  self.post_ts: str | None = None
143
149
  self.skip_deploy = "--skip-deploy" in commit_message
@@ -195,6 +201,11 @@ class Deployer:
195
201
  *[self.uninstall_app(self.previous_app_definitions.apps[app_name]) for app_name in self.removed_apps]
196
202
  )
197
203
  without_nones = [r for r in update_results + uninstall_results if r is not None]
204
+ if self.skipped_on_shutdown:
205
+ # Not posting the result summary: skipped apps would be missing from the counts.
206
+ # Args, not an f-string, so Sentry groups these into one issue.
207
+ logger.log(DROPPED_LOG_LEVEL, "Shutdown skipped apps: %s", sorted(self.skipped_on_shutdown))
208
+ return
198
209
  await post_result_summary(self.current_app_definitions.name, without_nones)
199
210
 
200
211
  async def uninstall_app(self, app: App) -> UpdateAppResult:
@@ -232,6 +243,9 @@ class Deployer:
232
243
  from_timestamp = time.time()
233
244
  async with self.semaphore_manager.app_semaphore(app.name):
234
245
  async with helm_parallel_semaphore:
246
+ if shutting_down.is_set():
247
+ self.skipped_on_shutdown.append(app.name)
248
+ return None
235
249
  try:
236
250
  return await self._update_app_deployment(app)
237
251
  except Exception as e:
@@ -6,7 +6,7 @@ from typing import Any
6
6
  from opentelemetry import trace
7
7
 
8
8
  from ... import settings
9
- from .deploy import Deployer
9
+ from .deploy import DROPPED_LOG_LEVEL, Deployer, shutting_down
10
10
  from .semaphore_manager import AppSemaphoreManager
11
11
 
12
12
  logger = logging.getLogger("gitops_worker")
@@ -91,6 +91,22 @@ class DeployQueueWorker:
91
91
  except Exception as e:
92
92
  logger.error(str(e), exc_info=True)
93
93
 
94
+ async def drain(self, timeout: float) -> None:
95
+ """Wait up to `timeout` for running deployments, skipping apps not yet started.
96
+
97
+ Cancel `run()` first, or it keeps dequeuing.
98
+ """
99
+ shutting_down.set()
100
+ if queued := self.queue.qsize():
101
+ logger.log(DROPPED_LOG_LEVEL, "Shutting down with %d pushes still queued.", queued)
102
+ running = [task for task in self.active_deployments if not task.done()]
103
+ if not running:
104
+ return
105
+ logger.info(f"Waiting up to {timeout:.0f}s for {len(running)} deployments to finish.")
106
+ _, pending = await asyncio.wait(running, timeout=timeout)
107
+ if pending:
108
+ logger.log(DROPPED_LOG_LEVEL, "%d deployments still running at shutdown.", len(pending))
109
+
94
110
  async def process_deployment(self, work: Any) -> None:
95
111
  """Process a single deployment in a separate task.
96
112
 
@@ -1,7 +1,7 @@
1
1
 
2
2
  [project]
3
3
  name = "gitops"
4
- version = "1.11.0"
4
+ version = "1.12.0"
5
5
  description = "Manage multiple apps across one or more k8s clusters."
6
6
  requires-python = ">=3.12"
7
7
  readme = "README.md"
@@ -0,0 +1,78 @@
1
+ import asyncio
2
+ from unittest.mock import patch
3
+
4
+ import pytest
5
+
6
+ from gitops_server.workers.deployer import Deployer
7
+ from gitops_server.workers.deployer.deploy import shutting_down
8
+ from gitops_server.workers.deployer.semaphore_manager import AppSemaphoreManager
9
+ from gitops_server.workers.deployer.worker import DeployQueueWorker
10
+
11
+ from .sample_data import SAMPLE_GITHUB_PAYLOAD
12
+ from .utils import mock_load_app_definitions
13
+
14
+
15
+ @pytest.fixture(autouse=True)
16
+ def reset_shutdown():
17
+ AppSemaphoreManager._instance = None
18
+ yield
19
+ shutting_down.clear()
20
+
21
+
22
+ async def start_worker(deployment) -> tuple[DeployQueueWorker, asyncio.Task]:
23
+ worker = DeployQueueWorker()
24
+ worker._process_deployment = deployment # type: ignore[method-assign]
25
+ runner = asyncio.create_task(worker.run())
26
+ await worker.enqueue({"ref": "refs/heads/master"})
27
+ for _ in range(5):
28
+ await asyncio.sleep(0)
29
+ return worker, runner
30
+
31
+
32
+ @pytest.mark.asyncio
33
+ async def test_drain_waits_for_running_deployment():
34
+ finished = asyncio.Event()
35
+
36
+ async def deployment(work, ref):
37
+ await asyncio.sleep(0.05)
38
+ finished.set()
39
+
40
+ worker, runner = await start_worker(deployment)
41
+ runner.cancel()
42
+ await worker.drain(timeout=5)
43
+
44
+ assert finished.is_set()
45
+ assert shutting_down.is_set()
46
+
47
+
48
+ @pytest.mark.asyncio
49
+ async def test_drain_gives_up_after_timeout():
50
+ async def deployment(work, ref):
51
+ await asyncio.Event().wait()
52
+
53
+ worker, runner = await start_worker(deployment)
54
+ runner.cancel()
55
+ await asyncio.wait_for(worker.drain(timeout=0.05), timeout=1)
56
+
57
+ assert worker.is_busy(), "the stuck deployment is left running"
58
+
59
+
60
+ @pytest.mark.asyncio
61
+ @patch("gitops_server.workers.deployer.deploy.run")
62
+ @patch("gitops_server.workers.deployer.deploy.post_result_summary")
63
+ @patch("gitops_server.utils.slack.post")
64
+ @patch("gitops_server.workers.deployer.deploy.load_app_definitions", mock_load_app_definitions)
65
+ @patch("gitops_server.workers.deployer.deploy.temp_repo")
66
+ async def test_apps_not_started_are_skipped_once_shutting_down(
67
+ temp_repo_mock, post_mock, summary_mock, run_mock, caplog
68
+ ):
69
+ deployer = await Deployer.from_push_event(SAMPLE_GITHUB_PAYLOAD, AppSemaphoreManager())
70
+ shutting_down.set()
71
+
72
+ await deployer.deploy()
73
+
74
+ run_mock.assert_not_called()
75
+ summary_mock.assert_not_called()
76
+ [record] = [r for r in caplog.records if r.levelname == "ERROR"]
77
+ assert record.args == (sorted(deployer.skipped_on_shutdown),)
78
+ assert deployer.skipped_on_shutdown, "the error names the apps to redeploy"
@@ -222,16 +222,16 @@ wheels = [
222
222
 
223
223
  [[package]]
224
224
  name = "boto3"
225
- version = "1.35.4"
225
+ version = "1.43.117"
226
226
  source = { registry = "https://pypi.org/simple" }
227
227
  dependencies = [
228
228
  { name = "botocore" },
229
229
  { name = "jmespath" },
230
230
  { name = "s3transfer" },
231
231
  ]
232
- sdist = { url = "https://files.pythonhosted.org/packages/ca/59/baeef26b73a6fd71602370b6e1ba3eb79d0d43dff6efcf552065548c49a0/boto3-1.35.4.tar.gz", hash = "sha256:d997b82c468bd5c2d5cd29810d47079b66b178d2b5ae021aebe262c4d78d4c94", size = 108591, upload-time = "2024-08-22T20:02:16.884Z" }
232
+ sdist = { url = "https://files.pythonhosted.org/packages/94/a7/61f0295f79dfdcebb5aa01f86c614fac7e1294faabbd66259d3609c50539/boto3-1.43.117.tar.gz", hash = "sha256:f3d314908d866b577ee6b74ed432c21e565c4c4dbd640ef3fd5e0da30fa13a98", size = 112677, upload-time = "2026-10-21T19:30:03.849Z" }
233
233
  wheels = [
234
- { url = "https://files.pythonhosted.org/packages/76/88/73608e1f1c4f4276213a0d8658cfe799a3b2d6e4189543676b8b852a788e/boto3-1.35.4-py3-none-any.whl", hash = "sha256:96c39593afb7b55ebb74d08c8e3201041d105b557c8c8536c9054c9f13da5f2a", size = 139142, upload-time = "2024-08-22T20:02:13.231Z" },
234
+ { url = "https://files.pythonhosted.org/packages/f3/3b/22b05a545fb95983733d84681364c6b0a36afb0710d832f77732d1fc4c0b/boto3-1.43.117-py3-none-any.whl", hash = "sha256:a5b6cd7e67653987fcf0e212187c16f7b58af2ae192e368f7212ddab7c05b25d", size = 140043, upload-time = "2026-10-21T19:30:02.114Z" },
235
235
  ]
236
236
 
237
237
  [[package]]
@@ -249,16 +249,16 @@ wheels = [
249
249
 
250
250
  [[package]]
251
251
  name = "botocore"
252
- version = "1.35.99"
252
+ version = "1.43.117"
253
253
  source = { registry = "https://pypi.org/simple" }
254
254
  dependencies = [
255
255
  { name = "jmespath" },
256
256
  { name = "python-dateutil" },
257
257
  { name = "urllib3" },
258
258
  ]
259
- sdist = { url = "https://files.pythonhosted.org/packages/7c/9c/1df6deceee17c88f7170bad8325aa91452529d683486273928eecfd946d8/botocore-1.35.99.tar.gz", hash = "sha256:1eab44e969c39c5f3d9a3104a0836c24715579a455f12b3979a31d7cde51b3c3", size = 13490969, upload-time = "2025-01-14T20:20:11.419Z" }
259
+ sdist = { url = "https://files.pythonhosted.org/packages/6e/a0/d0a5c44ad6a01f195681ddcb4ce203f06c712811daf1d15f8f8785e8a9f8/botocore-1.43.117.tar.gz", hash = "sha256:71993702832cc37c2495048b9945f2929d306fccb3fb767e9964e437e637fa6c", size = 16366888, upload-time = "2026-10-21T19:29:59.274Z" }
260
260
  wheels = [
261
- { url = "https://files.pythonhosted.org/packages/fc/dd/d87e2a145fad9e08d0ec6edcf9d71f838ccc7acdd919acc4c0d4a93515f8/botocore-1.35.99-py3-none-any.whl", hash = "sha256:b22d27b6b617fc2d7342090d6129000af2efd20174215948c0d7ae2da0fab445", size = 13293216, upload-time = "2025-01-14T20:20:06.427Z" },
261
+ { url = "https://files.pythonhosted.org/packages/10/94/050e35c9febf6dd2fce4a76be587ae4a323964865700467d9d7b082f7133/botocore-1.43.117-py3-none-any.whl", hash = "sha256:5920ef9b3002e1361846549078549d9154a6e0004c22853c01ce7b279d05d495", size = 16061765, upload-time = "2026-10-21T19:29:56.001Z" },
262
262
  ]
263
263
 
264
264
  [[package]]
@@ -536,7 +536,7 @@ wheels = [
536
536
 
537
537
  [[package]]
538
538
  name = "gitops"
539
- version = "1.11.0"
539
+ version = "1.12.0"
540
540
  source = { editable = "." }
541
541
  dependencies = [
542
542
  { name = "boto3" },
@@ -1532,14 +1532,14 @@ wheels = [
1532
1532
 
1533
1533
  [[package]]
1534
1534
  name = "s3transfer"
1535
- version = "0.10.4"
1535
+ version = "0.19.3"
1536
1536
  source = { registry = "https://pypi.org/simple" }
1537
1537
  dependencies = [
1538
1538
  { name = "botocore" },
1539
1539
  ]
1540
- sdist = { url = "https://files.pythonhosted.org/packages/c0/0a/1cdbabf9edd0ea7747efdf6c9ab4e7061b085aa7f9bfc36bb1601563b069/s3transfer-0.10.4.tar.gz", hash = "sha256:29edc09801743c21eb5ecbc617a152df41d3c287f67b615f73e5f750583666a7", size = 145287, upload-time = "2024-11-20T21:06:05.981Z" }
1540
+ sdist = { url = "https://files.pythonhosted.org/packages/49/c5/0a5ce655109cb96b8dfad36908a4e108d15f5dc2eff8fbc3146c4312e704/s3transfer-0.19.3.tar.gz", hash = "sha256:8326acc3d056d7f7b8a37110c7d2aea41f67e83f6ae79cd3b5fbcca34c726406", size = 166087, upload-time = "2026-10-19T19:19:49.751Z" }
1541
1541
  wheels = [
1542
- { url = "https://files.pythonhosted.org/packages/66/05/7957af15543b8c9799209506df4660cba7afc4cf94bfb60513827e96bed6/s3transfer-0.10.4-py3-none-any.whl", hash = "sha256:244a76a24355363a68164241438de1b72f8781664920260c48465896b712a41e", size = 83175, upload-time = "2024-11-20T21:06:03.961Z" },
1542
+ { url = "https://files.pythonhosted.org/packages/e2/a4/88f9e10498759121060b8050a1554753dfc04df39bbbcc7aad9ecc8d9440/s3transfer-0.19.3-py3-none-any.whl", hash = "sha256:24eb7535804306355e31c952a90022bf5b2f9d760f9a11062c7493a217c08553", size = 90252, upload-time = "2026-10-19T19:19:48.309Z" },
1543
1543
  ]
1544
1544
 
1545
1545
  [[package]]
@@ -1,5 +0,0 @@
1
- {
2
- ".": "1.11.0",
3
- "gitops_server": "0.15.1",
4
- "charts/gitops": "1.5.0"
5
- }
@@ -1 +0,0 @@
1
- __version__ = "1.11.0"
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes