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.
@@ -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-patch, apply-patch, prepare-release, etc.
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 new: Create new patch branch and directory
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 new
10
+ - create-patch → patch create
11
11
  - apply-patch → patch apply
12
- - add-to-release → patch add
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 new <patch_id>
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 new 456
74
+ $ half_orm dev patch create 456
75
75
 
76
76
  Create patch with full ID and description:
77
- $ half_orm dev patch new 456-user-auth -d "Add user authentication"
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 new 457-hotfix --before 456-user-auth
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 new <patch_id>"
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 new <next_patch_id>')}")
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 add <patch_id>
33
- 3. half_orm dev release promote rc
34
- 4. half_orm dev release promote prod
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 new <patch_id>
87
- • Add to release: half_orm dev patch add <patch_id>
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 new <patch_id>')}")
121
- click.echo(f" 3. Close patches: {utils.Color.bold(f'half_orm dev patch close <patch_id>')}")
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 new <patch_id>')}")
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 new <patch_id>')}")
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 new <patch_id>
331
- Close patches: half_orm dev patch close <patch_id>
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 new <patch_id>')}")
360
- click.echo(f" • Close patches: {utils.Color.bold('half_orm dev patch close <patch_id>')}")
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-patch': 'Create ho-patch/patch-name branch with Patches/patch-name/ directory',
34
- 'apply-patch': 'Apply current patch files using PatchManager.apply_patch_files()',
35
- 'add-to-release': 'Add patch to releases/X.Y.Z-stage.txt and merge to ho-prod',
36
- 'prepare-release': 'Create next releases/X.Y.Z-stage.txt file',
37
- 'promote-to': "Promote stage → target ('rc', 'prod') with automatic branch cleanup",
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('prepare-release <level>')} - Prepare next release stage file (patch/minor/major)")
232
- click.echo(f" • {utils.Color.bold('promote-to <target>')} - Promote stage to rc or prod")
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:
@@ -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 new <level>' first to create a 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
 
@@ -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 new <level>' first"
89
+ f"Hint: Run 'half_orm dev release create <level>' first"
90
90
  )
91
91
 
92
92
  try:
@@ -890,7 +890,7 @@ class ReleaseManager:
890
890
 
891
891
  Raises:
892
892
  ReleaseManagerError:
893
- - No development release found (need prepare-release first)
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 'prepare-release' first."
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 prepare-release <type>' first."
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: half_orm dev add-to-release {patch_id}\n\n"
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 new"
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. Close candidate patches: half_orm dev patch close <patch_id>\n"
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. Close patches: half_orm dev patch close <patch_id>\n"
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 patch branch: `half_orm dev create-patch <patch-id>`
1902
- 2. Add SQL/Python files to Patches/<patch-id>/
1903
- 3. Apply patch: `half_orm dev apply-patch`
1904
- 4. Test your changes
1905
- 5. Add to release: `half_orm dev add-to-release <patch-id>`
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. **Stage**: Development work
1944
- - `half_orm dev add-to-release <patch-id>`
1945
- - Patches added to X.Y.Z-stage.txt
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-to rc`
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
- # Get user schemas from half_orm metadata
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
- schemas = {'half_orm_meta', 'half_orm_meta.view'}
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 schemas:
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:
@@ -1,25 +1,230 @@
1
- # halfORM package `{package_name}` for the `{dbname}` database.
1
+ # {package_name}
2
2
 
3
- This package has been generated by [hop](https://github.com/collorg/halfORM/blob/main/doc/hop.md) version {hop_version}.
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
- Use the `hop` command in this directory of any subdirectory to synchronise
6
- the modules in this package with any changes in your model.
5
+ **Database:** `{dbname}`
6
+ **Generated with:** half-orm-dev=={hop_version}
7
7
 
8
- If you manually add any file to this package, make sure its name
9
- does not conflict with a relation name in your model.
8
+ ---
10
9
 
11
- # Usage
10
+ ## 🚀 Quick Start
12
11
 
13
- Before you can use this package you will have to:
12
+ ### Prerequisites
14
13
 
15
- - install [half-orm](https://github.com/collorg/halfORM),
16
- - specify the connection parameters to the `{dbname}` database in `/etc/half_orm/{package_name}` file:
17
- ```
18
- [database]
19
- name = {dbname}
20
- user = <username>
21
- password = <password>
22
- host = <ip address|localhost>
23
- port = <port number|5432>
24
- ```
25
- - install the package by running `pip3 install --upgrade .` in this directory.
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 new <patch_id>
119
+ $ half_orm dev patch create <patch_id>
120
120
 
121
- To add a patch to a release:
122
- $ half_orm dev patch <patch_id> add-to-release [release]
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 promote a stage release to rc/production:
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-a2
1
+ 0.17.3-a4