From 981dd58f4e88fb4b8ebfd9fa4cbd4b7504fe7a98 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 17 Jun 2026 10:03:54 +0000 Subject: [PATCH] feat(ir): add typed helper for DeleteFiles@1 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds `delete_files_step()` to `src/compile/ir/tasks.rs` — a typed factory for the ADO `DeleteFiles@1` task. Required input (`Contents`) is a positional parameter; optional inputs (`SourceFolder`, `RemoveSourceFolder`, `RemoveDotFiles`) are applied via the existing `.with_input(…)` builder on the returned `TaskStep`. Five unit tests are included covering: - default (required-only) construction - optional `SourceFolder` - `RemoveSourceFolder` flag - `RemoveDotFiles` flag - multiline `Contents` patterns Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- src/compile/ir/tasks.rs | 85 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 85 insertions(+) diff --git a/src/compile/ir/tasks.rs b/src/compile/ir/tasks.rs index bdc75f7c..44bb1665 100644 --- a/src/compile/ir/tasks.rs +++ b/src/compile/ir/tasks.rs @@ -291,6 +291,29 @@ pub fn powershell_inline_step(script: impl Into) -> TaskStep { .with_input("script", script) } +/// Returns a [`TaskStep`] for `DeleteFiles@1`. +/// +/// Deletes files or folders matching one or more patterns from a source folder. +/// +/// - `contents` — newline-separated glob patterns identifying the files or +/// folders to remove (e.g. `"**/*.tmp"` or `"dist\n*.log"`). This is the +/// only required input. +/// +/// Optional inputs (applied with `.with_input(…)` on the returned value): +/// +/// | Input key | Type | Default | Description | +/// |---|---|---|---| +/// | `SourceFolder` | string | working directory | Root folder to delete from. Use `$(Build.ArtifactStagingDirectory)` to clean staging. | +/// | `RemoveSourceFolder` | bool string | `"false"` | Remove the `SourceFolder` itself after deleting its contents. Set to `"true"` and `contents` to `"*"` to wipe the whole folder. | +/// | `RemoveDotFiles` | bool string | `"false"` | Also delete files whose name starts with a dot. Defaults to `"false"` (dot files are preserved). | +/// +/// ADO task reference: +/// +pub fn delete_files_step(contents: impl Into) -> TaskStep { + TaskStep::new("DeleteFiles@1", "Delete Files") + .with_input("Contents", contents) +} + #[cfg(test)] mod tests { use super::*; @@ -841,4 +864,66 @@ mod tests { Some("$version = Get-Content VERSION\nWrite-Host \"Building version $version\"") ); } + + // ── DeleteFiles@1 ──────────────────────────────────────────────────── + + #[test] + fn delete_files_step_sets_task_and_required_input() { + let t = delete_files_step("**/*.tmp"); + assert_eq!(t.task, "DeleteFiles@1"); + assert_eq!(t.display_name, "Delete Files"); + assert_eq!( + t.inputs.get("Contents").map(|s| s.as_str()), + Some("**/*.tmp") + ); + // only the required input is set by default + assert_eq!(t.inputs.len(), 1); + } + + #[test] + fn delete_files_step_accepts_source_folder() { + let t = delete_files_step("**/*.log") + .with_input("SourceFolder", "$(Build.ArtifactStagingDirectory)"); + assert_eq!(t.task, "DeleteFiles@1"); + assert_eq!( + t.inputs.get("SourceFolder").map(|s| s.as_str()), + Some("$(Build.ArtifactStagingDirectory)") + ); + assert_eq!(t.inputs.len(), 2); + } + + #[test] + fn delete_files_step_accepts_remove_source_folder_flag() { + let t = delete_files_step("*") + .with_input("SourceFolder", "$(Build.ArtifactStagingDirectory)") + .with_input("RemoveSourceFolder", "true"); + assert_eq!(t.task, "DeleteFiles@1"); + assert_eq!( + t.inputs.get("RemoveSourceFolder").map(|s| s.as_str()), + Some("true") + ); + assert_eq!(t.inputs.len(), 3); + } + + #[test] + fn delete_files_step_accepts_remove_dot_files_flag() { + let t = delete_files_step("**") + .with_input("RemoveDotFiles", "true"); + assert_eq!(t.task, "DeleteFiles@1"); + assert_eq!( + t.inputs.get("RemoveDotFiles").map(|s| s.as_str()), + Some("true") + ); + assert_eq!(t.inputs.len(), 2); + } + + #[test] + fn delete_files_step_multiline_contents() { + let t = delete_files_step("**/*.tmp\n**/*.log\ndist/"); + assert_eq!(t.task, "DeleteFiles@1"); + assert_eq!( + t.inputs.get("Contents").map(|s| s.as_str()), + Some("**/*.tmp\n**/*.log\ndist/") + ); + } }