Skip to content
Merged
Show file tree
Hide file tree
Changes from 27 commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
6504a7e
feat(workflow-engine): Add support for callback hooks
tanmoysrt Apr 16, 2026
612da86
feat(press-job): Integrate Workflow Engine and create wrapper
tanmoysrt Apr 16, 2026
5cf1ced
feat(press-job): Move all press job types to code
tanmoysrt Apr 16, 2026
2ac199b
feat(workflow-engine): Allow press admin and member in permissions
tanmoysrt Apr 16, 2026
9eb8587
fix(ci): Add OpenSSL in mypy ignore
tanmoysrt Apr 16, 2026
97c8834
feat(press-job): Delete the step and scripts from fixture
tanmoysrt Apr 16, 2026
d332720
Merge branch 'develop' into move_press_job_to_code
tanmoysrt Apr 16, 2026
78ca7ca
refactor(release-pipeline): Use defer_current_task function for retry
tanmoysrt Apr 16, 2026
d141bec
fix(server): Fix server creation tests
tanmoysrt Apr 18, 2026
ea0d785
fix(release-pipeline): Don't override workflow_name
tanmoysrt Apr 18, 2026
01f375d
feat(press-job): Add option to retry
tanmoysrt Apr 18, 2026
bb6cf93
Merge branch 'develop' into move_press_job_to_code
tanmoysrt Apr 18, 2026
797284c
Merge branch 'develop' into move_press_job_to_code
tanmoysrt Apr 24, 2026
d4bc751
feat(press-job): Make functions idempotent
tanmoysrt Apr 24, 2026
3fc42f0
feat(press-workflow): Add Support for requesting force failure
tanmoysrt Apr 24, 2026
02ea86c
feat(workflow-kv): Store primitive types as json data
tanmoysrt Apr 24, 2026
72ca62e
feat(workflow-engine): Store args and kwargs as json if possible
tanmoysrt Apr 24, 2026
4e064bd
refactor(release-pipeline): Use workflow failure callback
tanmoysrt Apr 24, 2026
ebfba73
fix(press-workflow): In task while deserialize pass the type as well
tanmoysrt Apr 24, 2026
41a3e46
Merge branch 'develop' into move_press_job_to_code
tanmoysrt Apr 24, 2026
7d47f5d
fix(workflow-engine): Test cases
tanmoysrt Apr 24, 2026
b1f7224
Merge branch 'develop' into move_press_job_to_code
tanmoysrt Apr 24, 2026
9c61826
fix(release-pipeline): In on_workflow_failure add 2nd args
tanmoysrt Apr 24, 2026
d9ee689
chore(workflow-engine): Make traceback fields read only
tanmoysrt Apr 24, 2026
80c4ed2
chore(workflow-engine): Make traceback fields read only
tanmoysrt Apr 24, 2026
14e4ce7
fix(workflow-engine): Load workflow_doc lazily
tanmoysrt Apr 24, 2026
af6aa46
feat(press-job): Expand job step details
tanmoysrt Apr 24, 2026
305542a
Merge branch 'develop' into move_press_job_to_code
tanmoysrt Apr 25, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions mypy.ini
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@ ignore_missing_imports = true
ignore_missing_imports = true
[mypy-PIL.*]
ignore_missing_imports = true
[mypy-OpenSSL.*]
ignore_missing_imports = true
[mypy-razorpay.*]
ignore_missing_imports = true
[mypy-sentry_sdk.*]
Expand Down
82 changes: 59 additions & 23 deletions press/api/tests/test_server.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@

from __future__ import annotations

from typing import TYPE_CHECKING
from unittest import mock
from unittest.mock import MagicMock, Mock, patch

import frappe
Expand All @@ -14,6 +16,7 @@
from press.press.doctype.cluster.cluster import Cluster
from press.press.doctype.cluster.test_cluster import create_test_cluster
from press.press.doctype.database_server.database_server import DatabaseServer
from press.press.doctype.press_job.jobs.resize_server import ResizeServerJob
from press.press.doctype.proxy_server.test_proxy_server import create_test_proxy_server
from press.press.doctype.server.server import BaseServer
from press.press.doctype.team.test_team import create_test_press_admin_team
Expand All @@ -27,6 +30,9 @@
from press.runner import Ansible
from press.utils.test import foreground_enqueue_doc_with_user

if TYPE_CHECKING:
from press.press.doctype.press_job.press_job import PressJob


def create_test_server_plan(
document_type: str,
Expand Down Expand Up @@ -67,53 +73,68 @@ def unavailable_check_machine_availability(self: Cluster, machine_type: str, ins
return False


def successful_sync(self: VirtualMachine):
def successful_sync_with_memory(memory):
def _sync(self):
return successful_sync(self, memory)

return _sync


def successful_sync(self: VirtualMachine, memory: int | None = None):
self.status = "Running"
if not self.volumes:
self.append(
"volumes", {"volume_id": "vol-123456", "size": 20, "volume_type": "gp2", "device": "/dev/sda1"}
)
if memory:
self.ram = memory
self.save()
self.update_servers()


def successful_ping_ansible(self: BaseServer):
create_test_ansible_play("Ping Server", "ping.yml", self.doctype, self.name)
def successful_ping_ansible(self: BaseServer, *args, **kwargs):
return create_test_ansible_play("Ping Server", "ping.yml", self.doctype, self.name)


def successful_upgrade_mariadb(self: DatabaseServer):
create_test_ansible_play("Upgrade MariaDB", "upgrade_mariadb.yml", self.doctype, self.name)
def successful_upgrade_mariadb(self: DatabaseServer, *args, **kwargs):
return create_test_ansible_play("Upgrade MariaDB", "upgrade_mariadb.yml", self.doctype, self.name)


def successful_upgrade_mariadb_patched(self: DatabaseServer):
create_test_ansible_play(
def successful_upgrade_mariadb_patched(self: DatabaseServer, *args, **kwargs):
return create_test_ansible_play(
"Upgrade MariaDB Patched", "upgrade_mariadb_patched.yml", self.doctype, self.name
)


def successful_tls_certificate(self: BaseServer):
create_test_ansible_play("Setup TLS Certificates", "tls.yml", self.doctype, self.name)
def successful_tls_certificate(self: BaseServer, *args, **kwargs):
return create_test_ansible_play("Setup TLS Certificates", "tls.yml", self.doctype, self.name)


def successful_update_agent_ansible(self: BaseServer):
create_test_ansible_play("Update Agent", "update_agent.yml", self.doctype, self.name)
def successful_update_agent_ansible(self: BaseServer, *args, **kwargs):
return create_test_ansible_play("Update Agent", "update_agent.yml", self.doctype, self.name)


def successful_wait_for_cloud_init(self: BaseServer):
create_test_ansible_play(
def successful_wait_for_cloud_init(self: BaseServer, *args, **kwargs):
return create_test_ansible_play(
"Wait for Cloud Init to finish", "wait_for_cloud_init.yml", self.doctype, self.name
)


@patch.object(VirtualMachineImage, "client", new=MagicMock())
@patch.object(VirtualMachine, "client", new=MagicMock())
@patch.object(VirtualMachine, "provision", new=successful_provision)
@patch.object(VirtualMachine, "sync", new=successful_sync)
@patch.object(Ansible, "run", new=Mock())
@patch.object(BaseServer, "ping_ansible", new=successful_ping_ansible)
@patch.object(DatabaseServer, "upgrade_mariadb", new=successful_upgrade_mariadb)
@patch.object(DatabaseServer, "upgrade_mariadb_patched", new=successful_upgrade_mariadb_patched)
@patch.object(DatabaseServer, "_upgrade_mariadb", new=successful_upgrade_mariadb)
@patch.object(DatabaseServer, "upgrade_mariadb_patched", new=successful_upgrade_mariadb)
@patch.object(DatabaseServer, "_upgrade_mariadb_patched", new=successful_upgrade_mariadb_patched)
@patch.object(BaseServer, "wait_for_cloud_init", new=successful_wait_for_cloud_init)
@patch.object(BaseServer, "_wait_for_cloud_init", new=successful_wait_for_cloud_init)
@patch.object(BaseServer, "update_tls_certificate", new=successful_tls_certificate)
@patch.object(BaseServer, "update_agent_ansible", new=successful_update_agent_ansible)
@patch.object(BaseServer, "_update_agent_ansible", new=successful_update_agent_ansible)
@patch.object(Cluster, "check_machine_availability", new=available_check_machine_availability)
class TestAPIServer(FrappeTestCase):
@patch.object(Cluster, "provision_on_aws_ec2", new=Mock())
Expand All @@ -140,12 +161,13 @@ def test_create_new_server_creates_pending_server_and_db_server(self):
create_test_virtual_machine_image(
cluster=self.cluster, series="f"
) # call from here and not setup, so mocks work

frappe.set_user(self.team.user)

servers_before = self._get_doc_count("Server", "Pending", self.team.name)
db_servers_before = self._get_doc_count("Database Server", "Pending", self.team.name)
servers_before = self._get_doc_count("Server", "Active", self.team.name)
db_servers_before = self._get_doc_count("Database Server", "Active", self.team.name)

new(
response = new(
{
"cluster": self.cluster.name,
"db_plan": self.db_plan.name,
Expand All @@ -154,8 +176,20 @@ def test_create_new_server_creates_pending_server_and_db_server(self):
}
)

servers_after = self._get_doc_count("Server", "Pending", self.team.name)
db_servers_after = self._get_doc_count("Database Server", "Pending", self.team.name)
server_name = response["server"]
database_server_name = frappe.db.get_value("Server", server_name, "database_server")

create_app_server_press_job: PressJob = frappe.get_last_doc(
"Press Job", {"server_type": "Server", "server": server_name}
)
create_db_server_press_job: PressJob = frappe.get_last_doc(
"Press Job", {"server_type": "Database Server", "server": database_server_name}
)
self.assertEqual(create_app_server_press_job.status, "Success")
self.assertEqual(create_db_server_press_job.status, "Success")

servers_after = self._get_doc_count("Server", "Active", self.team.name)
db_servers_after = self._get_doc_count("Database Server", "Active", self.team.name)

self.assertEqual(servers_before + 1, servers_after)
self.assertEqual(db_servers_before + 1, db_servers_after)
Expand Down Expand Up @@ -232,6 +266,7 @@ def test_new_fn_creates_server_with_active_subscription(self):

@patch.object(VirtualMachine, "provision", new=successful_provision)
@patch.object(VirtualMachine, "sync", new=successful_sync)
@patch.object(ResizeServerJob, "wait_for_virtual_machine_to_stop", new=mock.Mock())
def test_change_plan_changes_plan_of_server_and_updates_subscription_doc(self):
create_test_virtual_machine_image(cluster=self.cluster, series="m")
create_test_virtual_machine_image(
Expand Down Expand Up @@ -259,10 +294,11 @@ def test_change_plan_changes_plan_of_server_and_updates_subscription_doc(self):
"Press Job", {"status": "Running"}, "status", "Success"
) # Mark running jobs as success as extra steps we don't check

change_plan(
server.name,
app_plan_2.name,
)
with patch.object(VirtualMachine, "sync", new=successful_sync_with_memory(app_plan_2.memory)):
change_plan(
server.name,
app_plan_2.name,
)

server.reload()
app_subscription = frappe.get_doc(
Expand Down
Loading
Loading