djaploy 1.2.1__tar.gz → 1.2.2__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.
- {djaploy-1.2.1 → djaploy-1.2.2}/PKG-INFO +1 -1
- {djaploy-1.2.1 → djaploy-1.2.2}/djaploy/builtin_hooks.py +13 -0
- djaploy-1.2.2/djaploy/commands/status.py +88 -0
- {djaploy-1.2.1 → djaploy-1.2.2}/djaploy.egg-info/PKG-INFO +1 -1
- {djaploy-1.2.1 → djaploy-1.2.2}/pyproject.toml +1 -1
- djaploy-1.2.1/djaploy/commands/status.py +0 -62
- {djaploy-1.2.1 → djaploy-1.2.2}/LICENSE +0 -0
- {djaploy-1.2.1 → djaploy-1.2.2}/README.md +0 -0
- {djaploy-1.2.1 → djaploy-1.2.2}/djaploy/__init__.py +0 -0
- {djaploy-1.2.1 → djaploy-1.2.2}/djaploy/app.py +0 -0
- {djaploy-1.2.1 → djaploy-1.2.2}/djaploy/apps/__init__.py +0 -0
- {djaploy-1.2.1 → djaploy-1.2.2}/djaploy/apps/borg/__init__.py +0 -0
- {djaploy-1.2.1 → djaploy-1.2.2}/djaploy/apps/borg/infra/__init__.py +0 -0
- {djaploy-1.2.1 → djaploy-1.2.2}/djaploy/apps/borg/infra/djaploy_hooks.py +0 -0
- {djaploy-1.2.1 → djaploy-1.2.2}/djaploy/apps/janitor/__init__.py +0 -0
- {djaploy-1.2.1 → djaploy-1.2.2}/djaploy/apps/janitor/apps.py +0 -0
- {djaploy-1.2.1 → djaploy-1.2.2}/djaploy/apps/janitor/infra/__init__.py +0 -0
- {djaploy-1.2.1 → djaploy-1.2.2}/djaploy/apps/janitor/infra/commands/createjanitoruser.py +0 -0
- {djaploy-1.2.1 → djaploy-1.2.2}/djaploy/apps/janitor/infra/djaploy_hooks.py +0 -0
- {djaploy-1.2.1 → djaploy-1.2.2}/djaploy/apps/nginx/__init__.py +0 -0
- {djaploy-1.2.1 → djaploy-1.2.2}/djaploy/apps/nginx/apps.py +0 -0
- {djaploy-1.2.1 → djaploy-1.2.2}/djaploy/apps/nginx/infra/__init__.py +0 -0
- {djaploy-1.2.1 → djaploy-1.2.2}/djaploy/apps/nginx/infra/djaploy_hooks.py +0 -0
- {djaploy-1.2.1 → djaploy-1.2.2}/djaploy/apps/rclone/__init__.py +0 -0
- {djaploy-1.2.1 → djaploy-1.2.2}/djaploy/apps/rclone/apps.py +0 -0
- {djaploy-1.2.1 → djaploy-1.2.2}/djaploy/apps/rclone/infra/__init__.py +0 -0
- {djaploy-1.2.1 → djaploy-1.2.2}/djaploy/apps/rclone/infra/djaploy_hooks.py +0 -0
- {djaploy-1.2.1 → djaploy-1.2.2}/djaploy/apps/sync_certs/__init__.py +0 -0
- {djaploy-1.2.1 → djaploy-1.2.2}/djaploy/apps/sync_certs/apps.py +0 -0
- {djaploy-1.2.1 → djaploy-1.2.2}/djaploy/apps/sync_certs/infra/__init__.py +0 -0
- {djaploy-1.2.1 → djaploy-1.2.2}/djaploy/apps/sync_certs/infra/djaploy_hooks.py +0 -0
- {djaploy-1.2.1 → djaploy-1.2.2}/djaploy/apps/systemd/__init__.py +0 -0
- {djaploy-1.2.1 → djaploy-1.2.2}/djaploy/apps/systemd/apps.py +0 -0
- {djaploy-1.2.1 → djaploy-1.2.2}/djaploy/apps/systemd/infra/__init__.py +0 -0
- {djaploy-1.2.1 → djaploy-1.2.2}/djaploy/apps/systemd/infra/djaploy_hooks.py +0 -0
- {djaploy-1.2.1 → djaploy-1.2.2}/djaploy/apps/tailscale/__init__.py +0 -0
- {djaploy-1.2.1 → djaploy-1.2.2}/djaploy/apps/tailscale/apps.py +0 -0
- {djaploy-1.2.1 → djaploy-1.2.2}/djaploy/apps/tailscale/infra/__init__.py +0 -0
- {djaploy-1.2.1 → djaploy-1.2.2}/djaploy/apps/tailscale/infra/djaploy_hooks.py +0 -0
- {djaploy-1.2.1 → djaploy-1.2.2}/djaploy/apps/versioning/__init__.py +0 -0
- {djaploy-1.2.1 → djaploy-1.2.2}/djaploy/apps/versioning/apps.py +0 -0
- {djaploy-1.2.1 → djaploy-1.2.2}/djaploy/apps/versioning/infra/__init__.py +0 -0
- {djaploy-1.2.1 → djaploy-1.2.2}/djaploy/apps/versioning/infra/djaploy_hooks.py +0 -0
- {djaploy-1.2.1 → djaploy-1.2.2}/djaploy/artifact.py +0 -0
- {djaploy-1.2.1 → djaploy-1.2.2}/djaploy/bin/__init__.py +0 -0
- {djaploy-1.2.1 → djaploy-1.2.2}/djaploy/bin/django_pyinfra.py +0 -0
- {djaploy-1.2.1 → djaploy-1.2.2}/djaploy/bin/gunicornherder.py +0 -0
- {djaploy-1.2.1 → djaploy-1.2.2}/djaploy/certificates.py +0 -0
- {djaploy-1.2.1 → djaploy-1.2.2}/djaploy/changelog.py +0 -0
- {djaploy-1.2.1 → djaploy-1.2.2}/djaploy/commands/__init__.py +0 -0
- {djaploy-1.2.1 → djaploy-1.2.2}/djaploy/commands/_utils.py +0 -0
- {djaploy-1.2.1 → djaploy-1.2.2}/djaploy/commands/activate.py +0 -0
- {djaploy-1.2.1 → djaploy-1.2.2}/djaploy/commands/configure.py +0 -0
- {djaploy-1.2.1 → djaploy-1.2.2}/djaploy/commands/deploy.py +0 -0
- {djaploy-1.2.1 → djaploy-1.2.2}/djaploy/commands/restore.py +0 -0
- {djaploy-1.2.1 → djaploy-1.2.2}/djaploy/commands/rollback.py +0 -0
- {djaploy-1.2.1 → djaploy-1.2.2}/djaploy/commands/sync_certs.py +0 -0
- {djaploy-1.2.1 → djaploy-1.2.2}/djaploy/config.py +0 -0
- {djaploy-1.2.1 → djaploy-1.2.2}/djaploy/deploy.py +0 -0
- {djaploy-1.2.1 → djaploy-1.2.2}/djaploy/discovery.py +0 -0
- {djaploy-1.2.1 → djaploy-1.2.2}/djaploy/hooks.py +0 -0
- {djaploy-1.2.1 → djaploy-1.2.2}/djaploy/infra/__init__.py +0 -0
- {djaploy-1.2.1 → djaploy-1.2.2}/djaploy/infra/bluegreen.py +0 -0
- {djaploy-1.2.1 → djaploy-1.2.2}/djaploy/infra/djaploy_hooks.py +0 -0
- {djaploy-1.2.1 → djaploy-1.2.2}/djaploy/infra/templates.py +0 -0
- {djaploy-1.2.1 → djaploy-1.2.2}/djaploy/infra/utils.py +0 -0
- {djaploy-1.2.1 → djaploy-1.2.2}/djaploy/management/__init__.py +0 -0
- {djaploy-1.2.1 → djaploy-1.2.2}/djaploy/management/commands/__init__.py +0 -0
- {djaploy-1.2.1 → djaploy-1.2.2}/djaploy/management/commands/djaploy.py +0 -0
- {djaploy-1.2.1 → djaploy-1.2.2}/djaploy/management/commands/restore_backup.py +0 -0
- {djaploy-1.2.1 → djaploy-1.2.2}/djaploy/management/commands/sync_certs.py +0 -0
- {djaploy-1.2.1 → djaploy-1.2.2}/djaploy/management/commands/update_certs.py +0 -0
- {djaploy-1.2.1 → djaploy-1.2.2}/djaploy/management/commands/verify.py +0 -0
- {djaploy-1.2.1 → djaploy-1.2.2}/djaploy/management/utils.py +0 -0
- {djaploy-1.2.1 → djaploy-1.2.2}/djaploy/notifications.py +0 -0
- {djaploy-1.2.1 → djaploy-1.2.2}/djaploy/utils.py +0 -0
- {djaploy-1.2.1 → djaploy-1.2.2}/djaploy/version.py +0 -0
- {djaploy-1.2.1 → djaploy-1.2.2}/djaploy/versioning.py +0 -0
- {djaploy-1.2.1 → djaploy-1.2.2}/djaploy.egg-info/SOURCES.txt +0 -0
- {djaploy-1.2.1 → djaploy-1.2.2}/djaploy.egg-info/dependency_links.txt +0 -0
- {djaploy-1.2.1 → djaploy-1.2.2}/djaploy.egg-info/entry_points.txt +0 -0
- {djaploy-1.2.1 → djaploy-1.2.2}/djaploy.egg-info/requires.txt +0 -0
- {djaploy-1.2.1 → djaploy-1.2.2}/djaploy.egg-info/top_level.txt +0 -0
- {djaploy-1.2.1 → djaploy-1.2.2}/setup.cfg +0 -0
- {djaploy-1.2.1 → djaploy-1.2.2}/tests/test_bluegreen.py +0 -0
- {djaploy-1.2.1 → djaploy-1.2.2}/tests/test_borg.py +0 -0
- {djaploy-1.2.1 → djaploy-1.2.2}/tests/test_config.py +0 -0
- {djaploy-1.2.1 → djaploy-1.2.2}/tests/test_deploy_scripts.py +0 -0
- {djaploy-1.2.1 → djaploy-1.2.2}/tests/test_discovery.py +0 -0
- {djaploy-1.2.1 → djaploy-1.2.2}/tests/test_gunicornherder.py +0 -0
- {djaploy-1.2.1 → djaploy-1.2.2}/tests/test_hooks.py +0 -0
- {djaploy-1.2.1 → djaploy-1.2.2}/tests/test_versioning.py +0 -0
|
@@ -103,6 +103,19 @@ def _deploy_calculate_release_info(context):
|
|
|
103
103
|
if release_info:
|
|
104
104
|
context["pyinfra_data"]["version"] = release_info["new_version"]
|
|
105
105
|
context["pyinfra_data"]["commit"] = release_info["commit"]
|
|
106
|
+
elif "commit" not in context["pyinfra_data"]:
|
|
107
|
+
# Always pass commit hash even without versioning configured
|
|
108
|
+
try:
|
|
109
|
+
import subprocess
|
|
110
|
+
from django.conf import settings
|
|
111
|
+
commit = subprocess.check_output(
|
|
112
|
+
["git", "rev-parse", "--short", "HEAD"],
|
|
113
|
+
cwd=str(settings.GIT_DIR),
|
|
114
|
+
text=True,
|
|
115
|
+
).strip()
|
|
116
|
+
context["pyinfra_data"]["commit"] = commit
|
|
117
|
+
except Exception:
|
|
118
|
+
pass
|
|
106
119
|
|
|
107
120
|
|
|
108
121
|
# ── deploy:postcommand ───────────────────────────────────────────────
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Pyinfra command: show blue-green deployment status.
|
|
3
|
+
|
|
4
|
+
Reads and displays the blue-green state from each host.
|
|
5
|
+
|
|
6
|
+
Usage (via djaploy management command):
|
|
7
|
+
manage.py djaploy status --env production
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
from pyinfra import host
|
|
11
|
+
from pyinfra.api import deploy as _deploy_decorator
|
|
12
|
+
from pyinfra.operations import python as python_op
|
|
13
|
+
|
|
14
|
+
from djaploy.hooks import discover_hooks, get_registry
|
|
15
|
+
from djaploy.infra.utils import is_bluegreen, get_app_path, get_slot_socket_path
|
|
16
|
+
from djaploy.infra.djaploy_hooks import _read_slot_info_from_remote
|
|
17
|
+
|
|
18
|
+
discover_hooks()
|
|
19
|
+
registry = get_registry()
|
|
20
|
+
|
|
21
|
+
if is_bluegreen(host.data):
|
|
22
|
+
app_name = getattr(host.data, 'app_name', 'unknown')
|
|
23
|
+
app_path = get_app_path(host.data)
|
|
24
|
+
state_file = f"{app_path}/state.json"
|
|
25
|
+
|
|
26
|
+
def _show_status(app_n, state_f):
|
|
27
|
+
blue_info = _read_slot_info_from_remote(host, "blue", state_f)
|
|
28
|
+
green_info = _read_slot_info_from_remote(host, "green", state_f)
|
|
29
|
+
|
|
30
|
+
# Read active slot
|
|
31
|
+
import json
|
|
32
|
+
result = host.run_shell_command(command=f"cat {state_f}")
|
|
33
|
+
active = "none"
|
|
34
|
+
if result[0] and len(result) > 1:
|
|
35
|
+
try:
|
|
36
|
+
lines = [l.line if hasattr(l, 'line') else str(l) for l in result[1]]
|
|
37
|
+
state_data = json.loads("\n".join(lines))
|
|
38
|
+
active = state_data.get("active_slot") or "none"
|
|
39
|
+
except (json.JSONDecodeError, KeyError):
|
|
40
|
+
pass
|
|
41
|
+
|
|
42
|
+
print(f"\nBlue-Green Status for {app_n}")
|
|
43
|
+
print("=" * 40)
|
|
44
|
+
print(f"Active slot: {active}\n")
|
|
45
|
+
|
|
46
|
+
for slot, info in [("blue", blue_info), ("green", green_info)]:
|
|
47
|
+
tag = "ACTIVE" if active == slot else "inactive"
|
|
48
|
+
print(f"{slot.upper()} ({tag}):")
|
|
49
|
+
if info:
|
|
50
|
+
print(f" Release: {info.get('release', 'unknown')}")
|
|
51
|
+
print(f" Commit: {info.get('commit', 'unknown')}")
|
|
52
|
+
print(f" Deployed at: {info.get('deployed_at', 'unknown')}")
|
|
53
|
+
print(f" Python: {info.get('python_interpreter', 'unknown')}")
|
|
54
|
+
print(f" Venv: {info.get('venv_path', 'unknown')}")
|
|
55
|
+
print(f" Socket: {get_slot_socket_path(app_n, slot)}")
|
|
56
|
+
else:
|
|
57
|
+
print(" (empty)")
|
|
58
|
+
print()
|
|
59
|
+
|
|
60
|
+
# Show service status
|
|
61
|
+
for slot in ("blue", "green"):
|
|
62
|
+
svc = f"{app_n}-{slot}.service"
|
|
63
|
+
res = host.run_shell_command(command=f"systemctl is-active {svc} 2>/dev/null || echo inactive")
|
|
64
|
+
status_str = "unknown"
|
|
65
|
+
if res[0] and len(res) > 1:
|
|
66
|
+
try:
|
|
67
|
+
status_str = (list(res[1])[0].line if hasattr(list(res[1])[0], 'line') else str(list(res[1])[0])).strip()
|
|
68
|
+
except (IndexError, AttributeError):
|
|
69
|
+
pass
|
|
70
|
+
print(f"Service {svc}: {status_str}")
|
|
71
|
+
print()
|
|
72
|
+
|
|
73
|
+
python_op.call(
|
|
74
|
+
name="Show blue-green status",
|
|
75
|
+
function=_show_status,
|
|
76
|
+
app_n=app_name,
|
|
77
|
+
state_f=state_file,
|
|
78
|
+
)
|
|
79
|
+
else:
|
|
80
|
+
def _show_non_bluegreen():
|
|
81
|
+
strategy = getattr(host.data, "deployment_strategy", "zero_downtime")
|
|
82
|
+
print(f"\nDeployment strategy: {strategy}")
|
|
83
|
+
print("Not a blue-green deployment. Use deploy/rollback commands.\n")
|
|
84
|
+
|
|
85
|
+
python_op.call(
|
|
86
|
+
name="Show deployment status",
|
|
87
|
+
function=_show_non_bluegreen,
|
|
88
|
+
)
|
|
@@ -1,62 +0,0 @@
|
|
|
1
|
-
"""
|
|
2
|
-
Pyinfra command: show blue-green deployment status.
|
|
3
|
-
|
|
4
|
-
Reads and displays the blue-green state from each host.
|
|
5
|
-
|
|
6
|
-
Usage (via djaploy management command):
|
|
7
|
-
manage.py djaploy status --env production
|
|
8
|
-
"""
|
|
9
|
-
|
|
10
|
-
from pyinfra import host
|
|
11
|
-
from pyinfra.api import deploy as _deploy_decorator
|
|
12
|
-
from pyinfra.operations import server
|
|
13
|
-
|
|
14
|
-
from djaploy.hooks import discover_hooks, get_registry
|
|
15
|
-
from djaploy.infra.utils import is_bluegreen, get_app_path, get_slot_socket_path
|
|
16
|
-
from djaploy.infra.bluegreen import print_status_cmd
|
|
17
|
-
|
|
18
|
-
discover_hooks()
|
|
19
|
-
registry = get_registry()
|
|
20
|
-
|
|
21
|
-
if is_bluegreen(host.data):
|
|
22
|
-
app_name = getattr(host.data, 'app_name', 'unknown')
|
|
23
|
-
app_path = get_app_path(host.data)
|
|
24
|
-
state_file = f"{app_path}/state.json"
|
|
25
|
-
|
|
26
|
-
@_deploy_decorator("show_bluegreen_status")
|
|
27
|
-
def show_bluegreen_status(host_data):
|
|
28
|
-
server.shell(
|
|
29
|
-
name="Show blue-green status",
|
|
30
|
-
commands=[
|
|
31
|
-
print_status_cmd(state_file, app_name),
|
|
32
|
-
f'echo "Sockets:"',
|
|
33
|
-
f'echo " Blue: {get_slot_socket_path(app_name, "blue")}"',
|
|
34
|
-
f'echo " Green: {get_slot_socket_path(app_name, "green")}"',
|
|
35
|
-
f'echo ""',
|
|
36
|
-
# Show systemd service status
|
|
37
|
-
f'echo "Services:"',
|
|
38
|
-
f'systemctl is-active {app_name}-blue.service 2>/dev/null && '
|
|
39
|
-
f'echo " {app_name}-blue: active" || '
|
|
40
|
-
f'echo " {app_name}-blue: inactive"',
|
|
41
|
-
f'systemctl is-active {app_name}-green.service 2>/dev/null && '
|
|
42
|
-
f'echo " {app_name}-green: active" || '
|
|
43
|
-
f'echo " {app_name}-green: inactive"',
|
|
44
|
-
f'echo ""',
|
|
45
|
-
],
|
|
46
|
-
_sudo=True,
|
|
47
|
-
)
|
|
48
|
-
|
|
49
|
-
show_bluegreen_status(host.data)
|
|
50
|
-
else:
|
|
51
|
-
@_deploy_decorator("show_status")
|
|
52
|
-
def show_status(host_data):
|
|
53
|
-
server.shell(
|
|
54
|
-
name="Show deployment status",
|
|
55
|
-
commands=[
|
|
56
|
-
f'echo "Deployment strategy: {getattr(host.data, "deployment_strategy", "zero_downtime")}"',
|
|
57
|
-
f'echo "Not a blue-green deployment. Use deploy/rollback commands."',
|
|
58
|
-
],
|
|
59
|
-
_sudo=True,
|
|
60
|
-
)
|
|
61
|
-
|
|
62
|
-
show_status(host.data)
|
|
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
|
|
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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|