1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
use crate::Status;
use chrono::{offset::TimeZone, Utc};
use rusoto_codebuild::Build;
use rusoto_core::Region;
use serde::{Deserialize, Serialize};
use std::collections::HashMap;

#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
pub struct CodeBuildResult {
    pub commit_id: String,
    pub project_name: String,
    pub repository_name: String,
    pub status: Status,
    pub tags: HashMap<String, String>,
    pub timestamp: i64,
    pub timestamp_formatted: String,
    pub url: String,
}

impl CodeBuildResult {
    pub fn is_failed(&self) -> bool {
        self.status.is_failed()
    }

    pub fn has_tag(&self, key: &str, value: &str) -> bool {
        if self.tags.contains_key(key) {
            self.tags.get(key).unwrap() == value
        } else {
            false
        }
    }
}

impl From<Build> for CodeBuildResult {
    fn from(build: Build) -> Self {
        let build_status = build.clone().build_status.unwrap();

        let commit_id = if build.clone().resolved_source_version.is_none() {
            build.clone().source_version.unwrap()
        } else {
            build.clone().resolved_source_version.unwrap()
        };

        let mut timestamp = 0i64;
        let mut timestamp_formatted = String::from("Undefined");
        if build.clone().end_time.is_some() {
            timestamp = Utc
                .timestamp(build.clone().end_time.unwrap() as i64, 0)
                .timestamp_millis();
            timestamp_formatted = Utc
                .timestamp(build.clone().end_time.unwrap() as i64, 0)
                .to_rfc2822();
        };

        let url = format!(
            "https://{}.console.aws.amazon.com/codesuite/codebuild/projects/{}/build/{}/log",
            Region::default().name(),
            build.clone().project_name.unwrap(),
            build.clone().id.unwrap().replace(':', "%3A")
        );

        let location = build
            .clone()
            .source
            .unwrap()
            .location
            .unwrap_or_else(|| String::from("Undefined"));
        let splitted = location.split('/').collect::<Vec<&str>>();
        let repository_name = splitted.last().unwrap().to_string();

        Self {
            commit_id,
            project_name: build.project_name.clone().unwrap(),
            repository_name,
            status: Status::from(build_status),
            tags: HashMap::new(),
            timestamp,
            timestamp_formatted,
            url,
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_tags() {
        let mut map = HashMap::new();
        map.insert("tag".to_string(), "test".to_string());

        let result = CodeBuildResult {
            commit_id: String::new(),
            project_name: String::new(),
            repository_name: String::new(),
            status: Status::Undefined,
            tags: map,
            timestamp: 0,
            timestamp_formatted: String::new(),
            url: String::new(),
        };

        assert!(result.has_tag("tag", "test"));
        assert!(!result.has_tag("another", "tag"));
    }
}