Skip to content

Commit e6489b8

Browse files
feat(ir): add tasks module with typed helper for PublishTestResults@2 (#1012)
Introduces `src/compile/ir/tasks.rs` — a new home for typed factory functions for ADO built-in pipeline tasks. The first entry is `publish_test_results_step(format, files)`, which returns a pre-configured `TaskStep` for `PublishTestResults@2`. Required inputs (`testResultsFormat`, `testResultsFiles`) are positional parameters; optional inputs (`testRunTitle`, `mergeTestResults`, `searchFolder`, `failTaskOnFailedTests`, `publishRunAttachments`) are applied via the existing `.with_input(…)` builder on the returned value. Three unit tests cover the required-inputs contract, all five supported format identifiers, and the optional-input extension pattern. Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent 1e567a9 commit e6489b8

2 files changed

Lines changed: 102 additions & 0 deletions

File tree

src/compile/ir/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ pub mod lower;
4545
pub mod output;
4646
pub mod stage;
4747
pub mod step;
48+
pub mod tasks;
4849

4950
use ids::StageId;
5051
use job::{Job, Pool};

src/compile/ir/tasks.rs

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
//! Typed factory helpers for ADO built-in pipeline tasks.
2+
//!
3+
//! Each public function returns a [`TaskStep`] pre-configured for a
4+
//! specific ADO task. Required inputs are positional parameters;
5+
//! optional inputs may be applied via `.with_input(…)` on the
6+
//! returned value.
7+
//!
8+
//! These helpers eliminate hand-crafted `TaskStep::new(…)` + raw
9+
//! string inputs at every call site, making task usage self-documenting
10+
//! and the required/optional input boundary explicit.
11+
12+
use super::step::TaskStep;
13+
14+
/// Returns a [`TaskStep`] for `PublishTestResults@2`.
15+
///
16+
/// Publishes test results to the ADO build summary and timeline.
17+
///
18+
/// - `test_results_format` — the test result format. One of `"JUnit"`,
19+
/// `"NUnit"`, `"VSTest"`, `"XUnit"`, or `"CTest"` (alias:
20+
/// `testRunner`).
21+
/// - `test_results_files` — glob pattern that selects the result files,
22+
/// e.g. `"**/TEST-*.xml"` or `"**/*.trx"`.
23+
///
24+
/// Optional inputs (applied with `.with_input(…)` on the returned
25+
/// value):
26+
///
27+
/// | Input key | Type | Default | Description |
28+
/// |---|---|---|---|
29+
/// | `testRunTitle` | string | — | Label shown in the build summary. |
30+
/// | `searchFolder` | string | `$(System.DefaultWorkingDirectory)` | Root for glob expansion. |
31+
/// | `mergeTestResults` | bool string | `"false"` | Combine results into one run. |
32+
/// | `failTaskOnFailedTests` | bool string | `"false"` | Fail the step if tests failed. |
33+
/// | `publishRunAttachments` | bool string | `"true"` | Upload result files. |
34+
///
35+
/// ADO task reference:
36+
/// <https://learn.microsoft.com/en-us/azure/devops/pipelines/tasks/reference/publish-test-results-v2>
37+
pub fn publish_test_results_step(
38+
test_results_format: impl Into<String>,
39+
test_results_files: impl Into<String>,
40+
) -> TaskStep {
41+
TaskStep::new("PublishTestResults@2", "Publish Test Results")
42+
.with_input("testResultsFormat", test_results_format)
43+
.with_input("testResultsFiles", test_results_files)
44+
}
45+
46+
#[cfg(test)]
47+
mod tests {
48+
use super::*;
49+
50+
#[test]
51+
fn publish_test_results_step_sets_task_and_required_inputs() {
52+
let t = publish_test_results_step("JUnit", "**/TEST-*.xml");
53+
assert_eq!(t.task, "PublishTestResults@2");
54+
assert_eq!(
55+
t.inputs.get("testResultsFormat").map(|s| s.as_str()),
56+
Some("JUnit")
57+
);
58+
assert_eq!(
59+
t.inputs.get("testResultsFiles").map(|s| s.as_str()),
60+
Some("**/TEST-*.xml")
61+
);
62+
// display name follows ADO convention
63+
assert_eq!(t.display_name, "Publish Test Results");
64+
// no optional inputs by default
65+
assert_eq!(t.inputs.len(), 2);
66+
}
67+
68+
#[test]
69+
fn publish_test_results_step_accepts_all_supported_formats() {
70+
for format in &["JUnit", "NUnit", "VSTest", "XUnit", "CTest"] {
71+
let t = publish_test_results_step(*format, "**/results.xml");
72+
assert_eq!(t.task, "PublishTestResults@2");
73+
assert_eq!(
74+
t.inputs.get("testResultsFormat").map(|s| s.as_str()),
75+
Some(*format)
76+
);
77+
}
78+
}
79+
80+
#[test]
81+
fn publish_test_results_step_optional_inputs_via_with_input() {
82+
let t = publish_test_results_step("VSTest", "**/*.trx")
83+
.with_input("testRunTitle", "Unit Tests")
84+
.with_input("mergeTestResults", "true")
85+
.with_input("searchFolder", "$(System.DefaultWorkingDirectory)");
86+
assert_eq!(t.task, "PublishTestResults@2");
87+
assert_eq!(
88+
t.inputs.get("testRunTitle").map(|s| s.as_str()),
89+
Some("Unit Tests")
90+
);
91+
assert_eq!(
92+
t.inputs.get("mergeTestResults").map(|s| s.as_str()),
93+
Some("true")
94+
);
95+
assert_eq!(
96+
t.inputs.get("searchFolder").map(|s| s.as_str()),
97+
Some("$(System.DefaultWorkingDirectory)")
98+
);
99+
assert_eq!(t.inputs.len(), 5);
100+
}
101+
}

0 commit comments

Comments
 (0)