posthog_cli/utils/
release.rs1use std::{collections::HashMap, path::PathBuf};
2
3use anyhow::Result;
4use serde::{Deserialize, Serialize};
5use serde_json::Value;
6use tracing::{info, warn};
7use uuid::Uuid;
8
9use super::{auth::Token, git::get_git_info};
10
11#[derive(Debug, Clone, Serialize, Deserialize)]
12struct CreateReleaseRequest {
13 #[serde(skip_serializing_if = "HashMap::is_empty")]
14 pub metadata: HashMap<String, Value>,
15 pub hash_id: Option<String>,
16 pub version: String,
17 pub project: String,
18}
19
20#[derive(Debug, Clone, Serialize, Deserialize)]
22pub struct CreateReleaseResponse {
23 pub id: Uuid,
24}
25
26pub fn create_release(
27 host: &str,
28 token: &Token,
29 dir: Option<PathBuf>,
30 hash_id: Option<String>,
31 project: Option<String>,
32 version: Option<String>,
33) -> Result<Option<CreateReleaseResponse>> {
34 let git_info = get_git_info(dir)?;
35
36 let Some(version) = version.or(git_info.as_ref().map(|g| g.commit_id.clone())) else {
37 warn!(
38 "Could not create release - no version provided, and one could not be derived via git"
39 );
40 return Ok(None);
41 };
42
43 let project = project.or_else(|| git_info.as_ref().and_then(|g| g.repo_name.clone()));
44 let Some(project) = project else {
45 warn!("Could not create release - no project name provided, and one could not be derived via git");
46 return Ok(None);
47 };
48
49 let mut metadata = HashMap::new();
50 if let Some(git_info) = git_info {
51 metadata.insert("git".to_string(), serde_json::to_value(git_info)?);
52 }
53
54 let request = CreateReleaseRequest {
55 metadata,
56 hash_id,
57 version,
58 project,
59 };
60
61 let url = format!(
62 "{}/api/environments/{}/error_tracking/releases",
63 host, token.env_id
64 );
65
66 let client = reqwest::blocking::Client::new();
67
68 let response = client
69 .post(&url)
70 .header("Authorization", format!("Bearer {}", token.token))
71 .header("Content-Type", "application/json")
72 .json(&request)
73 .send()?;
74
75 if response.status().is_success() {
76 let response = response.json::<CreateReleaseResponse>()?;
77 info!(
78 "Release {} of {} created successfully! {}",
79 request.version, request.project, response.id
80 );
81 Ok(Some(response))
82 } else {
83 let e = response.text()?;
84 Err(anyhow::anyhow!("Failed to create release: {}", e))
85 }
86}