gabriel / musehub public
0006_ci_system.py python
158 lines 7.0 KB
Raw
sha256:a10adeeb7a0169cb9900f9806ed7a973047258abb6283724fe55e8eb68ff3f0a init: musehub initial commit Human 171 days ago
1 """Add MuseHub CI tables — runs, jobs, steps, secrets.
2
3 Implements the MuseHub continuous integration system storage layer:
4 - musehub_ci_runs: a pipeline execution per push/proposal event
5 - musehub_ci_jobs: individual jobs within a run
6 - musehub_ci_steps: ordered shell steps within a job
7 - musehub_ci_secrets: per-repo Fernet-encrypted secrets for job environments
8
9 Revision ID: 0006
10 Revises: 0005
11 """
12
13 from __future__ import annotations
14
15 import sqlalchemy as sa
16 from alembic import op
17
18 revision = "0006"
19 down_revision = "0005"
20 branch_labels = None
21 depends_on = None
22
23
24 def upgrade() -> None:
25 # ── musehub_ci_runs ────────────────────────────────────────────────────────
26 op.create_table(
27 "musehub_ci_runs",
28 sa.Column("run_id", sa.String(36), primary_key=True),
29 sa.Column(
30 "repo_id",
31 sa.String(36),
32 sa.ForeignKey("musehub_repos.repo_id", ondelete="CASCADE"),
33 nullable=False,
34 ),
35 sa.Column("commit_id", sa.String(255), nullable=False),
36 sa.Column("branch", sa.String(255), nullable=False),
37 sa.Column(
38 "pr_id",
39 sa.String(36),
40 sa.ForeignKey("musehub_pull_requests.pr_id", ondelete="SET NULL"),
41 nullable=True,
42 ),
43 sa.Column("trigger", sa.String(20), nullable=False, server_default="push"),
44 sa.Column("workflow_name", sa.String(255), nullable=False, server_default="CI"),
45 sa.Column("workflow_object_id", sa.String(255), nullable=True),
46 sa.Column("status", sa.String(20), nullable=False, server_default="pending"),
47 sa.Column("changed_symbols", sa.JSON, nullable=False, server_default="[]"),
48 sa.Column("triggered_by", sa.String(255), nullable=False, server_default="system"),
49 sa.Column("started_at", sa.DateTime(timezone=True), nullable=True),
50 sa.Column("completed_at", sa.DateTime(timezone=True), nullable=True),
51 sa.Column(
52 "created_at",
53 sa.DateTime(timezone=True),
54 nullable=False,
55 server_default=sa.func.now(),
56 ),
57 )
58 op.create_index("ix_musehub_ci_runs_repo_id", "musehub_ci_runs", ["repo_id"])
59 op.create_index("ix_musehub_ci_runs_repo_status", "musehub_ci_runs", ["repo_id", "status"])
60 op.create_index("ix_musehub_ci_runs_commit_id", "musehub_ci_runs", ["commit_id"])
61 op.create_index("ix_musehub_ci_runs_pr_id", "musehub_ci_runs", ["pr_id"])
62 op.create_index("ix_musehub_ci_runs_status", "musehub_ci_runs", ["status"])
63 op.create_index("ix_musehub_ci_runs_created_at", "musehub_ci_runs", ["created_at"])
64
65 # ── musehub_ci_jobs ────────────────────────────────────────────────────────
66 op.create_table(
67 "musehub_ci_jobs",
68 sa.Column("job_id", sa.String(36), primary_key=True),
69 sa.Column(
70 "run_id",
71 sa.String(36),
72 sa.ForeignKey("musehub_ci_runs.run_id", ondelete="CASCADE"),
73 nullable=False,
74 ),
75 sa.Column("key", sa.String(255), nullable=False),
76 sa.Column("name", sa.String(500), nullable=False),
77 sa.Column("container_image", sa.String(500), nullable=False, server_default="python:3.14-slim"),
78 sa.Column("needs", sa.JSON, nullable=False, server_default="[]"),
79 sa.Column("condition", sa.Text, nullable=False, server_default=""),
80 sa.Column("env_vars", sa.JSON, nullable=False, server_default="{}"),
81 sa.Column("status", sa.String(20), nullable=False, server_default="pending"),
82 sa.Column("exit_code", sa.Integer, nullable=True),
83 sa.Column("runner_id", sa.String(255), nullable=True),
84 sa.Column("started_at", sa.DateTime(timezone=True), nullable=True),
85 sa.Column("completed_at", sa.DateTime(timezone=True), nullable=True),
86 sa.Column(
87 "created_at",
88 sa.DateTime(timezone=True),
89 nullable=False,
90 server_default=sa.func.now(),
91 ),
92 )
93 op.create_index("ix_musehub_ci_jobs_run_id", "musehub_ci_jobs", ["run_id"])
94 op.create_index("ix_musehub_ci_jobs_status", "musehub_ci_jobs", ["status"])
95
96 # ── musehub_ci_steps ───────────────────────────────────────────────────────
97 op.create_table(
98 "musehub_ci_steps",
99 sa.Column("step_id", sa.String(36), primary_key=True),
100 sa.Column(
101 "job_id",
102 sa.String(36),
103 sa.ForeignKey("musehub_ci_jobs.job_id", ondelete="CASCADE"),
104 nullable=False,
105 ),
106 sa.Column("order", sa.Integer, nullable=False, server_default="0"),
107 sa.Column("name", sa.String(500), nullable=False, server_default=""),
108 sa.Column("run_cmd", sa.Text, nullable=False),
109 sa.Column("status", sa.String(20), nullable=False, server_default="pending"),
110 sa.Column("log_output", sa.Text, nullable=False, server_default=""),
111 sa.Column("exit_code", sa.Integer, nullable=True),
112 sa.Column("started_at", sa.DateTime(timezone=True), nullable=True),
113 sa.Column("completed_at", sa.DateTime(timezone=True), nullable=True),
114 sa.Column(
115 "created_at",
116 sa.DateTime(timezone=True),
117 nullable=False,
118 server_default=sa.func.now(),
119 ),
120 )
121 op.create_index("ix_musehub_ci_steps_job_id", "musehub_ci_steps", ["job_id"])
122 op.create_index("ix_musehub_ci_steps_status", "musehub_ci_steps", ["status"])
123
124 # ── musehub_ci_secrets ─────────────────────────────────────────────────────
125 op.create_table(
126 "musehub_ci_secrets",
127 sa.Column("secret_id", sa.String(36), primary_key=True),
128 sa.Column(
129 "repo_id",
130 sa.String(36),
131 sa.ForeignKey("musehub_repos.repo_id", ondelete="CASCADE"),
132 nullable=False,
133 ),
134 sa.Column("name", sa.String(255), nullable=False),
135 sa.Column("encrypted_value", sa.Text, nullable=False),
136 sa.Column("description", sa.String(500), nullable=False, server_default=""),
137 sa.Column(
138 "created_at",
139 sa.DateTime(timezone=True),
140 nullable=False,
141 server_default=sa.func.now(),
142 ),
143 sa.Column(
144 "updated_at",
145 sa.DateTime(timezone=True),
146 nullable=False,
147 server_default=sa.func.now(),
148 ),
149 sa.UniqueConstraint("repo_id", "name", name="uq_musehub_ci_secrets_repo_name"),
150 )
151 op.create_index("ix_musehub_ci_secrets_repo_id", "musehub_ci_secrets", ["repo_id"])
152
153
154 def downgrade() -> None:
155 op.drop_table("musehub_ci_secrets")
156 op.drop_table("musehub_ci_steps")
157 op.drop_table("musehub_ci_jobs")
158 op.drop_table("musehub_ci_runs")
File History 1 commit
sha256:a10adeeb7a0169cb9900f9806ed7a973047258abb6283724fe55e8eb68ff3f0a init: musehub initial commit Human 171 days ago