Skip to content

Commit cae5715

Browse files
Merge branch 'main' into wait-service_id
2 parents f01928d + d961f07 commit cae5715

File tree

2 files changed

+106
-0
lines changed

2 files changed

+106
-0
lines changed
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
# Copyright 2024 Red Hat, Inc.
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
import time
15+
16+
from django.core.management.base import BaseCommand
17+
from django.db import connection
18+
from django.db.migrations.executor import MigrationExecutor
19+
20+
21+
class Command(BaseCommand):
22+
help = "Wait for all migrations to be applied within a timeout period."
23+
24+
def add_arguments(self, parser):
25+
parser.add_argument(
26+
"-t",
27+
"--timeout",
28+
type=int,
29+
default=10,
30+
help=(
31+
"Time in seconds to wait for migrations to be applied "
32+
"(default is 10 seconds)."
33+
),
34+
)
35+
36+
def handle(self, *args, **options):
37+
timeout = options["timeout"]
38+
start_time = time.time()
39+
elapsed_time = 0
40+
41+
while elapsed_time < timeout:
42+
if not self.migrations_pending():
43+
self.stdout.write(
44+
self.style.SUCCESS("All migrations are applied.")
45+
)
46+
return
47+
time.sleep(1)
48+
elapsed_time = time.time() - start_time
49+
50+
self.stderr.write(
51+
self.style.ERROR("Timeout exceeded. There are pending migrations.")
52+
)
53+
raise SystemExit(1)
54+
55+
def migrations_pending(self) -> bool:
56+
"""Check if there are pending migrations."""
57+
executor = MigrationExecutor(connection)
58+
targets = executor.loader.graph.leaf_nodes()
59+
plan = executor.migration_plan(targets)
60+
return bool(plan)
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
# Copyright 2024 Red Hat, Inc.
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
16+
import time
17+
18+
import pytest
19+
from django.core.management import call_command
20+
21+
22+
@pytest.fixture
23+
def rollback_migration():
24+
call_command("migrate", "core", "0039")
25+
yield
26+
call_command("migrate")
27+
28+
29+
@pytest.mark.django_db
30+
def test_no_pending_migrations(capsys):
31+
call_command("wait_for_migrations", timeout=1)
32+
33+
captured = capsys.readouterr()
34+
assert "All migrations are applied." in captured.out
35+
36+
37+
@pytest.mark.django_db
38+
def test_pending_migrations(capsys, rollback_migration):
39+
before = time.time()
40+
with pytest.raises(SystemExit) as excinfo:
41+
call_command("wait_for_migrations", timeout=3)
42+
43+
captured = capsys.readouterr()
44+
assert "Timeout exceeded. There are pending migrations." in captured.err
45+
assert excinfo.value.code == 1
46+
assert time.time() - before > 3

0 commit comments

Comments
 (0)