From f9231423a6caad22e58dc6d56114cfc1b5060491 Mon Sep 17 00:00:00 2001 From: noyez Date: Wed, 9 Jan 2019 12:36:04 -0500 Subject: [PATCH 1/4] Adding PipelineHooks --- data/pipeline.json | 157 +++++++++++++++++++++++++++++++++++++++++++++ src/test/types.rs | 6 ++ src/types.rs | 3 + src/webhooks.rs | 83 ++++++++++++++++++++++-- 4 files changed, 244 insertions(+), 5 deletions(-) create mode 100644 data/pipeline.json diff --git a/data/pipeline.json b/data/pipeline.json new file mode 100644 index 00000000..3cfab6de --- /dev/null +++ b/data/pipeline.json @@ -0,0 +1,157 @@ +{ + "builds": [ + { + "artifacts_file": { + "filename": "artifacts.zip", + "size": 57540037 + }, + "created_at": "2018-12-28 01:42:47 UTC", + "finished_at": "2018-12-28 02:03:51 UTC", + "id": 139419296, + "manual": false, + "name": "package-deb-armv7-build", + "runner": { + "active": true, + "description": "shared-runners-manager-6.gitlab.com", + "id": 380987, + "is_shared": true + }, + "stage": "build", + "started_at": "2018-12-28 01:42:47 UTC", + "status": "success", + "user": { + "avatar_url": "https:\/\/secure.gravatar.com\/avatar\/a871331a2dfc6a0711e397a3ad9abe53?s=80&d=identicon", + "name": "noyez", + "username": "noyez" + }, + "when": "on_success" + }, + { + "artifacts_file": { + "filename": "artifacts.zip", + "size": 57563165 + }, + "created_at": "2018-12-28 00:52:52 UTC", + "finished_at": "2018-12-28 01:25:40 UTC", + "id": 139413492, + "manual": false, + "name": "package-deb-armv7-build", + "runner": { + "active": true, + "description": "shared-runners-manager-3.gitlab.com", + "id": 44028, + "is_shared": true + }, + "stage": "build", + "started_at": "2018-12-28 00:52:53 UTC", + "status": "success", + "user": { + "avatar_url": "https:\/\/secure.gravatar.com\/avatar\/a871331a2dfc6a0711e397a3ad9abe53?s=80&d=identicon", + "name": "noyez", + "username": "noyez" + }, + "when": "on_success" + }, + { + "artifacts_file": { + "filename": "artifacts.zip", + "size": 57574697 + }, + "created_at": "2018-12-22 02:47:17 UTC", + "finished_at": "2018-12-22 03:20:10 UTC", + "id": 138014345, + "manual": false, + "name": "package-deb-armv7-build", + "runner": { + "active": true, + "description": "shared-runners-manager-3.gitlab.com", + "id": 44028, + "is_shared": true + }, + "stage": "build", + "started_at": "2018-12-22 03:00:11 UTC", + "status": "success", + "user": { + "avatar_url": "https:\/\/secure.gravatar.com\/avatar\/a871331a2dfc6a0711e397a3ad9abe53?s=80&d=identicon", + "name": "noyez", + "username": "noyez" + }, + "when": "on_success" + }, + { + "artifacts_file": { + "filename": "as", + "size": 15279 + }, + "created_at": "2018-12-22 02:47:17 UTC", + "finished_at": "2018-12-22 03:00:09 UTC", + "id": 138014344, + "manual": false, + "name": "test-native", + "runner": { + "active": true, + "description": "shared-runners-manager-5.gitlab.com", + "id": 380986, + "is_shared": true + }, + "stage": "test", + "started_at": "2018-12-22 02:47:17 UTC", + "status": "success", + "user": { + "avatar_url": "https:\/\/secure.gravatar.com\/avatar\/a871331a2dfc6a0711e397a3ad9abe53?s=80&d=identicon", + "name": "noyez", + "username": "noyez" + }, + "when": "on_success" + } + ], + "commit": { + "author": { + "email": "brad@bkn.lan", + "name": "noyez" + }, + "id": "e16784d8462ad3ee0eee0e27b5c195a5fa375154", + "message": "version bump\n", + "timestamp": "2018-12-22T02:47:10Z", + "url": "https:\/\/gitlab.com\/Embue\/hmm-core\/commit\/e16784d8462ad3ee0eee0e27b5c195a5fa375154" + }, + "object_attributes": { + "before_sha": "49a2ea8927c50664c2bcd133485b64d04526b367", + "created_at": "2018-12-22 02:47:17 UTC", + "detailed_status": "passed", + "duration": 2035, + "finished_at": "2018-12-28 02:03:51 UTC", + "id": 41064864, + "ref": "bkn_streamid_addition", + "sha": "e16784d8462ad3ee0eee0e27b5c195a5fa375154", + "stages": [ + "test", + "build" + ], + "status": "success", + "tag": false, + "variables": [ + + ] + }, + "object_kind": "pipeline", + "project": { + "avatar_url": null, + "ci_config_path": null, + "default_branch": "master", + "description": "", + "git_http_url": "https:\/\/gitlab.com\/Embue\/hmm-core.git", + "git_ssh_url": "git@gitlab.com:Embue\/hmm-core.git", + "id": 6529838, + "name": "hmm-core", + "namespace": "Embue", + "path_with_namespace": "Embue\/hmm-core", + "visibility_level": 0, + "web_url": "https:\/\/gitlab.com\/Embue\/hmm-core" + }, + "user": { + "avatar_url": "https:\/\/secure.gravatar.com\/avatar\/a871331a2dfc6a0711e397a3ad9abe53?s=80&d=identicon", + "name": "noyez", + "username": "noyez" + } +} diff --git a/src/test/types.rs b/src/test/types.rs index d4ef316f..4c815171 100644 --- a/src/test/types.rs +++ b/src/test/types.rs @@ -11,6 +11,7 @@ use crates::serde::de::DeserializeOwned; use crates::serde_json::from_reader; use types::*; +use webhooks::*; use std::fs::File; @@ -20,6 +21,11 @@ fn read_test_file(name: &str) -> T { from_reader::(fin).unwrap() } +#[test] +fn test_read_pipeline() { + let pipeline_hook: PipelineHook = read_test_file("pipeline"); +} + #[test] fn test_read_award_emoji() { diff --git a/src/types.rs b/src/types.rs index dd3b2121..ba855e8c 100644 --- a/src/types.rs +++ b/src/types.rs @@ -1893,6 +1893,8 @@ pub enum StatusState { Pending, /// The check is currently running. Running, + /// The check passed. + Passed, /// The check succeeded. Success, /// The check failed. @@ -1908,6 +1910,7 @@ pub enum StatusState { enum_serialize!(StatusState -> "status state", Created => "created", Pending => "pending", + Passed => "passed", Running => "running", Success => "success", Failed => "failed", diff --git a/src/webhooks.rs b/src/webhooks.rs index db55ba56..61ef847d 100644 --- a/src/webhooks.rs +++ b/src/webhooks.rs @@ -20,7 +20,7 @@ use crates::serde_json::{self, Value}; use types::{JobId, IssueId, IssueInternalId, IssueState, MergeRequestId, MergeRequestInternalId, MergeRequestState, MergeStatus, - MilestoneId, NoteId, NoteType, NoteableId, ObjectId, ProjectId, SnippetId, UserId}; + MilestoneId, NoteId, NoteType, NoteableId, ObjectId, ProjectId, SnippetId, UserId, JobArtifactFile, Runner, StatusState, User, PipelineId}; #[derive(Debug, Clone, Copy)] /// A wrapper struct for dates in web hooks. @@ -84,10 +84,10 @@ pub struct ProjectHookAttrs { pub path_with_namespace: String, /// The default branch for the project. pub default_branch: Option, - homepage: String, - http_url: String, - ssh_url: String, - url: String, + homepage: Option, + http_url: Option, + ssh_url: Option, + url: Option, } #[cfg_attr(feature="strict", serde(deny_unknown_fields))] @@ -146,6 +146,79 @@ pub struct CommitHookAttrs { pub removed: Option>, } +#[derive(Serialize, Deserialize, Debug, Clone)] +pub struct BuildAttrs { + pub artifacts_file : JobArtifactFile, + /// When the hook was created. + pub created_at: HookDate, + /// When the hook was finished + pub finished_at: HookDate, + /// When the hook was finished + pub started_at: HookDate, + /// The ID of the build. + pub id: JobId, + /// Manual job. + pub manual: bool, + /// Job name + pub name: String, + /// Runner + pub runner: Runner, + /// Build stage name + pub stage: String, + /// Status of the build + pub status: StatusState, + /// The user which triggered the hook. + pub user: UserHookAttrs, + /// How build was triggered + pub when: String, +} + +#[derive(Serialize, Deserialize, Debug, Clone)] +pub struct PipelineCommitAuthorAttrs { + pub email: String, + pub name: String, +} + +//#[cfg_attr(feature="strict", serde(deny_unknown_fields))] +#[derive(Serialize, Deserialize, Debug, Clone)] +pub struct PipelineHookAttrs { + /// + pub before_sha: ObjectId, + /// Date pipeline created + pub created_at: HookDate, + /// Status of Pipeline + pub detailed_status: StatusState, + /// Duration of pipeline (in seconds) + pub duration: u64, + /// Time pipeline finished. + pub finished_at: HookDate, + /// Id of pipeline + pub id: PipelineId, + /// References for pipeline, branch or tag. + #[serde(rename="ref")] + pub ref_: String, + pub sha: ObjectId, + /// All stages of pipeline + pub stages: Vec, + /// Status of pipeline + pub status: StatusState, + pub tag: bool, + /// Variables used to during pipeline + pub variables: Vec, +} + +#[cfg_attr(feature="strict", serde(deny_unknown_fields))] +#[derive(Serialize, Deserialize, Debug, Clone)] +/// A Pipeline hook. +pub struct PipelineHook { + pub builds : Vec, + pub commit : CommitHookAttrs, + pub object_attributes: PipelineHookAttrs, + pub object_kind : String, + pub project: ProjectHookAttrs, + pub user: UserHookAttrs, +} + #[cfg_attr(feature="strict", serde(deny_unknown_fields))] #[derive(Serialize, Deserialize, Debug, Clone)] /// A push hook. -- GitLab From 6ca41c01c609d6e323190de46ee01d94c6bca188 Mon Sep 17 00:00:00 2001 From: noyez Date: Wed, 9 Jan 2019 13:11:48 -0500 Subject: [PATCH 2/4] refactor --- src/test/types.rs | 2 +- src/webhooks.rs | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/test/types.rs b/src/test/types.rs index 4c815171..246d3d20 100644 --- a/src/test/types.rs +++ b/src/test/types.rs @@ -23,7 +23,7 @@ fn read_test_file(name: &str) -> T { } #[test] fn test_read_pipeline() { - let pipeline_hook: PipelineHook = read_test_file("pipeline"); + let pipeline_hook: PipelineHook = read_test_file("pipeline2"); } diff --git a/src/webhooks.rs b/src/webhooks.rs index 61ef847d..bee7d90d 100644 --- a/src/webhooks.rs +++ b/src/webhooks.rs @@ -150,11 +150,11 @@ pub struct CommitHookAttrs { pub struct BuildAttrs { pub artifacts_file : JobArtifactFile, /// When the hook was created. - pub created_at: HookDate, + pub created_at: DateTime, /// When the hook was finished - pub finished_at: HookDate, + pub finished_at: DateTime, /// When the hook was finished - pub started_at: HookDate, + pub started_at: DateTime, /// The ID of the build. pub id: JobId, /// Manual job. @@ -185,13 +185,13 @@ pub struct PipelineHookAttrs { /// pub before_sha: ObjectId, /// Date pipeline created - pub created_at: HookDate, + pub created_at: DateTime, /// Status of Pipeline pub detailed_status: StatusState, /// Duration of pipeline (in seconds) pub duration: u64, /// Time pipeline finished. - pub finished_at: HookDate, + pub finished_at: DateTime, /// Id of pipeline pub id: PipelineId, /// References for pipeline, branch or tag. -- GitLab From e6a78d1642e03a63d9187016ce0ad461f1f92401 Mon Sep 17 00:00:00 2001 From: noyez Date: Wed, 9 Jan 2019 15:42:21 -0500 Subject: [PATCH 3/4] Adding uid=502(brad) gid=20(staff) groups=20(staff),501(macports),101(access_bpf),505(ruby),12(everyone),61(localaccounts),399(com.apple.access_ssh),100(_lpoperator),701(com.apple.sharepoint.group.1) to ProjectHookAttrs --- src/webhooks.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/webhooks.rs b/src/webhooks.rs index bee7d90d..dfe0af56 100644 --- a/src/webhooks.rs +++ b/src/webhooks.rs @@ -84,6 +84,11 @@ pub struct ProjectHookAttrs { pub path_with_namespace: String, /// The default branch for the project. pub default_branch: Option, + /// Project id + pub id: u64, + /// ... + pub ci_config_path: Option, + homepage: Option, http_url: Option, ssh_url: Option, -- GitLab From b6b1305bab8ed63eaa8ed384050cc965000a669e Mon Sep 17 00:00:00 2001 From: noyez Date: Thu, 10 Jan 2019 09:51:43 -0500 Subject: [PATCH 4/4] Fixing pipeline to handle items, also unified datetimes --- src/test/types.rs | 35 +++++++++++++++++- src/types.rs | 2 +- src/webhooks.rs | 90 +++++++++++++++++++++++++++++++++++------------ 3 files changed, 103 insertions(+), 24 deletions(-) diff --git a/src/test/types.rs b/src/test/types.rs index 246d3d20..f80a3224 100644 --- a/src/test/types.rs +++ b/src/test/types.rs @@ -22,10 +22,43 @@ fn read_test_file(name: &str) -> T { from_reader::(fin).unwrap() } #[test] -fn test_read_pipeline() { +fn test_read_pipeline_1() { let pipeline_hook: PipelineHook = read_test_file("pipeline2"); } +#[test] +fn test_read_pipeline_2() { + let pipeline_hook: PipelineHook = read_test_file("pipeline2"); +} + +#[test] +fn test_read_pipeline_3() { + let pipeline_hook: PipelineHook = read_test_file("pipeline3"); +} + +#[test] +fn test_read_pipeline_4() { + let pipeline_hook: PipelineHook = read_test_file("pipeline4"); +} + +#[test] +fn test_read_pipeline_5() { + let pipeline_hook: PipelineHook = read_test_file("pipeline5"); +} + + +#[test] +fn test_read_pipeline_6() { + let pipeline_hook: PipelineHook = read_test_file("pipeline6"); +} +#[test] +fn test_read_pipeline_7() { + let pipeline_hook: PipelineHook = read_test_file("pipeline7"); +} +#[test] +fn test_read_pipeline_8() { + let pipeline_hook: PipelineHook = read_test_file("pipeline8"); +} #[test] fn test_read_award_emoji() { diff --git a/src/types.rs b/src/types.rs index ba855e8c..7dc9b755 100644 --- a/src/types.rs +++ b/src/types.rs @@ -2124,7 +2124,7 @@ pub struct Runner { /// An uploaded artifact from a job. pub struct JobArtifactFile { /// The name of the artifact. - pub filename: String, + pub filename: Option, /// The size (in bytes) of the artifact. pub size: usize, } diff --git a/src/webhooks.rs b/src/webhooks.rs index dfe0af56..e10e3f6d 100644 --- a/src/webhooks.rs +++ b/src/webhooks.rs @@ -22,6 +22,7 @@ use types::{JobId, IssueId, IssueInternalId, IssueState, MergeRequestId, MergeRequestInternalId, MergeRequestState, MergeStatus, MilestoneId, NoteId, NoteType, NoteableId, ObjectId, ProjectId, SnippetId, UserId, JobArtifactFile, Runner, StatusState, User, PipelineId}; + #[derive(Debug, Clone, Copy)] /// A wrapper struct for dates in web hooks. /// @@ -60,6 +61,29 @@ impl AsRef> for HookDate { } } +#[derive(Deserialize)] +/// A wrapper struct helper struct for gitlab's mixed date format +/// +/// Gitlab does not use a standard date format for dates in web hooks. This structure supports +/// deserializing from either format into a consistant DateTime +#[serde(untagged)] +enum ChronoDtOrHookDtHelper { ChronoDt(DateTime), HookDt(HookDate) } +fn chrono_dt_or_hook_dt<'de, D>(deserializer: D) -> Result, D::Error> + where D: Deserializer<'de> +{ + match ChronoDtOrHookDtHelper::deserialize(deserializer)? { + ChronoDtOrHookDtHelper::ChronoDt(v) => { Ok(v) } + ChronoDtOrHookDtHelper::HookDt(v) => { Ok(v.0) } + } +} + +fn chrono_dt_or_hook_dt_opt<'de, D>(deserializer: D) -> Result>, D::Error> + where D: Deserializer<'de> +{ + //chrono_dt_or_hook_dt(deserializer).map(|x| Some(x)).or(Ok(None)) + chrono_dt_or_hook_dt(deserializer).map(|x| Some(x)).or(Ok(None)) +} + #[cfg_attr(feature="strict", serde(deny_unknown_fields))] #[derive(Serialize, Deserialize, Debug, Clone)] /// Project information exposed in hooks. @@ -155,11 +179,14 @@ pub struct CommitHookAttrs { pub struct BuildAttrs { pub artifacts_file : JobArtifactFile, /// When the hook was created. + #[serde(deserialize_with = "chrono_dt_or_hook_dt")] pub created_at: DateTime, /// When the hook was finished - pub finished_at: DateTime, + #[serde(deserialize_with = "chrono_dt_or_hook_dt_opt")] + pub finished_at: Option>, /// When the hook was finished - pub started_at: DateTime, + #[serde(deserialize_with = "chrono_dt_or_hook_dt_opt")] + pub started_at: Option>, /// The ID of the build. pub id: JobId, /// Manual job. @@ -167,7 +194,7 @@ pub struct BuildAttrs { /// Job name pub name: String, /// Runner - pub runner: Runner, + pub runner: Option, /// Build stage name pub stage: String, /// Status of the build @@ -190,13 +217,15 @@ pub struct PipelineHookAttrs { /// pub before_sha: ObjectId, /// Date pipeline created + #[serde(deserialize_with = "chrono_dt_or_hook_dt")] pub created_at: DateTime, /// Status of Pipeline pub detailed_status: StatusState, /// Duration of pipeline (in seconds) - pub duration: u64, + pub duration: Option, /// Time pipeline finished. - pub finished_at: DateTime, + #[serde(deserialize_with = "chrono_dt_or_hook_dt_opt")] + pub finished_at: Option>, /// Id of pipeline pub id: PipelineId, /// References for pipeline, branch or tag. @@ -300,13 +329,17 @@ pub struct IssueHookAttrs { /// The ID of the project. pub project_id: ProjectId, /// When the issue was created. - pub created_at: HookDate, + #[serde(deserialize_with = "chrono_dt_or_hook_dt")] + pub created_at: DateTime, /// When the issue was last updated. - pub updated_at: HookDate, + #[serde(deserialize_with = "chrono_dt_or_hook_dt")] + pub updated_at: DateTime, /// When the issue was deleted. - pub deleted_at: Option, + #[serde(deserialize_with = "chrono_dt_or_hook_dt_opt")] + pub deleted_at: Option>, /// When the issue was closed. - pub closed_at: Option, + #[serde(deserialize_with = "chrono_dt_or_hook_dt_opt")] + pub closed_at: Option>, /// When the issue is due. pub due_date: Option, /// The ID of the user which last updated the issue. @@ -439,13 +472,17 @@ pub struct MergeRequestHookAttrs { /// The title of the merge request. pub title: String, /// When the merge request was created. - pub created_at: HookDate, + #[serde(deserialize_with = "chrono_dt_or_hook_dt")] + pub created_at: DateTime, /// When the merge request was last updated. - pub updated_at: HookDate, + #[serde(deserialize_with = "chrono_dt_or_hook_dt")] + pub updated_at: DateTime, /// When the merge request was deleted. - pub deleted_at: Option, + #[serde(deserialize_with = "chrono_dt_or_hook_dt_opt")] + pub deleted_at: Option>, /// When the merge request was locked. - pub locked_at: Option, + #[serde(deserialize_with = "chrono_dt_or_hook_dt_opt")] + pub locked_at: Option>, /// The ID of the user which last updated the merge request. pub updated_by_id: Option, /// The object ID of the commit which merged the merge request. @@ -523,9 +560,11 @@ pub struct SnippetHookAttrs { /// The project the snippet belongs to. pub project_id: Option, /// When the snippet was created. - pub created_at: HookDate, + #[serde(deserialize_with = "chrono_dt_or_hook_dt")] + pub created_at: DateTime, /// When the snippet was last updated. - pub updated_at: HookDate, + #[serde(deserialize_with = "chrono_dt_or_hook_dt")] + pub updated_at: DateTime, /// The name of the snippet. pub file_name: String, #[serde(rename="type")] @@ -623,13 +662,16 @@ pub struct NoteHookAttrs { /// The author of the note. pub author_id: UserId, /// When the note was created. - pub created_at: HookDate, + #[serde(deserialize_with = "chrono_dt_or_hook_dt")] + pub created_at: DateTime, /// When the note was last updated. - pub updated_at: HookDate, + #[serde(deserialize_with = "chrono_dt_or_hook_dt")] + pub updated_at: DateTime, /// The ID of the user who last updated the note. pub updated_by_id: Option, /// When the note was marked as resolved. - pub resolved_at: Option, + #[serde(deserialize_with = "chrono_dt_or_hook_dt_opt")] + pub resolved_at: Option>, /// The ID of the user who marked the note as resolved. pub resolved_by_id: Option, /// The ID of the project. @@ -733,9 +775,11 @@ pub struct BuildCommitHookAttrs { pub status: String, pub duration: u64, /// When the build started. - pub started_at: Option, + #[serde(deserialize_with = "chrono_dt_or_hook_dt_opt")] + pub started_at: Option>, /// When the build completed. - pub finished_at: Option, + #[serde(deserialize_with = "chrono_dt_or_hook_dt_opt")] + pub finished_at: Option>, } #[cfg_attr(feature="strict", serde(deny_unknown_fields))] @@ -775,9 +819,11 @@ pub struct BuildHook { pub build_name: String, pub build_stage: String, /// When the build started. - pub build_started_at: Option, + #[serde(deserialize_with = "chrono_dt_or_hook_dt_opt")] + pub build_started_at: Option>, /// When the build completed. - pub build_finished_at: Option, + #[serde(deserialize_with = "chrono_dt_or_hook_dt_opt")] + pub build_finished_at: Option>, pub build_duration: Option, /// Whether the build is allowed to fail. pub build_allow_failure: bool, -- GitLab