half-orm-dev 0.17.3a2__py3-none-any.whl → 0.17.3a4__py3-none-any.whl
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/cli/commands/init.py +1 -1
- half_orm_dev/cli/commands/patch.py +9 -9
- half_orm_dev/cli/commands/release.py +14 -13
- half_orm_dev/cli/commands/todo.py +5 -5
- half_orm_dev/cli/main.py +2 -2
- half_orm_dev/patch_manager.py +1 -1
- half_orm_dev/release_file.py +1 -1
- half_orm_dev/release_manager.py +7 -7
- half_orm_dev/repo.py +33 -15
- half_orm_dev/templates/README +224 -19
- half_orm_dev/templates/git-hooks/pre-commit +8 -4
- half_orm_dev/version.txt +1 -1
- half_orm_dev-0.17.3a4.dist-info/METADATA +553 -0
- {half_orm_dev-0.17.3a2.dist-info → half_orm_dev-0.17.3a4.dist-info}/RECORD +18 -18
- half_orm_dev-0.17.3a2.dist-info/METADATA +0 -1284
- {half_orm_dev-0.17.3a2.dist-info → half_orm_dev-0.17.3a4.dist-info}/WHEEL +0 -0
- {half_orm_dev-0.17.3a2.dist-info → half_orm_dev-0.17.3a4.dist-info}/licenses/AUTHORS +0 -0
- {half_orm_dev-0.17.3a2.dist-info → half_orm_dev-0.17.3a4.dist-info}/licenses/LICENSE +0 -0
- {half_orm_dev-0.17.3a2.dist-info → half_orm_dev-0.17.3a4.dist-info}/top_level.txt +0 -0
|
@@ -80,7 +80,7 @@ def init(project_name, host, port, user, password, git_origin, production, force
|
|
|
80
80
|
\b
|
|
81
81
|
MODES:
|
|
82
82
|
- Full development mode (default): Database with half_orm_dev metadata
|
|
83
|
-
→ Enables: create
|
|
83
|
+
→ Enables: patch create, patch apply, release create, etc.
|
|
84
84
|
|
|
85
85
|
- Sync-only mode (--force-sync-only or user declines metadata):
|
|
86
86
|
→ Only enables: sync-package (code generation from schema)
|
|
@@ -2,14 +2,14 @@
|
|
|
2
2
|
Patch command group - Unified patch development and management.
|
|
3
3
|
|
|
4
4
|
Groups all patch-related commands under 'half_orm dev patch':
|
|
5
|
-
- patch
|
|
5
|
+
- patch create: Create new patch branch and directory
|
|
6
6
|
- patch apply: Apply current patch files to database
|
|
7
7
|
- patch merge: Add patch to stage release with validation
|
|
8
8
|
|
|
9
9
|
Replaces legacy commands:
|
|
10
|
-
- create-patch → patch
|
|
10
|
+
- create-patch → patch create
|
|
11
11
|
- apply-patch → patch apply
|
|
12
|
-
- add-to-release → patch
|
|
12
|
+
- add-to-release → patch merge
|
|
13
13
|
"""
|
|
14
14
|
|
|
15
15
|
import click
|
|
@@ -31,7 +31,7 @@ def patch():
|
|
|
31
31
|
|
|
32
32
|
\b
|
|
33
33
|
Common workflow:
|
|
34
|
-
1. half_orm dev patch
|
|
34
|
+
1. half_orm dev patch create <patch_id>
|
|
35
35
|
2. half_orm dev patch apply
|
|
36
36
|
3. half_orm dev patch merge
|
|
37
37
|
"""
|
|
@@ -71,13 +71,13 @@ def patch_create(patch_id: str, description: Optional[str] = None, before: Optio
|
|
|
71
71
|
\b
|
|
72
72
|
Examples:
|
|
73
73
|
Create patch with numeric ID:
|
|
74
|
-
$ half_orm dev patch
|
|
74
|
+
$ half_orm dev patch create 456
|
|
75
75
|
|
|
76
76
|
Create patch with full ID and description:
|
|
77
|
-
$ half_orm dev patch
|
|
77
|
+
$ half_orm dev patch create 456-user-auth -d "Add user authentication"
|
|
78
78
|
|
|
79
79
|
Insert patch before another patch (to control application order):
|
|
80
|
-
$ half_orm dev patch
|
|
80
|
+
$ half_orm dev patch create 457-hotfix --before 456-user-auth
|
|
81
81
|
|
|
82
82
|
\b
|
|
83
83
|
Raises:
|
|
@@ -174,7 +174,7 @@ def patch_apply() -> None:
|
|
|
174
174
|
if not current_branch.startswith('ho-patch/'):
|
|
175
175
|
raise click.ClickException(
|
|
176
176
|
f"Must be on ho-patch/* branch. Current branch: {current_branch}\n"
|
|
177
|
-
f"Use: half_orm dev patch
|
|
177
|
+
f"Use: half_orm dev patch create <patch_id>"
|
|
178
178
|
)
|
|
179
179
|
|
|
180
180
|
# Extract patch_id from branch name
|
|
@@ -344,7 +344,7 @@ def patch_merge(force: bool) -> None:
|
|
|
344
344
|
click.echo()
|
|
345
345
|
click.echo("📝 Next steps:")
|
|
346
346
|
click.echo(f""" • Other developers: {utils.Color.bold(f'git pull && git merge origin/{result["merged_into"]}')}""")
|
|
347
|
-
click.echo(f" • Continue development: {utils.Color.bold('half_orm dev patch
|
|
347
|
+
click.echo(f" • Continue development: {utils.Color.bold('half_orm dev patch create <next_patch_id>')}")
|
|
348
348
|
click.echo(f" • Promote to RC: {utils.Color.bold('half_orm dev release promote rc')}")
|
|
349
349
|
click.echo()
|
|
350
350
|
|
|
@@ -29,9 +29,10 @@ def release():
|
|
|
29
29
|
\b
|
|
30
30
|
Common workflow:
|
|
31
31
|
1. half_orm dev release create <level>
|
|
32
|
-
2. half_orm dev patch
|
|
33
|
-
3. half_orm dev
|
|
34
|
-
4. half_orm dev release promote
|
|
32
|
+
2. half_orm dev patch create <patch_id>
|
|
33
|
+
3. git checkout ho-patch/<patch_id> && half_orm dev patch merge
|
|
34
|
+
4. half_orm dev release promote rc
|
|
35
|
+
5. half_orm dev release promote prod
|
|
35
36
|
"""
|
|
36
37
|
pass
|
|
37
38
|
|
|
@@ -83,8 +84,8 @@ def release_create(level: str) -> None:
|
|
|
83
84
|
|
|
84
85
|
\b
|
|
85
86
|
Next steps after release create:
|
|
86
|
-
• Create patches: half_orm dev patch
|
|
87
|
-
• Add to release: half_orm dev patch
|
|
87
|
+
• Create patches: half_orm dev patch create <patch_id>
|
|
88
|
+
• Add to release: half_orm dev patch merge <patch_id>
|
|
88
89
|
• Promote to RC: half_orm dev release promote rc
|
|
89
90
|
"""
|
|
90
91
|
# Normalize level to lowercase
|
|
@@ -117,8 +118,8 @@ def release_create(level: str) -> None:
|
|
|
117
118
|
click.echo()
|
|
118
119
|
click.echo(f"📝 Next steps:")
|
|
119
120
|
click.echo(f" 1. Switch to release branch: {utils.Color.bold(f'git checkout {branch}')}")
|
|
120
|
-
click.echo(f" 2. Create patches: {utils.Color.bold(f'half_orm dev patch
|
|
121
|
-
click.echo(f" 3.
|
|
121
|
+
click.echo(f" 2. Create patches: {utils.Color.bold(f'half_orm dev patch create <patch_id>')}")
|
|
122
|
+
click.echo(f" 3. Merge patches: {utils.Color.bold('git checkout ho-patch/<patch_id> && half_orm dev patch merge')}")
|
|
122
123
|
click.echo(f" 4. Promote to RC: {utils.Color.bold('half_orm dev release promote rc')}")
|
|
123
124
|
click.echo()
|
|
124
125
|
click.echo(f"ℹ️ You are now on {utils.Color.bold(branch)} - patches will be merged here")
|
|
@@ -249,7 +250,7 @@ def release_promote(target: str) -> None:
|
|
|
249
250
|
click.echo()
|
|
250
251
|
click.echo("📝 Next steps:")
|
|
251
252
|
click.echo(f" • Test RC thoroughly")
|
|
252
|
-
click.echo(f" • If fixes needed: {utils.Color.bold('half_orm dev patch
|
|
253
|
+
click.echo(f" • If fixes needed: {utils.Color.bold('half_orm dev patch create <patch_id>')}")
|
|
253
254
|
click.echo(f" • Deploy to production: {utils.Color.bold('half_orm dev release promote prod')}")
|
|
254
255
|
click.echo()
|
|
255
256
|
click.echo(f"ℹ️ You are now on {utils.Color.bold(result['branch'])} - patches will be merged here")
|
|
@@ -263,7 +264,7 @@ def release_promote(target: str) -> None:
|
|
|
263
264
|
click.echo("📝 Next steps:")
|
|
264
265
|
click.echo(f" • Deploy hotfix to production servers")
|
|
265
266
|
click.echo(f" • Monitor for additional issues")
|
|
266
|
-
click.echo(f" • If more fixes needed: {utils.Color.bold('half_orm dev patch
|
|
267
|
+
click.echo(f" • If more fixes needed: {utils.Color.bold('half_orm dev patch create <patch_id>')}")
|
|
267
268
|
click.echo()
|
|
268
269
|
click.echo(f"ℹ️ You are back on {utils.Color.bold(result['branch'])} - ready for more hotfixes if needed")
|
|
269
270
|
|
|
@@ -327,8 +328,8 @@ def release_hotfix(version: Optional[str] = None) -> None:
|
|
|
327
328
|
|
|
328
329
|
\b
|
|
329
330
|
Next steps after hotfix:
|
|
330
|
-
• Create patches: half_orm dev patch
|
|
331
|
-
•
|
|
331
|
+
• Create patches: half_orm dev patch create <patch_id>
|
|
332
|
+
• Merge patches: From ho-patch/<patch_id> branch, run: half_orm dev patch merge
|
|
332
333
|
• Promote hotfix: half_orm dev release promote hotfix
|
|
333
334
|
|
|
334
335
|
\b
|
|
@@ -356,8 +357,8 @@ def release_hotfix(version: Optional[str] = None) -> None:
|
|
|
356
357
|
click.echo(f" Patches file: {utils.Color.bold(result['patches_file'])}")
|
|
357
358
|
click.echo()
|
|
358
359
|
click.echo("📝 Next steps:")
|
|
359
|
-
click.echo(f" • Create patches: {utils.Color.bold('half_orm dev patch
|
|
360
|
-
click.echo(f" •
|
|
360
|
+
click.echo(f" • Create patches: {utils.Color.bold('half_orm dev patch create <patch_id>')}")
|
|
361
|
+
click.echo(f" • Merge patches: {utils.Color.bold('git checkout ho-patch/<patch_id> && half_orm dev patch merge')}")
|
|
361
362
|
click.echo(f" • Promote hotfix: {utils.Color.bold('half_orm dev release promote hotfix')}")
|
|
362
363
|
click.echo()
|
|
363
364
|
click.echo(f"ℹ️ You are now on {utils.Color.bold(result['branch'])} - patches will be merged here")
|
|
@@ -30,11 +30,11 @@ def todo(ctx):
|
|
|
30
30
|
command_descriptions = {
|
|
31
31
|
# 🚧 New Git-centric commands
|
|
32
32
|
'init-project': 'Initialize new project with ho-prod branch and Patches/ structure',
|
|
33
|
-
'create
|
|
34
|
-
'apply
|
|
35
|
-
'
|
|
36
|
-
'
|
|
37
|
-
'promote
|
|
33
|
+
'patch create': 'Create ho-patch/patch-name branch with Patches/patch-name/ directory',
|
|
34
|
+
'patch apply': 'Apply current patch files using PatchManager.apply_patch_files()',
|
|
35
|
+
'patch merge': 'Merge patch into release branch with validation',
|
|
36
|
+
'release create': 'Create next releases/X.Y.Z-patches.toml file',
|
|
37
|
+
'release promote': "Promote stage → target ('rc', 'prod') with automatic branch cleanup",
|
|
38
38
|
'update': 'Apply patches in production (adapt for Git-centric)',
|
|
39
39
|
'upgrade': 'Apply patches in production (adapt for Git-centric)',
|
|
40
40
|
|
half_orm_dev/cli/main.py
CHANGED
|
@@ -228,8 +228,8 @@ def create_cli_group():
|
|
|
228
228
|
else:
|
|
229
229
|
# Development commands
|
|
230
230
|
click.echo(f" • {utils.Color.bold('patch')}")
|
|
231
|
-
click.echo(f" • {utils.Color.bold('
|
|
232
|
-
click.echo(f" • {utils.Color.bold('promote
|
|
231
|
+
click.echo(f" • {utils.Color.bold('release create <level>')} - Create next release (patch/minor/major)")
|
|
232
|
+
click.echo(f" • {utils.Color.bold('release promote <target>')} - Promote stage to rc or prod")
|
|
233
233
|
|
|
234
234
|
click.echo(f"\nTry {utils.Color.bold('half_orm dev <command> --help')} for more information.\n")
|
|
235
235
|
else:
|
half_orm_dev/patch_manager.py
CHANGED
|
@@ -2171,7 +2171,7 @@ class PatchManager:
|
|
|
2171
2171
|
raise PatchManagerError(
|
|
2172
2172
|
"Must be on ho-release/X.Y.Z branch to create patch. "
|
|
2173
2173
|
f"Current branch: {current_branch}\n"
|
|
2174
|
-
"Hint: Run 'half_orm dev release
|
|
2174
|
+
"Hint: Run 'half_orm dev release create <level>' first to create a release "
|
|
2175
2175
|
"or switch to a release branch."
|
|
2176
2176
|
)
|
|
2177
2177
|
|
half_orm_dev/release_file.py
CHANGED
|
@@ -86,7 +86,7 @@ class ReleaseFile:
|
|
|
86
86
|
if not self.file_path.exists():
|
|
87
87
|
raise ReleaseFileError(
|
|
88
88
|
f"Release file not found: {self.file_path}\n"
|
|
89
|
-
f"Hint: Run 'half_orm dev release
|
|
89
|
+
f"Hint: Run 'half_orm dev release create <level>' first"
|
|
90
90
|
)
|
|
91
91
|
|
|
92
92
|
try:
|
half_orm_dev/release_manager.py
CHANGED
|
@@ -890,7 +890,7 @@ class ReleaseManager:
|
|
|
890
890
|
|
|
891
891
|
Raises:
|
|
892
892
|
ReleaseManagerError:
|
|
893
|
-
- No development release found (need
|
|
893
|
+
- No development release found (need release create first)
|
|
894
894
|
- Multiple releases without explicit version
|
|
895
895
|
- Specified release doesn't exist
|
|
896
896
|
|
|
@@ -904,7 +904,7 @@ class ReleaseManager:
|
|
|
904
904
|
# Returns: ("1.4.0", "1.4.0-patches.toml")
|
|
905
905
|
|
|
906
906
|
# Error cases
|
|
907
|
-
# No release: "No development release found. Run '
|
|
907
|
+
# No release: "No development release found. Run 'release create' first."
|
|
908
908
|
# Multiple releases: "Multiple releases found. Use --to-version."
|
|
909
909
|
# Invalid: "Release 1.9.9 not found"
|
|
910
910
|
"""
|
|
@@ -935,7 +935,7 @@ class ReleaseManager:
|
|
|
935
935
|
if len(patches_files) == 0:
|
|
936
936
|
raise ReleaseManagerError(
|
|
937
937
|
"No development release found.\n"
|
|
938
|
-
"Run 'half_orm dev
|
|
938
|
+
"Run 'half_orm dev release create <level>' first."
|
|
939
939
|
)
|
|
940
940
|
|
|
941
941
|
if len(patches_files) > 1:
|
|
@@ -1316,7 +1316,7 @@ class ReleaseManager:
|
|
|
1316
1316
|
f" git add .\n"
|
|
1317
1317
|
f" git commit\n"
|
|
1318
1318
|
f" git push\n\n"
|
|
1319
|
-
f"Then retry:
|
|
1319
|
+
f"Then retry: git checkout ho-patch/{patch_id} && half_orm dev patch merge\n\n"
|
|
1320
1320
|
f"Git error: {e}"
|
|
1321
1321
|
)
|
|
1322
1322
|
|
|
@@ -2229,7 +2229,7 @@ class ReleaseManager:
|
|
|
2229
2229
|
if not patches_files:
|
|
2230
2230
|
raise ReleaseManagerError(
|
|
2231
2231
|
"No stage release found. "
|
|
2232
|
-
"Create a stage release first with: half_orm dev release
|
|
2232
|
+
"Create a stage release first with: half_orm dev release create <level>"
|
|
2233
2233
|
)
|
|
2234
2234
|
|
|
2235
2235
|
# Sort by version to get the smallest (oldest) one first
|
|
@@ -2412,7 +2412,7 @@ class ReleaseManager:
|
|
|
2412
2412
|
raise ReleaseManagerError(
|
|
2413
2413
|
f"Promotion cancelled.\n"
|
|
2414
2414
|
f"To proceed, either:\n"
|
|
2415
|
-
f" 1.
|
|
2415
|
+
f" 1. Merge candidate patches: git checkout ho-patch/<patch_id> && half_orm dev patch merge\n"
|
|
2416
2416
|
f" 2. Accept candidate migration when prompted"
|
|
2417
2417
|
)
|
|
2418
2418
|
|
|
@@ -2879,7 +2879,7 @@ class ReleaseManager:
|
|
|
2879
2879
|
f"Cannot promote hotfix: {len(candidates)} candidate patch(es) remain:\n"
|
|
2880
2880
|
f" • " + "\n • ".join(candidates) + "\n\n"
|
|
2881
2881
|
f"Actions required:\n"
|
|
2882
|
-
f" 1.
|
|
2882
|
+
f" 1. Merge patches: git checkout ho-patch/<patch_id> && half_orm dev patch merge\n"
|
|
2883
2883
|
f" 2. OR delete branches: git branch -D ho-patch/<patch_id>\n"
|
|
2884
2884
|
f" 3. OR move to another release (edit patches file manually)"
|
|
2885
2885
|
)
|
half_orm_dev/repo.py
CHANGED
|
@@ -1898,11 +1898,12 @@ Patches/
|
|
|
1898
1898
|
|
|
1899
1899
|
## Workflow
|
|
1900
1900
|
|
|
1901
|
-
1. Create
|
|
1902
|
-
2.
|
|
1903
|
-
3.
|
|
1904
|
-
4.
|
|
1905
|
-
5.
|
|
1901
|
+
1. Create release: `half_orm dev release create <level>`
|
|
1902
|
+
2. Create patch branch: `half_orm dev patch create <patch-id>`
|
|
1903
|
+
3. Add SQL/Python files to Patches/<patch-id>/
|
|
1904
|
+
4. Apply patch: `half_orm dev patch apply`
|
|
1905
|
+
5. Test your changes
|
|
1906
|
+
6. Merge patch: `git checkout ho-patch/<patch-id> && half_orm dev patch merge`
|
|
1906
1907
|
|
|
1907
1908
|
## File Naming
|
|
1908
1909
|
|
|
@@ -1940,12 +1941,14 @@ Each file contains patch IDs, one per line:
|
|
|
1940
1941
|
|
|
1941
1942
|
## Workflow
|
|
1942
1943
|
|
|
1943
|
-
1. **
|
|
1944
|
-
- `half_orm dev
|
|
1945
|
-
-
|
|
1944
|
+
1. **Development**: Patch development
|
|
1945
|
+
- `half_orm dev patch create <patch-id>`
|
|
1946
|
+
- `half_orm dev patch apply`
|
|
1947
|
+
- `half_orm dev patch merge` (from ho-patch/<patch-id> branch)
|
|
1948
|
+
- Patches added to X.Y.Z-patches.toml
|
|
1946
1949
|
|
|
1947
1950
|
2. **RC**: Release candidate
|
|
1948
|
-
- `half_orm dev promote
|
|
1951
|
+
- `half_orm dev release promote rc`
|
|
1949
1952
|
- Creates X.Y.Z-rc.txt
|
|
1950
1953
|
- Deletes patch branches
|
|
1951
1954
|
|
|
@@ -2187,22 +2190,37 @@ See docs/half_orm_dev.md for complete documentation.
|
|
|
2187
2190
|
return True
|
|
2188
2191
|
|
|
2189
2192
|
def _reset_database_schemas(self) -> None:
|
|
2190
|
-
"""Drop all user schemas with CASCADE (including half_orm_meta).
|
|
2191
|
-
|
|
2193
|
+
"""Drop all user schemas with CASCADE (including half_orm_meta).
|
|
2194
|
+
|
|
2195
|
+
Note: Database-level objects persist and are NOT reset:
|
|
2196
|
+
- Extensions (will be recreated by schema.sql with IF NOT EXISTS)
|
|
2197
|
+
- Foreign Data Wrappers and servers
|
|
2198
|
+
- Event triggers
|
|
2199
|
+
- Database settings (ALTER DATABASE SET)
|
|
2200
|
+
|
|
2201
|
+
This is by design: these objects are typically configured once
|
|
2202
|
+
and should persist across schema resets.
|
|
2203
|
+
"""
|
|
2204
|
+
schemas_to_drop = {'half_orm_meta', 'half_orm_meta.view'}
|
|
2205
|
+
# Add user schemas from half_orm metadata
|
|
2192
2206
|
relations = self.model.desc()
|
|
2193
|
-
|
|
2194
|
-
_ = [schemas.add(rel[1][1]) for rel in relations]
|
|
2207
|
+
_ = [schemas_to_drop.add(rel[1][1]) for rel in relations]
|
|
2195
2208
|
|
|
2196
2209
|
# Drop each schema with CASCADE
|
|
2197
|
-
for schema_name in
|
|
2210
|
+
for schema_name in schemas_to_drop:
|
|
2198
2211
|
self.model.execute_query(f'DROP SCHEMA IF EXISTS "{schema_name}" CASCADE')
|
|
2199
2212
|
|
|
2213
|
+
# Recreate public schema (PostgreSQL standard schema)
|
|
2214
|
+
# The public schema is expected to exist by many applications and tools
|
|
2215
|
+
if 'public' in schemas_to_drop:
|
|
2216
|
+
self.model.execute_query('CREATE SCHEMA public')
|
|
2217
|
+
self.model.execute_query('GRANT ALL ON SCHEMA public TO public')
|
|
2218
|
+
|
|
2200
2219
|
def restore_database_from_schema(self) -> None:
|
|
2201
2220
|
"""
|
|
2202
2221
|
Restore database from model/schema.sql and model/metadata-X.Y.Z.sql.
|
|
2203
2222
|
|
|
2204
2223
|
Restores database to clean production state by dropping all user schemas
|
|
2205
|
-
and reloading schema structure and half_orm_meta data. This provides
|
|
2206
2224
|
a clean baseline before applying patch files during patch development.
|
|
2207
2225
|
|
|
2208
2226
|
Process:
|
half_orm_dev/templates/README
CHANGED
|
@@ -1,25 +1,230 @@
|
|
|
1
|
-
#
|
|
1
|
+
# {package_name}
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Database-driven application using [half-orm](https://github.com/half-orm/half-orm) with [half-orm-dev](https://github.com/half-orm/half-orm-dev) workflow.
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
5
|
+
**Database:** `{dbname}`
|
|
6
|
+
**Generated with:** half-orm-dev=={hop_version}
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
does not conflict with a relation name in your model.
|
|
8
|
+
---
|
|
10
9
|
|
|
11
|
-
|
|
10
|
+
## 🚀 Quick Start
|
|
12
11
|
|
|
13
|
-
|
|
12
|
+
### Prerequisites
|
|
14
13
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
14
|
+
```bash
|
|
15
|
+
# Install half-orm-dev (includes half-orm)
|
|
16
|
+
# IMPORTANT: Install the version specified in .hop/config.
|
|
17
|
+
# Replace <version> by the value of hop_version.
|
|
18
|
+
pip install half-orm-dev==<version>
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
**Version requirement:** This project requires `half-orm-dev >= {hop_version}`
|
|
22
|
+
|
|
23
|
+
### Clone This Project
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
# Clone project with automatic database setup (use git_origin in .hop/config)
|
|
27
|
+
half_orm dev clone <git_origin>
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
This will:
|
|
31
|
+
- Clone the repository and checkout `ho-prod` branch
|
|
32
|
+
- Configure database connection in `/etc/half_orm/{dbname}` or `${{HALFORM_CONF_DIR}}/{dbname}`
|
|
33
|
+
- Restore production schema from `.hop/model/schema.sql`
|
|
34
|
+
- Generate Python ORM classes in `{package_name}/` directory
|
|
35
|
+
|
|
36
|
+
---
|
|
37
|
+
|
|
38
|
+
## 📖 Development Workflow
|
|
39
|
+
|
|
40
|
+
This project uses **half-orm-dev** for database versioning and patch management.
|
|
41
|
+
|
|
42
|
+
### 1. Create a Release
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
# Create new minor release (e.g., 0.17.0)
|
|
46
|
+
half_orm dev release create minor
|
|
47
|
+
|
|
48
|
+
# Creates ho-release/0.17.0 branch
|
|
49
|
+
# Creates .hop/releases/0.17.0-patches.toml
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
### 2. Create a Patch
|
|
53
|
+
|
|
54
|
+
# Create patch (auto-added as candidate)
|
|
55
|
+
half_orm dev patch create <number>-<description>
|
|
56
|
+
|
|
57
|
+
# Example: Create user authentication patch
|
|
58
|
+
half_orm dev patch create 456-user-auth
|
|
59
|
+
|
|
60
|
+
# Creates ho-patch/456-user-auth branch
|
|
61
|
+
# Creates Patches/456-user-auth/ directory
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
### 3. Develop Your Changes
|
|
65
|
+
|
|
66
|
+
```bash
|
|
67
|
+
# Add SQL migration
|
|
68
|
+
echo "CREATE TABLE users (id SERIAL PRIMARY KEY, username TEXT);" > Patches/456-user-auth/1-create-users.sql
|
|
69
|
+
|
|
70
|
+
# Add Python migration (optional)
|
|
71
|
+
cat > Patches/456-user-auth/2-seed-data.py << 'EOF'
|
|
72
|
+
from {package_name}.public.users import Users
|
|
73
|
+
|
|
74
|
+
def apply(model):
|
|
75
|
+
Users(username='admin').ho_insert()
|
|
76
|
+
EOF
|
|
77
|
+
|
|
78
|
+
# Apply patch to test database
|
|
79
|
+
half_orm dev patch apply
|
|
80
|
+
|
|
81
|
+
# Generated ORM classes available in {package_name}/
|
|
82
|
+
from {package_name}.public.users import Users
|
|
83
|
+
user = Users(username='john').ho_insert()
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
### 4. Test Your Changes
|
|
87
|
+
|
|
88
|
+
```bash
|
|
89
|
+
# Run tests (pytest must be configured)
|
|
90
|
+
pytest tests/
|
|
91
|
+
|
|
92
|
+
# half-orm-dev validates:
|
|
93
|
+
# - Patch SQL syntax
|
|
94
|
+
# - Patch idempotency (can be applied twice)
|
|
95
|
+
# - Test suite passes with full release context
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
### 5. Merge Patch into Release
|
|
99
|
+
|
|
100
|
+
```bash
|
|
101
|
+
# Merge patch (automatic validation + tests)
|
|
102
|
+
half_orm dev patch merge
|
|
103
|
+
|
|
104
|
+
# What happens:
|
|
105
|
+
# 1. Creates temp validation branch
|
|
106
|
+
# 2. Applies ALL staged patches + your patch
|
|
107
|
+
# 3. Runs pytest tests/
|
|
108
|
+
# 4. If tests pass → merges into ho-release/X.Y.Z
|
|
109
|
+
# 5. Changes patch status to "staged" in TOML
|
|
110
|
+
# 6. Deletes patch branch
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
### 6. Promote Release
|
|
114
|
+
|
|
115
|
+
```bash
|
|
116
|
+
# Stage → RC (first release candidate)
|
|
117
|
+
half_orm dev release promote rc
|
|
118
|
+
|
|
119
|
+
# Creates .hop/releases/0.17.0-rc1.txt snapshot
|
|
120
|
+
# Tags ho-release-0.17.0-rc1
|
|
121
|
+
|
|
122
|
+
# RC → Production (after validation)
|
|
123
|
+
half_orm dev release promote prod
|
|
124
|
+
|
|
125
|
+
# Merges into ho-prod branch
|
|
126
|
+
# Creates .hop/releases/0.17.0.txt
|
|
127
|
+
# Tags production-0.17.0
|
|
128
|
+
# Generates .hop/model/schema-0.17.0.sql
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
---
|
|
132
|
+
|
|
133
|
+
## 🔧 Common Commands
|
|
134
|
+
|
|
135
|
+
### Status & Information
|
|
136
|
+
|
|
137
|
+
```bash
|
|
138
|
+
half_orm dev check # Show repository state
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
### Patch Management
|
|
142
|
+
|
|
143
|
+
```bash
|
|
144
|
+
half_orm dev patch create # create a new patch for release
|
|
145
|
+
half_orm dev patch apply # Apply patch to dev database
|
|
146
|
+
half_orm dev patch merge # Integrate patch into release
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
### Release Management
|
|
150
|
+
|
|
151
|
+
```bash
|
|
152
|
+
half_orm dev release create <level> # Create release (patch/minor/major)
|
|
153
|
+
half_orm dev release promote rc # Stage → RC
|
|
154
|
+
half_orm dev release promote prod # RC → Production
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
### Production Deployment
|
|
158
|
+
|
|
159
|
+
```bash
|
|
160
|
+
# On production server
|
|
161
|
+
half_orm dev update # Check available releases
|
|
162
|
+
half_orm dev upgrade <version> # Deploy specific version
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
---
|
|
166
|
+
|
|
167
|
+
## 📁 Project Structure
|
|
168
|
+
|
|
169
|
+
```
|
|
170
|
+
{package_name}/
|
|
171
|
+
├── .hop/ # half-orm-dev metadata
|
|
172
|
+
│ ├── config # Repository configuration
|
|
173
|
+
│ ├── model/ # Database schemas
|
|
174
|
+
│ │ ├── schema.sql # Current production schema (symlink)
|
|
175
|
+
│ │ ├── schema-X.Y.Z.sql # Versioned schemas
|
|
176
|
+
│ │ └── metadata-X.Y.Z.sql # half_orm_meta data dumps
|
|
177
|
+
│ └── releases/ # Release tracking files
|
|
178
|
+
│ ├── X.Y.Z-patches.toml # Development releases (mutable)
|
|
179
|
+
│ ├── X.Y.Z-rcN.txt # Release candidates (immutable)
|
|
180
|
+
│ └── X.Y.Z.txt # Production releases (immutable)
|
|
181
|
+
├── Patches/ # Patch directories
|
|
182
|
+
│ └── <id>-<description>/ # Individual patch files
|
|
183
|
+
│ ├── *.sql # SQL migrations (numbered)
|
|
184
|
+
│ └── *.py # Python migrations (optional)
|
|
185
|
+
├── {package_name}/ # Generated ORM package
|
|
186
|
+
│ └── <schema>/ # schema classes
|
|
187
|
+
└── tests/ # Test suite (pytest)
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
---
|
|
191
|
+
|
|
192
|
+
## 🌿 Git Branch Structure
|
|
193
|
+
|
|
194
|
+
- **`ho-prod`**: Production branch (stable, source of truth)
|
|
195
|
+
- **`ho-release/X.Y.Z`**: Release integration branches (temporary)
|
|
196
|
+
- **`ho-patch/ID`**: Patch development branches (temporary)
|
|
197
|
+
|
|
198
|
+
All development happens on patch branches, merged into release branches, then promoted to production.
|
|
199
|
+
|
|
200
|
+
---
|
|
201
|
+
|
|
202
|
+
## 📚 Documentation
|
|
203
|
+
|
|
204
|
+
- **half-orm-dev**: https://github.com/half-orm/half-orm-dev
|
|
205
|
+
- **half-orm**: https://github.com/half-orm/half-orm
|
|
206
|
+
- **Workflow guide**: https://github.com/half-orm/half-orm-dev#readme
|
|
207
|
+
|
|
208
|
+
---
|
|
209
|
+
|
|
210
|
+
## 🆘 Getting Help
|
|
211
|
+
|
|
212
|
+
```bash
|
|
213
|
+
half_orm dev --help # General help
|
|
214
|
+
half_orm dev patch --help # Patch commands
|
|
215
|
+
half_orm dev release --help # Release commands
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
---
|
|
219
|
+
|
|
220
|
+
## ⚠️ Important Notes
|
|
221
|
+
|
|
222
|
+
1. **Always work on patch branches** - Never commit directly to ho-prod or ho-release
|
|
223
|
+
2. **Test before merging** - `patch merge` runs tests automatically
|
|
224
|
+
3. **Sequential releases** - Only the smallest version in preparation can be promoted
|
|
225
|
+
4. **Idempotent patches** - SQL must be replayable (use `IF NOT EXISTS`, etc.)
|
|
226
|
+
5. **Production schema** - `.hop/model/schema.sql` is the source of truth
|
|
227
|
+
|
|
228
|
+
---
|
|
229
|
+
|
|
230
|
+
Generated by half-orm-dev {hop_version}
|
|
@@ -116,12 +116,16 @@ The ho-prod branch is a protected production branch. Changes must be
|
|
|
116
116
|
promoted through the official Half-ORM release workflow.
|
|
117
117
|
|
|
118
118
|
To create a patch:
|
|
119
|
-
$ half_orm dev patch
|
|
119
|
+
$ half_orm dev patch create <patch_id>
|
|
120
120
|
|
|
121
|
-
To
|
|
122
|
-
$
|
|
121
|
+
To merge a patch into a release:
|
|
122
|
+
$ git checkout ho-patch/<patch_id>
|
|
123
|
+
$ half_orm dev patch merge
|
|
123
124
|
|
|
124
|
-
To
|
|
125
|
+
To add a patch to a release (on a patch branch):
|
|
126
|
+
$ half_orm dev patch merge
|
|
127
|
+
|
|
128
|
+
To promote a stage release to rc/production (on a release branch):
|
|
125
129
|
$ half_orm dev release promote <rc|prod>
|
|
126
130
|
|
|
127
131
|
This workflow ensures:
|
half_orm_dev/version.txt
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
0.17.3-
|
|
1
|
+
0.17.3-a4
|