gabriel / musehub public
0004_release_system_v2.py python
139 lines 4.6 KB
0bfb4569 add agent rules: Muse-only VCS, no Git/GitHub gabriel 9h ago
1 """Release system v2 — semver + channel + changelog + wire tags.
2
3 Revision ID: 0004
4 Revises: 0003
5 Create Date: 2026-03-21
6
7 Changes:
8 MUSEHUB_RELEASES
9 - DROP COLUMN is_prerelease (replaced by channel)
10 - ADD COLUMN channel VARCHAR(20) NOT NULL DEFAULT 'stable'
11 - ADD COLUMN semver_major INT NOT NULL DEFAULT 0
12 - ADD COLUMN semver_minor INT NOT NULL DEFAULT 0
13 - ADD COLUMN semver_patch INT NOT NULL DEFAULT 0
14 - ADD COLUMN semver_pre VARCHAR(255) NOT NULL DEFAULT ''
15 - ADD COLUMN semver_build VARCHAR(255) NOT NULL DEFAULT ''
16 - ADD COLUMN snapshot_id VARCHAR(128) NULL
17 - ADD COLUMN agent_id VARCHAR(255) NOT NULL DEFAULT ''
18 - ADD COLUMN model_id VARCHAR(255) NOT NULL DEFAULT ''
19 - ADD COLUMN changelog_json TEXT NOT NULL DEFAULT '[]'
20 - Make title nullable (default '') — CLI may omit it
21
22 NEW TABLE
23 - musehub_wire_tags: lightweight semantic tags pushed via wire protocol
24 """
25 import sqlalchemy as sa
26 from alembic import op
27
28
29 revision = "0004"
30 down_revision = "0003"
31 branch_labels = None
32 depends_on = None
33
34
35 def upgrade() -> None:
36 # ── musehub_releases — drop is_prerelease, add rich semver/channel fields ──
37 op.drop_column("musehub_releases", "is_prerelease")
38
39 op.add_column(
40 "musehub_releases",
41 sa.Column("channel", sa.String(20), nullable=False, server_default="stable"),
42 )
43 op.create_index(
44 "ix_musehub_releases_channel",
45 "musehub_releases",
46 ["channel"],
47 )
48
49 op.add_column(
50 "musehub_releases",
51 sa.Column("semver_major", sa.Integer(), nullable=False, server_default="0"),
52 )
53 op.add_column(
54 "musehub_releases",
55 sa.Column("semver_minor", sa.Integer(), nullable=False, server_default="0"),
56 )
57 op.add_column(
58 "musehub_releases",
59 sa.Column("semver_patch", sa.Integer(), nullable=False, server_default="0"),
60 )
61 op.add_column(
62 "musehub_releases",
63 sa.Column("semver_pre", sa.String(255), nullable=False, server_default=""),
64 )
65 op.add_column(
66 "musehub_releases",
67 sa.Column("semver_build", sa.String(255), nullable=False, server_default=""),
68 )
69 op.add_column(
70 "musehub_releases",
71 sa.Column("snapshot_id", sa.String(128), nullable=True),
72 )
73 op.add_column(
74 "musehub_releases",
75 sa.Column("agent_id", sa.String(255), nullable=False, server_default=""),
76 )
77 op.add_column(
78 "musehub_releases",
79 sa.Column("model_id", sa.String(255), nullable=False, server_default=""),
80 )
81 op.add_column(
82 "musehub_releases",
83 sa.Column("changelog_json", sa.Text(), nullable=False, server_default="[]"),
84 )
85
86 # title was NOT NULL with no default — make it nullable so CLI omitting it works.
87 op.alter_column("musehub_releases", "title", server_default="", nullable=False)
88
89 # ── musehub_wire_tags — new table ─────────────────────────────────────────
90 op.create_table(
91 "musehub_wire_tags",
92 sa.Column("tag_id", sa.String(36), primary_key=True),
93 sa.Column(
94 "repo_id",
95 sa.String(36),
96 sa.ForeignKey("musehub_repos.repo_id", ondelete="CASCADE"),
97 nullable=False,
98 ),
99 sa.Column("commit_id", sa.String(64), nullable=False),
100 sa.Column("tag", sa.String(500), nullable=False),
101 sa.Column(
102 "created_at",
103 sa.DateTime(timezone=True),
104 nullable=False,
105 server_default=sa.text("NOW()"),
106 ),
107 sa.UniqueConstraint("repo_id", "tag", name="uq_musehub_wire_tags_repo_tag"),
108 )
109 op.create_index(
110 "ix_musehub_wire_tags_repo_id",
111 "musehub_wire_tags",
112 ["repo_id"],
113 )
114 op.create_index(
115 "ix_musehub_wire_tags_tag",
116 "musehub_wire_tags",
117 ["tag"],
118 )
119
120
121 def downgrade() -> None:
122 op.drop_table("musehub_wire_tags")
123
124 op.drop_column("musehub_releases", "changelog_json")
125 op.drop_column("musehub_releases", "model_id")
126 op.drop_column("musehub_releases", "agent_id")
127 op.drop_column("musehub_releases", "snapshot_id")
128 op.drop_column("musehub_releases", "semver_build")
129 op.drop_column("musehub_releases", "semver_pre")
130 op.drop_column("musehub_releases", "semver_patch")
131 op.drop_column("musehub_releases", "semver_minor")
132 op.drop_column("musehub_releases", "semver_major")
133 op.drop_index("ix_musehub_releases_channel", table_name="musehub_releases")
134 op.drop_column("musehub_releases", "channel")
135
136 op.add_column(
137 "musehub_releases",
138 sa.Column("is_prerelease", sa.Boolean(), nullable=False, server_default="false"),
139 )