half-orm-dev 0.17.3a5__tar.gz → 0.17.3a7__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.
- {half_orm_dev-0.17.3a5/half_orm_dev.egg-info → half_orm_dev-0.17.3a7}/PKG-INFO +1 -1
- {half_orm_dev-0.17.3a5 → half_orm_dev-0.17.3a7}/half_orm_dev/cli/commands/release.py +103 -24
- {half_orm_dev-0.17.3a5 → half_orm_dev-0.17.3a7}/half_orm_dev/database.py +66 -5
- {half_orm_dev-0.17.3a5 → half_orm_dev-0.17.3a7}/half_orm_dev/patch_manager.py +1 -1
- {half_orm_dev-0.17.3a5 → half_orm_dev-0.17.3a7}/half_orm_dev/release_manager.py +350 -55
- {half_orm_dev-0.17.3a5 → half_orm_dev-0.17.3a7}/half_orm_dev/repo.py +94 -25
- half_orm_dev-0.17.3a7/half_orm_dev/scripts/repair-metadata.py +352 -0
- {half_orm_dev-0.17.3a5 → half_orm_dev-0.17.3a7}/half_orm_dev/templates/README +36 -2
- half_orm_dev-0.17.3a7/half_orm_dev/version.txt +1 -0
- {half_orm_dev-0.17.3a5 → half_orm_dev-0.17.3a7/half_orm_dev.egg-info}/PKG-INFO +1 -1
- {half_orm_dev-0.17.3a5 → half_orm_dev-0.17.3a7}/half_orm_dev.egg-info/SOURCES.txt +1 -0
- {half_orm_dev-0.17.3a5 → half_orm_dev-0.17.3a7}/pyproject.toml +1 -0
- half_orm_dev-0.17.3a5/half_orm_dev/version.txt +0 -1
- {half_orm_dev-0.17.3a5 → half_orm_dev-0.17.3a7}/AUTHORS +0 -0
- {half_orm_dev-0.17.3a5 → half_orm_dev-0.17.3a7}/LICENSE +0 -0
- {half_orm_dev-0.17.3a5 → half_orm_dev-0.17.3a7}/README.md +0 -0
- {half_orm_dev-0.17.3a5 → half_orm_dev-0.17.3a7}/half_orm_dev/__init__.py +0 -0
- {half_orm_dev-0.17.3a5 → half_orm_dev-0.17.3a7}/half_orm_dev/cli/__init__.py +0 -0
- {half_orm_dev-0.17.3a5 → half_orm_dev-0.17.3a7}/half_orm_dev/cli/commands/__init__.py +0 -0
- {half_orm_dev-0.17.3a5 → half_orm_dev-0.17.3a7}/half_orm_dev/cli/commands/apply.py +0 -0
- {half_orm_dev-0.17.3a5 → half_orm_dev-0.17.3a7}/half_orm_dev/cli/commands/check.py +0 -0
- {half_orm_dev-0.17.3a5 → half_orm_dev-0.17.3a7}/half_orm_dev/cli/commands/clone.py +0 -0
- {half_orm_dev-0.17.3a5 → half_orm_dev-0.17.3a7}/half_orm_dev/cli/commands/init.py +0 -0
- {half_orm_dev-0.17.3a5 → half_orm_dev-0.17.3a7}/half_orm_dev/cli/commands/migrate.py +0 -0
- {half_orm_dev-0.17.3a5 → half_orm_dev-0.17.3a7}/half_orm_dev/cli/commands/patch.py +0 -0
- {half_orm_dev-0.17.3a5 → half_orm_dev-0.17.3a7}/half_orm_dev/cli/commands/restore.py +0 -0
- {half_orm_dev-0.17.3a5 → half_orm_dev-0.17.3a7}/half_orm_dev/cli/commands/sync.py +0 -0
- {half_orm_dev-0.17.3a5 → half_orm_dev-0.17.3a7}/half_orm_dev/cli/commands/todo.py +0 -0
- {half_orm_dev-0.17.3a5 → half_orm_dev-0.17.3a7}/half_orm_dev/cli/commands/undo.py +0 -0
- {half_orm_dev-0.17.3a5 → half_orm_dev-0.17.3a7}/half_orm_dev/cli/commands/update.py +0 -0
- {half_orm_dev-0.17.3a5 → half_orm_dev-0.17.3a7}/half_orm_dev/cli/commands/upgrade.py +0 -0
- {half_orm_dev-0.17.3a5 → half_orm_dev-0.17.3a7}/half_orm_dev/cli/main.py +0 -0
- {half_orm_dev-0.17.3a5 → half_orm_dev-0.17.3a7}/half_orm_dev/cli_extension.py +0 -0
- {half_orm_dev-0.17.3a5 → half_orm_dev-0.17.3a7}/half_orm_dev/decorators.py +0 -0
- {half_orm_dev-0.17.3a5 → half_orm_dev-0.17.3a7}/half_orm_dev/hgit.py +0 -0
- {half_orm_dev-0.17.3a5 → half_orm_dev-0.17.3a7}/half_orm_dev/migration_manager.py +0 -0
- {half_orm_dev-0.17.3a5 → half_orm_dev-0.17.3a7}/half_orm_dev/migrations/0/17/1/00_move_to_hop.py +0 -0
- {half_orm_dev-0.17.3a5 → half_orm_dev-0.17.3a7}/half_orm_dev/migrations/0/17/1/01_txt_to_toml.py +0 -0
- {half_orm_dev-0.17.3a5 → half_orm_dev-0.17.3a7}/half_orm_dev/modules.py +0 -0
- {half_orm_dev-0.17.3a5 → half_orm_dev-0.17.3a7}/half_orm_dev/patch_validator.py +0 -0
- {half_orm_dev-0.17.3a5 → half_orm_dev-0.17.3a7}/half_orm_dev/patches/0/1/0/00_half_orm_meta.database.sql +0 -0
- {half_orm_dev-0.17.3a5 → half_orm_dev-0.17.3a7}/half_orm_dev/patches/0/1/0/01_alter_half_orm_meta.hop_release.sql +0 -0
- {half_orm_dev-0.17.3a5 → half_orm_dev-0.17.3a7}/half_orm_dev/patches/0/1/0/02_half_orm_meta.view.hop_penultimate_release.sql +0 -0
- {half_orm_dev-0.17.3a5 → half_orm_dev-0.17.3a7}/half_orm_dev/patches/log +0 -0
- {half_orm_dev-0.17.3a5 → half_orm_dev-0.17.3a7}/half_orm_dev/patches/sql/half_orm_meta.sql +0 -0
- {half_orm_dev-0.17.3a5 → half_orm_dev-0.17.3a7}/half_orm_dev/release_file.py +0 -0
- {half_orm_dev-0.17.3a5 → half_orm_dev-0.17.3a7}/half_orm_dev/templates/.gitignore +0 -0
- {half_orm_dev-0.17.3a5 → half_orm_dev-0.17.3a7}/half_orm_dev/templates/MANIFEST.in +0 -0
- {half_orm_dev-0.17.3a5 → half_orm_dev-0.17.3a7}/half_orm_dev/templates/Pipfile +0 -0
- {half_orm_dev-0.17.3a5 → half_orm_dev-0.17.3a7}/half_orm_dev/templates/conftest_template +0 -0
- {half_orm_dev-0.17.3a5 → half_orm_dev-0.17.3a7}/half_orm_dev/templates/git-hooks/pre-commit +0 -0
- {half_orm_dev-0.17.3a5 → half_orm_dev-0.17.3a7}/half_orm_dev/templates/git-hooks/prepare-commit-msg +0 -0
- {half_orm_dev-0.17.3a5 → half_orm_dev-0.17.3a7}/half_orm_dev/templates/init_module_template +0 -0
- {half_orm_dev-0.17.3a5 → half_orm_dev-0.17.3a7}/half_orm_dev/templates/module_template_1 +0 -0
- {half_orm_dev-0.17.3a5 → half_orm_dev-0.17.3a7}/half_orm_dev/templates/module_template_2 +0 -0
- {half_orm_dev-0.17.3a5 → half_orm_dev-0.17.3a7}/half_orm_dev/templates/module_template_3 +0 -0
- {half_orm_dev-0.17.3a5 → half_orm_dev-0.17.3a7}/half_orm_dev/templates/pyproject.toml +0 -0
- {half_orm_dev-0.17.3a5 → half_orm_dev-0.17.3a7}/half_orm_dev/templates/relation_test +0 -0
- {half_orm_dev-0.17.3a5 → half_orm_dev-0.17.3a7}/half_orm_dev/templates/sql_adapter +0 -0
- {half_orm_dev-0.17.3a5 → half_orm_dev-0.17.3a7}/half_orm_dev/templates/warning +0 -0
- {half_orm_dev-0.17.3a5 → half_orm_dev-0.17.3a7}/half_orm_dev/utils.py +0 -0
- {half_orm_dev-0.17.3a5 → half_orm_dev-0.17.3a7}/half_orm_dev.egg-info/dependency_links.txt +0 -0
- {half_orm_dev-0.17.3a5 → half_orm_dev-0.17.3a7}/half_orm_dev.egg-info/requires.txt +0 -0
- {half_orm_dev-0.17.3a5 → half_orm_dev-0.17.3a7}/half_orm_dev.egg-info/top_level.txt +0 -0
- {half_orm_dev-0.17.3a5 → half_orm_dev-0.17.3a7}/setup.cfg +0 -0
- {half_orm_dev-0.17.3a5 → half_orm_dev-0.17.3a7}/setup.py +0 -0
|
@@ -369,39 +369,118 @@ def release_hotfix(version: Optional[str] = None) -> None:
|
|
|
369
369
|
|
|
370
370
|
|
|
371
371
|
@release.command('apply')
|
|
372
|
-
@click.
|
|
373
|
-
|
|
372
|
+
@click.option(
|
|
373
|
+
'--skip-tests',
|
|
374
|
+
is_flag=True,
|
|
375
|
+
help='Skip running pytest after applying patches'
|
|
376
|
+
)
|
|
377
|
+
def release_apply(skip_tests: bool) -> None:
|
|
374
378
|
"""
|
|
375
|
-
|
|
379
|
+
Apply all patches for integration testing.
|
|
380
|
+
|
|
381
|
+
Restores the database from production schema and applies ALL patches
|
|
382
|
+
(candidates + staged) to test the complete release integration.
|
|
383
|
+
Optionally runs pytest to validate the release.
|
|
376
384
|
|
|
377
|
-
|
|
378
|
-
|
|
385
|
+
Unlike 'patch apply' which only applies validated (staged) patches,
|
|
386
|
+
this command applies ALL patches including candidates that haven't
|
|
387
|
+
passed individual validation yet. This enables testing the complete
|
|
388
|
+
release before promotion.
|
|
379
389
|
|
|
380
390
|
\b
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
391
|
+
Workflow:
|
|
392
|
+
1. Validate on release branch (ho-release/X.Y.Z)
|
|
393
|
+
2. Restore database from model/schema.sql
|
|
394
|
+
3. Apply all RC patches (if any)
|
|
395
|
+
4. Apply ALL TOML patches (candidates + staged)
|
|
396
|
+
5. Generate Python code
|
|
397
|
+
6. Run pytest (unless --skip-tests)
|
|
398
|
+
|
|
399
|
+
\b
|
|
400
|
+
Requirements:
|
|
401
|
+
- Must be on ho-release/X.Y.Z branch
|
|
402
|
+
- Development release must exist
|
|
384
403
|
|
|
385
404
|
\b
|
|
386
405
|
Examples:
|
|
387
|
-
|
|
406
|
+
Apply all patches and run tests:
|
|
388
407
|
$ half_orm dev release apply
|
|
389
408
|
|
|
390
|
-
|
|
391
|
-
$ half_orm dev release apply
|
|
392
|
-
|
|
393
|
-
Test stage release:
|
|
394
|
-
$ half_orm dev release apply 1.3.5-stage
|
|
409
|
+
Apply patches without running tests:
|
|
410
|
+
$ half_orm dev release apply --skip-tests
|
|
395
411
|
|
|
396
412
|
\b
|
|
397
|
-
|
|
413
|
+
Output:
|
|
414
|
+
✓ Applied 5 patches for version 1.3.6
|
|
415
|
+
✓ Tests passed (42 tests)
|
|
416
|
+
|
|
417
|
+
Or on failure:
|
|
418
|
+
✗ Tests failed
|
|
419
|
+
<test output>
|
|
398
420
|
"""
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
421
|
+
try:
|
|
422
|
+
# Get repository instance
|
|
423
|
+
repo = Repo()
|
|
424
|
+
release_mgr = repo.release_manager
|
|
425
|
+
|
|
426
|
+
# Display context
|
|
427
|
+
click.echo("🔄 Applying all release patches for integration testing...")
|
|
428
|
+
click.echo()
|
|
429
|
+
|
|
430
|
+
# Apply release
|
|
431
|
+
result = release_mgr.apply_release(run_tests=not skip_tests)
|
|
432
|
+
|
|
433
|
+
# Display results
|
|
434
|
+
version = result['version']
|
|
435
|
+
patches = result['patches_applied']
|
|
436
|
+
candidates = result.get('candidates_merged', [])
|
|
437
|
+
patch_count = len(patches)
|
|
438
|
+
|
|
439
|
+
click.echo(f"✓ {utils.Color.green('Patches applied successfully!')}")
|
|
440
|
+
click.echo()
|
|
441
|
+
click.echo(f" Version: {utils.Color.bold(version)}")
|
|
442
|
+
click.echo(f" Patches: {utils.Color.bold(str(patch_count))}")
|
|
443
|
+
if candidates:
|
|
444
|
+
click.echo(f" Candidates merged: {utils.Color.bold(str(len(candidates)))}")
|
|
445
|
+
click.echo()
|
|
446
|
+
|
|
447
|
+
# Show candidates merged (simulated merges)
|
|
448
|
+
if candidates:
|
|
449
|
+
click.echo(" Candidate branches merged (simulated):")
|
|
450
|
+
for patch_id in candidates:
|
|
451
|
+
click.echo(f" • ho-patch/{patch_id}")
|
|
452
|
+
click.echo()
|
|
453
|
+
|
|
454
|
+
# Show patches applied
|
|
455
|
+
if patches:
|
|
456
|
+
click.echo(" Applied patches (SQL):")
|
|
457
|
+
for patch_id in patches:
|
|
458
|
+
click.echo(f" • {patch_id}")
|
|
459
|
+
click.echo()
|
|
460
|
+
|
|
461
|
+
# Show test results
|
|
462
|
+
if skip_tests:
|
|
463
|
+
click.echo(f"⚠️ {utils.Color.bold('Tests skipped')} (--skip-tests flag)")
|
|
464
|
+
elif result['tests_passed'] is None:
|
|
465
|
+
click.echo(f"⚠️ {utils.Color.bold('Tests not run')} (pytest not found)")
|
|
466
|
+
elif result['tests_passed']:
|
|
467
|
+
click.echo(f"✓ {utils.Color.green('Tests passed!')}")
|
|
468
|
+
else:
|
|
469
|
+
click.echo(f"✗ {utils.Color.red('Tests failed!')}")
|
|
470
|
+
click.echo()
|
|
471
|
+
click.echo("Test output:")
|
|
472
|
+
click.echo(result['test_output'])
|
|
473
|
+
sys.exit(1)
|
|
474
|
+
|
|
475
|
+
click.echo()
|
|
476
|
+
click.echo("📝 Next steps:")
|
|
477
|
+
if result['tests_passed'] or result['tests_passed'] is None:
|
|
478
|
+
click.echo(f" • Promote to RC: {utils.Color.bold('half_orm dev release promote rc')}")
|
|
479
|
+
else:
|
|
480
|
+
click.echo(f" • Fix failing tests")
|
|
481
|
+
click.echo(f" • Re-run: {utils.Color.bold('half_orm dev release apply')}")
|
|
482
|
+
|
|
483
|
+
except ReleaseManagerError as e:
|
|
484
|
+
click.echo(f"❌ {utils.Color.red('Release apply failed:')}", err=True)
|
|
485
|
+
click.echo(f" {str(e)}", err=True)
|
|
486
|
+
sys.exit(1)
|
|
@@ -181,10 +181,22 @@ class Database:
|
|
|
181
181
|
*command_args
|
|
182
182
|
)
|
|
183
183
|
|
|
184
|
-
def register_release(self, major, minor, patch, changelog=None):
|
|
185
|
-
"
|
|
184
|
+
def register_release(self, major, minor, patch, pre_release='', pre_release_num='', changelog=None):
|
|
185
|
+
"""
|
|
186
|
+
Register the release into half_orm_meta.hop_release.
|
|
187
|
+
|
|
188
|
+
Args:
|
|
189
|
+
major: Major version number
|
|
190
|
+
minor: Minor version number
|
|
191
|
+
patch: Patch version number
|
|
192
|
+
pre_release: Pre-release type ('alpha', 'beta', 'rc', or '' for production)
|
|
193
|
+
pre_release_num: Pre-release number (e.g., '1' for rc1)
|
|
194
|
+
changelog: Optional changelog text
|
|
195
|
+
"""
|
|
186
196
|
return self.__model.get_relation_class('half_orm_meta.hop_release')(
|
|
187
|
-
major=major, minor=minor, patch=patch,
|
|
197
|
+
major=major, minor=minor, patch=patch,
|
|
198
|
+
pre_release=pre_release, pre_release_num=pre_release_num,
|
|
199
|
+
changelog=changelog
|
|
188
200
|
).ho_insert()
|
|
189
201
|
|
|
190
202
|
def _generate_schema_sql(self, version: str, model_dir: Path) -> Path:
|
|
@@ -275,6 +287,7 @@ class Database:
|
|
|
275
287
|
|
|
276
288
|
# Construct versioned schema file path
|
|
277
289
|
schema_file = model_dir / f"schema-{version}.sql"
|
|
290
|
+
temp_schema_file = model_dir / f".schema-{version}.sql.tmp"
|
|
278
291
|
|
|
279
292
|
# Generate schema dump using pg_dump
|
|
280
293
|
try:
|
|
@@ -282,16 +295,45 @@ class Database:
|
|
|
282
295
|
'pg_dump',
|
|
283
296
|
self.__name,
|
|
284
297
|
'--schema-only',
|
|
298
|
+
'--no-owner',
|
|
285
299
|
'-f',
|
|
286
|
-
str(
|
|
300
|
+
str(temp_schema_file)
|
|
287
301
|
)
|
|
302
|
+
|
|
303
|
+
# Filter out version-specific lines for cross-version compatibility
|
|
304
|
+
content = temp_schema_file.read_text()
|
|
305
|
+
filtered_lines = []
|
|
306
|
+
# SET commands that are version-specific and should be removed
|
|
307
|
+
version_specific_sets = (
|
|
308
|
+
'SET transaction_timeout', # PG17+
|
|
309
|
+
)
|
|
310
|
+
for line in content.split('\n'):
|
|
311
|
+
# Skip \restrict and \unrestrict lines
|
|
312
|
+
if line.startswith('\\restrict') or line.startswith('\\unrestrict'):
|
|
313
|
+
continue
|
|
314
|
+
# Skip "-- Dumped from/by" comments (version-specific)
|
|
315
|
+
if line.startswith('-- Dumped from') or line.startswith('-- Dumped by'):
|
|
316
|
+
continue
|
|
317
|
+
# Skip version-specific SET commands
|
|
318
|
+
if any(line.startswith(s) for s in version_specific_sets):
|
|
319
|
+
continue
|
|
320
|
+
filtered_lines.append(line)
|
|
321
|
+
|
|
322
|
+
schema_file.write_text('\n'.join(filtered_lines))
|
|
288
323
|
except Exception as e:
|
|
289
324
|
raise Exception(f"Failed to generate schema SQL: {e}") from e
|
|
325
|
+
finally:
|
|
326
|
+
# Clean up temporary file
|
|
327
|
+
if temp_schema_file.exists():
|
|
328
|
+
temp_schema_file.unlink()
|
|
290
329
|
|
|
291
330
|
# Generate metadata dump (half_orm_meta data only)
|
|
331
|
+
# Keep only COPY statements to avoid version-specific SET commands
|
|
292
332
|
metadata_file = model_dir / f"metadata-{version}.sql"
|
|
333
|
+
temp_file = model_dir / f".metadata-{version}.sql.tmp"
|
|
293
334
|
|
|
294
335
|
try:
|
|
336
|
+
# Dump to temporary file
|
|
295
337
|
self.execute_pg_command(
|
|
296
338
|
'pg_dump',
|
|
297
339
|
self.__name,
|
|
@@ -300,10 +342,29 @@ class Database:
|
|
|
300
342
|
'--table=half_orm_meta.hop_release',
|
|
301
343
|
'--table=half_orm_meta.hop_release_issue',
|
|
302
344
|
'-f',
|
|
303
|
-
str(
|
|
345
|
+
str(temp_file)
|
|
304
346
|
)
|
|
347
|
+
|
|
348
|
+
# Filter to keep only COPY blocks (COPY ... FROM stdin; ... \.)
|
|
349
|
+
content = temp_file.read_text()
|
|
350
|
+
filtered_lines = []
|
|
351
|
+
in_copy_block = False
|
|
352
|
+
for line in content.split('\n'):
|
|
353
|
+
if line.startswith('COPY '):
|
|
354
|
+
in_copy_block = True
|
|
355
|
+
if in_copy_block:
|
|
356
|
+
filtered_lines.append(line)
|
|
357
|
+
if line == '\\.':
|
|
358
|
+
in_copy_block = False
|
|
359
|
+
filtered_lines.append('') # Empty line between blocks
|
|
360
|
+
|
|
361
|
+
metadata_file.write_text('\n'.join(filtered_lines))
|
|
305
362
|
except Exception as e:
|
|
306
363
|
raise Exception(f"Failed to generate metadata SQL: {e}") from e
|
|
364
|
+
finally:
|
|
365
|
+
# Clean up temporary file
|
|
366
|
+
if temp_file.exists():
|
|
367
|
+
temp_file.unlink()
|
|
307
368
|
|
|
308
369
|
# Create or update symlink
|
|
309
370
|
symlink_path = model_dir / "schema.sql"
|
|
@@ -1916,7 +1916,7 @@ class PatchManager:
|
|
|
1916
1916
|
# This also syncs .hop/ to all active branches automatically via decorator
|
|
1917
1917
|
try:
|
|
1918
1918
|
self._repo.commit_and_sync_to_active_branches(
|
|
1919
|
-
message=f"[HOP] move patch #{patch_id} from candidate to stage %{version}"
|
|
1919
|
+
message=f"[HOP] move patch #{patch_id} from candidate to stage %{version}\nFixes #{patch_id}."
|
|
1920
1920
|
)
|
|
1921
1921
|
except Exception as e:
|
|
1922
1922
|
raise PatchManagerError(f"Failed to commit/push changes: {e}")
|