posthog_cli/utils/
release.rs

1use 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// The API returns more than this, but we only care about the ID
21#[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}