fix(release): make durable runs recovery safe
This commit is contained in:
@@ -100,6 +100,7 @@ class RepositoryTagRequest(BaseModel):
|
||||
|
||||
|
||||
class ReleaseRunCreateRequest(BaseModel):
|
||||
request_id: str = Field(min_length=8, max_length=128)
|
||||
repo_versions: dict[str, str] = Field(default_factory=dict)
|
||||
channel: str = Field(default="stable", min_length=1, max_length=64)
|
||||
online: bool = False
|
||||
@@ -128,10 +129,15 @@ def create_app(
|
||||
app.state.workspace_root = workspace_root
|
||||
app.state.token = token
|
||||
app.state.workspace_fingerprint = release_workspace_fingerprint(workspace_root)
|
||||
app.state.release_runs = ReleaseRunStore(
|
||||
run_state_root
|
||||
release_run_root = (
|
||||
workspace_release_run_root(
|
||||
run_state_root, app.state.workspace_fingerprint
|
||||
)
|
||||
if run_state_root is not None
|
||||
else default_release_run_root(workspace_root),
|
||||
else default_release_run_root(workspace_root)
|
||||
)
|
||||
app.state.release_runs = ReleaseRunStore(
|
||||
release_run_root,
|
||||
expected_workspace_fingerprint=app.state.workspace_fingerprint,
|
||||
)
|
||||
|
||||
@@ -255,6 +261,24 @@ def create_app(
|
||||
raise HTTPException(
|
||||
status_code=400, detail="At least one repository version is required"
|
||||
)
|
||||
input_snapshot = {
|
||||
"channel": request.channel,
|
||||
"repo_versions": dict(request.repo_versions),
|
||||
"online": request.online,
|
||||
"remote_tags": request.remote_tags,
|
||||
"public_catalog": request.public_catalog,
|
||||
"include_migrations": request.include_migrations,
|
||||
"workspace_fingerprint": app.state.workspace_fingerprint,
|
||||
}
|
||||
try:
|
||||
existing = app.state.release_runs.find_created_run(
|
||||
request_id=request.request_id,
|
||||
input_snapshot=input_snapshot,
|
||||
)
|
||||
except (ReleaseRunConflict, ReleaseRunCorrupt) as exc:
|
||||
raise HTTPException(status_code=409, detail=str(exc)) from exc
|
||||
if existing is not None:
|
||||
return existing
|
||||
snapshot = build_dashboard(
|
||||
workspace_root=app.state.workspace_root,
|
||||
online=request.online,
|
||||
@@ -294,15 +318,8 @@ def create_app(
|
||||
)
|
||||
try:
|
||||
return app.state.release_runs.create(
|
||||
input_snapshot={
|
||||
"channel": request.channel,
|
||||
"repo_versions": dict(request.repo_versions),
|
||||
"online": request.online,
|
||||
"remote_tags": request.remote_tags,
|
||||
"public_catalog": request.public_catalog,
|
||||
"include_migrations": request.include_migrations,
|
||||
"workspace_fingerprint": app.state.workspace_fingerprint,
|
||||
},
|
||||
request_id=request.request_id,
|
||||
input_snapshot=input_snapshot,
|
||||
plan_snapshot=plan_payload,
|
||||
)
|
||||
except (ReleaseRunConflict, ReleaseRunCorrupt) as exc:
|
||||
@@ -492,6 +509,14 @@ def default_release_run_root(workspace_root: Path) -> Path:
|
||||
)
|
||||
|
||||
|
||||
def workspace_release_run_root(state_root: Path, workspace_fingerprint: str) -> Path:
|
||||
return (
|
||||
state_root.expanduser()
|
||||
/ f"workspace-{workspace_fingerprint}"
|
||||
/ "release-runs"
|
||||
)
|
||||
|
||||
|
||||
def release_workspace_fingerprint(workspace_root: Path) -> str:
|
||||
canonical = str(workspace_root.expanduser().resolve()).encode("utf-8")
|
||||
return hashlib.sha256(canonical).hexdigest()
|
||||
|
||||
Reference in New Issue
Block a user