Skip to content

Commit 218bd82

Browse files
committed
feat(graph-proxy): add workflow creator to graph
1 parent 4044462 commit 218bd82

File tree

1 file changed

+85
-0
lines changed

1 file changed

+85
-0
lines changed

backend/graph-proxy/src/graphql/workflows.rs

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,11 @@ impl Workflow {
107107
.as_ref()
108108
.and_then(|template_ref| template_ref.name.as_deref())
109109
}
110+
111+
/// The workflow creator
112+
async fn creator(&self) -> WorkflowCreator {
113+
WorkflowCreator::from_argo_workflow_labels(&self.manifest.metadata.labels)
114+
}
110115
}
111116

112117
#[derive(Debug)]
@@ -627,6 +632,34 @@ impl WorkflowsQuery {
627632
}
628633
}
629634

635+
/// Information about the creator of a workflow.
636+
#[derive(Debug, Clone, SimpleObject, Eq, PartialEq)]
637+
struct WorkflowCreator {
638+
/// An identifier unique to the creator of the workflow.
639+
/// Typically this is the creator's Fed-ID.
640+
creator_id: String,
641+
}
642+
643+
impl WorkflowCreator {
644+
/// Creates a new [`WorkflowCreator`] from the given creator ID.
645+
fn new(creator_id: impl Into<String>) -> Self {
646+
Self {
647+
creator_id: creator_id.into(),
648+
}
649+
}
650+
651+
/// Builds a [`WorkflowCreator`] from Argo workflow labels.
652+
fn from_argo_workflow_labels(labels: &HashMap<String, String>) -> Self {
653+
let creator_id = labels
654+
.get("workflows.argoproj.io/creator-preferred-username")
655+
.or_else(|| labels.get("workflows.argoproj.io/creator"))
656+
.cloned()
657+
.unwrap_or_default();
658+
659+
Self::new(creator_id)
660+
}
661+
}
662+
630663
#[cfg(test)]
631664
mod tests {
632665
use crate::graphql::{root_schema_builder, Authorization, Bearer, Visit};
@@ -1557,4 +1590,56 @@ mod tests {
15571590
});
15581591
assert_eq!(resp.data.into_json().unwrap(), expected_data);
15591592
}
1593+
1594+
#[tokio::test]
1595+
async fn workflow_creator() {
1596+
let workflow_name = "numpy-benchmark-wdkwj";
1597+
let visit = Visit {
1598+
proposal_code: "mg".to_string(),
1599+
proposal_number: 36964,
1600+
number: 1,
1601+
};
1602+
1603+
let mut server = mockito::Server::new_async().await;
1604+
let mut response_file_path = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
1605+
response_file_path.push("test-assets");
1606+
response_file_path.push("get-workflow-wdkwj.json");
1607+
let workflow_endpoint = server
1608+
.mock(
1609+
"GET",
1610+
&format!("/api/v1/workflows/{visit}/{workflow_name}")[..],
1611+
)
1612+
.with_status(200)
1613+
.with_header("content-type", "application/json")
1614+
.with_body_from_file(response_file_path)
1615+
.create_async()
1616+
.await;
1617+
1618+
let argo_server_url = Url::parse(&server.url()).unwrap();
1619+
let schema = root_schema_builder()
1620+
.data(ArgoServerUrl(argo_server_url))
1621+
.data(None::<Authorization<Bearer>>)
1622+
.finish();
1623+
let query = format!(
1624+
r#"
1625+
query {{
1626+
workflow(name: "{}", visit: {{proposalCode: "{}", proposalNumber: {}, number: {}}}) {{
1627+
creator {{ creatorId }}
1628+
}}
1629+
}}
1630+
"#,
1631+
workflow_name, visit.proposal_code, visit.proposal_number, visit.number
1632+
);
1633+
let resp = schema.execute(query).await.into_result().unwrap();
1634+
1635+
workflow_endpoint.assert_async().await;
1636+
let expected_data = json!({
1637+
"workflow": {
1638+
"creator": {
1639+
"creatorId": "enu43627",
1640+
}
1641+
}
1642+
});
1643+
assert_eq!(resp.data.into_json().unwrap(), expected_data);
1644+
}
15601645
}

0 commit comments

Comments
 (0)