Skip to content

Commit ba00b7e

Browse files
authored
Merge pull request #3 from d-ganchar/migration_file_name
added numbers to revision name, reg exp: ^[0-9]{14}[a-z0-9_]+.py$
2 parents f6fb529 + ced13e5 commit ba00b7e

File tree

8 files changed

+107
-88
lines changed

8 files changed

+107
-88
lines changed

.github/workflows/ci_cd.yml

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ permissions:
1111
pages: write
1212
id-token: write
1313

14+
1415
jobs:
1516
build:
1617
runs-on: ubuntu-22.04
@@ -47,11 +48,16 @@ jobs:
4748
runs-on: ubuntu-22.04
4849
permissions: write-all
4950
needs: [ build ]
51+
5052
services:
5153
clickhouse:
52-
image: clickhouse/clickhouse-server:latest
54+
image: clickhouse/clickhouse-server:23.4
55+
env:
56+
CLICKHOUSE_USER: thedus_tests
57+
CLICKHOUSE_PASSWORD: thedus_tests
5358
ports:
5459
- 9000:9000
60+
- 8123:8123
5561
options: >-
5662
--health-cmd "wget --no-verbose --tries=1 --spider http://localhost:8123/ping || exit 1"
5763
--health-interval 10s

docker-compose.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,3 +14,6 @@ services:
1414
interval: 2s
1515
timeout: 2s
1616
retries: 16
17+
environment:
18+
CLICKHOUSE_USER: thedus_tests
19+
CLICKHOUSE_PASSWORD: thedus_tests

pyproject.toml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ dependencies = [
1111
"rich>=13.9, < 14",
1212
"typer>=0.15, < 0.16",
1313
"clickhouse-driver>=0.2.9, < 0.3",
14-
"ripley==0.2.0a0"
14+
"ripley==0.1.0b0"
1515
]
1616

1717
classifiers = [
@@ -41,8 +41,8 @@ build-backend = "setuptools.build_meta"
4141

4242
[dependency-groups]
4343
dev = [
44-
"ruff>=0.9.1, <1",
45-
"parameterized==0.9.0",
44+
"ruff>=0.11.4, <1",
45+
"parameterized==0.9.0, < 1",
4646
"pytest>=8.3.4, <9",
4747
]
4848

tests/migrations/.gitignore

Whitespace-only changes.

tests/test_cli.py

Lines changed: 45 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,16 @@
1010
from clickhouse_driver import Client
1111

1212

13+
os.environ['CLICKHOUSE_USER'] = 'thedus_tests'
14+
os.environ['CLICKHOUSE_PASSWORD'] = 'thedus_tests'
15+
16+
1317
def init_clickhouse(database: str = 'default') -> Client:
1418
return Client(
1519
host='localhost',
1620
port=9000,
17-
user='default',
18-
password='',
21+
user=os.environ['CLICKHOUSE_USER'],
22+
password=os.environ['CLICKHOUSE_PASSWORD'],
1923
database=database,
2024
)
2125

@@ -84,7 +88,7 @@ def setUp(self):
8488
'',
8589
),
8690
):
87-
file_path = os.path.join(self.thedus_dir, f'2025010100000{file_name}.py')
91+
file_path = os.path.join(self.thedus_dir, f'20250101000000_{file_name}.py')
8892
get_env_to_skip = f"""
8993
@classmethod
9094
def get_env_to_skip(cls) -> list:
@@ -150,32 +154,32 @@ def down(self):
150154
[
151155
'dev',
152156
[
153-
'upgrade to 20250101000000_create_tbl_metrics',
154-
'SKIP 20250101000001_insert_into_metrics',
155-
'upgrade to 20250101000002_create_tbl_events',
156-
'upgrade to 20250101000003_create_tbl_logs',
157+
'upgrade to 20250101000000_0_create_tbl_metrics',
158+
'SKIP 20250101000000_1_insert_into_metrics',
159+
'upgrade to 20250101000000_2_create_tbl_events',
160+
'upgrade to 20250101000000_3_create_tbl_logs',
157161
'done',
158162
],
159163
[[(0,)], [(0,)], [(0,)]],
160-
[('upgrade', '20250101000000_create_tbl_metrics', 'dev', 0),
161-
('upgrade', '20250101000001_insert_into_metrics', 'dev', 1),
162-
('upgrade', '20250101000002_create_tbl_events', 'dev', 0),
163-
('upgrade', '20250101000003_create_tbl_logs', 'dev', 0)],
164+
[('upgrade', '20250101000000_0_create_tbl_metrics', 'dev', 0),
165+
('upgrade', '20250101000000_1_insert_into_metrics', 'dev', 1),
166+
('upgrade', '20250101000000_2_create_tbl_events', 'dev', 0),
167+
('upgrade', '20250101000000_3_create_tbl_logs', 'dev', 0)],
164168
],
165169
[
166170
'prod',
167171
[
168-
'upgrade to 20250101000000_create_tbl_metrics',
169-
'upgrade to 20250101000001_insert_into_metrics',
170-
'upgrade to 20250101000002_create_tbl_events',
171-
'upgrade to 20250101000003_create_tbl_logs',
172+
'upgrade to 20250101000000_0_create_tbl_metrics',
173+
'upgrade to 20250101000000_1_insert_into_metrics',
174+
'upgrade to 20250101000000_2_create_tbl_events',
175+
'upgrade to 20250101000000_3_create_tbl_logs',
172176
'done',
173177
],
174178
[[(1,)], [(0,)], [(0,)]],
175-
[('upgrade', '20250101000000_create_tbl_metrics', 'prod', 0),
176-
('upgrade', '20250101000001_insert_into_metrics', 'prod', 0),
177-
('upgrade', '20250101000002_create_tbl_events', 'prod', 0),
178-
('upgrade', '20250101000003_create_tbl_logs', 'prod', 0)],
179+
[('upgrade', '20250101000000_0_create_tbl_metrics', 'prod', 0),
180+
('upgrade', '20250101000000_1_insert_into_metrics', 'prod', 0),
181+
('upgrade', '20250101000000_2_create_tbl_events', 'prod', 0),
182+
('upgrade', '20250101000000_3_create_tbl_logs', 'prod', 0)],
179183
],
180184
])
181185
def test_upgrade_downgrade(
@@ -198,48 +202,48 @@ def test_upgrade_downgrade(
198202

199203
# 1 downgrade
200204
result = subprocess.getoutput('thedus downgrade')
201-
self.check_thedus_output(result, ['rollback 20250101000003_create_tbl_logs', 'done'])
205+
self.check_thedus_output(result, ['rollback 20250101000000_3_create_tbl_logs', 'done'])
202206
self.assertEqual(
203207
[],
204208
self.clickhouse.execute(
205209
f"SELECT * FROM system.tables WHERE table = 'logs' AND database = '{self.db_name}'"
206210
))
207211

208212
def test_upgrade_to_revision(self):
209-
result = subprocess.getoutput('thedus upgrade 20250101000000_create_tbl_metrics')
210-
self.check_thedus_output(result, ['upgrade to 20250101000000_create_tbl_metrics', 'done'])
213+
result = subprocess.getoutput('thedus upgrade 20250101000000_0_create_tbl_metrics')
214+
self.check_thedus_output(result, ['upgrade to 20250101000000_0_create_tbl_metrics', 'done'])
211215
self.check_thedus_migration_log([
212-
('upgrade 20250101000000_create_tbl_metrics', '20250101000000_create_tbl_metrics', 'dev', 0),
216+
('upgrade 20250101000000_0_create_tbl_metrics', '20250101000000_0_create_tbl_metrics', 'dev', 0),
213217
])
214218

215219
self.assertEqual([(0,)], self.clickhouse.execute('SELECT count() FROM metrics'))
216-
result = subprocess.getoutput('thedus upgrade 20250101000002_create_tbl_events')
220+
result = subprocess.getoutput('thedus upgrade 20250101000000_2_create_tbl_events')
217221
self.check_thedus_output(
218222
result,
219223
[
220-
'SKIP 20250101000001_insert_into_metrics',
221-
'upgrade to 20250101000002_create_tbl_events',
224+
'SKIP 20250101000000_1_insert_into_metrics',
225+
'upgrade to 20250101000000_2_create_tbl_events',
222226
'done',
223227
])
224228

225229
self.check_thedus_migration_log([
226-
('upgrade 20250101000000_create_tbl_metrics', '20250101000000_create_tbl_metrics', 'dev', 0),
227-
('upgrade 20250101000002_create_tbl_events', '20250101000001_insert_into_metrics', 'dev', 1),
228-
('upgrade 20250101000002_create_tbl_events', '20250101000002_create_tbl_events', 'dev', 0),
230+
('upgrade 20250101000000_0_create_tbl_metrics', '20250101000000_0_create_tbl_metrics', 'dev', 0),
231+
('upgrade 20250101000000_2_create_tbl_events', '20250101000000_1_insert_into_metrics', 'dev', 1),
232+
('upgrade 20250101000000_2_create_tbl_events', '20250101000000_2_create_tbl_events', 'dev', 0),
229233
])
230234

231235
self.assertEqual([(0,)], self.clickhouse.execute('SELECT count() FROM events'))
232236

233237
def test_downgrade_to_revision(self):
234238
subprocess.getoutput('thedus upgrade')
235-
result = subprocess.getoutput('thedus downgrade 20250101000001_insert_into_metrics')
239+
result = subprocess.getoutput('thedus downgrade 20250101000000_1_insert_into_metrics')
236240

237241
self.check_thedus_output(
238242
result,
239243
[
240-
'rollback 20250101000003_create_tbl_logs',
241-
'rollback 20250101000002_create_tbl_events',
242-
'SKIP 20250101000001_insert_into_metrics',
244+
'rollback 20250101000000_3_create_tbl_logs',
245+
'rollback 20250101000000_2_create_tbl_events',
246+
'SKIP 20250101000000_1_insert_into_metrics',
243247
'done',
244248
]
245249
)
@@ -253,15 +257,15 @@ def test_downgrade_to_revision(self):
253257
)
254258

255259
self.check_thedus_migration_log([
256-
('upgrade', '20250101000000_create_tbl_metrics', 'dev', 0),
257-
('upgrade', '20250101000001_insert_into_metrics', 'dev', 1),
258-
('upgrade', '20250101000002_create_tbl_events', 'dev', 0),
259-
('upgrade', '20250101000003_create_tbl_logs', 'dev', 0),
260-
('downgrade 20250101000001_insert_into_metrics', '20250101000002_create_tbl_events', 'dev', 0),
261-
('downgrade 20250101000001_insert_into_metrics', '20250101000001_insert_into_metrics', 'dev', 0),
262-
('downgrade 20250101000001_insert_into_metrics', '20250101000000_create_tbl_metrics', 'dev', 1)])
260+
('upgrade', '20250101000000_0_create_tbl_metrics', 'dev', 0),
261+
('upgrade', '20250101000000_1_insert_into_metrics', 'dev', 1),
262+
('upgrade', '20250101000000_2_create_tbl_events', 'dev', 0),
263+
('upgrade', '20250101000000_3_create_tbl_logs', 'dev', 0),
264+
('downgrade 20250101000000_1_insert_into_metrics', '20250101000000_2_create_tbl_events', 'dev', 0),
265+
('downgrade 20250101000000_1_insert_into_metrics', '20250101000000_1_insert_into_metrics', 'dev', 0),
266+
('downgrade 20250101000000_1_insert_into_metrics', '20250101000000_0_create_tbl_metrics', 'dev', 1)])
263267

264268
result = subprocess.getoutput('thedus downgrade')
265-
self.check_thedus_output(result, ['rollback 20250101000000_create_tbl_metrics', 'done'])
269+
self.check_thedus_output(result, ['rollback 20250101000000_0_create_tbl_metrics', 'done'])
266270
result = subprocess.getoutput('thedus downgrade')
267271
self.check_thedus_output(result, ['done'])

thedus/migration_file_manager.py

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,17 @@
11
import codecs
22
import os
33
import re
4-
from datetime import datetime, timezone
54
from typing import List
65

76
from .env_manager import EnvManager as Env
87

98

109
class MigrationFileManager:
11-
@staticmethod
12-
def create_migration(name: str) -> str:
13-
name = '_'.join([datetime.now(timezone.utc).strftime('%Y%m%d%H%M%S'), name])
14-
migration_path = os.path.join(Env.get_thedus_dir(), name) + '.py'
10+
MIGRATION_FILENAME_PATTERN = '^[0-9]{14}[a-z0-9_]+.py$'
1511

16-
with codecs.open(migration_path, 'w', encoding='utf-8') as file:
12+
@staticmethod
13+
def create_migration(file_path: str) -> str:
14+
with codecs.open(file_path, 'w', encoding='utf-8') as file:
1715
file.write("""from thedus.base_migration import BaseMigration
1816
1917
@@ -24,23 +22,26 @@ def up(self):
2422
def down(self):
2523
self._clickhouse.exec('SELECT 1')
2624
""")
27-
return migration_path
25+
return file_path
2826

29-
@staticmethod
30-
def get_migrations(asc: bool = True) -> List[str]:
27+
@classmethod
28+
def get_migrations(cls, asc: bool = True) -> List[str]:
3129
"""
3230
Returns a list of all migrations in the thedus directory
3331
"""
3432
files = []
3533
for filename in os.listdir(Env.get_thedus_dir()):
36-
if not re.fullmatch('^[0-9]{14}[a-z_]+.py$', filename):
37-
continue
38-
39-
files.append(os.path.join(Env.get_thedus_dir(), filename))
34+
if cls.is_valid_migration_file(filename):
35+
files.append(os.path.join(Env.get_thedus_dir(), filename))
4036

4137
files = sorted(files)
4238
if asc:
4339
return files
4440

4541
files.reverse()
4642
return files
43+
44+
@classmethod
45+
def is_valid_migration_file(cls, filename: str) -> bool:
46+
if re.fullmatch(cls.MIGRATION_FILENAME_PATTERN, filename):
47+
return True

thedus/run.py

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
1-
import re
1+
import os
22
import logging
3+
from datetime import timezone, datetime
34
from logging.config import dictConfig
45

56
import typer
@@ -93,13 +94,17 @@ def state(
9394

9495
@app.command(help='Generates a new migration file. example: thedus create-migration create_metrics')
9596
def create_migration(name: str):
96-
pattern = '[a-z_]{6,30}'
97-
if re.fullmatch(pattern, name):
98-
migration_path = Migrations.create_migration(name)
97+
now = datetime.now(timezone.utc).strftime('%Y%m%d%H%M%S')
98+
file_name = f'{now}_{name}.py'
99+
migration_path = os.path.join(Env.get_thedus_dir(), file_name)
100+
101+
if Migrations.is_valid_migration_file(file_name):
102+
migration_path = Migrations.create_migration(migration_path)
99103
logging.info(f'{migration_path} created')
100104
return
101105

102-
logging.info(f'Invalid migration name "{name}". The name must match reg exp {pattern}')
106+
logging.error(f'Invalid migration name "{name}". The name must match reg exp '
107+
f'{Migrations.MIGRATION_FILENAME_PATTERN}')
103108
exit(1)
104109

105110

0 commit comments

Comments
 (0)