Skip to content

Commit 1bfbe0c

Browse files
committed
Add fingerprinting.
1 parent 0f78165 commit 1bfbe0c

22 files changed

Lines changed: 719 additions & 86 deletions

Cargo.lock

Lines changed: 2 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/app/src/commands/task.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -395,8 +395,8 @@ async fn build_command(
395395
let node = ActionNode::run_task(RunTaskNode::new(task.target.clone()));
396396

397397
// Use command builder so that we inherit all paths and env vars
398-
let builder = CommandBuilder::new(&app_context, project, task, &node);
399-
let command = builder.build(&action_context, "").await?;
398+
let builder = CommandBuilder::new(&app_context, project, task);
399+
let command = builder.build(&action_context, &node, "").await?;
400400

401401
Ok(command)
402402
}

crates/config/src/task/checks_config.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -91,13 +91,13 @@ config_unit_enum!(
9191

9292
#[derive(Clone, Debug, Eq, PartialEq, Deserialize)]
9393
#[serde(try_from = "TaskCheckEntryShape")]
94-
pub enum TaskCheckEntry {
94+
pub enum TaskCheck {
9595
Condition(TaskCheckConditionConfig),
9696
Requirement(TaskCheckRequirementConfig),
9797
Fingerprint(TaskCheckFingerprintConfig),
9898
}
9999

100-
impl TaskCheckEntry {
100+
impl TaskCheck {
101101
pub fn get_script(&self) -> &str {
102102
match self {
103103
Self::Condition(config) => &config.script,
@@ -115,7 +115,7 @@ impl TaskCheckEntry {
115115
}
116116
}
117117

118-
impl Serialize for TaskCheckEntry {
118+
impl Serialize for TaskCheck {
119119
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
120120
where
121121
S: Serializer,
@@ -134,7 +134,7 @@ impl Serialize for TaskCheckEntry {
134134
}
135135
}
136136

137-
impl Schematic for TaskCheckEntry {
137+
impl Schematic for TaskCheck {
138138
fn schema_name() -> Option<String> {
139139
Some("TaskCheckEntry".into())
140140
}
@@ -161,7 +161,7 @@ enum TaskCheckEntryShape {
161161
Tagged(TaggedTaskCheckEntry),
162162
}
163163

164-
impl TryFrom<TaskCheckEntryShape> for TaskCheckEntry {
164+
impl TryFrom<TaskCheckEntryShape> for TaskCheck {
165165
type Error = ParseError;
166166

167167
fn try_from(shape: TaskCheckEntryShape) -> Result<Self, Self::Error> {

crates/config/src/task_config.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use crate::shapes::{Input, OneOrMany, Output};
2-
use crate::task::TaskCheckEntry;
2+
use crate::task::TaskCheck;
33
use crate::task_options_config::{PartialTaskOptionsConfig, TaskOptionsConfig};
44
use crate::{config_enum, config_struct, config_unit_enum};
55
use indexmap::IndexMap;
@@ -247,7 +247,7 @@ config_struct!(
247247
/// type of check, the task may be skipped, will fail, or continue.
248248
/// @since 2.4.0
249249
#[serde(default, skip_serializing_if = "Option::is_none")]
250-
pub checks: Option<Vec<TaskCheckEntry>>,
250+
pub checks: Option<Vec<TaskCheck>>,
251251

252252
/// Other tasks that this task depends on, and must run to completion
253253
/// before this task is ran. Can depend on sibling tasks, or tasks in

crates/config/tests/task_config_test.rs

Lines changed: 34 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use indexmap::IndexMap;
44
use moon_common::Id;
55
use moon_config::{
66
FileGroupInput, FileGroupInputFormat, FilePath, Input, OneOrMany, Output, ProjectInput,
7-
TaskArgs, TaskCheckConditionConfig, TaskCheckEntry, TaskCheckFingerprint,
7+
TaskArgs, TaskCheck, TaskCheckConditionConfig, TaskCheckFingerprint,
88
TaskCheckFingerprintConfig, TaskCheckRequirementConfig, TaskConfig, TaskDependency,
99
TaskDependencyCacheStrategy, TaskDependencyConfig, TaskMergeStrategy, TaskOptionCache,
1010
TaskOutputStyle, TaskType,
@@ -760,11 +760,9 @@ checks:
760760

761761
assert_eq!(
762762
config.checks,
763-
Some(vec![TaskCheckEntry::Requirement(
764-
TaskCheckRequirementConfig {
765-
script: "which cargo".into()
766-
}
767-
)])
763+
Some(vec![TaskCheck::Requirement(TaskCheckRequirementConfig {
764+
script: "which cargo".into()
765+
})])
768766
);
769767
}
770768

@@ -782,10 +780,10 @@ checks:
782780
assert_eq!(
783781
config.checks,
784782
Some(vec![
785-
TaskCheckEntry::Requirement(TaskCheckRequirementConfig {
783+
TaskCheck::Requirement(TaskCheckRequirementConfig {
786784
script: "which cargo".into()
787785
}),
788-
TaskCheckEntry::Requirement(TaskCheckRequirementConfig {
786+
TaskCheck::Requirement(TaskCheckRequirementConfig {
789787
script: "which node".into()
790788
}),
791789
])
@@ -805,11 +803,9 @@ checks:
805803

806804
assert_eq!(
807805
config.checks,
808-
Some(vec![TaskCheckEntry::Requirement(
809-
TaskCheckRequirementConfig {
810-
script: "which cargo".into()
811-
}
812-
)])
806+
Some(vec![TaskCheck::Requirement(TaskCheckRequirementConfig {
807+
script: "which cargo".into()
808+
})])
813809
);
814810
}
815811

@@ -826,7 +822,7 @@ checks:
826822

827823
assert_eq!(
828824
config.checks,
829-
Some(vec![TaskCheckEntry::Condition(TaskCheckConditionConfig {
825+
Some(vec![TaskCheck::Condition(TaskCheckConditionConfig {
830826
script: "test -f dist/index.js".into()
831827
})])
832828
);
@@ -846,12 +842,10 @@ checks:
846842

847843
assert_eq!(
848844
config.checks,
849-
Some(vec![TaskCheckEntry::Fingerprint(
850-
TaskCheckFingerprintConfig {
851-
script: "rustc --version".into(),
852-
hash: TaskCheckFingerprint::Stdout,
853-
}
854-
)])
845+
Some(vec![TaskCheck::Fingerprint(TaskCheckFingerprintConfig {
846+
script: "rustc --version".into(),
847+
hash: TaskCheckFingerprint::Stdout,
848+
})])
855849
);
856850
}
857851

@@ -869,12 +863,10 @@ checks:
869863

870864
assert_eq!(
871865
config.checks,
872-
Some(vec![TaskCheckEntry::Fingerprint(
873-
TaskCheckFingerprintConfig {
874-
script: "rustc --version".into(),
875-
hash: TaskCheckFingerprint::Stderr,
876-
}
877-
)])
866+
Some(vec![TaskCheck::Fingerprint(TaskCheckFingerprintConfig {
867+
script: "rustc --version".into(),
868+
hash: TaskCheckFingerprint::Stderr,
869+
})])
878870
);
879871
}
880872

@@ -892,12 +884,10 @@ checks:
892884

893885
assert_eq!(
894886
config.checks,
895-
Some(vec![TaskCheckEntry::Fingerprint(
896-
TaskCheckFingerprintConfig {
897-
script: "rustc --version".into(),
898-
hash: TaskCheckFingerprint::ExitCode,
899-
}
900-
)])
887+
Some(vec![TaskCheck::Fingerprint(TaskCheckFingerprintConfig {
888+
script: "rustc --version".into(),
889+
hash: TaskCheckFingerprint::ExitCode,
890+
})])
901891
);
902892
}
903893

@@ -915,12 +905,10 @@ checks:
915905

916906
assert_eq!(
917907
config.checks,
918-
Some(vec![TaskCheckEntry::Fingerprint(
919-
TaskCheckFingerprintConfig {
920-
script: "rustc --version".into(),
921-
hash: TaskCheckFingerprint::Enabled(true),
922-
}
923-
)])
908+
Some(vec![TaskCheck::Fingerprint(TaskCheckFingerprintConfig {
909+
script: "rustc --version".into(),
910+
hash: TaskCheckFingerprint::Enabled(true),
911+
})])
924912
);
925913
}
926914

@@ -937,12 +925,10 @@ checks:
937925

938926
assert_eq!(
939927
config.checks,
940-
Some(vec![TaskCheckEntry::Fingerprint(
941-
TaskCheckFingerprintConfig {
942-
script: "rustc --version".into(),
943-
hash: TaskCheckFingerprint::Enabled(true),
944-
}
945-
)])
928+
Some(vec![TaskCheck::Fingerprint(TaskCheckFingerprintConfig {
929+
script: "rustc --version".into(),
930+
hash: TaskCheckFingerprint::Enabled(true),
931+
})])
946932
);
947933
}
948934

@@ -966,17 +952,17 @@ checks:
966952
assert_eq!(
967953
config.checks,
968954
Some(vec![
969-
TaskCheckEntry::Requirement(TaskCheckRequirementConfig {
955+
TaskCheck::Requirement(TaskCheckRequirementConfig {
970956
script: "which cargo".into()
971957
}),
972-
TaskCheckEntry::Condition(TaskCheckConditionConfig {
958+
TaskCheck::Condition(TaskCheckConditionConfig {
973959
script: "test -f dist/index.js".into()
974960
}),
975-
TaskCheckEntry::Fingerprint(TaskCheckFingerprintConfig {
961+
TaskCheck::Fingerprint(TaskCheckFingerprintConfig {
976962
script: "rustc --version".into(),
977963
hash: TaskCheckFingerprint::Stdout,
978964
}),
979-
TaskCheckEntry::Requirement(TaskCheckRequirementConfig {
965+
TaskCheck::Requirement(TaskCheckRequirementConfig {
980966
script: "node --version".into()
981967
}),
982968
])

crates/process-augment/src/augmented_command.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use moon_pdk_api::{
77
};
88
use moon_process::{Command, CommandArg, Env};
99
use moon_project::Project;
10-
use moon_task::{Task, TaskCheckEntry};
10+
use moon_task::{Task, TaskCheck};
1111
use moon_toolchain::{
1212
get_version_env_key, get_version_env_value, is_using_global_toolchain,
1313
is_using_global_toolchains,
@@ -97,7 +97,7 @@ impl<'app> AugmentedCommand<'app> {
9797
pub fn from_task_check(
9898
context: &'app AppContext,
9999
bag: &'app GlobalEnvBag,
100-
check: &TaskCheckEntry,
100+
check: &TaskCheck,
101101
) -> Self {
102102
let mut builder = Self::new(context, bag, "noop");
103103
builder.set_script(check.get_script());

crates/process/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ moon_console = { path = "../console" }
1414
moon_env_var = { path = "../env-var" }
1515
miette = { workspace = true }
1616
rustc-hash = { workspace = true }
17+
serde = { workspace = true }
1718
starbase_shell = { workspace = true }
1819
system_env = { workspace = true }
1920
thiserror = { workspace = true }

crates/process/src/output.rs

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,30 @@
11
use crate::process_error::ProcessError;
22
use crate::shared_child::ChildExit;
3+
use serde::{Deserialize, Serialize};
34
use std::process::ExitStatus;
5+
46
pub use std::process::Output as NativeOutput;
57

8+
#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
9+
pub struct OutputInfo {
10+
#[serde(skip_serializing_if = "Option::is_none")]
11+
pub exit_code: Option<i32>,
12+
13+
#[serde(skip_serializing_if = "Option::is_none")]
14+
pub signal: Option<u8>,
15+
16+
#[serde(skip_serializing_if = "Option::is_none")]
17+
pub stderr: Option<String>,
18+
19+
#[serde(skip_serializing_if = "Option::is_none")]
20+
pub stdout: Option<String>,
21+
}
22+
623
#[derive(Clone, Debug, Eq, PartialEq)]
724
pub struct Output {
825
pub exit: ChildExit,
9-
pub stdout: Vec<u8>,
1026
pub stderr: Vec<u8>,
27+
pub stdout: Vec<u8>,
1128
}
1229

1330
impl Output {
@@ -26,6 +43,28 @@ impl Output {
2643
self.status().is_some_and(|status| status.success())
2744
}
2845

46+
pub fn to_info(&self) -> OutputInfo {
47+
OutputInfo {
48+
exit_code: self.code(),
49+
signal: match self.exit {
50+
ChildExit::Completed(_) => None,
51+
ChildExit::Interrupted => Some(2),
52+
ChildExit::Killed => Some(9),
53+
ChildExit::Terminated => Some(15),
54+
},
55+
stderr: if self.stderr.is_empty() {
56+
None
57+
} else {
58+
Some(output_to_trimmed_string(&self.stderr))
59+
},
60+
stdout: if self.stdout.is_empty() {
61+
None
62+
} else {
63+
Some(output_to_trimmed_string(&self.stdout))
64+
},
65+
}
66+
}
67+
2968
pub fn to_error(&self, bin: impl AsRef<str>, with_message: bool) -> ProcessError {
3069
let bin = bin.as_ref().to_owned();
3170

crates/task-hasher/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ moon_env_var = { path = "../env-var" }
1818
moon_feature_flags = { path = "../feature-flags" }
1919
moon_hash = { path = "../hash" }
2020
moon_pdk_api = { path = "../pdk-api" }
21+
moon_process = { path = "../process" }
2122
moon_project = { path = "../project" }
2223
moon_task = { path = "../task" }
2324
moon_toolchain_plugin = { path = "../toolchain-plugin" }

crates/task-hasher/src/task_fingerprint.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ use moon_common::Id;
22
use moon_common::path::WorkspaceRelativePathBuf;
33
use moon_config::Output;
44
use moon_hash::fingerprint;
5+
use moon_process::OutputInfo;
56
use moon_project::Project;
67
use moon_task::{Target, Task};
78
use std::collections::BTreeMap;
@@ -77,3 +78,11 @@ impl<'task> TaskFingerprint<'task> {
7778
}
7879
}
7980
}
81+
82+
fingerprint!(
83+
#[derive(Default)]
84+
pub struct TaskChecksFingerprint {
85+
// Check script to their executed output
86+
pub checks: BTreeMap<String, OutputInfo>,
87+
}
88+
);

0 commit comments

Comments
 (0)