From 786d7b823b921e7213d4a85b3f1769a5a1d926d1 Mon Sep 17 00:00:00 2001 From: Ethan Hall Date: Sun, 3 Mar 2024 12:13:19 -0800 Subject: [PATCH 01/14] Extract models into workspace --- Cargo.lock | 370 ++++++++++++++- Cargo.toml | 2 +- scope-models/Cargo.toml | 20 + .../examples/v1alpha/DoctorGroup.yaml | 0 scope-models/examples/v1alpha/KnownError.yaml | 8 + .../examples/v1alpha/ReportDefinition.yaml | 14 + .../v1alpha/ReportLocation.github.yaml | 9 + .../v1alpha/ReportLocation.rustyPaste.yaml | 8 + scope-models/schema/merged.json | 423 +++++++++++++++++ ...pha.com.github.scope.ScopeDoctorGroup.json | 430 ++++++++++++++++++ ...lpha.com.github.scope.ScopeKnownError.json | 430 ++++++++++++++++++ ...om.github.scope.ScopeReportDefinition.json | 430 ++++++++++++++++++ ....com.github.scope.ScopeReportLocation.json | 430 ++++++++++++++++++ scope-models/src/core.rs | 95 ++++ scope-models/src/lib.rs | 152 +++++++ scope-models/src/v1alpha/doctor_group.rs | 99 ++++ scope-models/src/v1alpha/known_error.rs | 62 +++ scope-models/src/v1alpha/mod.rs | 24 + scope-models/src/v1alpha/report_definition.rs | 64 +++ scope-models/src/v1alpha/report_location.rs | 82 ++++ scope/Cargo.toml | 1 + scope/examples/group-1.yaml | 28 ++ scope/src/doctor/check.rs | 8 +- scope/src/doctor/commands/list.rs | 4 +- scope/src/doctor/commands/run.rs | 8 +- scope/src/doctor/runner.rs | 18 +- scope/src/doctor/tests.rs | 35 +- scope/src/shared/config_load.rs | 28 +- scope/src/shared/mod.rs | 11 +- .../shared/models/internal/doctor_group.rs | 127 +++++- .../src/shared/models/internal/known_error.rs | 51 +++ scope/src/shared/models/internal/mod.rs | 35 ++ .../models/internal/report_definition.rs | 49 ++ .../shared/models/internal/upload_location.rs | 23 + scope/src/shared/models/mod.rs | 129 ------ .../src/shared/models/v1alpha/doctor_exec.rs | 149 ------ .../src/shared/models/v1alpha/doctor_group.rs | 161 ------- .../src/shared/models/v1alpha/doctor_setup.rs | 147 ------ .../models/v1alpha/examples/setup-1.yaml | 12 - .../models/v1alpha/examples/setup-2.yaml | 12 - .../src/shared/models/v1alpha/known_error.rs | 53 --- scope/src/shared/models/v1alpha/mod.rs | 101 ---- .../models/v1alpha/report_definition.rs | 57 --- .../shared/models/v1alpha/report_location.rs | 100 ---- scope/src/shared/report.rs | 4 +- 45 files changed, 3500 insertions(+), 1003 deletions(-) create mode 100644 scope-models/Cargo.toml rename scope/src/shared/models/v1alpha/examples/group-1.yaml => scope-models/examples/v1alpha/DoctorGroup.yaml (100%) create mode 100644 scope-models/examples/v1alpha/KnownError.yaml create mode 100644 scope-models/examples/v1alpha/ReportDefinition.yaml create mode 100644 scope-models/examples/v1alpha/ReportLocation.github.yaml create mode 100644 scope-models/examples/v1alpha/ReportLocation.rustyPaste.yaml create mode 100644 scope-models/schema/merged.json create mode 100644 scope-models/schema/v1alpha.com.github.scope.ScopeDoctorGroup.json create mode 100644 scope-models/schema/v1alpha.com.github.scope.ScopeKnownError.json create mode 100644 scope-models/schema/v1alpha.com.github.scope.ScopeReportDefinition.json create mode 100644 scope-models/schema/v1alpha.com.github.scope.ScopeReportLocation.json create mode 100644 scope-models/src/core.rs create mode 100644 scope-models/src/lib.rs create mode 100644 scope-models/src/v1alpha/doctor_group.rs create mode 100644 scope-models/src/v1alpha/known_error.rs create mode 100644 scope-models/src/v1alpha/mod.rs create mode 100644 scope-models/src/v1alpha/report_definition.rs create mode 100644 scope-models/src/v1alpha/report_location.rs create mode 100644 scope/examples/group-1.yaml delete mode 100644 scope/src/shared/models/v1alpha/doctor_exec.rs delete mode 100644 scope/src/shared/models/v1alpha/doctor_group.rs delete mode 100644 scope/src/shared/models/v1alpha/doctor_setup.rs delete mode 100644 scope/src/shared/models/v1alpha/examples/setup-1.yaml delete mode 100644 scope/src/shared/models/v1alpha/examples/setup-2.yaml delete mode 100644 scope/src/shared/models/v1alpha/known_error.rs delete mode 100644 scope/src/shared/models/v1alpha/mod.rs delete mode 100644 scope/src/shared/models/v1alpha/report_definition.rs delete mode 100644 scope/src/shared/models/v1alpha/report_location.rs diff --git a/Cargo.lock b/Cargo.lock index 95be27c..ab384ec 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -17,6 +17,20 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" +[[package]] +name = "ahash" +version = "0.8.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b79b82693f705137f8fb9b37871d99e4f9a7df12b917eed79c3d3954830a60b" +dependencies = [ + "cfg-if", + "getrandom", + "once_cell", + "serde", + "version_check", + "zerocopy", +] + [[package]] name = "aho-corasick" version = "1.1.2" @@ -163,6 +177,21 @@ version = "0.21.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" +[[package]] +name = "bit-set" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0700ddab506f33b20a03b13996eccd309a48e5ff77d0d95926aa0210fb4e95f1" +dependencies = [ + "bit-vec", +] + +[[package]] +name = "bit-vec" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "349f9b6a179ed607305526ca489b34ad0a41aed5f7980fa90eb03160b69598fb" + [[package]] name = "bitflags" version = "1.3.2" @@ -201,6 +230,12 @@ version = "3.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f30e7476521f6f8af1a1c4c0b8cc94f0bee37d91763d0ca2665f299b6cd8aec" +[[package]] +name = "bytecount" +version = "0.6.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1e5f035d16fc623ae5f74981db80a439803888314e3a555fd6f04acd51a3205" + [[package]] name = "bytes" version = "1.5.0" @@ -393,8 +428,18 @@ version = "0.14.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7b750cb3417fd1b327431a470f388520309479ab0bf5e323505daf0290cd3850" dependencies = [ - "darling_core", - "darling_macro", + "darling_core 0.14.4", + "darling_macro 0.14.4", +] + +[[package]] +name = "darling" +version = "0.20.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "54e36fcd13ed84ffdfda6f5be89b31287cbb80c439841fe69e04841435464391" +dependencies = [ + "darling_core 0.20.8", + "darling_macro 0.20.8", ] [[package]] @@ -411,17 +456,42 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "darling_core" +version = "0.20.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c2cf1c23a687a1feeb728783b993c4e1ad83d99f351801977dd809b48d0a70f" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "strsim", + "syn 2.0.48", +] + [[package]] name = "darling_macro" version = "0.14.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a4aab4dbc9f7611d8b55048a3a16d2d010c2c8334e46304b40ac1cc14bf3b48e" dependencies = [ - "darling_core", + "darling_core 0.14.4", "quote", "syn 1.0.109", ] +[[package]] +name = "darling_macro" +version = "0.20.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a668eda54683121533a393014d8692171709ff57a7d61f187b6e782719f8933f" +dependencies = [ + "darling_core 0.20.8", + "quote", + "syn 2.0.48", +] + [[package]] name = "deranged" version = "0.3.11" @@ -448,7 +518,16 @@ version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "660047478bc508c0fde22c868991eec0c40a63e48d610befef466d48e2bee574" dependencies = [ - "derive_builder_macro", + "derive_builder_macro 0.13.0", +] + +[[package]] +name = "derive_builder" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0350b5cb0331628a5916d6c5c0b72e97393b8b6b03b47a9284f4e7f5a405ffd7" +dependencies = [ + "derive_builder_macro 0.20.0", ] [[package]] @@ -457,22 +536,44 @@ version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b217e6dd1011a54d12f3b920a411b5abd44b1716ecfe94f5f2f2f7b52e08ab7" dependencies = [ - "darling", + "darling 0.14.4", "proc-macro2", "quote", "syn 1.0.109", ] +[[package]] +name = "derive_builder_core" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d48cda787f839151732d396ac69e3473923d54312c070ee21e9effcaa8ca0b1d" +dependencies = [ + "darling 0.20.8", + "proc-macro2", + "quote", + "syn 2.0.48", +] + [[package]] name = "derive_builder_macro" version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7a5f77d7e20ac9153428f7ca14a88aba652adfc7a0ef0a06d654386310ef663b" dependencies = [ - "derive_builder_core", + "derive_builder_core 0.13.0", "syn 1.0.109", ] +[[package]] +name = "derive_builder_macro" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "206868b8242f27cecce124c19fd88157fbd0dd334df2587f36417bafbc85097b" +dependencies = [ + "derive_builder_core 0.20.0", + "syn 2.0.48", +] + [[package]] name = "dev-scope" version = "2024.2.6" @@ -485,7 +586,8 @@ dependencies = [ "clap", "colored", "derivative", - "derive_builder", + "derive_builder 0.13.0", + "dev-scope-model", "directories", "dotenv", "educe", @@ -509,7 +611,7 @@ dependencies = [ "serde_json", "serde_yaml", "sha256", - "strum", + "strum 0.25.0", "thiserror", "time", "tokio", @@ -520,6 +622,21 @@ dependencies = [ "which", ] +[[package]] +name = "dev-scope-model" +version = "2024.2.6" +dependencies = [ + "anyhow", + "derive_builder 0.20.0", + "jsonschema", + "schemars", + "serde", + "serde_json", + "serde_yaml", + "strum 0.26.1", + "thiserror", +] + [[package]] name = "difflib" version = "0.4.0" @@ -656,6 +773,16 @@ dependencies = [ "serde_json", ] +[[package]] +name = "fancy-regex" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b95f7c0680e4142284cf8b22c14a476e87d61b004a3a0861872b32ef7ead40a2" +dependencies = [ + "bit-set", + "regex", +] + [[package]] name = "fastrand" version = "2.0.1" @@ -707,6 +834,16 @@ dependencies = [ "percent-encoding", ] +[[package]] +name = "fraction" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3027ae1df8d41b4bed2241c8fdad4acc1e7af60c8e17743534b545e77182d678" +dependencies = [ + "lazy_static", + "num", +] + [[package]] name = "fragile" version = "2.0.0" @@ -728,6 +865,12 @@ version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" +[[package]] +name = "futures-io" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1" + [[package]] name = "futures-sink" version = "0.3.30" @@ -747,9 +890,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" dependencies = [ "futures-core", + "futures-io", "futures-task", + "memchr", "pin-project-lite", "pin-utils", + "slab", ] [[package]] @@ -769,8 +915,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "190092ea657667030ac6a35e305e62fc4dd69fd98ac98631e5d3a2b1575a12b5" dependencies = [ "cfg-if", + "js-sys", "libc", "wasi", + "wasm-bindgen", ] [[package]] @@ -1063,6 +1211,15 @@ version = "2.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f518f335dce6725a761382244631d86cf0ccb2863413590b31338feb467f9c3" +[[package]] +name = "iso8601" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "924e5d73ea28f59011fec52a0d12185d496a9b075d360657aed2a5707f701153" +dependencies = [ + "nom", +] + [[package]] name = "itertools" version = "0.12.1" @@ -1102,6 +1259,36 @@ version = "0.12.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "078e285eafdfb6c4b434e0d31e8cfcb5115b651496faca5749b88fafd4f23bfd" +[[package]] +name = "jsonschema" +version = "0.17.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a071f4f7efc9a9118dfb627a0a94ef247986e1ab8606a4c806ae2b3aa3b6978" +dependencies = [ + "ahash", + "anyhow", + "base64", + "bytecount", + "clap", + "fancy-regex", + "fraction", + "getrandom", + "iso8601", + "itoa", + "memchr", + "num-cmp", + "once_cell", + "parking_lot", + "percent-encoding", + "regex", + "reqwest", + "serde", + "serde_json", + "time", + "url", + "uuid", +] + [[package]] name = "lazy_static" version = "1.4.0" @@ -1202,6 +1389,12 @@ dependencies = [ "serde", ] +[[package]] +name = "minimal-lexical" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" + [[package]] name = "miniz_oxide" version = "0.7.2" @@ -1286,6 +1479,16 @@ dependencies = [ "unicode-segmentation", ] +[[package]] +name = "nom" +version = "7.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" +dependencies = [ + "memchr", + "minimal-lexical", +] + [[package]] name = "normalize-line-endings" version = "0.3.0" @@ -1302,12 +1505,84 @@ dependencies = [ "winapi", ] +[[package]] +name = "num" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b05180d69e3da0e530ba2a1dae5110317e49e3b7f3d41be227dc5f92e49ee7af" +dependencies = [ + "num-bigint", + "num-complex", + "num-integer", + "num-iter", + "num-rational", + "num-traits", +] + +[[package]] +name = "num-bigint" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "608e7659b5c3d7cba262d894801b9ec9d00de989e8a82bd4bef91d08da45cdc0" +dependencies = [ + "autocfg", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-cmp" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "63335b2e2c34fae2fb0aa2cecfd9f0832a1e24b3b32ecec612c3426d46dc8aaa" + +[[package]] +name = "num-complex" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23c6602fda94a57c990fe0df199a035d83576b496aa29f4e634a8ac6004e68a6" +dependencies = [ + "num-traits", +] + [[package]] name = "num-conv" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" +[[package]] +name = "num-integer" +version = "0.1.46" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" +dependencies = [ + "num-traits", +] + +[[package]] +name = "num-iter" +version = "0.1.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d869c01cc0c455284163fd0092f1f93835385ccab5a98a0dcc497b2f8bf055a9" +dependencies = [ + "autocfg", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-rational" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0638a1c9d0a3c0914158145bc76cff373a75a627e6ecbfb71cbe6f453a5a19b0" +dependencies = [ + "autocfg", + "num-bigint", + "num-integer", + "num-traits", +] + [[package]] name = "num-traits" version = "0.2.17" @@ -1792,6 +2067,30 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "schemars" +version = "0.8.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "45a28f4c49489add4ce10783f7911893516f15afe45d015608d41faca6bc4d29" +dependencies = [ + "dyn-clone", + "schemars_derive", + "serde", + "serde_json", +] + +[[package]] +name = "schemars_derive" +version = "0.8.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c767fd6fa65d9ccf9cf026122c1b555f2ef9a4f0cea69da4d7dbc3e258d30967" +dependencies = [ + "proc-macro2", + "quote", + "serde_derive_internals", + "syn 1.0.109", +] + [[package]] name = "scopeguard" version = "1.2.0" @@ -1851,6 +2150,17 @@ dependencies = [ "syn 2.0.48", ] +[[package]] +name = "serde_derive_internals" +version = "0.26.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85bf8229e7920a9f636479437026331ce11aa132b4dde37d121944a44d6e5f3c" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + [[package]] name = "serde_json" version = "1.0.113" @@ -2002,7 +2312,16 @@ version = "0.25.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "290d54ea6f91c969195bdbcd7442c8c2a2ba87da8bf60a7ee86a235d4bc1e125" dependencies = [ - "strum_macros", + "strum_macros 0.25.3", +] + +[[package]] +name = "strum" +version = "0.26.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "723b93e8addf9aa965ebe2d11da6d7540fa2283fcea14b3371ff055f7ba13f5f" +dependencies = [ + "strum_macros 0.26.1", ] [[package]] @@ -2018,6 +2337,19 @@ dependencies = [ "syn 2.0.48", ] +[[package]] +name = "strum_macros" +version = "0.26.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a3417fc93d76740d974a01654a09777cb500428cc874ca9f45edfe0c4d4cd18" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "rustversion", + "syn 2.0.48", +] + [[package]] name = "syn" version = "1.0.109" @@ -2784,3 +3116,23 @@ dependencies = [ "cfg-if", "windows-sys 0.48.0", ] + +[[package]] +name = "zerocopy" +version = "0.7.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74d4d3961e53fa4c9a25a8637fc2bfaf2595b3d3ae34875568a5cf64787716be" +dependencies = [ + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.7.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ce1b18ccd8e73a9321186f97e46f9f04b778851177567b1975109d26a08d2a6" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.48", +] diff --git a/Cargo.toml b/Cargo.toml index d0efacd..0395809 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,5 +1,5 @@ [workspace] -members = ["scope"] +members = ["scope", "scope-models"] resolver = "2" # Config for 'cargo dist' diff --git a/scope-models/Cargo.toml b/scope-models/Cargo.toml new file mode 100644 index 0000000..fb4da5e --- /dev/null +++ b/scope-models/Cargo.toml @@ -0,0 +1,20 @@ +[package] +name = "dev-scope-model" +version = "2024.2.6" +edition = "2021" + +[package.metadata.dist] +dist = true + +[dependencies] +anyhow = "1.0.57" +thiserror = "1.0.30" +serde = { version = "1.0", features = ["derive"] } +serde_yaml = "0.9" +serde_json = "1.0" +schemars = "0.8" +derive_builder = "0.20" +strum = { version = "0.26", features = ["derive"] } + +[dev-dependencies] +jsonschema = "0.17" \ No newline at end of file diff --git a/scope/src/shared/models/v1alpha/examples/group-1.yaml b/scope-models/examples/v1alpha/DoctorGroup.yaml similarity index 100% rename from scope/src/shared/models/v1alpha/examples/group-1.yaml rename to scope-models/examples/v1alpha/DoctorGroup.yaml diff --git a/scope-models/examples/v1alpha/KnownError.yaml b/scope-models/examples/v1alpha/KnownError.yaml new file mode 100644 index 0000000..f12dee7 --- /dev/null +++ b/scope-models/examples/v1alpha/KnownError.yaml @@ -0,0 +1,8 @@ +apiVersion: scope.github.com/v1alpha +kind: ScopeKnownError +metadata: + name: error-exists +spec: + description: Check if the word error is in the logs + pattern: error + help: The command had an error, try reading the logs around there to find out what happened. \ No newline at end of file diff --git a/scope-models/examples/v1alpha/ReportDefinition.yaml b/scope-models/examples/v1alpha/ReportDefinition.yaml new file mode 100644 index 0000000..e2a2be2 --- /dev/null +++ b/scope-models/examples/v1alpha/ReportDefinition.yaml @@ -0,0 +1,14 @@ +apiVersion: scope.github.com/v1alpha +kind: ScopeReportDefinition +metadata: + name: template +spec: + additionalData: + username: id -u + ruby: which ruby + node: which node + nodeVersion: node -v + template: | + # There was an error! + + When running `{{ command }}` scope ran into an error \ No newline at end of file diff --git a/scope-models/examples/v1alpha/ReportLocation.github.yaml b/scope-models/examples/v1alpha/ReportLocation.github.yaml new file mode 100644 index 0000000..8907317 --- /dev/null +++ b/scope-models/examples/v1alpha/ReportLocation.github.yaml @@ -0,0 +1,9 @@ +apiVersion: scope.github.com/v1alpha +kind: ScopeReportLocation +metadata: + name: github +spec: + destination: + githubIssue: + owner: ethankhall + repo: dummy-repo \ No newline at end of file diff --git a/scope-models/examples/v1alpha/ReportLocation.rustyPaste.yaml b/scope-models/examples/v1alpha/ReportLocation.rustyPaste.yaml new file mode 100644 index 0000000..c2a6594 --- /dev/null +++ b/scope-models/examples/v1alpha/ReportLocation.rustyPaste.yaml @@ -0,0 +1,8 @@ +apiVersion: scope.github.com/v1alpha +kind: ScopeReportLocation +metadata: + name: report +spec: + destination: + rustyPaste: + url: http://localhost:8000 \ No newline at end of file diff --git a/scope-models/schema/merged.json b/scope-models/schema/merged.json new file mode 100644 index 0000000..ccfed64 --- /dev/null +++ b/scope-models/schema/merged.json @@ -0,0 +1,423 @@ +{ + "$schema": "https://json-schema.org/draft/2019-09/schema", + "title": "ScopeTypes", + "anyOf": [ + { + "$ref": "#/definitions/V1AlphaReportLocation" + }, + { + "$ref": "#/definitions/V1AlphaReportDefinition" + }, + { + "$ref": "#/definitions/V1AlphaKnownError" + }, + { + "$ref": "#/definitions/V1AlphaDoctorGroup" + } + ], + "definitions": { + "DoctorCheckSpec": { + "type": "object", + "properties": { + "commands": { + "default": null, + "type": [ + "array", + "null" + ], + "items": { + "type": "string" + }, + "nullable": true + }, + "paths": { + "default": null, + "type": [ + "array", + "null" + ], + "items": { + "type": "string" + }, + "nullable": true + } + } + }, + "DoctorFixSpec": { + "type": "object", + "properties": { + "commands": { + "default": [], + "type": "array", + "items": { + "type": "string" + } + }, + "helpText": { + "default": null, + "type": [ + "string", + "null" + ], + "nullable": true + }, + "helpUrl": { + "default": null, + "type": [ + "string", + "null" + ], + "nullable": true + } + } + }, + "DoctorGroupActionSpec": { + "type": "object", + "required": [ + "check" + ], + "properties": { + "check": { + "$ref": "#/definitions/DoctorCheckSpec" + }, + "description": { + "type": [ + "string", + "null" + ], + "nullable": true + }, + "fix": { + "anyOf": [ + { + "$ref": "#/definitions/DoctorFixSpec" + }, + { + "type": "null" + } + ], + "nullable": true + }, + "name": { + "type": [ + "string", + "null" + ], + "nullable": true + }, + "required": { + "default": true, + "type": "boolean" + } + } + }, + "DoctorGroupKind": { + "type": "string", + "enum": [ + "ScopeDoctorGroup" + ] + }, + "DoctorGroupSpec": { + "type": "object", + "required": [ + "actions" + ], + "properties": { + "actions": { + "type": "array", + "items": { + "$ref": "#/definitions/DoctorGroupActionSpec" + } + }, + "description": { + "type": [ + "string", + "null" + ], + "nullable": true + }, + "needs": { + "default": [], + "type": "array", + "items": { + "type": "string" + } + } + } + }, + "KnownErrorKind": { + "type": "string", + "enum": [ + "ScopeKnownError" + ] + }, + "KnownErrorSpec": { + "type": "object", + "required": [ + "description", + "help", + "pattern" + ], + "properties": { + "description": { + "type": "string" + }, + "help": { + "type": "string" + }, + "pattern": { + "type": "string" + } + } + }, + "ModelMetadata": { + "type": "object", + "required": [ + "name" + ], + "properties": { + "annotations": { + "default": { + "scope.github.com/bin-path": null, + "scope.github.com/file-dir": null, + "scope.github.com/file-path": null + }, + "$ref": "#/definitions/ModelMetadataAnnotations" + }, + "labels": { + "default": {}, + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "name": { + "type": "string" + } + } + }, + "ModelMetadataAnnotations": { + "type": "object", + "properties": { + "scope.github.com/bin-path": { + "type": [ + "string", + "null" + ], + "nullable": true + }, + "scope.github.com/file-dir": { + "type": [ + "string", + "null" + ], + "nullable": true + }, + "scope.github.com/file-path": { + "type": [ + "string", + "null" + ], + "nullable": true + } + } + }, + "ReportDefinitionKind": { + "type": "string", + "enum": [ + "ScopeReportDefinition" + ] + }, + "ReportDefinitionSpec": { + "type": "object", + "required": [ + "template" + ], + "properties": { + "additionalData": { + "default": {}, + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "template": { + "type": "string" + } + } + }, + "ReportDestinationGithubIssueSpec": { + "type": "object", + "required": [ + "owner", + "repo" + ], + "properties": { + "owner": { + "type": "string" + }, + "repo": { + "type": "string" + }, + "tags": { + "default": [], + "type": "array", + "items": { + "type": "string" + } + } + } + }, + "ReportDestinationSpec": { + "oneOf": [ + { + "type": "object", + "required": [ + "rustyPaste" + ], + "properties": { + "rustyPaste": { + "type": "object", + "required": [ + "url" + ], + "properties": { + "url": { + "type": "string" + } + } + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "githubIssue" + ], + "properties": { + "githubIssue": { + "$ref": "#/definitions/ReportDestinationGithubIssueSpec" + } + }, + "additionalProperties": false + } + ] + }, + "ReportLocationKind": { + "type": "string", + "enum": [ + "ScopeReportLocation" + ] + }, + "ReportLocationSpec": { + "type": "object", + "required": [ + "destination" + ], + "properties": { + "destination": { + "$ref": "#/definitions/ReportDestinationSpec" + } + } + }, + "V1AlphaApiVersion": { + "type": "string", + "enum": [ + "scope.github.com/v1alpha" + ] + }, + "V1AlphaDoctorGroup": { + "type": "object", + "required": [ + "apiVersion", + "kind", + "metadata", + "spec" + ], + "properties": { + "apiVersion": { + "$ref": "#/definitions/V1AlphaApiVersion" + }, + "kind": { + "$ref": "#/definitions/DoctorGroupKind" + }, + "metadata": { + "$ref": "#/definitions/ModelMetadata" + }, + "spec": { + "$ref": "#/definitions/DoctorGroupSpec" + } + } + }, + "V1AlphaKnownError": { + "type": "object", + "required": [ + "apiVersion", + "kind", + "metadata", + "spec" + ], + "properties": { + "apiVersion": { + "$ref": "#/definitions/V1AlphaApiVersion" + }, + "kind": { + "$ref": "#/definitions/KnownErrorKind" + }, + "metadata": { + "$ref": "#/definitions/ModelMetadata" + }, + "spec": { + "$ref": "#/definitions/KnownErrorSpec" + } + } + }, + "V1AlphaReportDefinition": { + "type": "object", + "required": [ + "apiVersion", + "kind", + "metadata", + "spec" + ], + "properties": { + "apiVersion": { + "$ref": "#/definitions/V1AlphaApiVersion" + }, + "kind": { + "$ref": "#/definitions/ReportDefinitionKind" + }, + "metadata": { + "$ref": "#/definitions/ModelMetadata" + }, + "spec": { + "$ref": "#/definitions/ReportDefinitionSpec" + } + } + }, + "V1AlphaReportLocation": { + "type": "object", + "required": [ + "apiVersion", + "kind", + "metadata", + "spec" + ], + "properties": { + "apiVersion": { + "$ref": "#/definitions/V1AlphaApiVersion" + }, + "kind": { + "$ref": "#/definitions/ReportLocationKind" + }, + "metadata": { + "$ref": "#/definitions/ModelMetadata" + }, + "spec": { + "$ref": "#/definitions/ReportLocationSpec" + } + } + } + } +} \ No newline at end of file diff --git a/scope-models/schema/v1alpha.com.github.scope.ScopeDoctorGroup.json b/scope-models/schema/v1alpha.com.github.scope.ScopeDoctorGroup.json new file mode 100644 index 0000000..2b39a38 --- /dev/null +++ b/scope-models/schema/v1alpha.com.github.scope.ScopeDoctorGroup.json @@ -0,0 +1,430 @@ +{ + "$schema": "https://json-schema.org/draft/2019-09/schema", + "title": "V1AlphaDoctorGroup", + "type": "object", + "required": [ + "apiVersion", + "kind", + "metadata", + "spec" + ], + "properties": { + "apiVersion": { + "$ref": "#/definitions/V1AlphaApiVersion" + }, + "kind": { + "$ref": "#/definitions/DoctorGroupKind" + }, + "metadata": { + "$ref": "#/definitions/ModelMetadata" + }, + "spec": { + "$ref": "#/definitions/DoctorGroupSpec" + } + }, + "definitions": { + "DoctorCheckSpec": { + "type": "object", + "properties": { + "commands": { + "default": null, + "type": [ + "array", + "null" + ], + "items": { + "type": "string" + }, + "nullable": true + }, + "paths": { + "default": null, + "type": [ + "array", + "null" + ], + "items": { + "type": "string" + }, + "nullable": true + } + } + }, + "DoctorFixSpec": { + "type": "object", + "properties": { + "commands": { + "default": [], + "type": "array", + "items": { + "type": "string" + } + }, + "helpText": { + "default": null, + "type": [ + "string", + "null" + ], + "nullable": true + }, + "helpUrl": { + "default": null, + "type": [ + "string", + "null" + ], + "nullable": true + } + } + }, + "DoctorGroupActionSpec": { + "type": "object", + "required": [ + "check" + ], + "properties": { + "check": { + "$ref": "#/definitions/DoctorCheckSpec" + }, + "description": { + "type": [ + "string", + "null" + ], + "nullable": true + }, + "fix": { + "anyOf": [ + { + "$ref": "#/definitions/DoctorFixSpec" + }, + { + "type": "null" + } + ], + "nullable": true + }, + "name": { + "type": [ + "string", + "null" + ], + "nullable": true + }, + "required": { + "default": true, + "type": "boolean" + } + } + }, + "DoctorGroupKind": { + "type": "string", + "enum": [ + "ScopeDoctorGroup" + ] + }, + "DoctorGroupSpec": { + "type": "object", + "required": [ + "actions" + ], + "properties": { + "actions": { + "type": "array", + "items": { + "$ref": "#/definitions/DoctorGroupActionSpec" + } + }, + "description": { + "type": [ + "string", + "null" + ], + "nullable": true + }, + "needs": { + "default": [], + "type": "array", + "items": { + "type": "string" + } + } + } + }, + "KnownErrorKind": { + "type": "string", + "enum": [ + "ScopeKnownError" + ] + }, + "KnownErrorSpec": { + "type": "object", + "required": [ + "description", + "help", + "pattern" + ], + "properties": { + "description": { + "type": "string" + }, + "help": { + "type": "string" + }, + "pattern": { + "type": "string" + } + } + }, + "ModelMetadata": { + "type": "object", + "required": [ + "name" + ], + "properties": { + "annotations": { + "default": { + "scope.github.com/bin-path": null, + "scope.github.com/file-dir": null, + "scope.github.com/file-path": null + }, + "$ref": "#/definitions/ModelMetadataAnnotations" + }, + "labels": { + "default": {}, + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "name": { + "type": "string" + } + } + }, + "ModelMetadataAnnotations": { + "type": "object", + "properties": { + "scope.github.com/bin-path": { + "type": [ + "string", + "null" + ], + "nullable": true + }, + "scope.github.com/file-dir": { + "type": [ + "string", + "null" + ], + "nullable": true + }, + "scope.github.com/file-path": { + "type": [ + "string", + "null" + ], + "nullable": true + } + } + }, + "ReportDefinitionKind": { + "type": "string", + "enum": [ + "ScopeReportDefinition" + ] + }, + "ReportDefinitionSpec": { + "type": "object", + "required": [ + "template" + ], + "properties": { + "additionalData": { + "default": {}, + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "template": { + "type": "string" + } + } + }, + "ReportDestinationGithubIssueSpec": { + "type": "object", + "required": [ + "owner", + "repo" + ], + "properties": { + "owner": { + "type": "string" + }, + "repo": { + "type": "string" + }, + "tags": { + "default": [], + "type": "array", + "items": { + "type": "string" + } + } + } + }, + "ReportDestinationSpec": { + "oneOf": [ + { + "type": "object", + "required": [ + "rustyPaste" + ], + "properties": { + "rustyPaste": { + "type": "object", + "required": [ + "url" + ], + "properties": { + "url": { + "type": "string" + } + } + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "githubIssue" + ], + "properties": { + "githubIssue": { + "$ref": "#/definitions/ReportDestinationGithubIssueSpec" + } + }, + "additionalProperties": false + } + ] + }, + "ReportLocationKind": { + "type": "string", + "enum": [ + "ScopeReportLocation" + ] + }, + "ReportLocationSpec": { + "type": "object", + "required": [ + "destination" + ], + "properties": { + "destination": { + "$ref": "#/definitions/ReportDestinationSpec" + } + } + }, + "V1AlphaApiVersion": { + "type": "string", + "enum": [ + "scope.github.com/v1alpha" + ] + }, + "V1AlphaDoctorGroup": { + "type": "object", + "required": [ + "apiVersion", + "kind", + "metadata", + "spec" + ], + "properties": { + "apiVersion": { + "$ref": "#/definitions/V1AlphaApiVersion" + }, + "kind": { + "$ref": "#/definitions/DoctorGroupKind" + }, + "metadata": { + "$ref": "#/definitions/ModelMetadata" + }, + "spec": { + "$ref": "#/definitions/DoctorGroupSpec" + } + } + }, + "V1AlphaKnownError": { + "type": "object", + "required": [ + "apiVersion", + "kind", + "metadata", + "spec" + ], + "properties": { + "apiVersion": { + "$ref": "#/definitions/V1AlphaApiVersion" + }, + "kind": { + "$ref": "#/definitions/KnownErrorKind" + }, + "metadata": { + "$ref": "#/definitions/ModelMetadata" + }, + "spec": { + "$ref": "#/definitions/KnownErrorSpec" + } + } + }, + "V1AlphaReportDefinition": { + "type": "object", + "required": [ + "apiVersion", + "kind", + "metadata", + "spec" + ], + "properties": { + "apiVersion": { + "$ref": "#/definitions/V1AlphaApiVersion" + }, + "kind": { + "$ref": "#/definitions/ReportDefinitionKind" + }, + "metadata": { + "$ref": "#/definitions/ModelMetadata" + }, + "spec": { + "$ref": "#/definitions/ReportDefinitionSpec" + } + } + }, + "V1AlphaReportLocation": { + "type": "object", + "required": [ + "apiVersion", + "kind", + "metadata", + "spec" + ], + "properties": { + "apiVersion": { + "$ref": "#/definitions/V1AlphaApiVersion" + }, + "kind": { + "$ref": "#/definitions/ReportLocationKind" + }, + "metadata": { + "$ref": "#/definitions/ModelMetadata" + }, + "spec": { + "$ref": "#/definitions/ReportLocationSpec" + } + } + } + } +} \ No newline at end of file diff --git a/scope-models/schema/v1alpha.com.github.scope.ScopeKnownError.json b/scope-models/schema/v1alpha.com.github.scope.ScopeKnownError.json new file mode 100644 index 0000000..ebbffb4 --- /dev/null +++ b/scope-models/schema/v1alpha.com.github.scope.ScopeKnownError.json @@ -0,0 +1,430 @@ +{ + "$schema": "https://json-schema.org/draft/2019-09/schema", + "title": "V1AlphaKnownError", + "type": "object", + "required": [ + "apiVersion", + "kind", + "metadata", + "spec" + ], + "properties": { + "apiVersion": { + "$ref": "#/definitions/V1AlphaApiVersion" + }, + "kind": { + "$ref": "#/definitions/KnownErrorKind" + }, + "metadata": { + "$ref": "#/definitions/ModelMetadata" + }, + "spec": { + "$ref": "#/definitions/KnownErrorSpec" + } + }, + "definitions": { + "DoctorCheckSpec": { + "type": "object", + "properties": { + "commands": { + "default": null, + "type": [ + "array", + "null" + ], + "items": { + "type": "string" + }, + "nullable": true + }, + "paths": { + "default": null, + "type": [ + "array", + "null" + ], + "items": { + "type": "string" + }, + "nullable": true + } + } + }, + "DoctorFixSpec": { + "type": "object", + "properties": { + "commands": { + "default": [], + "type": "array", + "items": { + "type": "string" + } + }, + "helpText": { + "default": null, + "type": [ + "string", + "null" + ], + "nullable": true + }, + "helpUrl": { + "default": null, + "type": [ + "string", + "null" + ], + "nullable": true + } + } + }, + "DoctorGroupActionSpec": { + "type": "object", + "required": [ + "check" + ], + "properties": { + "check": { + "$ref": "#/definitions/DoctorCheckSpec" + }, + "description": { + "type": [ + "string", + "null" + ], + "nullable": true + }, + "fix": { + "anyOf": [ + { + "$ref": "#/definitions/DoctorFixSpec" + }, + { + "type": "null" + } + ], + "nullable": true + }, + "name": { + "type": [ + "string", + "null" + ], + "nullable": true + }, + "required": { + "default": true, + "type": "boolean" + } + } + }, + "DoctorGroupKind": { + "type": "string", + "enum": [ + "ScopeDoctorGroup" + ] + }, + "DoctorGroupSpec": { + "type": "object", + "required": [ + "actions" + ], + "properties": { + "actions": { + "type": "array", + "items": { + "$ref": "#/definitions/DoctorGroupActionSpec" + } + }, + "description": { + "type": [ + "string", + "null" + ], + "nullable": true + }, + "needs": { + "default": [], + "type": "array", + "items": { + "type": "string" + } + } + } + }, + "KnownErrorKind": { + "type": "string", + "enum": [ + "ScopeKnownError" + ] + }, + "KnownErrorSpec": { + "type": "object", + "required": [ + "description", + "help", + "pattern" + ], + "properties": { + "description": { + "type": "string" + }, + "help": { + "type": "string" + }, + "pattern": { + "type": "string" + } + } + }, + "ModelMetadata": { + "type": "object", + "required": [ + "name" + ], + "properties": { + "annotations": { + "default": { + "scope.github.com/bin-path": null, + "scope.github.com/file-dir": null, + "scope.github.com/file-path": null + }, + "$ref": "#/definitions/ModelMetadataAnnotations" + }, + "labels": { + "default": {}, + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "name": { + "type": "string" + } + } + }, + "ModelMetadataAnnotations": { + "type": "object", + "properties": { + "scope.github.com/bin-path": { + "type": [ + "string", + "null" + ], + "nullable": true + }, + "scope.github.com/file-dir": { + "type": [ + "string", + "null" + ], + "nullable": true + }, + "scope.github.com/file-path": { + "type": [ + "string", + "null" + ], + "nullable": true + } + } + }, + "ReportDefinitionKind": { + "type": "string", + "enum": [ + "ScopeReportDefinition" + ] + }, + "ReportDefinitionSpec": { + "type": "object", + "required": [ + "template" + ], + "properties": { + "additionalData": { + "default": {}, + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "template": { + "type": "string" + } + } + }, + "ReportDestinationGithubIssueSpec": { + "type": "object", + "required": [ + "owner", + "repo" + ], + "properties": { + "owner": { + "type": "string" + }, + "repo": { + "type": "string" + }, + "tags": { + "default": [], + "type": "array", + "items": { + "type": "string" + } + } + } + }, + "ReportDestinationSpec": { + "oneOf": [ + { + "type": "object", + "required": [ + "rustyPaste" + ], + "properties": { + "rustyPaste": { + "type": "object", + "required": [ + "url" + ], + "properties": { + "url": { + "type": "string" + } + } + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "githubIssue" + ], + "properties": { + "githubIssue": { + "$ref": "#/definitions/ReportDestinationGithubIssueSpec" + } + }, + "additionalProperties": false + } + ] + }, + "ReportLocationKind": { + "type": "string", + "enum": [ + "ScopeReportLocation" + ] + }, + "ReportLocationSpec": { + "type": "object", + "required": [ + "destination" + ], + "properties": { + "destination": { + "$ref": "#/definitions/ReportDestinationSpec" + } + } + }, + "V1AlphaApiVersion": { + "type": "string", + "enum": [ + "scope.github.com/v1alpha" + ] + }, + "V1AlphaDoctorGroup": { + "type": "object", + "required": [ + "apiVersion", + "kind", + "metadata", + "spec" + ], + "properties": { + "apiVersion": { + "$ref": "#/definitions/V1AlphaApiVersion" + }, + "kind": { + "$ref": "#/definitions/DoctorGroupKind" + }, + "metadata": { + "$ref": "#/definitions/ModelMetadata" + }, + "spec": { + "$ref": "#/definitions/DoctorGroupSpec" + } + } + }, + "V1AlphaKnownError": { + "type": "object", + "required": [ + "apiVersion", + "kind", + "metadata", + "spec" + ], + "properties": { + "apiVersion": { + "$ref": "#/definitions/V1AlphaApiVersion" + }, + "kind": { + "$ref": "#/definitions/KnownErrorKind" + }, + "metadata": { + "$ref": "#/definitions/ModelMetadata" + }, + "spec": { + "$ref": "#/definitions/KnownErrorSpec" + } + } + }, + "V1AlphaReportDefinition": { + "type": "object", + "required": [ + "apiVersion", + "kind", + "metadata", + "spec" + ], + "properties": { + "apiVersion": { + "$ref": "#/definitions/V1AlphaApiVersion" + }, + "kind": { + "$ref": "#/definitions/ReportDefinitionKind" + }, + "metadata": { + "$ref": "#/definitions/ModelMetadata" + }, + "spec": { + "$ref": "#/definitions/ReportDefinitionSpec" + } + } + }, + "V1AlphaReportLocation": { + "type": "object", + "required": [ + "apiVersion", + "kind", + "metadata", + "spec" + ], + "properties": { + "apiVersion": { + "$ref": "#/definitions/V1AlphaApiVersion" + }, + "kind": { + "$ref": "#/definitions/ReportLocationKind" + }, + "metadata": { + "$ref": "#/definitions/ModelMetadata" + }, + "spec": { + "$ref": "#/definitions/ReportLocationSpec" + } + } + } + } +} \ No newline at end of file diff --git a/scope-models/schema/v1alpha.com.github.scope.ScopeReportDefinition.json b/scope-models/schema/v1alpha.com.github.scope.ScopeReportDefinition.json new file mode 100644 index 0000000..07497eb --- /dev/null +++ b/scope-models/schema/v1alpha.com.github.scope.ScopeReportDefinition.json @@ -0,0 +1,430 @@ +{ + "$schema": "https://json-schema.org/draft/2019-09/schema", + "title": "V1AlphaReportDefinition", + "type": "object", + "required": [ + "apiVersion", + "kind", + "metadata", + "spec" + ], + "properties": { + "apiVersion": { + "$ref": "#/definitions/V1AlphaApiVersion" + }, + "kind": { + "$ref": "#/definitions/ReportDefinitionKind" + }, + "metadata": { + "$ref": "#/definitions/ModelMetadata" + }, + "spec": { + "$ref": "#/definitions/ReportDefinitionSpec" + } + }, + "definitions": { + "DoctorCheckSpec": { + "type": "object", + "properties": { + "commands": { + "default": null, + "type": [ + "array", + "null" + ], + "items": { + "type": "string" + }, + "nullable": true + }, + "paths": { + "default": null, + "type": [ + "array", + "null" + ], + "items": { + "type": "string" + }, + "nullable": true + } + } + }, + "DoctorFixSpec": { + "type": "object", + "properties": { + "commands": { + "default": [], + "type": "array", + "items": { + "type": "string" + } + }, + "helpText": { + "default": null, + "type": [ + "string", + "null" + ], + "nullable": true + }, + "helpUrl": { + "default": null, + "type": [ + "string", + "null" + ], + "nullable": true + } + } + }, + "DoctorGroupActionSpec": { + "type": "object", + "required": [ + "check" + ], + "properties": { + "check": { + "$ref": "#/definitions/DoctorCheckSpec" + }, + "description": { + "type": [ + "string", + "null" + ], + "nullable": true + }, + "fix": { + "anyOf": [ + { + "$ref": "#/definitions/DoctorFixSpec" + }, + { + "type": "null" + } + ], + "nullable": true + }, + "name": { + "type": [ + "string", + "null" + ], + "nullable": true + }, + "required": { + "default": true, + "type": "boolean" + } + } + }, + "DoctorGroupKind": { + "type": "string", + "enum": [ + "ScopeDoctorGroup" + ] + }, + "DoctorGroupSpec": { + "type": "object", + "required": [ + "actions" + ], + "properties": { + "actions": { + "type": "array", + "items": { + "$ref": "#/definitions/DoctorGroupActionSpec" + } + }, + "description": { + "type": [ + "string", + "null" + ], + "nullable": true + }, + "needs": { + "default": [], + "type": "array", + "items": { + "type": "string" + } + } + } + }, + "KnownErrorKind": { + "type": "string", + "enum": [ + "ScopeKnownError" + ] + }, + "KnownErrorSpec": { + "type": "object", + "required": [ + "description", + "help", + "pattern" + ], + "properties": { + "description": { + "type": "string" + }, + "help": { + "type": "string" + }, + "pattern": { + "type": "string" + } + } + }, + "ModelMetadata": { + "type": "object", + "required": [ + "name" + ], + "properties": { + "annotations": { + "default": { + "scope.github.com/bin-path": null, + "scope.github.com/file-dir": null, + "scope.github.com/file-path": null + }, + "$ref": "#/definitions/ModelMetadataAnnotations" + }, + "labels": { + "default": {}, + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "name": { + "type": "string" + } + } + }, + "ModelMetadataAnnotations": { + "type": "object", + "properties": { + "scope.github.com/bin-path": { + "type": [ + "string", + "null" + ], + "nullable": true + }, + "scope.github.com/file-dir": { + "type": [ + "string", + "null" + ], + "nullable": true + }, + "scope.github.com/file-path": { + "type": [ + "string", + "null" + ], + "nullable": true + } + } + }, + "ReportDefinitionKind": { + "type": "string", + "enum": [ + "ScopeReportDefinition" + ] + }, + "ReportDefinitionSpec": { + "type": "object", + "required": [ + "template" + ], + "properties": { + "additionalData": { + "default": {}, + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "template": { + "type": "string" + } + } + }, + "ReportDestinationGithubIssueSpec": { + "type": "object", + "required": [ + "owner", + "repo" + ], + "properties": { + "owner": { + "type": "string" + }, + "repo": { + "type": "string" + }, + "tags": { + "default": [], + "type": "array", + "items": { + "type": "string" + } + } + } + }, + "ReportDestinationSpec": { + "oneOf": [ + { + "type": "object", + "required": [ + "rustyPaste" + ], + "properties": { + "rustyPaste": { + "type": "object", + "required": [ + "url" + ], + "properties": { + "url": { + "type": "string" + } + } + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "githubIssue" + ], + "properties": { + "githubIssue": { + "$ref": "#/definitions/ReportDestinationGithubIssueSpec" + } + }, + "additionalProperties": false + } + ] + }, + "ReportLocationKind": { + "type": "string", + "enum": [ + "ScopeReportLocation" + ] + }, + "ReportLocationSpec": { + "type": "object", + "required": [ + "destination" + ], + "properties": { + "destination": { + "$ref": "#/definitions/ReportDestinationSpec" + } + } + }, + "V1AlphaApiVersion": { + "type": "string", + "enum": [ + "scope.github.com/v1alpha" + ] + }, + "V1AlphaDoctorGroup": { + "type": "object", + "required": [ + "apiVersion", + "kind", + "metadata", + "spec" + ], + "properties": { + "apiVersion": { + "$ref": "#/definitions/V1AlphaApiVersion" + }, + "kind": { + "$ref": "#/definitions/DoctorGroupKind" + }, + "metadata": { + "$ref": "#/definitions/ModelMetadata" + }, + "spec": { + "$ref": "#/definitions/DoctorGroupSpec" + } + } + }, + "V1AlphaKnownError": { + "type": "object", + "required": [ + "apiVersion", + "kind", + "metadata", + "spec" + ], + "properties": { + "apiVersion": { + "$ref": "#/definitions/V1AlphaApiVersion" + }, + "kind": { + "$ref": "#/definitions/KnownErrorKind" + }, + "metadata": { + "$ref": "#/definitions/ModelMetadata" + }, + "spec": { + "$ref": "#/definitions/KnownErrorSpec" + } + } + }, + "V1AlphaReportDefinition": { + "type": "object", + "required": [ + "apiVersion", + "kind", + "metadata", + "spec" + ], + "properties": { + "apiVersion": { + "$ref": "#/definitions/V1AlphaApiVersion" + }, + "kind": { + "$ref": "#/definitions/ReportDefinitionKind" + }, + "metadata": { + "$ref": "#/definitions/ModelMetadata" + }, + "spec": { + "$ref": "#/definitions/ReportDefinitionSpec" + } + } + }, + "V1AlphaReportLocation": { + "type": "object", + "required": [ + "apiVersion", + "kind", + "metadata", + "spec" + ], + "properties": { + "apiVersion": { + "$ref": "#/definitions/V1AlphaApiVersion" + }, + "kind": { + "$ref": "#/definitions/ReportLocationKind" + }, + "metadata": { + "$ref": "#/definitions/ModelMetadata" + }, + "spec": { + "$ref": "#/definitions/ReportLocationSpec" + } + } + } + } +} \ No newline at end of file diff --git a/scope-models/schema/v1alpha.com.github.scope.ScopeReportLocation.json b/scope-models/schema/v1alpha.com.github.scope.ScopeReportLocation.json new file mode 100644 index 0000000..4afdf1b --- /dev/null +++ b/scope-models/schema/v1alpha.com.github.scope.ScopeReportLocation.json @@ -0,0 +1,430 @@ +{ + "$schema": "https://json-schema.org/draft/2019-09/schema", + "title": "V1AlphaReportLocation", + "type": "object", + "required": [ + "apiVersion", + "kind", + "metadata", + "spec" + ], + "properties": { + "apiVersion": { + "$ref": "#/definitions/V1AlphaApiVersion" + }, + "kind": { + "$ref": "#/definitions/ReportLocationKind" + }, + "metadata": { + "$ref": "#/definitions/ModelMetadata" + }, + "spec": { + "$ref": "#/definitions/ReportLocationSpec" + } + }, + "definitions": { + "DoctorCheckSpec": { + "type": "object", + "properties": { + "commands": { + "default": null, + "type": [ + "array", + "null" + ], + "items": { + "type": "string" + }, + "nullable": true + }, + "paths": { + "default": null, + "type": [ + "array", + "null" + ], + "items": { + "type": "string" + }, + "nullable": true + } + } + }, + "DoctorFixSpec": { + "type": "object", + "properties": { + "commands": { + "default": [], + "type": "array", + "items": { + "type": "string" + } + }, + "helpText": { + "default": null, + "type": [ + "string", + "null" + ], + "nullable": true + }, + "helpUrl": { + "default": null, + "type": [ + "string", + "null" + ], + "nullable": true + } + } + }, + "DoctorGroupActionSpec": { + "type": "object", + "required": [ + "check" + ], + "properties": { + "check": { + "$ref": "#/definitions/DoctorCheckSpec" + }, + "description": { + "type": [ + "string", + "null" + ], + "nullable": true + }, + "fix": { + "anyOf": [ + { + "$ref": "#/definitions/DoctorFixSpec" + }, + { + "type": "null" + } + ], + "nullable": true + }, + "name": { + "type": [ + "string", + "null" + ], + "nullable": true + }, + "required": { + "default": true, + "type": "boolean" + } + } + }, + "DoctorGroupKind": { + "type": "string", + "enum": [ + "ScopeDoctorGroup" + ] + }, + "DoctorGroupSpec": { + "type": "object", + "required": [ + "actions" + ], + "properties": { + "actions": { + "type": "array", + "items": { + "$ref": "#/definitions/DoctorGroupActionSpec" + } + }, + "description": { + "type": [ + "string", + "null" + ], + "nullable": true + }, + "needs": { + "default": [], + "type": "array", + "items": { + "type": "string" + } + } + } + }, + "KnownErrorKind": { + "type": "string", + "enum": [ + "ScopeKnownError" + ] + }, + "KnownErrorSpec": { + "type": "object", + "required": [ + "description", + "help", + "pattern" + ], + "properties": { + "description": { + "type": "string" + }, + "help": { + "type": "string" + }, + "pattern": { + "type": "string" + } + } + }, + "ModelMetadata": { + "type": "object", + "required": [ + "name" + ], + "properties": { + "annotations": { + "default": { + "scope.github.com/bin-path": null, + "scope.github.com/file-dir": null, + "scope.github.com/file-path": null + }, + "$ref": "#/definitions/ModelMetadataAnnotations" + }, + "labels": { + "default": {}, + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "name": { + "type": "string" + } + } + }, + "ModelMetadataAnnotations": { + "type": "object", + "properties": { + "scope.github.com/bin-path": { + "type": [ + "string", + "null" + ], + "nullable": true + }, + "scope.github.com/file-dir": { + "type": [ + "string", + "null" + ], + "nullable": true + }, + "scope.github.com/file-path": { + "type": [ + "string", + "null" + ], + "nullable": true + } + } + }, + "ReportDefinitionKind": { + "type": "string", + "enum": [ + "ScopeReportDefinition" + ] + }, + "ReportDefinitionSpec": { + "type": "object", + "required": [ + "template" + ], + "properties": { + "additionalData": { + "default": {}, + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "template": { + "type": "string" + } + } + }, + "ReportDestinationGithubIssueSpec": { + "type": "object", + "required": [ + "owner", + "repo" + ], + "properties": { + "owner": { + "type": "string" + }, + "repo": { + "type": "string" + }, + "tags": { + "default": [], + "type": "array", + "items": { + "type": "string" + } + } + } + }, + "ReportDestinationSpec": { + "oneOf": [ + { + "type": "object", + "required": [ + "rustyPaste" + ], + "properties": { + "rustyPaste": { + "type": "object", + "required": [ + "url" + ], + "properties": { + "url": { + "type": "string" + } + } + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "githubIssue" + ], + "properties": { + "githubIssue": { + "$ref": "#/definitions/ReportDestinationGithubIssueSpec" + } + }, + "additionalProperties": false + } + ] + }, + "ReportLocationKind": { + "type": "string", + "enum": [ + "ScopeReportLocation" + ] + }, + "ReportLocationSpec": { + "type": "object", + "required": [ + "destination" + ], + "properties": { + "destination": { + "$ref": "#/definitions/ReportDestinationSpec" + } + } + }, + "V1AlphaApiVersion": { + "type": "string", + "enum": [ + "scope.github.com/v1alpha" + ] + }, + "V1AlphaDoctorGroup": { + "type": "object", + "required": [ + "apiVersion", + "kind", + "metadata", + "spec" + ], + "properties": { + "apiVersion": { + "$ref": "#/definitions/V1AlphaApiVersion" + }, + "kind": { + "$ref": "#/definitions/DoctorGroupKind" + }, + "metadata": { + "$ref": "#/definitions/ModelMetadata" + }, + "spec": { + "$ref": "#/definitions/DoctorGroupSpec" + } + } + }, + "V1AlphaKnownError": { + "type": "object", + "required": [ + "apiVersion", + "kind", + "metadata", + "spec" + ], + "properties": { + "apiVersion": { + "$ref": "#/definitions/V1AlphaApiVersion" + }, + "kind": { + "$ref": "#/definitions/KnownErrorKind" + }, + "metadata": { + "$ref": "#/definitions/ModelMetadata" + }, + "spec": { + "$ref": "#/definitions/KnownErrorSpec" + } + } + }, + "V1AlphaReportDefinition": { + "type": "object", + "required": [ + "apiVersion", + "kind", + "metadata", + "spec" + ], + "properties": { + "apiVersion": { + "$ref": "#/definitions/V1AlphaApiVersion" + }, + "kind": { + "$ref": "#/definitions/ReportDefinitionKind" + }, + "metadata": { + "$ref": "#/definitions/ModelMetadata" + }, + "spec": { + "$ref": "#/definitions/ReportDefinitionSpec" + } + } + }, + "V1AlphaReportLocation": { + "type": "object", + "required": [ + "apiVersion", + "kind", + "metadata", + "spec" + ], + "properties": { + "apiVersion": { + "$ref": "#/definitions/V1AlphaApiVersion" + }, + "kind": { + "$ref": "#/definitions/ReportLocationKind" + }, + "metadata": { + "$ref": "#/definitions/ModelMetadata" + }, + "spec": { + "$ref": "#/definitions/ReportLocationSpec" + } + } + } + } +} \ No newline at end of file diff --git a/scope-models/src/core.rs b/scope-models/src/core.rs new file mode 100644 index 0000000..1a7f7f8 --- /dev/null +++ b/scope-models/src/core.rs @@ -0,0 +1,95 @@ +use crate::prelude::DoctorGroupSpec; +use derive_builder::Builder; +use schemars::JsonSchema; +use serde::{Deserialize, Serialize}; +use std::collections::BTreeMap; + +pub const FILE_PATH_ANNOTATION: &str = "scope.github.com/file-path"; +pub const FILE_DIR_ANNOTATION: &str = "scope.github.com/file-dir"; +pub const FILE_EXEC_PATH_ANNOTATION: &str = "scope.github.com/bin-path"; + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Default, Builder, JsonSchema)] +pub struct ModelMetadataAnnotations { + #[serde(rename = "scope.github.com/file-path")] + pub file_path: Option, + #[serde(rename = "scope.github.com/file-dir")] + pub file_dir: Option, + #[serde(rename = "scope.github.com/bin-path")] + pub bin_path: Option, + #[serde(flatten)] + pub extra: BTreeMap, +} + +impl ModelMetadata { + pub fn name(&self) -> String { + self.name.to_string() + } + + pub fn file_path(&self) -> String { + match &self.annotations.file_path { + Some(v) => v.to_string(), + None => "unknown".to_string() + } + } + + pub fn containing_dir(&self) -> String { + match &self.annotations.file_dir { + Some(v) => v.to_string(), + None => "unknown".to_string() + } + } + + pub fn exec_path(&self) -> String { + match &self.annotations.bin_path { + Some(v) => { + format!("{}:{}", v.to_string(), std::env::var("PATH").unwrap_or_else(|_| "".to_string())) + }, + None => std::env::var("PATH").unwrap_or_else(|_| "".to_string()) + } + } + + pub fn new(name: &str) -> ModelMetadata { + Self { + name: name.to_string(), + ..Default::default() + } + } +} + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Default, Builder, JsonSchema)] +#[builder(setter(into))] +pub struct ModelMetadata { + pub name: String, + #[serde(default)] + pub annotations: ModelMetadataAnnotations, + #[serde(default)] + pub labels: BTreeMap, +} + +#[derive(Serialize, Deserialize, Debug, PartialEq, Clone, Builder)] +#[builder(setter(into))] +#[serde(rename_all = "camelCase")] +pub struct ModelRoot { + pub api_version: String, + pub kind: String, + pub metadata: ModelMetadata, + pub spec: V, +} + +impl crate::ScopeModel for ModelRoot { + fn api_version(&self) -> String { + self.api_version.to_string() + } + + fn kind(&self) -> String { + self.kind.to_string() + } + + fn metadata(&self) -> &ModelMetadata { + &self.metadata + } + + fn spec(&self) -> &S { + &self.spec + } +} diff --git a/scope-models/src/lib.rs b/scope-models/src/lib.rs new file mode 100644 index 0000000..6af3a81 --- /dev/null +++ b/scope-models/src/lib.rs @@ -0,0 +1,152 @@ +use crate::core::ModelMetadata; +use schemars::gen::{SchemaGenerator, SchemaSettings}; +use schemars::JsonSchema; +use serde::{Deserialize, Serialize}; + +mod core; +mod v1alpha; + +pub mod prelude { + pub use crate::core::*; + pub use crate::v1alpha::prelude::*; + pub use crate::ScopeModel; +} + +pub trait ScopeModel { + fn api_version(&self) -> String; + fn kind(&self) -> String; + fn metadata(&self) -> &ModelMetadata; + fn spec(&self) -> &S; + fn name(&self) -> &str { + &self.metadata().name + } + fn file_path(&self) -> String { + self.metadata().file_path() + } + fn containing_dir(&self) -> String { + self.metadata().containing_dir() + } + + fn exec_path(&self) -> String { + self.metadata().exec_path() + } + fn full_name(&self) -> String { + format!("{}/{}", self.kind(), self.name()) + } +} + +pub trait InternalScopeModel: + JsonSchema + Serialize + for<'a> Deserialize<'a> + ScopeModel +{ + fn int_api_version() -> String; + fn int_kind() -> String; + #[cfg(test)] + fn examples() -> Vec; + + #[cfg(test)] + fn create_and_validate( + schema_gen: &mut SchemaGenerator, + out_dir: &str, + merged_schema: &str, + ) -> anyhow::Result<()> { + let schema = schema_gen.root_schema_for::(); + let schema_json = serde_json::to_string_pretty(&schema)?; + + let path_prefix: String = Self::int_api_version() + .split(&['.', '/']) + .rev() + .collect::>() + .join("."); + + std::fs::write( + format!("{}/{}.{}.json", out_dir, path_prefix, Self::int_kind()), + &schema_json, + )?; + + for example in Self::examples() { + validate_schema::(&schema_json, &example)?; + validate_schema::(&merged_schema, &example)?; + } + Ok(()) + } +} + +#[cfg(test)] +pub fn make_schema_generator() -> SchemaGenerator { + let settings = SchemaSettings::draft2019_09().with(|s| { + s.option_nullable = true; + }); + settings.into_generator() +} + +#[cfg(test)] +fn validate_schema(schema_json: &str, example_path: &str) -> anyhow::Result<()> +where + T: schemars::JsonSchema + for<'a> serde::Deserialize<'a> + Serialize, +{ + let example = std::fs::read_to_string(format!( + "{}/examples/{}", + env!("CARGO_MANIFEST_DIR"), + example_path + )) + .unwrap(); + let parsed: T = serde_yaml::from_str(&example)?; + + let schema = serde_json::from_str(schema_json)?; + + let compiled_schema = jsonschema::JSONSchema::compile(&schema).expect("A valid schema"); + + let parsed_json = serde_json::to_value(&parsed)?; + if let Err(err_iter) = compiled_schema.validate(&parsed_json) { + println!("{}", serde_json::to_string_pretty(&parsed_json).unwrap()); + for e in err_iter { + println!("error: {}", e.to_string()); + } + assert!(false); + }; + + Ok(()) +} + +#[cfg(test)] +mod schema_gen { + use crate::v1alpha::prelude::*; + use crate::InternalScopeModel; + use derive_builder::Builder; + use schemars::JsonSchema; + use serde::{Deserialize, Serialize}; + + #[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema)] + #[serde(untagged)] + enum ScopeTypes { + ReportLocation(V1AlphaReportLocation), + ReportDefinition(V1AlphaReportDefinition), + KnownError(V1AlphaKnownError), + DoctorGroup(V1AlphaDoctorGroup), + } + + #[test] + fn create_and_validate_schemas() { + let out_dir = format!("{}/schema", env!("CARGO_MANIFEST_DIR")); + std::fs::remove_dir_all(&out_dir).unwrap(); + std::fs::create_dir_all(&out_dir).unwrap(); + + let mut schema_gen = crate::make_schema_generator(); + let merged_schema = schema_gen.root_schema_for::(); + let merged_schema_json = serde_json::to_string_pretty(&merged_schema).unwrap(); + std::fs::write(format!("{}/merged.json", out_dir), &merged_schema_json).unwrap(); + + V1AlphaReportLocation::create_and_validate(&mut schema_gen, &out_dir, &merged_schema_json) + .unwrap(); + V1AlphaReportDefinition::create_and_validate( + &mut schema_gen, + &out_dir, + &merged_schema_json, + ) + .unwrap(); + V1AlphaKnownError::create_and_validate(&mut schema_gen, &out_dir, &merged_schema_json) + .unwrap(); + V1AlphaDoctorGroup::create_and_validate(&mut schema_gen, &out_dir, &merged_schema_json) + .unwrap(); + } +} diff --git a/scope-models/src/v1alpha/doctor_group.rs b/scope-models/src/v1alpha/doctor_group.rs new file mode 100644 index 0000000..ba84f12 --- /dev/null +++ b/scope-models/src/v1alpha/doctor_group.rs @@ -0,0 +1,99 @@ +use crate::core::ModelMetadata; +use crate::v1alpha::known_error::{KnownErrorKind, V1AlphaKnownError}; +use crate::v1alpha::V1AlphaApiVersion; +use derive_builder::Builder; +use schemars::JsonSchema; +use serde::{Deserialize, Serialize}; + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema)] +#[serde(rename_all = "camelCase")] +pub struct DoctorCheckSpec { + #[serde(default)] + pub paths: Option>, + #[serde(default)] + pub commands: Option>, +} + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema)] +#[serde(rename_all = "camelCase")] +pub struct DoctorFixSpec { + #[serde(default)] + pub commands: Vec, + #[serde(default)] + pub help_text: Option, + #[serde(default)] + pub help_url: Option, +} + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema)] +#[serde(rename_all = "camelCase")] +pub struct DoctorGroupActionSpec { + pub name: Option, + pub description: Option, + pub check: DoctorCheckSpec, + pub fix: Option, + #[serde(default = "doctor_group_action_required_default")] + pub required: bool, +} + +fn doctor_group_action_required_default() -> bool { + true +} + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema)] +#[serde(rename_all = "camelCase")] +pub struct DoctorGroupSpec { + #[serde(default)] + pub needs: Vec, + pub description: Option, + pub actions: Vec, +} + +#[derive(Serialize, Deserialize, Debug, strum::Display, Clone, PartialEq, JsonSchema)] +pub enum DoctorGroupKind { + #[strum(serialize = "ScopeDoctorGroup")] + ScopeDoctorGroup, +} + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Builder, JsonSchema)] +#[builder(setter(into))] +#[serde(rename_all = "camelCase")] +pub struct V1AlphaDoctorGroup { + pub api_version: V1AlphaApiVersion, + pub kind: DoctorGroupKind, + pub metadata: ModelMetadata, + pub spec: DoctorGroupSpec, +} + +impl crate::ScopeModel for V1AlphaDoctorGroup { + fn api_version(&self) -> String { + >::int_api_version() + } + + fn kind(&self) -> String { + >::int_kind() + } + + fn metadata(&self) -> &ModelMetadata { + &self.metadata + } + + fn spec(&self) -> &DoctorGroupSpec { + &self.spec + } +} + +impl crate::InternalScopeModel for V1AlphaDoctorGroup { + fn int_api_version() -> String { + V1AlphaApiVersion::ScopeV1Alpha.to_string() + } + + fn int_kind() -> String { + DoctorGroupKind::ScopeDoctorGroup.to_string() + } + + #[cfg(test)] + fn examples() -> Vec { + vec!["v1alpha/DoctorGroup.yaml".to_string()] + } +} diff --git a/scope-models/src/v1alpha/known_error.rs b/scope-models/src/v1alpha/known_error.rs new file mode 100644 index 0000000..ec5a990 --- /dev/null +++ b/scope-models/src/v1alpha/known_error.rs @@ -0,0 +1,62 @@ +use crate::core::ModelMetadata; +use crate::v1alpha::V1AlphaApiVersion; +use derive_builder::Builder; +use schemars::JsonSchema; +use serde::{Deserialize, Serialize}; + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema)] +#[serde(rename_all = "camelCase")] +pub struct KnownErrorSpec { + pub description: String, + pub help: String, + pub pattern: String, +} + +#[derive(Serialize, Deserialize, Debug, strum::Display, Clone, PartialEq, JsonSchema)] +pub enum KnownErrorKind { + #[strum(serialize = "ScopeKnownError")] + ScopeKnownError, +} + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Builder, JsonSchema)] +#[builder(setter(into))] +#[serde(rename_all = "camelCase")] +pub struct V1AlphaKnownError { + pub api_version: V1AlphaApiVersion, + pub kind: KnownErrorKind, + pub metadata: ModelMetadata, + pub spec: KnownErrorSpec, +} + +impl crate::ScopeModel for V1AlphaKnownError { + fn api_version(&self) -> String { + >::int_api_version() + } + + fn kind(&self) -> String { + >::int_kind() + } + + fn metadata(&self) -> &ModelMetadata { + &self.metadata + } + + fn spec(&self) -> &KnownErrorSpec { + &self.spec + } +} + +impl crate::InternalScopeModel for V1AlphaKnownError { + fn int_api_version() -> String { + V1AlphaApiVersion::ScopeV1Alpha.to_string() + } + + fn int_kind() -> String { + KnownErrorKind::ScopeKnownError.to_string() + } + + #[cfg(test)] + fn examples() -> Vec { + vec!["v1alpha/KnownError.yaml".to_string()] + } +} diff --git a/scope-models/src/v1alpha/mod.rs b/scope-models/src/v1alpha/mod.rs new file mode 100644 index 0000000..0fbc735 --- /dev/null +++ b/scope-models/src/v1alpha/mod.rs @@ -0,0 +1,24 @@ +use schemars::JsonSchema; +use serde::{Deserialize, Serialize}; +use strum::EnumString; + +mod doctor_group; +mod known_error; +mod report_definition; +mod report_location; + +#[derive( + Serialize, Deserialize, Debug, strum::Display, Clone, PartialEq, EnumString, JsonSchema, +)] +pub enum V1AlphaApiVersion { + #[serde(rename = "scope.github.com/v1alpha")] + #[strum(serialize = "scope.github.com/v1alpha")] + ScopeV1Alpha, +} + +pub mod prelude { + pub use super::doctor_group::*; + pub use super::known_error::*; + pub use super::report_definition::*; + pub use super::report_location::*; +} diff --git a/scope-models/src/v1alpha/report_definition.rs b/scope-models/src/v1alpha/report_definition.rs new file mode 100644 index 0000000..8166713 --- /dev/null +++ b/scope-models/src/v1alpha/report_definition.rs @@ -0,0 +1,64 @@ +use crate::core::ModelMetadata; +use crate::v1alpha::prelude::{ReportLocationKind, V1AlphaReportLocation}; +use crate::v1alpha::V1AlphaApiVersion; +use derive_builder::Builder; +use schemars::gen::SchemaGenerator; +use schemars::JsonSchema; +use serde::{Deserialize, Serialize}; +use std::collections::BTreeMap; + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Builder, JsonSchema)] +#[serde(rename_all = "camelCase")] +pub struct ReportDefinitionSpec { + #[serde(default)] + pub additional_data: BTreeMap, + pub template: String, +} + +#[derive(Serialize, Deserialize, Debug, strum::Display, Clone, PartialEq, JsonSchema)] +pub enum ReportDefinitionKind { + #[strum(serialize = "ScopeReportDefinition")] + ScopeReportDefinition, +} + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Builder, JsonSchema)] +#[builder(setter(into))] +#[serde(rename_all = "camelCase")] +pub struct V1AlphaReportDefinition { + pub api_version: V1AlphaApiVersion, + pub kind: ReportDefinitionKind, + pub metadata: ModelMetadata, + pub spec: ReportDefinitionSpec, +} + +impl crate::ScopeModel for V1AlphaReportDefinition { + fn api_version(&self) -> String { + >::int_api_version() + } + + fn kind(&self) -> String { + >::int_kind() + } + + fn metadata(&self) -> &ModelMetadata { + &self.metadata + } + + fn spec(&self) -> &ReportDefinitionSpec { + &self.spec + } +} + +impl crate::InternalScopeModel for V1AlphaReportDefinition { + fn int_api_version() -> String { + V1AlphaApiVersion::ScopeV1Alpha.to_string() + } + + fn int_kind() -> String { + ReportDefinitionKind::ScopeReportDefinition.to_string() + } + #[cfg(test)] + fn examples() -> Vec { + vec!["v1alpha/ReportDefinition.yaml".to_string()] + } +} diff --git a/scope-models/src/v1alpha/report_location.rs b/scope-models/src/v1alpha/report_location.rs new file mode 100644 index 0000000..7c84fc5 --- /dev/null +++ b/scope-models/src/v1alpha/report_location.rs @@ -0,0 +1,82 @@ +use crate::core::ModelMetadata; +use crate::v1alpha::V1AlphaApiVersion; +use derive_builder::Builder; +use schemars::gen::SchemaGenerator; +use schemars::JsonSchema; +use serde::{Deserialize, Serialize}; +use std::collections::BTreeMap; + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema)] +#[serde(rename_all = "camelCase")] +pub struct ReportDestinationGithubIssueSpec { + pub owner: String, + pub repo: String, + #[serde(default)] + pub tags: Vec, +} + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema)] +#[serde(rename_all = "camelCase")] +pub enum ReportDestinationSpec { + RustyPaste { url: String }, + GithubIssue(ReportDestinationGithubIssueSpec), +} + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema)] +#[serde(rename_all = "camelCase")] +pub struct ReportLocationSpec { + #[serde(with = "serde_yaml::with::singleton_map")] + #[schemars(with = "ReportDestinationSpec")] + pub destination: ReportDestinationSpec, +} + +#[derive(Serialize, Deserialize, Debug, strum::Display, Clone, PartialEq, JsonSchema)] +pub enum ReportLocationKind { + #[strum(serialize = "ScopeReportLocation")] + ScopeReportLocation, +} + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Builder, JsonSchema)] +#[builder(setter(into))] +#[serde(rename_all = "camelCase")] +pub struct V1AlphaReportLocation { + pub api_version: V1AlphaApiVersion, + pub kind: ReportLocationKind, + pub metadata: ModelMetadata, + pub spec: ReportLocationSpec, +} + +impl crate::ScopeModel for V1AlphaReportLocation { + fn api_version(&self) -> String { + >::int_api_version() + } + + fn kind(&self) -> String { + >::int_kind() + } + + fn metadata(&self) -> &ModelMetadata { + &self.metadata + } + + fn spec(&self) -> &ReportLocationSpec { + &self.spec + } +} + +impl crate::InternalScopeModel for V1AlphaReportLocation { + fn int_api_version() -> String { + V1AlphaApiVersion::ScopeV1Alpha.to_string() + } + + fn int_kind() -> String { + ReportLocationKind::ScopeReportLocation.to_string() + } + #[cfg(test)] + fn examples() -> Vec { + vec![ + "v1alpha/ReportLocation.github.yaml".to_string(), + "v1alpha/ReportLocation.rustyPaste.yaml".to_string(), + ] + } +} diff --git a/scope/Cargo.toml b/scope/Cargo.toml index 26d41e0..2a4f0f0 100644 --- a/scope/Cargo.toml +++ b/scope/Cargo.toml @@ -23,6 +23,7 @@ name = "scope" name = "scope-intercept" [dependencies] +dev-scope-model = { path = "../scope-models" } clap = { version = "4.4.11", features = ["derive", "env"]} human-panic = "1.0.3" anyhow = "1.0.57" diff --git a/scope/examples/group-1.yaml b/scope/examples/group-1.yaml new file mode 100644 index 0000000..af7364e --- /dev/null +++ b/scope/examples/group-1.yaml @@ -0,0 +1,28 @@ +apiVersion: scope.github.com/v1alpha +kind: ScopeDoctorGroup +metadata: + name: foo +spec: + description: Check your shell for basic functionality + needs: + - bar + actions: + - description: foo1 + check: + paths: + - 'flig/bar/**/*' + commands: + - ./foo1.sh + fix: + commands: + - ./fix1.sh + helpText: | + There is a good way to fix this, maybe... + helpUrl: https://go.example.com/fixit + required: false + - description: foo2 + check: + paths: + - '*/*.txt' + commands: + - sleep infinity diff --git a/scope/src/doctor/check.rs b/scope/src/doctor/check.rs index 145fdaf..cf98d73 100644 --- a/scope/src/doctor/check.rs +++ b/scope/src/doctor/check.rs @@ -5,7 +5,7 @@ use std::cmp::max; use crate::shared::prelude::{ CaptureError, CaptureOpts, DoctorGroup, DoctorGroupAction, DoctorGroupActionCommand, - DoctorGroupCachePath, ExecutionProvider, ModelRoot, OutputDestination, ScopeModel, + DoctorGroupCachePath, ExecutionProvider, OutputDestination, }; use async_trait::async_trait; use derive_builder::Builder; @@ -90,7 +90,7 @@ pub trait DoctorActionRun: Send + Sync { #[educe(Debug)] #[builder(setter(into))] pub struct DefaultDoctorActionRun { - pub model: ModelRoot, + pub model: DoctorGroup, pub action: DoctorGroupAction, pub working_dir: PathBuf, pub file_cache: Arc, @@ -160,7 +160,7 @@ impl DefaultDoctorActionRun { .update_cache( &cache_path.base_path, &cache_path.paths, - self.model.name(), + &self.model.metadata.name(), self.file_cache.clone(), ) .await; @@ -238,7 +238,7 @@ impl DefaultDoctorActionRun { .have_globs_changed( &paths.base_path, &paths.paths, - self.model.name(), + &self.model.metadata.name(), self.file_cache.clone(), ) .await?; diff --git a/scope/src/doctor/commands/list.rs b/scope/src/doctor/commands/list.rs index 655605b..33551ec 100644 --- a/scope/src/doctor/commands/list.rs +++ b/scope/src/doctor/commands/list.rs @@ -1,5 +1,5 @@ use crate::doctor::runner::compute_group_order; -use crate::shared::prelude::{DoctorGroup, FoundConfig, ModelRoot}; +use crate::shared::prelude::{DoctorGroup, FoundConfig}; use crate::shared::print_details; use anyhow::Result; use clap::Args; @@ -16,7 +16,7 @@ pub async fn doctor_list(found_config: &FoundConfig, _args: &DoctorListArgs) -> Ok(()) } -pub fn generate_doctor_list(found_config: &FoundConfig) -> Vec<&ModelRoot> { +pub fn generate_doctor_list(found_config: &FoundConfig) -> Vec<&DoctorGroup> { let all_keys = BTreeSet::from_iter(found_config.doctor_group.keys().map(|x| x.to_string())); let all_paths = compute_group_order(&found_config.doctor_group, all_keys); diff --git a/scope/src/doctor/commands/run.rs b/scope/src/doctor/commands/run.rs index 3c34456..8b5ee9b 100644 --- a/scope/src/doctor/commands/run.rs +++ b/scope/src/doctor/commands/run.rs @@ -56,12 +56,12 @@ pub async fn doctor_run(found_config: &FoundConfig, args: &DoctorRunArgs) -> Res for check in found_config.doctor_group.values() { let should_group_run = match &args.only { None => true, - Some(names) => names.contains(&check.name().to_string()), + Some(names) => names.contains(&check.metadata.name().to_string()), }; let mut action_runs = Vec::new(); - for action in &check.spec.actions { + for action in &check.actions { let run = DefaultDoctorActionRun { model: check.clone(), action: action.clone(), @@ -75,10 +75,10 @@ pub async fn doctor_run(found_config: &FoundConfig, args: &DoctorRunArgs) -> Res action_runs.push(run); } - groups.insert(check.name().to_string(), action_runs); + groups.insert(check.metadata.name().to_string(), action_runs); if should_group_run { - desired_groups.insert(check.name().to_string()); + desired_groups.insert(check.metadata.name().to_string()); } } diff --git a/scope/src/doctor/runner.rs b/scope/src/doctor/runner.rs index d43dd5e..f988e6d 100644 --- a/scope/src/doctor/runner.rs +++ b/scope/src/doctor/runner.rs @@ -1,5 +1,5 @@ use super::check::{ActionRunResult, DoctorActionRun}; -use crate::shared::prelude::{DoctorGroup, ModelRoot}; +use crate::shared::prelude::{DoctorGroup}; use anyhow::Result; use colored::Colorize; use petgraph::algo::all_simple_paths; @@ -147,7 +147,7 @@ where } pub fn compute_group_order( - groups: &BTreeMap>, + groups: &BTreeMap, desired_groups: BTreeSet, ) -> Vec> { let mut graph = DiGraph::<&str, i32>::new(); @@ -162,7 +162,7 @@ pub fn compute_group_order( for (name, model) in groups { let this = node_graph.get(name).unwrap(); let mut needs_start = true; - for dep in &model.spec.requires { + for dep in &model.requires { if let Some(other) = node_graph.get(dep) { graph.add_edge(*other, *this, 1); needs_start = false; @@ -212,7 +212,7 @@ mod tests { use crate::doctor::check::tests::build_run_fail_fix_succeed_action; use crate::doctor::check::{ActionRunResult, MockDoctorActionRun}; use crate::doctor::runner::{compute_group_order, RunGroups}; - use crate::doctor::tests::{group_noop, make_root_model_additional, root_noop}; + use crate::doctor::tests::{group_noop, make_root_model_additional}; use anyhow::Result; use std::collections::{BTreeMap, BTreeSet}; @@ -225,7 +225,6 @@ mod tests { let step_1 = make_root_model_additional( vec![action.clone()], |meta| meta.name("step_1"), - root_noop, group_noop, ); groups.insert("step_1".to_string(), step_1); @@ -233,7 +232,6 @@ mod tests { let step_2 = make_root_model_additional( vec![action.clone()], |meta| meta.name("step_2"), - root_noop, |group| group.requires(vec!["step_1".to_string()]), ); groups.insert("step_2".to_string(), step_2); @@ -252,7 +250,6 @@ mod tests { let step_1 = make_root_model_additional( vec![action.clone()], |meta| meta.name("step_1"), - root_noop, group_noop, ); groups.insert("step_1".to_string(), step_1); @@ -260,7 +257,6 @@ mod tests { let step_2 = make_root_model_additional( vec![action.clone()], |meta| meta.name("step_2"), - root_noop, |group| group.requires(vec!["step_1".to_string()]), ); groups.insert("step_2".to_string(), step_2); @@ -282,7 +278,6 @@ mod tests { let step_1 = make_root_model_additional( vec![action.clone()], |meta| meta.name("step_1"), - root_noop, group_noop, ); groups.insert("step_1".to_string(), step_1); @@ -290,7 +285,6 @@ mod tests { let step_2 = make_root_model_additional( vec![action.clone()], |meta| meta.name("step_2"), - root_noop, |group| group.requires(vec!["step_1".to_string()]), ); groups.insert("step_2".to_string(), step_2); @@ -298,7 +292,6 @@ mod tests { let step_3 = make_root_model_additional( vec![action.clone()], |meta| meta.name("step_3"), - root_noop, |group| group.requires(vec!["step_1".to_string()]), ); groups.insert("step_3".to_string(), step_3); @@ -323,7 +316,6 @@ mod tests { let step_1 = make_root_model_additional( vec![action.clone()], |meta| meta.name("step_1"), - root_noop, group_noop, ); groups.insert("step_1".to_string(), step_1); @@ -331,7 +323,6 @@ mod tests { let step_2 = make_root_model_additional( vec![action.clone()], |meta| meta.name("step_2"), - root_noop, |group| group.requires(vec!["step_1".to_string()]), ); groups.insert("step_2".to_string(), step_2); @@ -339,7 +330,6 @@ mod tests { let step_3 = make_root_model_additional( vec![action.clone()], |meta| meta.name("step_3"), - root_noop, group_noop, ); groups.insert("step_3".to_string(), step_3); diff --git a/scope/src/doctor/tests.rs b/scope/src/doctor/tests.rs index 1056fe0..679c4a9 100644 --- a/scope/src/doctor/tests.rs +++ b/scope/src/doctor/tests.rs @@ -1,28 +1,19 @@ use crate::shared::prelude::{ - DoctorGroup, DoctorGroupAction, DoctorGroupBuilder, ModelMetadataBuilder, ModelRoot, - ModelRootBuilder, + DoctorGroup, DoctorGroupAction, DoctorGroupBuilder, }; use std::collections::BTreeMap; +use dev_scope_model::prelude::{ModelMetadataBuilder, ModelRootBuilder}; pub fn make_root_model_additional( actions: Vec, edit_meta: Meta, - edit_root: Root, edit_group: Group, -) -> ModelRoot +) -> DoctorGroup where Meta: FnOnce(&mut ModelMetadataBuilder) -> &mut ModelMetadataBuilder, Root: FnOnce(&mut ModelRootBuilder) -> &mut ModelRootBuilder, Group: FnOnce(&mut DoctorGroupBuilder) -> &mut DoctorGroupBuilder, { - let mut binding = DoctorGroupBuilder::default(); - let group_builder = binding - .description("a description") - .actions(actions) - .requires(Vec::new()); - - let group = edit_group(group_builder).build().unwrap(); - let mut binding = ModelMetadataBuilder::default(); let metadata_builder = binding .name("fake-name") @@ -30,28 +21,24 @@ where .labels(BTreeMap::default()); let metadata = edit_meta(metadata_builder).build().unwrap(); - let mut binding = ModelRootBuilder::default(); - let root_builder = binding - .api_version("fake") - .kind("fake-kind") + let mut binding = DoctorGroupBuilder::default(); + let group_builder = binding + .description("a description") + .actions(actions) .metadata(metadata) - .spec(group); + .requires(Vec::new()); - edit_root(root_builder).build().unwrap() + edit_group(group_builder).build().unwrap() } pub fn meta_noop(input: &mut ModelMetadataBuilder) -> &mut ModelMetadataBuilder { input } -pub fn root_noop(input: &mut ModelRootBuilder) -> &mut ModelRootBuilder { - input -} - pub fn group_noop(input: &mut DoctorGroupBuilder) -> &mut DoctorGroupBuilder { input } -pub fn build_root_model(actions: Vec) -> ModelRoot { - make_root_model_additional(actions, meta_noop, root_noop, group_noop) +pub fn build_root_model(actions: Vec) -> DoctorGroup { + make_root_model_additional(actions, meta_noop, group_noop) } diff --git a/scope/src/shared/config_load.rs b/scope/src/shared/config_load.rs index ef0c475..df60021 100644 --- a/scope/src/shared/config_load.rs +++ b/scope/src/shared/config_load.rs @@ -1,9 +1,9 @@ use crate::shared::models::prelude::{ - DoctorGroup, KnownError, ModelRoot, ParsedConfig, ReportDefinition, ReportUploadLocation, - ScopeModel, + DoctorGroup, KnownError, ParsedConfig, ReportDefinition, ReportUploadLocation, + }; use crate::shared::{ - FILE_DIR_ANNOTATION, FILE_EXEC_PATH_ANNOTATION, FILE_PATH_ANNOTATION, RUN_ID_ENV_VAR, + RUN_ID_ENV_VAR, }; use anyhow::{anyhow, Result}; use clap::{ArgGroup, Parser}; @@ -18,6 +18,8 @@ use std::fs::{self, File}; use std::io::Write; use std::path::{Path, PathBuf}; use tracing::{debug, error, warn}; +use dev_scope_model::prelude::{ModelMetadata, ModelRoot}; +use dev_scope_model::ScopeModel; #[derive(Parser, Debug)] #[clap(group = ArgGroup::new("config"))] @@ -106,10 +108,10 @@ impl ConfigOptions { pub struct FoundConfig { pub working_dir: PathBuf, pub raw_config: Vec>, - pub doctor_group: BTreeMap>, - pub known_error: BTreeMap>, - pub report_upload: BTreeMap>, - pub report_definition: Option>, + pub doctor_group: BTreeMap, + pub known_error: BTreeMap, + pub report_upload: BTreeMap, + pub report_definition: Option, pub config_path: Vec, pub bin_path: String, pub run_id: String, @@ -184,10 +186,9 @@ impl FoundConfig { pub fn get_report_definition(&self) -> ReportDefinition { self.report_definition - .as_ref() - .map(|x| x.spec.clone()) .clone() .unwrap_or_else(|| ReportDefinition { + metadata: ModelMetadata::new("generated"), template: "== Error report for {{ command }}.".to_string(), additional_data: Default::default(), }) @@ -256,18 +257,15 @@ pub(crate) fn parse_model(doc: Deserializer, file_path: &Path) -> Option>(value) { Ok(mut value) => { - value.metadata.annotations.insert( - FILE_PATH_ANNOTATION.to_string(), + value.metadata.annotations.file_path = Some( file_path.display().to_string(), ); - value.metadata.annotations.insert( - FILE_DIR_ANNOTATION.to_string(), + value.metadata.annotations.file_dir = Some( file_path.parent().unwrap().display().to_string(), ); - value.metadata.annotations.insert( - FILE_EXEC_PATH_ANNOTATION.to_string(), + value.metadata.annotations.bin_path( build_exec_path(file_path), ); Some(value) diff --git a/scope/src/shared/mod.rs b/scope/src/shared/mod.rs index 3ca3d0a..fcc9107 100644 --- a/scope/src/shared/mod.rs +++ b/scope/src/shared/mod.rs @@ -1,8 +1,9 @@ -use self::models::{ModelRoot, ScopeModel}; use colored::Colorize; use std::cmp::max; use std::path::Path; use tracing::info; +use dev_scope_model::prelude::ModelRoot; +use dev_scope_model::ScopeModel; mod capture; mod config_load; @@ -12,14 +13,12 @@ mod models; mod redact; mod report; -pub const FILE_PATH_ANNOTATION: &str = "scope.github.com/file-path"; -pub const FILE_DIR_ANNOTATION: &str = "scope.github.com/file-dir"; -pub const FILE_EXEC_PATH_ANNOTATION: &str = "scope.github.com/bin-path"; pub const CONFIG_FILE_PATH_ENV: &str = "SCOPE_CONFIG_JSON"; pub const RUN_ID_ENV_VAR: &str = "SCOPE_RUN_ID"; pub trait HelpMetadata { fn description(&self) -> &str; + fn name(&self) -> &str; } pub mod prelude { @@ -40,7 +39,7 @@ pub(crate) fn convert_to_string(input: Vec<&str>) -> Vec { input.iter().map(|x| x.to_string()).collect() } -pub fn print_details(working_dir: &Path, config: Vec<&ModelRoot>) +pub fn print_details(working_dir: &Path, config: Vec<&T>) where T: HelpMetadata, { @@ -49,7 +48,7 @@ where info!(target: "user", "{:max_name_length$}{:60}{}", "Name".white().bold(), "Description".white().bold(), "Path".white().bold()); for check in config { - let mut description = check.spec.description().to_string(); + let mut description = check.description().to_string(); if description.len() > 55 { description.truncate(55); description = format!("{}...", description); diff --git a/scope/src/shared/models/internal/doctor_group.rs b/scope/src/shared/models/internal/doctor_group.rs index ea080f5..b3cd4a1 100644 --- a/scope/src/shared/models/internal/doctor_group.rs +++ b/scope/src/shared/models/internal/doctor_group.rs @@ -1,6 +1,9 @@ -use crate::shared::{models::v1alpha::extract_command_path, HelpMetadata}; +use crate::shared::{HelpMetadata}; use derive_builder::Builder; use std::path::{Path, PathBuf}; +use dev_scope_model::prelude::{ModelMetadata, V1AlphaDoctorGroup}; +use dev_scope_model::ScopeModel; +use crate::shared::models::internal::extract_command_path; #[derive(Debug, PartialEq, Clone, Builder)] #[builder(setter(into))] @@ -110,6 +113,7 @@ where #[derive(Debug, PartialEq, Clone, Builder)] #[builder(setter(into))] pub struct DoctorGroup { + pub metadata: ModelMetadata, pub requires: Vec, pub description: String, pub actions: Vec, @@ -119,4 +123,125 @@ impl HelpMetadata for DoctorGroup { fn description(&self) -> &str { &self.description } + + fn name(&self) -> &str { + &self.metadata.name + } +} + +impl TryFrom for DoctorGroup { + + type Error = anyhow::Error; + + fn try_from(model: V1AlphaDoctorGroup) -> Result { + let containing_dir = Path::new(&model.containing_dir()); + let mut actions: Vec<_> = Default::default(); + for (count, spec_action) in model.spec.actions.into_iter().enumerate() { + let help_text = spec_action + .fix + .as_ref() + .and_then(|x| x.help_text.as_ref().map(|st| st.trim().to_string()).clone()); + let help_url = spec_action.fix.as_ref().and_then(|x| x.help_url.clone()); + let fix_command = spec_action.fix.as_ref().map(|commands| { + DoctorGroupActionCommand::from((containing_dir, commands.commands.clone())) + }); + + actions.push(DoctorGroupAction { + name: spec_action.name.unwrap_or_else(|| format!("{}", count + 1)), + required: spec_action.required, + description: spec_action + .description + .unwrap_or_else(|| "default".to_string()), + fix: DoctorGroupActionFix { + command: fix_command, + help_text, + help_url, + }, + check: DoctorGroupActionCheck { + command: spec_action + .check + .commands + .map(|commands| DoctorGroupActionCommand::from((&containing_dir, commands))), + files: spec_action.check.paths.map(|paths| DoctorGroupCachePath { + paths, + base_path: containing_dir.parent().unwrap().to_path_buf(), + }), + }, + }) + } + + Ok(DoctorGroup { + metadata: model.metadata, + description: model.spec.description.unwrap_or_else(|| "default".to_string()), + actions, + requires: model.spec.needs, + }) + } +} + +#[cfg(test)] +mod tests { + use crate::shared::models::parse_models_from_string; + use crate::shared::models::prelude::{ + DoctorGroup, DoctorGroupAction, DoctorGroupActionCheck, DoctorGroupActionCommand, + DoctorGroupActionFix, + }; + use crate::shared::prelude::DoctorGroupCachePath; + use std::path::Path; + use dev_scope_model::prelude::ModelMetadata; + + #[test] + fn parse_group_1() { + let text = include_str!("examples/group-1.yaml"); + let path = Path::new("/foo/bar/.scope/file.yaml"); + let configs = parse_models_from_string(path, text).unwrap(); + assert_eq!(1, configs.len()); + assert_eq!( + configs[0].get_doctor_group().unwrap(), + DoctorGroup { + metadata: ModelMetadata::new("group-1"), + requires: vec!["bar".to_string()], + description: "Check your shell for basic functionality".to_string(), + actions: vec![ + DoctorGroupAction { + name: "1".to_string(), + required: false, + description: "foo1".to_string(), + fix: DoctorGroupActionFix { + command: Some(DoctorGroupActionCommand::from(vec![ + "/foo/bar/.scope/fix1.sh" + ])), + help_text: Some( + "There is a good way to fix this, maybe...".to_string() + ), + help_url: Some("https://go.example.com/fixit".to_string()), + }, + check: DoctorGroupActionCheck { + command: Some(DoctorGroupActionCommand::from(vec![ + "/foo/bar/.scope/foo1.sh" + ])), + files: Some(DoctorGroupCachePath::from(( + "/foo/bar", + vec!["flig/bar/**/*"] + ))) + } + }, + DoctorGroupAction { + name: "2".to_string(), + required: true, + description: "foo2".to_string(), + fix: DoctorGroupActionFix { + command: None, + help_text: None, + help_url: None, + }, + check: DoctorGroupActionCheck { + command: Some(DoctorGroupActionCommand::from(vec!["sleep infinity"])), + files: Some(DoctorGroupCachePath::from(("/foo/bar", vec!["*/*.txt"]))) + } + } + ] + } + ); + } } diff --git a/scope/src/shared/models/internal/known_error.rs b/scope/src/shared/models/internal/known_error.rs index dd07c96..b616be6 100644 --- a/scope/src/shared/models/internal/known_error.rs +++ b/scope/src/shared/models/internal/known_error.rs @@ -1,11 +1,13 @@ use crate::shared::HelpMetadata; use derivative::Derivative; use regex::Regex; +use dev_scope_model::prelude::{ModelMetadata, V1AlphaKnownError}; #[derive(Derivative)] #[derivative(PartialEq)] #[derive(Debug, Clone)] pub struct KnownError { + pub metadata: ModelMetadata, pub description: String, pub pattern: String, #[derivative(PartialEq = "ignore")] @@ -17,4 +19,53 @@ impl HelpMetadata for KnownError { fn description(&self) -> &str { &self.description } + + fn name(&self) -> &str { + &self.metadata.name + } +} + +impl TryFrom for KnownError { + type Error = anyhow::Error; + + fn try_from(value: V1AlphaKnownError) -> Result { + let regex = Regex::new(&value.spec.pattern)?; + Ok(KnownError { + metadata: value.metadata, + pattern: value.spec.pattern, + regex, + help_text: value.spec.help, + description: value.spec.description, + }) + } +} + +#[cfg(test)] +mod tests { + use crate::shared::models::parse_models_from_string; + use crate::shared::models::prelude::KnownError; + use regex::Regex; + use std::path::Path; + + #[test] + fn test_parse_scope_known_error() { + let text = "apiVersion: scope.github.com/v1alpha +kind: ScopeKnownError +metadata: + name: error-exists +spec: + description: Check if the word error is in the logs + pattern: error + help: The command had an error, try reading the logs around there to find out what happened."; + + let path = Path::new("/foo/bar/file.yaml"); + let configs = parse_models_from_string(path, text).unwrap(); + assert_eq!(1, configs.len()); + assert_eq!(configs[0].get_known_error_spec().unwrap(), KnownError { + description: "Check if the word error is in the logs".to_string(), + help_text: "The command had an error, try reading the logs around there to find out what happened.".to_string(), + pattern: "error".to_string(), + regex: Regex::new("error").unwrap() + }); + } } diff --git a/scope/src/shared/models/internal/mod.rs b/scope/src/shared/models/internal/mod.rs index 7417bfa..d46d658 100644 --- a/scope/src/shared/models/internal/mod.rs +++ b/scope/src/shared/models/internal/mod.rs @@ -1,3 +1,5 @@ +use std::collections::VecDeque; +use std::path::Path; use crate::shared::prelude::*; use serde_yaml::Value; @@ -61,3 +63,36 @@ impl TryFrom> for ParsedConfig { ParsedConfig::try_from(&value) } } + +pub(crate) fn extract_command_path(parent_dir: &Path, exec: &str) -> String { + let mut parts: VecDeque<_> = exec.split(' ').map(|x| x.to_string()).collect(); + let mut command = parts.pop_front().unwrap(); + + if command.starts_with('.') { + let full_command = parent_dir.join(command).clean().display().to_string(); + command = full_command; + } + + parts.push_front(command); + + parts + .iter() + .map(|x| x.to_string()) + .collect::>() + .join(" ") +} + +#[test] +fn test_extract_command_path() { + let base_path = Path::new("/foo/bar"); + assert_eq!( + "/foo/bar/scripts/foo.sh", + crate::shared::models::v1alpha::extract_command_path(base_path, "./scripts/foo.sh") + ); + assert_eq!( + "/scripts/foo.sh", + crate::shared::models::v1alpha::extract_command_path(base_path, "/scripts/foo.sh") + ); + assert_eq!("foo", crate::shared::models::v1alpha::extract_command_path(base_path, "foo")); + assert_eq!("foo bar", crate::shared::models::v1alpha::extract_command_path(base_path, "foo bar")); +} diff --git a/scope/src/shared/models/internal/report_definition.rs b/scope/src/shared/models/internal/report_definition.rs index 6da9eac..a077824 100644 --- a/scope/src/shared/models/internal/report_definition.rs +++ b/scope/src/shared/models/internal/report_definition.rs @@ -1,7 +1,56 @@ use std::collections::BTreeMap; +use dev_scope_model::prelude::{ModelMetadata, V1AlphaReportDefinition}; #[derive(Debug, PartialEq, Clone)] pub struct ReportDefinition { + pub metadata: ModelMetadata, pub additional_data: BTreeMap, pub template: String, } + +impl TryFrom for ReportDefinition { + type Error = anyhow::Error; + + fn try_from(value: V1AlphaReportDefinition) -> Result { + Ok(ReportDefinition { + metadata: value.metadata, + template: value.spec.template.trim().to_string(), + additional_data: value.spec.additional_data, + }) + } +} + +#[cfg(test)] +mod tests { + use crate::shared::models::parse_models_from_string; + use crate::shared::models::prelude::ReportDefinition; + use std::path::Path; + + #[test] + fn test_parse_scope_report_def() { + let text = " +--- +apiVersion: scope.github.com/v1alpha +kind: ScopeReportDefinition +metadata: + name: report +spec: + additionalData: + env: env + template: | + hello bob + "; + + let path = Path::new("/foo/bar/file.yaml"); + let configs = parse_models_from_string(path, text).unwrap(); + assert_eq!(1, configs.len()); + + assert_eq!( + configs[0].get_report_def_spec().unwrap(), + ReportDefinition { + template: "hello bob".to_string(), + additional_data: [("env".to_string(), "env".to_string())].into() + } + ); + } +} \ No newline at end of file diff --git a/scope/src/shared/models/internal/upload_location.rs b/scope/src/shared/models/internal/upload_location.rs index 53ea9f5..aeb430c 100644 --- a/scope/src/shared/models/internal/upload_location.rs +++ b/scope/src/shared/models/internal/upload_location.rs @@ -1,3 +1,5 @@ +use dev_scope_model::prelude::{ModelMetadata, V1AlphaReportLocation}; + #[derive(Debug, PartialEq, Clone)] pub enum ReportUploadLocationDestination { RustyPaste { @@ -11,5 +13,26 @@ pub enum ReportUploadLocationDestination { } #[derive(Debug, PartialEq, Clone)] pub struct ReportUploadLocation { + pub metadata: ModelMetadata, pub destination: ReportUploadLocationDestination, } + +impl TryFrom for ReportUploadLocation { + type Error = anyhow::Error; + + fn try_from(value: V1AlphaReportLocation) -> Result { + let destination = match value.spec.destination { + dev_scope_model::prelude::ReportDestinationSpec::RustyPaste { url } => { + ReportUploadLocationDestination::RustyPaste { url } + } + dev_scope_model::prelude::ReportDestinationSpec::GithubIssue(github_issue) => { + ReportUploadLocationDestination::GithubIssue { + owner: github_issue.owner, + repo: github_issue.repo, + tags: github_issue.tags, + } + } + }; + Ok(ReportUploadLocation { metadata: value.metadata, destination }) + } +} diff --git a/scope/src/shared/models/mod.rs b/scope/src/shared/models/mod.rs index 7719dd1..55ab7fd 100644 --- a/scope/src/shared/models/mod.rs +++ b/scope/src/shared/models/mod.rs @@ -1,5 +1,4 @@ use crate::shared::models::internal::ParsedConfig; -use crate::shared::{FILE_DIR_ANNOTATION, FILE_EXEC_PATH_ANNOTATION, FILE_PATH_ANNOTATION}; use anyhow::anyhow; use serde::{Deserialize, Serialize}; use serde_yaml::Value; @@ -9,136 +8,8 @@ use derive_builder::Builder; use strum::EnumString; mod internal; -mod v1alpha; pub mod prelude { pub use super::internal::prelude::*; - pub use super::ScopeModel; - pub use super::{ModelMetadata, ModelMetadataBuilder, ModelRoot, ModelRootBuilder}; } -#[derive(Debug, PartialEq, EnumString)] -#[strum(ascii_case_insensitive)] -pub enum KnownApiVersion { - #[strum(serialize = "scope.github.com/v1alpha")] - ScopeV1Alpha, - #[strum(default)] - UnknownApiVersion(String), -} - -#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Default, Builder)] -#[builder(setter(into))] -pub struct ModelMetadata { - pub name: String, - #[serde(default)] - pub annotations: BTreeMap, - #[serde(default)] - pub labels: BTreeMap, -} - -impl ModelMetadata { - fn file_path(&self) -> String { - self.annotations - .get(FILE_PATH_ANNOTATION) - .cloned() - .unwrap_or_else(|| "unknown".to_string()) - } - - fn containing_dir(&self) -> String { - self.annotations - .get(FILE_DIR_ANNOTATION) - .cloned() - .unwrap_or_else(|| "unknown".to_string()) - } - - fn exec_path(&self) -> String { - self.annotations - .get(FILE_EXEC_PATH_ANNOTATION) - .cloned() - .unwrap_or_else(|| std::env::var("PATH").unwrap_or_else(|_| "".to_string())) - } -} - -pub trait ScopeModel { - fn name(&self) -> &str; - fn kind(&self) -> &str; - fn full_name(&self) -> String { - format!("{}/{}", self.kind(), self.name()) - } -} - -#[derive(Serialize, Deserialize, Debug, PartialEq, Clone, Builder)] -#[builder(setter(into))] -#[serde(rename_all = "camelCase")] -pub struct ModelRoot { - pub api_version: String, - pub kind: String, - pub metadata: ModelMetadata, - pub spec: V, -} - -impl ModelRoot { - pub fn with_spec(&self, spec: T) -> ModelRoot { - ModelRoot { - api_version: self.api_version.clone(), - kind: self.kind.clone(), - metadata: self.metadata.clone(), - spec, - } - } - - pub fn file_path(&self) -> String { - self.metadata.file_path() - } - pub fn containing_dir(&self) -> String { - self.metadata.containing_dir() - } - - pub fn exec_path(&self) -> String { - self.metadata.exec_path() - } -} - -impl ScopeModel for ModelRoot { - fn name(&self) -> &str { - &self.metadata.name - } - - fn kind(&self) -> &str { - &self.kind - } -} - -impl TryFrom<&ModelRoot> for ParsedConfig { - type Error = anyhow::Error; - - fn try_from(root: &ModelRoot) -> Result { - let api_version: &str = &root.api_version.trim().to_ascii_lowercase(); - let api_versions = KnownApiVersion::try_from(api_version) - .unwrap_or_else(|_| KnownApiVersion::UnknownApiVersion(api_version.to_string())); - - match api_versions { - KnownApiVersion::ScopeV1Alpha => Ok(v1alpha::parse_v1_alpha1(root)?), - KnownApiVersion::UnknownApiVersion(_) => { - Err(anyhow!("Unable to parse {}", api_version)) - } - } - } -} - -#[cfg(test)] -pub(crate) fn parse_models_from_string( - file_path: &std::path::Path, - input: &str, -) -> anyhow::Result> { - use serde_yaml::Deserializer; - - let mut models = Vec::new(); - for doc in Deserializer::from_str(input) { - if let Some(parsed_model) = crate::shared::config_load::parse_model(doc, file_path) { - models.push(parsed_model.try_into()?) - } - } - - Ok(models) -} diff --git a/scope/src/shared/models/v1alpha/doctor_exec.rs b/scope/src/shared/models/v1alpha/doctor_exec.rs deleted file mode 100644 index ec1748f..0000000 --- a/scope/src/shared/models/v1alpha/doctor_exec.rs +++ /dev/null @@ -1,149 +0,0 @@ -use crate::shared::models::{prelude::*, v1alpha::extract_command_path}; -use anyhow::Result; - -use serde::{Deserialize, Serialize}; -use serde_yaml::Value; -use std::path::Path; - -#[derive(Serialize, Deserialize, Debug)] -#[serde(rename_all = "camelCase")] -struct DoctorCheckType { - target: String, -} - -#[derive(Serialize, Deserialize, Debug)] -#[serde(rename_all = "camelCase")] -struct DoctorCheckSpec { - #[serde(default = "default_order")] - order: i32, - #[serde(with = "serde_yaml::with::singleton_map")] - check: DoctorCheckType, - #[serde(with = "serde_yaml::with::singleton_map", default)] - fix: Option, - description: String, - help: String, -} - -fn default_order() -> i32 { - 100 -} - -pub(super) fn parse(base_path: &Path, value: &Value) -> Result { - let parsed: DoctorCheckSpec = serde_yaml::from_value(value.clone())?; - - let check_path = extract_command_path(base_path, &parsed.check.target); - let fix_exec = parsed.fix.map(|path| DoctorGroupActionCommand { - commands: vec![extract_command_path(base_path, &path.target)], - }); - - Ok(DoctorGroup { - requires: Default::default(), - actions: vec![DoctorGroupAction { - name: "1".to_string(), - required: true, - description: parsed.description.clone(), - fix: DoctorGroupActionFix { - command: fix_exec, - help_text: None, - help_url: None, - }, - check: DoctorGroupActionCheck { - command: Some(DoctorGroupActionCommand { - commands: vec![check_path], - }), - files: None, - }, - }], - description: parsed.description, - }) -} - -#[cfg(test)] -mod tests { - use crate::shared::models::parse_models_from_string; - use crate::shared::models::prelude::{DoctorGroup, DoctorGroupAction}; - use std::path::Path; - - #[test] - fn test_parse_scope_doctor_check_exec() { - let text = "--- -apiVersion: scope.github.com/v1alpha -kind: ScopeDoctorCheck -metadata: - name: path-exists -spec: - check: - target: ./scripts/does-path-env-exist.sh - fix: - target: 'true' - description: Check your shell for basic functionality - help: You're shell does not have a path env. Reload your shell. ---- -apiVersion: scope.github.com/v1alpha -kind: ScopeDoctorCheck -metadata: - name: path-exists -spec: - check: - target: /scripts/does-path-env-exist.sh - description: Check your shell for basic functionality - help: You're shell does not have a path env. Reload your shell. ---- -apiVersion: scope.github.com/v1alpha -kind: ScopeDoctorCheck -metadata: - name: path-exists -spec: - check: - target: does-path-env-exist.sh - description: Check your shell for basic functionality - help: You're shell does not have a path env. Reload your shell. -"; - - let path = Path::new("/foo/bar/file.yaml"); - let configs = parse_models_from_string(path, text).unwrap(); - assert_eq!(3, configs.len()); - assert_eq!( - configs[0].get_doctor_group().unwrap(), - DoctorGroup { - requires: Default::default(), - description: "Check your shell for basic functionality".to_string(), - actions: vec![DoctorGroupAction::make_from( - "1", - "Check your shell for basic functionality", - Some(vec!["true"]), - None, - Some(vec!["/foo/bar/scripts/does-path-env-exist.sh"]) - )] - } - ); - assert_eq!( - configs[1].get_doctor_group().unwrap(), - DoctorGroup { - requires: Default::default(), - description: "Check your shell for basic functionality".to_string(), - actions: vec![DoctorGroupAction::make_from( - "1", - "Check your shell for basic functionality", - None, - None, - Some(vec!["/scripts/does-path-env-exist.sh"]) - )] - } - ); - assert_eq!( - configs[2].get_doctor_group().unwrap(), - DoctorGroup { - requires: Default::default(), - description: "Check your shell for basic functionality".to_string(), - actions: vec![DoctorGroupAction::make_from( - "1", - "Check your shell for basic functionality", - None, - None, - Some(vec!["does-path-env-exist.sh"]) - )] - } - ); - } -} diff --git a/scope/src/shared/models/v1alpha/doctor_group.rs b/scope/src/shared/models/v1alpha/doctor_group.rs deleted file mode 100644 index edbad90..0000000 --- a/scope/src/shared/models/v1alpha/doctor_group.rs +++ /dev/null @@ -1,161 +0,0 @@ -use crate::shared::models::prelude::*; -use anyhow::Result; - -use serde::{Deserialize, Serialize}; -use serde_yaml::Value; - -use std::path::Path; - -#[derive(Serialize, Deserialize, Debug)] -#[serde(rename_all = "camelCase")] -pub struct DoctorCheckSpec { - #[serde(default)] - pub paths: Option>, - #[serde(default)] - pub commands: Option>, -} - -#[derive(Serialize, Deserialize, Debug)] -#[serde(rename_all = "camelCase")] -pub struct DoctorFixSpec { - #[serde(default)] - pub commands: Vec, - #[serde(default)] - pub help_text: Option, - #[serde(default)] - pub help_url: Option, -} - -#[derive(Serialize, Deserialize, Debug)] -#[serde(rename_all = "camelCase")] -pub struct DoctorGroupActionSpec { - pub name: Option, - pub description: Option, - pub check: DoctorCheckSpec, - pub fix: Option, - #[serde(default = "doctor_group_action_required_default")] - pub required: bool, -} - -fn doctor_group_action_required_default() -> bool { - true -} - -#[derive(Serialize, Deserialize, Debug)] -#[serde(rename_all = "camelCase")] -pub struct DoctorGroupSpec { - #[serde(default)] - pub needs: Vec, - pub description: Option, - pub actions: Vec, -} - -pub(super) fn parse(containing_dir: &Path, value: &Value) -> Result { - let parsed: DoctorGroupSpec = serde_yaml::from_value(value.clone())?; - - let mut actions: Vec<_> = Default::default(); - for (count, spec_action) in parsed.actions.into_iter().enumerate() { - let help_text = spec_action - .fix - .as_ref() - .and_then(|x| x.help_text.as_ref().map(|st| st.trim().to_string()).clone()); - let help_url = spec_action.fix.as_ref().and_then(|x| x.help_url.clone()); - let fix_command = spec_action.fix.as_ref().map(|commands| { - DoctorGroupActionCommand::from((containing_dir, commands.commands.clone())) - }); - - actions.push(DoctorGroupAction { - name: spec_action.name.unwrap_or_else(|| format!("{}", count + 1)), - required: spec_action.required, - description: spec_action - .description - .unwrap_or_else(|| "default".to_string()), - fix: DoctorGroupActionFix { - command: fix_command, - help_text, - help_url, - }, - check: DoctorGroupActionCheck { - command: spec_action - .check - .commands - .map(|commands| DoctorGroupActionCommand::from((containing_dir, commands))), - files: spec_action.check.paths.map(|paths| DoctorGroupCachePath { - paths, - base_path: containing_dir.parent().unwrap().to_path_buf(), - }), - }, - }) - } - - Ok(DoctorGroup { - description: parsed.description.unwrap_or_else(|| "default".to_string()), - actions, - requires: parsed.needs, - }) -} - -#[cfg(test)] -mod tests { - use crate::shared::models::parse_models_from_string; - use crate::shared::models::prelude::{ - DoctorGroup, DoctorGroupAction, DoctorGroupActionCheck, DoctorGroupActionCommand, - DoctorGroupActionFix, - }; - use crate::shared::prelude::DoctorGroupCachePath; - use std::path::Path; - - #[test] - fn parse_group_1() { - let text = include_str!("examples/group-1.yaml"); - let path = Path::new("/foo/bar/.scope/file.yaml"); - let configs = parse_models_from_string(path, text).unwrap(); - assert_eq!(1, configs.len()); - assert_eq!( - configs[0].get_doctor_group().unwrap(), - DoctorGroup { - requires: vec!["bar".to_string()], - description: "Check your shell for basic functionality".to_string(), - actions: vec![ - DoctorGroupAction { - name: "1".to_string(), - required: false, - description: "foo1".to_string(), - fix: DoctorGroupActionFix { - command: Some(DoctorGroupActionCommand::from(vec![ - "/foo/bar/.scope/fix1.sh" - ])), - help_text: Some( - "There is a good way to fix this, maybe...".to_string() - ), - help_url: Some("https://go.example.com/fixit".to_string()), - }, - check: DoctorGroupActionCheck { - command: Some(DoctorGroupActionCommand::from(vec![ - "/foo/bar/.scope/foo1.sh" - ])), - files: Some(DoctorGroupCachePath::from(( - "/foo/bar", - vec!["flig/bar/**/*"] - ))) - } - }, - DoctorGroupAction { - name: "2".to_string(), - required: true, - description: "foo2".to_string(), - fix: DoctorGroupActionFix { - command: None, - help_text: None, - help_url: None, - }, - check: DoctorGroupActionCheck { - command: Some(DoctorGroupActionCommand::from(vec!["sleep infinity"])), - files: Some(DoctorGroupCachePath::from(("/foo/bar", vec!["*/*.txt"]))) - } - } - ] - } - ); - } -} diff --git a/scope/src/shared/models/v1alpha/doctor_setup.rs b/scope/src/shared/models/v1alpha/doctor_setup.rs deleted file mode 100644 index 2c44c80..0000000 --- a/scope/src/shared/models/v1alpha/doctor_setup.rs +++ /dev/null @@ -1,147 +0,0 @@ -use crate::shared::models::prelude::*; -use anyhow::Result; - -use serde::{Deserialize, Serialize}; -use serde_yaml::Value; - -use std::path::Path; - -#[derive(Serialize, Deserialize, Debug)] -#[serde(rename_all = "camelCase")] -pub enum DoctorSetupSpecExec { - Exec(Vec), -} - -#[derive(Serialize, Deserialize, Debug)] -#[serde(rename_all = "camelCase")] -pub enum DoctorSetupSpecCache { - Paths(Vec), -} - -#[derive(Serialize, Deserialize, Debug)] -#[serde(rename_all = "camelCase")] -pub struct DoctorSetupSpec { - #[serde(default = "default_order")] - pub order: i32, - #[serde(with = "serde_yaml::with::singleton_map")] - pub cache: DoctorSetupSpecCache, - #[serde(with = "serde_yaml::with::singleton_map")] - pub setup: DoctorSetupSpecExec, - pub description: String, -} - -fn default_order() -> i32 { - 100 -} - -pub(super) fn parse(containing_dir: &Path, value: &Value) -> Result { - let parsed: DoctorSetupSpec = serde_yaml::from_value(value.clone())?; - - let cache = match parsed.cache { - DoctorSetupSpecCache::Paths(paths) => DoctorGroupCachePath { - paths, - base_path: containing_dir.parent().unwrap().to_path_buf(), - }, - }; - - let exec = match parsed.setup { - DoctorSetupSpecExec::Exec(commands) => { - DoctorGroupActionCommand::from((containing_dir, commands)) - } - }; - - Ok(DoctorGroup { - requires: Default::default(), - actions: vec![DoctorGroupAction { - name: "1".to_string(), - required: true, - description: parsed.description.clone(), - fix: DoctorGroupActionFix { - command: Some(exec), - help_text: None, - help_url: None, - }, - check: DoctorGroupActionCheck { - command: None, - files: Some(cache), - }, - }], - description: parsed.description, - }) -} - -#[cfg(test)] -mod tests { - use crate::shared::models::parse_models_from_string; - use crate::shared::models::prelude::{ - DoctorGroup, DoctorGroupAction, DoctorGroupActionCheck, DoctorGroupActionCommand, - DoctorGroupActionFix, DoctorGroupCachePath, - }; - use std::path::Path; - - #[test] - fn test_parse_scope_setup() { - let text = include_str!("examples/setup-1.yaml"); - let path = Path::new("/foo/bar/.scope/file.yaml"); - let configs = parse_models_from_string(path, text).unwrap(); - assert_eq!(1, configs.len()); - assert_eq!( - configs[0].get_doctor_group().unwrap(), - DoctorGroup { - requires: Default::default(), - description: "Check your shell for basic functionality".to_string(), - actions: vec![DoctorGroupAction { - name: "1".to_string(), - required: true, - description: "Check your shell for basic functionality".to_string(), - fix: DoctorGroupActionFix { - command: Some(DoctorGroupActionCommand::from(vec![ - "/foo/bar/.scope/bin/setup" - ])), - help_text: None, - help_url: None, - }, - check: DoctorGroupActionCheck { - command: None, - files: Some(DoctorGroupCachePath::from(( - "/foo/bar", - vec!["flig/bar/**/*"] - ))) - } - }] - } - ); - } - - #[test] - fn test_parse_command_without_rel_path() { - let text = include_str!("examples/setup-2.yaml"); - let path = Path::new("/foo/bar/.scope/file.yaml"); - let configs = parse_models_from_string(path, text).unwrap(); - assert_eq!(1, configs.len()); - assert_eq!( - configs[0].get_doctor_group().unwrap(), - DoctorGroup { - requires: Default::default(), - description: "Check your shell for basic functionality".to_string(), - actions: vec![DoctorGroupAction { - name: "1".to_string(), - required: true, - description: "Check your shell for basic functionality".to_string(), - fix: DoctorGroupActionFix { - command: Some(DoctorGroupActionCommand::from(vec!["sleep infinity"])), - help_text: None, - help_url: None, - }, - check: DoctorGroupActionCheck { - command: None, - files: Some(DoctorGroupCachePath::from(( - "/foo/bar", - vec!["flig/bar/**/*"] - ))) - } - }] - } - ); - } -} diff --git a/scope/src/shared/models/v1alpha/examples/setup-1.yaml b/scope/src/shared/models/v1alpha/examples/setup-1.yaml deleted file mode 100644 index 8a5f9d0..0000000 --- a/scope/src/shared/models/v1alpha/examples/setup-1.yaml +++ /dev/null @@ -1,12 +0,0 @@ -apiVersion: scope.github.com/v1alpha -kind: ScopeDoctorSetup -metadata: - name: setup -spec: - cache: - paths: - - flig/bar/**/* - setup: - exec: - - ./bin/setup - description: Check your shell for basic functionality \ No newline at end of file diff --git a/scope/src/shared/models/v1alpha/examples/setup-2.yaml b/scope/src/shared/models/v1alpha/examples/setup-2.yaml deleted file mode 100644 index fa8f66d..0000000 --- a/scope/src/shared/models/v1alpha/examples/setup-2.yaml +++ /dev/null @@ -1,12 +0,0 @@ -apiVersion: scope.github.com/v1alpha -kind: ScopeDoctorSetup -metadata: - name: setup -spec: - cache: - paths: - - flig/bar/**/* - setup: - exec: - - sleep infinity - description: Check your shell for basic functionality \ No newline at end of file diff --git a/scope/src/shared/models/v1alpha/known_error.rs b/scope/src/shared/models/v1alpha/known_error.rs deleted file mode 100644 index b2dc8c4..0000000 --- a/scope/src/shared/models/v1alpha/known_error.rs +++ /dev/null @@ -1,53 +0,0 @@ -use crate::shared::models::prelude::KnownError; -use anyhow::Result; -use regex::Regex; -use serde::{Deserialize, Serialize}; -use serde_yaml::Value; - -#[derive(Serialize, Deserialize, Debug)] -#[serde(rename_all = "camelCase")] -struct KnownErrorSpec { - description: String, - help: String, - pattern: String, -} -pub(super) fn parse(value: &Value) -> Result { - let parsed: KnownErrorSpec = serde_yaml::from_value(value.clone())?; - let regex = Regex::new(&parsed.pattern)?; - Ok(KnownError { - pattern: parsed.pattern, - regex, - help_text: parsed.help, - description: parsed.description, - }) -} - -#[cfg(test)] -mod tests { - use crate::shared::models::parse_models_from_string; - use crate::shared::models::prelude::KnownError; - use regex::Regex; - use std::path::Path; - - #[test] - fn test_parse_scope_known_error() { - let text = "apiVersion: scope.github.com/v1alpha -kind: ScopeKnownError -metadata: - name: error-exists -spec: - description: Check if the word error is in the logs - pattern: error - help: The command had an error, try reading the logs around there to find out what happened."; - - let path = Path::new("/foo/bar/file.yaml"); - let configs = parse_models_from_string(path, text).unwrap(); - assert_eq!(1, configs.len()); - assert_eq!(configs[0].get_known_error_spec().unwrap(), KnownError { - description: "Check if the word error is in the logs".to_string(), - help_text: "The command had an error, try reading the logs around there to find out what happened.".to_string(), - pattern: "error".to_string(), - regex: Regex::new("error").unwrap() - }); - } -} diff --git a/scope/src/shared/models/v1alpha/mod.rs b/scope/src/shared/models/v1alpha/mod.rs deleted file mode 100644 index 9fbfc1f..0000000 --- a/scope/src/shared/models/v1alpha/mod.rs +++ /dev/null @@ -1,101 +0,0 @@ -use crate::shared::models::internal::ParsedConfig; -use crate::shared::models::ModelRoot; -use anyhow::{anyhow, Result}; -use path_clean::PathClean; -use serde_yaml::Value; -use std::collections::VecDeque; -use std::path::{Path, PathBuf}; - -use strum::EnumString; - -mod doctor_exec; -mod doctor_group; -mod doctor_setup; -mod known_error; -mod report_definition; -mod report_location; - -#[derive(Debug, PartialEq, EnumString, Clone)] -#[strum(ascii_case_insensitive)] -pub enum KnownKinds { - ScopeReportDefinition, - ScopeReportLocation, - ScopeKnownError, - ScopeDoctorCheck, - ScopeDoctorSetup, - ScopeDoctorGroup, - #[strum(default)] - UnknownKind(String), -} - -pub fn parse_v1_alpha1(root: &ModelRoot) -> Result { - let kind: &str = &root.kind.trim().to_ascii_lowercase(); - - let known_kinds = - KnownKinds::try_from(kind).unwrap_or_else(|_| KnownKinds::UnknownKind(kind.to_string())); - let file_path = PathBuf::from(root.file_path()); - let containing_dir = file_path.parent().unwrap(); - - let parsed = match known_kinds { - KnownKinds::ScopeDoctorCheck => { - let exec_check = doctor_exec::parse(containing_dir, &root.spec)?; - ParsedConfig::DoctorGroup(root.with_spec(exec_check)) - } - KnownKinds::ScopeKnownError => { - let known_error = known_error::parse(&root.spec)?; - ParsedConfig::KnownError(root.with_spec(known_error)) - } - KnownKinds::ScopeReportLocation => { - let report_upload = report_location::parse(&root.spec)?; - ParsedConfig::ReportUpload(root.with_spec(report_upload)) - } - KnownKinds::ScopeReportDefinition => { - let report_upload = report_definition::parse(&root.spec)?; - ParsedConfig::ReportDefinition(root.with_spec(report_upload)) - } - KnownKinds::ScopeDoctorSetup => { - let setup = doctor_setup::parse(containing_dir, &root.spec)?; - ParsedConfig::DoctorGroup(root.with_spec(setup)) - } - KnownKinds::ScopeDoctorGroup => { - let group = doctor_group::parse(containing_dir, &root.spec)?; - ParsedConfig::DoctorGroup(root.with_spec(group)) - } - _ => return Err(anyhow!("Unable to parse v1alpha/{}", kind)), - }; - - Ok(parsed) -} - -pub(crate) fn extract_command_path(parent_dir: &Path, exec: &str) -> String { - let mut parts: VecDeque<_> = exec.split(' ').map(|x| x.to_string()).collect(); - let mut command = parts.pop_front().unwrap(); - - if command.starts_with('.') { - let full_command = parent_dir.join(command).clean().display().to_string(); - command = full_command; - } - - parts.push_front(command); - - parts - .iter() - .map(|x| x.to_string()) - .collect::>() - .join(" ") -} - -#[test] -fn test_extract_command_path() { - let base_path = Path::new("/foo/bar"); - assert_eq!( - "/foo/bar/scripts/foo.sh", - extract_command_path(base_path, "./scripts/foo.sh") - ); - assert_eq!( - "/scripts/foo.sh", - extract_command_path(base_path, "/scripts/foo.sh") - ); - assert_eq!("foo", extract_command_path(base_path, "foo")); - assert_eq!("foo bar", extract_command_path(base_path, "foo bar")); -} diff --git a/scope/src/shared/models/v1alpha/report_definition.rs b/scope/src/shared/models/v1alpha/report_definition.rs deleted file mode 100644 index d8bcaca..0000000 --- a/scope/src/shared/models/v1alpha/report_definition.rs +++ /dev/null @@ -1,57 +0,0 @@ -use crate::shared::models::prelude::ReportDefinition; -use anyhow::Result; - -use serde::{Deserialize, Serialize}; -use serde_yaml::Value; -use std::collections::BTreeMap; - -#[derive(Serialize, Deserialize, Debug)] -#[serde(rename_all = "camelCase")] -struct ReportDefinitionSpec { - #[serde(default)] - additional_data: BTreeMap, - template: String, -} -pub(super) fn parse(value: &Value) -> Result { - let parsed: ReportDefinitionSpec = serde_yaml::from_value(value.clone())?; - - Ok(ReportDefinition { - template: parsed.template.trim().to_string(), - additional_data: parsed.additional_data, - }) -} - -#[cfg(test)] -mod tests { - use crate::shared::models::parse_models_from_string; - use crate::shared::models::prelude::ReportDefinition; - use std::path::Path; - - #[test] - fn test_parse_scope_report_def() { - let text = " ---- -apiVersion: scope.github.com/v1alpha -kind: ScopeReportDefinition -metadata: - name: report -spec: - additionalData: - env: env - template: | - hello bob - "; - - let path = Path::new("/foo/bar/file.yaml"); - let configs = parse_models_from_string(path, text).unwrap(); - assert_eq!(1, configs.len()); - - assert_eq!( - configs[0].get_report_def_spec().unwrap(), - ReportDefinition { - template: "hello bob".to_string(), - additional_data: [("env".to_string(), "env".to_string())].into() - } - ); - } -} diff --git a/scope/src/shared/models/v1alpha/report_location.rs b/scope/src/shared/models/v1alpha/report_location.rs deleted file mode 100644 index 5073800..0000000 --- a/scope/src/shared/models/v1alpha/report_location.rs +++ /dev/null @@ -1,100 +0,0 @@ -use crate::shared::models::prelude::{ReportUploadLocation, ReportUploadLocationDestination}; -use anyhow::Result; - -use serde::{Deserialize, Serialize}; -use serde_yaml::Value; - -#[derive(Serialize, Deserialize, Debug)] -#[serde(rename_all = "camelCase")] -struct ReportDestinationGithubIssueSpec { - owner: String, - repo: String, - #[serde(default)] - tags: Vec, -} - -#[derive(Serialize, Deserialize, Debug)] -#[serde(rename_all = "camelCase")] -enum ReportDestinationSpec { - RustyPaste { url: String }, - GithubIssue(ReportDestinationGithubIssueSpec), -} - -#[derive(Serialize, Deserialize, Debug)] -#[serde(rename_all = "camelCase")] -struct ReportLocationSpec { - #[serde(with = "serde_yaml::with::singleton_map")] - destination: ReportDestinationSpec, -} -pub(super) fn parse(value: &Value) -> Result { - let parsed: ReportLocationSpec = serde_yaml::from_value(value.clone())?; - let destination = match parsed.destination { - ReportDestinationSpec::RustyPaste { url } => { - ReportUploadLocationDestination::RustyPaste { url } - } - ReportDestinationSpec::GithubIssue(github_issue) => { - ReportUploadLocationDestination::GithubIssue { - owner: github_issue.owner, - repo: github_issue.repo, - tags: github_issue.tags, - } - } - }; - Ok(ReportUploadLocation { destination }) -} - -#[cfg(test)] -mod tests { - use crate::shared::models::parse_models_from_string; - use crate::shared::models::prelude::{ReportUploadLocation, ReportUploadLocationDestination}; - use std::path::Path; - - #[test] - fn test_parse_scope_report_loc() { - let text = " ---- -apiVersion: scope.github.com/v1alpha -kind: ScopeReportLocation -metadata: - name: report -spec: - destination: - rustyPaste: - url: https://foo.bar ---- -apiVersion: scope.github.com/v1alpha -kind: ScopeReportLocation -metadata: - name: github -spec: - destination: - githubIssue: - owner: scope - repo: party - "; - - let path = Path::new("/foo/bar/file.yaml"); - let configs = parse_models_from_string(path, text).unwrap(); - assert_eq!(2, configs.len()); - - assert_eq!( - configs[0].get_report_upload_spec().unwrap(), - ReportUploadLocation { - destination: ReportUploadLocationDestination::RustyPaste { - url: "https://foo.bar".to_string() - }, - } - ); - - assert_eq!( - configs[1].get_report_upload_spec().unwrap(), - ReportUploadLocation { - destination: ReportUploadLocationDestination::GithubIssue { - owner: "scope".to_string(), - repo: "party".to_string(), - tags: Vec::new(), - } - } - ); - } -} diff --git a/scope/src/shared/report.rs b/scope/src/shared/report.rs index fd5ac71..117f9de 100644 --- a/scope/src/shared/report.rs +++ b/scope/src/shared/report.rs @@ -81,8 +81,8 @@ impl<'a> ReportBuilder<'a> { let report = self.make_report_test(); for dest in self.config.report_upload.values() { - if let Err(e) = &dest.spec.destination.upload(&report).await { - warn!(target: "user", "Unable to upload to {}: {}", dest.name(), e); + if let Err(e) = &dest.destination.upload(&report).await { + warn!(target: "user", "Unable to upload to {}: {}", dest.metadata.name(), e); } } From 09b7683aa833c8ebe6d4901a266d875114d34659 Mon Sep 17 00:00:00 2001 From: Ethan Hall Date: Sun, 3 Mar 2024 14:16:06 -0800 Subject: [PATCH 02/14] move moving files --- scope-models/src/core.rs | 15 +- scope-models/src/lib.rs | 33 ++-- scope-models/src/v1alpha/doctor_group.rs | 9 +- scope-models/src/v1alpha/known_error.rs | 7 +- scope-models/src/v1alpha/report_definition.rs | 11 +- scope-models/src/v1alpha/report_location.rs | 10 +- scope/src/analyze/cli.rs | 7 +- scope/src/bin/scope-intercept.rs | 4 +- scope/src/doctor/check.rs | 9 +- scope/src/doctor/commands/run.rs | 2 +- scope/src/doctor/runner.rs | 2 +- scope/src/doctor/tests.rs | 12 +- scope/src/shared/config_load.rs | 32 ++-- scope/src/shared/mod.rs | 12 +- .../shared/models/internal/doctor_group.rs | 143 ++++++++++-------- .../src/shared/models/internal/known_error.rs | 34 +++-- scope/src/shared/models/internal/mod.rs | 53 +++++-- .../models/internal/report_definition.rs | 43 ++++-- .../shared/models/internal/upload_location.rs | 41 ++++- scope/src/shared/models/mod.rs | 18 +++ scope/src/shared/report.rs | 2 +- 21 files changed, 324 insertions(+), 175 deletions(-) diff --git a/scope-models/src/core.rs b/scope-models/src/core.rs index 1a7f7f8..7fedc34 100644 --- a/scope-models/src/core.rs +++ b/scope-models/src/core.rs @@ -1,4 +1,3 @@ -use crate::prelude::DoctorGroupSpec; use derive_builder::Builder; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; @@ -28,23 +27,27 @@ impl ModelMetadata { pub fn file_path(&self) -> String { match &self.annotations.file_path { Some(v) => v.to_string(), - None => "unknown".to_string() + None => "unknown".to_string(), } } pub fn containing_dir(&self) -> String { match &self.annotations.file_dir { Some(v) => v.to_string(), - None => "unknown".to_string() + None => "unknown".to_string(), } } pub fn exec_path(&self) -> String { match &self.annotations.bin_path { Some(v) => { - format!("{}:{}", v.to_string(), std::env::var("PATH").unwrap_or_else(|_| "".to_string())) - }, - None => std::env::var("PATH").unwrap_or_else(|_| "".to_string()) + format!( + "{}:{}", + v, + std::env::var("PATH").unwrap_or_else(|_| "".to_string()) + ) + } + None => std::env::var("PATH").unwrap_or_else(|_| "".to_string()), } } diff --git a/scope-models/src/lib.rs b/scope-models/src/lib.rs index 6af3a81..6bd5a8b 100644 --- a/scope-models/src/lib.rs +++ b/scope-models/src/lib.rs @@ -1,7 +1,8 @@ -use crate::core::ModelMetadata; -use schemars::gen::{SchemaGenerator, SchemaSettings}; +use crate::core::{ModelMetadata, ModelRoot}; + use schemars::JsonSchema; use serde::{Deserialize, Serialize}; +use serde_yaml::Value; mod core; mod v1alpha; @@ -35,17 +36,29 @@ pub trait ScopeModel { } } -pub trait InternalScopeModel: +pub trait InternalScopeModel: JsonSchema + Serialize + for<'a> Deserialize<'a> + ScopeModel +where + R: for<'a> Deserialize<'a>, { fn int_api_version() -> String; fn int_kind() -> String; + fn known_type(input: &ModelRoot) -> anyhow::Result> { + if Self::int_api_version().to_lowercase() == input.api_version.to_lowercase() + && Self::int_kind().to_lowercase() == input.kind.to_lowercase() + { + let value = serde_json::to_value(input)?; + return Ok(Some(serde_json::from_value::(value)?)); + } + Ok(None) + } + #[cfg(test)] fn examples() -> Vec; #[cfg(test)] fn create_and_validate( - schema_gen: &mut SchemaGenerator, + schema_gen: &mut schemars::gen::SchemaGenerator, out_dir: &str, merged_schema: &str, ) -> anyhow::Result<()> { @@ -65,15 +78,15 @@ pub trait InternalScopeModel: for example in Self::examples() { validate_schema::(&schema_json, &example)?; - validate_schema::(&merged_schema, &example)?; + validate_schema::(merged_schema, &example)?; } Ok(()) } } #[cfg(test)] -pub fn make_schema_generator() -> SchemaGenerator { - let settings = SchemaSettings::draft2019_09().with(|s| { +pub fn make_schema_generator() -> schemars::gen::SchemaGenerator { + let settings = schemars::gen::SchemaSettings::draft2019_09().with(|s| { s.option_nullable = true; }); settings.into_generator() @@ -100,9 +113,9 @@ where if let Err(err_iter) = compiled_schema.validate(&parsed_json) { println!("{}", serde_json::to_string_pretty(&parsed_json).unwrap()); for e in err_iter { - println!("error: {}", e.to_string()); + println!("error: {}", e); } - assert!(false); + unreachable!(); }; Ok(()) @@ -112,7 +125,7 @@ where mod schema_gen { use crate::v1alpha::prelude::*; use crate::InternalScopeModel; - use derive_builder::Builder; + use schemars::JsonSchema; use serde::{Deserialize, Serialize}; diff --git a/scope-models/src/v1alpha/doctor_group.rs b/scope-models/src/v1alpha/doctor_group.rs index ba84f12..5138983 100644 --- a/scope-models/src/v1alpha/doctor_group.rs +++ b/scope-models/src/v1alpha/doctor_group.rs @@ -1,6 +1,7 @@ use crate::core::ModelMetadata; -use crate::v1alpha::known_error::{KnownErrorKind, V1AlphaKnownError}; + use crate::v1alpha::V1AlphaApiVersion; +use crate::InternalScopeModel; use derive_builder::Builder; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; @@ -67,11 +68,11 @@ pub struct V1AlphaDoctorGroup { impl crate::ScopeModel for V1AlphaDoctorGroup { fn api_version(&self) -> String { - >::int_api_version() + Self::int_api_version() } fn kind(&self) -> String { - >::int_kind() + Self::int_kind() } fn metadata(&self) -> &ModelMetadata { @@ -83,7 +84,7 @@ impl crate::ScopeModel for V1AlphaDoctorGroup { } } -impl crate::InternalScopeModel for V1AlphaDoctorGroup { +impl InternalScopeModel for V1AlphaDoctorGroup { fn int_api_version() -> String { V1AlphaApiVersion::ScopeV1Alpha.to_string() } diff --git a/scope-models/src/v1alpha/known_error.rs b/scope-models/src/v1alpha/known_error.rs index ec5a990..e1d55d7 100644 --- a/scope-models/src/v1alpha/known_error.rs +++ b/scope-models/src/v1alpha/known_error.rs @@ -1,5 +1,6 @@ use crate::core::ModelMetadata; use crate::v1alpha::V1AlphaApiVersion; +use crate::InternalScopeModel; use derive_builder::Builder; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; @@ -30,11 +31,11 @@ pub struct V1AlphaKnownError { impl crate::ScopeModel for V1AlphaKnownError { fn api_version(&self) -> String { - >::int_api_version() + Self::int_api_version() } fn kind(&self) -> String { - >::int_kind() + Self::int_kind() } fn metadata(&self) -> &ModelMetadata { @@ -46,7 +47,7 @@ impl crate::ScopeModel for V1AlphaKnownError { } } -impl crate::InternalScopeModel for V1AlphaKnownError { +impl InternalScopeModel for V1AlphaKnownError { fn int_api_version() -> String { V1AlphaApiVersion::ScopeV1Alpha.to_string() } diff --git a/scope-models/src/v1alpha/report_definition.rs b/scope-models/src/v1alpha/report_definition.rs index 8166713..40ede3d 100644 --- a/scope-models/src/v1alpha/report_definition.rs +++ b/scope-models/src/v1alpha/report_definition.rs @@ -1,8 +1,9 @@ use crate::core::ModelMetadata; -use crate::v1alpha::prelude::{ReportLocationKind, V1AlphaReportLocation}; + use crate::v1alpha::V1AlphaApiVersion; use derive_builder::Builder; -use schemars::gen::SchemaGenerator; + +use crate::InternalScopeModel; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; use std::collections::BTreeMap; @@ -33,11 +34,11 @@ pub struct V1AlphaReportDefinition { impl crate::ScopeModel for V1AlphaReportDefinition { fn api_version(&self) -> String { - >::int_api_version() + Self::int_api_version() } fn kind(&self) -> String { - >::int_kind() + Self::int_kind() } fn metadata(&self) -> &ModelMetadata { @@ -49,7 +50,7 @@ impl crate::ScopeModel for V1AlphaReportDefinition { } } -impl crate::InternalScopeModel for V1AlphaReportDefinition { +impl InternalScopeModel for V1AlphaReportDefinition { fn int_api_version() -> String { V1AlphaApiVersion::ScopeV1Alpha.to_string() } diff --git a/scope-models/src/v1alpha/report_location.rs b/scope-models/src/v1alpha/report_location.rs index 7c84fc5..addb7a0 100644 --- a/scope-models/src/v1alpha/report_location.rs +++ b/scope-models/src/v1alpha/report_location.rs @@ -1,10 +1,10 @@ use crate::core::ModelMetadata; use crate::v1alpha::V1AlphaApiVersion; use derive_builder::Builder; -use schemars::gen::SchemaGenerator; + +use crate::InternalScopeModel; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; -use std::collections::BTreeMap; #[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema)] #[serde(rename_all = "camelCase")] @@ -48,11 +48,11 @@ pub struct V1AlphaReportLocation { impl crate::ScopeModel for V1AlphaReportLocation { fn api_version(&self) -> String { - >::int_api_version() + V1AlphaReportLocation::int_api_version() } fn kind(&self) -> String { - >::int_kind() + V1AlphaReportLocation::int_kind() } fn metadata(&self) -> &ModelMetadata { @@ -64,7 +64,7 @@ impl crate::ScopeModel for V1AlphaReportLocation { } } -impl crate::InternalScopeModel for V1AlphaReportLocation { +impl InternalScopeModel for V1AlphaReportLocation { fn int_api_version() -> String { V1AlphaApiVersion::ScopeV1Alpha.to_string() } diff --git a/scope/src/analyze/cli.rs b/scope/src/analyze/cli.rs index 3115563..5efcf27 100644 --- a/scope/src/analyze/cli.rs +++ b/scope/src/analyze/cli.rs @@ -1,5 +1,6 @@ use super::error::AnalyzeError; -use crate::shared::prelude::{FoundConfig, ScopeModel}; +use crate::prelude::HelpMetadata; +use crate::shared::prelude::FoundConfig; use anyhow::Result; use clap::{Args, Subcommand}; use std::collections::BTreeMap; @@ -62,9 +63,9 @@ where let mut known_errors_to_remove = Vec::new(); for (name, ke) in &known_errors { debug!("Checking known error {}", ke.name()); - if ke.spec.regex.is_match(&line) { + if ke.regex.is_match(&line) { warn!(target: "always", "Known error '{}' found on line {}", ke.name(), line_number); - info!(target: "always", "\t==> {}", ke.spec.help_text); + info!(target: "always", "\t==> {}", ke.help_text); known_errors_to_remove.push(name.clone()); has_known_error = true; } diff --git a/scope/src/bin/scope-intercept.rs b/scope/src/bin/scope-intercept.rs index 7c3a725..9df85d0 100644 --- a/scope/src/bin/scope-intercept.rs +++ b/scope/src/bin/scope-intercept.rs @@ -88,9 +88,9 @@ async fn run_command(opts: Cli) -> anyhow::Result { for known_error in found_config.known_error.values() { debug!("Checking known error {}", known_error.name()); - if known_error.spec.regex.is_match(&command_output) { + if known_error.regex.is_match(&command_output) { info!(target: "always", "Known error '{}' found", known_error.name()); - info!(target: "always", "\t==> {}", known_error.spec.help_text); + info!(target: "always", "\t==> {}", known_error.help_text); } } diff --git a/scope/src/doctor/check.rs b/scope/src/doctor/check.rs index cf98d73..b2b9e3c 100644 --- a/scope/src/doctor/check.rs +++ b/scope/src/doctor/check.rs @@ -7,6 +7,7 @@ use crate::shared::prelude::{ CaptureError, CaptureOpts, DoctorGroup, DoctorGroupAction, DoctorGroupActionCommand, DoctorGroupCachePath, ExecutionProvider, OutputDestination, }; +use crate::shared::HelpMetadata; use async_trait::async_trait; use derive_builder::Builder; use educe::Educe; @@ -195,7 +196,7 @@ impl DefaultDoctorActionRun { working_dir: &self.working_dir, args: &args, output_dest: OutputDestination::StandardOut, - path: &self.model.exec_path(), + path: &self.model.metadata.exec_path(), env_vars: Default::default(), }) .await?; @@ -257,7 +258,11 @@ impl DefaultDoctorActionRun { let mut result: Option = None; for command in &action_command.commands { let args = vec![command.clone()]; - let path = format!("{}:{}", self.model.containing_dir(), self.model.exec_path()); + let path = format!( + "{}:{}", + self.model.metadata().containing_dir(), + self.model.metadata().exec_path() + ); let output = self .exec_runner .run_command(CaptureOpts { diff --git a/scope/src/doctor/commands/run.rs b/scope/src/doctor/commands/run.rs index 8b5ee9b..386a63a 100644 --- a/scope/src/doctor/commands/run.rs +++ b/scope/src/doctor/commands/run.rs @@ -1,6 +1,6 @@ use crate::doctor::check::{DefaultDoctorActionRun, DefaultGlobWalker}; use crate::doctor::file_cache::{FileBasedCache, FileCache, NoOpCache}; -use crate::shared::prelude::{DefaultExecutionProvider, FoundConfig, ScopeModel}; +use crate::shared::prelude::{DefaultExecutionProvider, FoundConfig}; use anyhow::Result; use clap::Parser; use std::collections::{BTreeMap, BTreeSet}; diff --git a/scope/src/doctor/runner.rs b/scope/src/doctor/runner.rs index f988e6d..076c016 100644 --- a/scope/src/doctor/runner.rs +++ b/scope/src/doctor/runner.rs @@ -1,5 +1,5 @@ use super::check::{ActionRunResult, DoctorActionRun}; -use crate::shared::prelude::{DoctorGroup}; +use crate::shared::prelude::DoctorGroup; use anyhow::Result; use colored::Colorize; use petgraph::algo::all_simple_paths; diff --git a/scope/src/doctor/tests.rs b/scope/src/doctor/tests.rs index 679c4a9..95f38ae 100644 --- a/scope/src/doctor/tests.rs +++ b/scope/src/doctor/tests.rs @@ -1,29 +1,27 @@ -use crate::shared::prelude::{ - DoctorGroup, DoctorGroupAction, DoctorGroupBuilder, -}; +use crate::shared::prelude::{DoctorGroup, DoctorGroupAction, DoctorGroupBuilder}; +use dev_scope_model::prelude::{ModelMetadataAnnotations, ModelMetadataBuilder, ModelRootBuilder}; use std::collections::BTreeMap; -use dev_scope_model::prelude::{ModelMetadataBuilder, ModelRootBuilder}; -pub fn make_root_model_additional( +pub fn make_root_model_additional( actions: Vec, edit_meta: Meta, edit_group: Group, ) -> DoctorGroup where Meta: FnOnce(&mut ModelMetadataBuilder) -> &mut ModelMetadataBuilder, - Root: FnOnce(&mut ModelRootBuilder) -> &mut ModelRootBuilder, Group: FnOnce(&mut DoctorGroupBuilder) -> &mut DoctorGroupBuilder, { let mut binding = ModelMetadataBuilder::default(); let metadata_builder = binding .name("fake-name") - .annotations(BTreeMap::default()) + .annotations(ModelMetadataAnnotations::default()) .labels(BTreeMap::default()); let metadata = edit_meta(metadata_builder).build().unwrap(); let mut binding = DoctorGroupBuilder::default(); let group_builder = binding .description("a description") + .full_name("DoctorGroup/fake-name") .actions(actions) .metadata(metadata) .requires(Vec::new()); diff --git a/scope/src/shared/config_load.rs b/scope/src/shared/config_load.rs index df60021..3f3a176 100644 --- a/scope/src/shared/config_load.rs +++ b/scope/src/shared/config_load.rs @@ -1,13 +1,13 @@ +use crate::prelude::HelpMetadata; use crate::shared::models::prelude::{ DoctorGroup, KnownError, ParsedConfig, ReportDefinition, ReportUploadLocation, - -}; -use crate::shared::{ - RUN_ID_ENV_VAR, }; +use crate::shared::RUN_ID_ENV_VAR; use anyhow::{anyhow, Result}; use clap::{ArgGroup, Parser}; use colored::*; +use dev_scope_model::prelude::{ModelMetadata, ModelRoot}; +use dev_scope_model::ScopeModel; use directories::{BaseDirs, UserDirs}; use itertools::Itertools; use serde::Deserialize; @@ -18,8 +18,6 @@ use std::fs::{self, File}; use std::io::Write; use std::path::{Path, PathBuf}; use tracing::{debug, error, warn}; -use dev_scope_model::prelude::{ModelMetadata, ModelRoot}; -use dev_scope_model::ScopeModel; #[derive(Parser, Debug)] #[clap(group = ArgGroup::new("config"))] @@ -188,6 +186,7 @@ impl FoundConfig { self.report_definition .clone() .unwrap_or_else(|| ReportDefinition { + full_name: "ReportDefinition/generated".to_string(), metadata: ModelMetadata::new("generated"), template: "== Error report for {{ command }}.".to_string(), additional_data: Default::default(), @@ -209,17 +208,17 @@ impl FoundConfig { if self.report_definition.is_none() { self.report_definition.replace(report_definition); } else { - warn!(target: "user", "A ReportDefinition with duplicate name found, dropping ReportUpload {} in {}", report_definition.name(), report_definition.file_path()); + warn!(target: "user", "A ReportDefinition with duplicate name found, dropping ReportUpload {} in {}", report_definition.name(), report_definition.metadata().file_path()); } } } } } -fn insert_if_absent(map: &mut BTreeMap>, entry: ModelRoot) { +fn insert_if_absent(map: &mut BTreeMap, entry: T) { let name = entry.name(); - if map.contains_key(name) { - warn!(target: "user", "A {} with duplicate name found, dropping {} in {}", entry.kind().to_string().bold(), entry.name().bold(), entry.file_path()); + if map.contains_key(&name) { + warn!(target: "user", "Duplicate {} found, dropping {} in {}", entry.full_name().to_string().bold(), entry.name().bold(), entry.metadata().file_path()); } else { map.insert(name.to_string(), entry); } @@ -257,17 +256,12 @@ pub(crate) fn parse_model(doc: Deserializer, file_path: &Path) -> Option>(value) { Ok(mut value) => { - value.metadata.annotations.file_path = Some( - file_path.display().to_string(), - ); + value.metadata.annotations.file_path = Some(file_path.display().to_string()); - value.metadata.annotations.file_dir = Some( - file_path.parent().unwrap().display().to_string(), - ); + value.metadata.annotations.file_dir = + Some(file_path.parent().unwrap().display().to_string()); - value.metadata.annotations.bin_path( - build_exec_path(file_path), - ); + value.metadata.annotations.bin_path = Some(build_exec_path(file_path)); Some(value) } Err(e) => { diff --git a/scope/src/shared/mod.rs b/scope/src/shared/mod.rs index fcc9107..578bab9 100644 --- a/scope/src/shared/mod.rs +++ b/scope/src/shared/mod.rs @@ -1,9 +1,9 @@ use colored::Colorize; +use dev_scope_model::prelude::{ModelMetadata, ModelRoot}; +use dev_scope_model::ScopeModel; use std::cmp::max; use std::path::Path; use tracing::info; -use dev_scope_model::prelude::ModelRoot; -use dev_scope_model::ScopeModel; mod capture; mod config_load; @@ -17,8 +17,10 @@ pub const CONFIG_FILE_PATH_ENV: &str = "SCOPE_CONFIG_JSON"; pub const RUN_ID_ENV_VAR: &str = "SCOPE_RUN_ID"; pub trait HelpMetadata { - fn description(&self) -> &str; - fn name(&self) -> &str; + fn description(&self) -> String; + fn name(&self) -> String; + fn metadata(&self) -> &ModelMetadata; + fn full_name(&self) -> String; } pub mod prelude { @@ -54,7 +56,7 @@ where description = format!("{}...", description); } - let mut loc = check.file_path(); + let mut loc = check.metadata().file_path(); let diff_path = pathdiff::diff_paths(&loc, working_dir); if let Some(diff) = diff_path { loc = diff.display().to_string(); diff --git a/scope/src/shared/models/internal/doctor_group.rs b/scope/src/shared/models/internal/doctor_group.rs index b3cd4a1..9181a62 100644 --- a/scope/src/shared/models/internal/doctor_group.rs +++ b/scope/src/shared/models/internal/doctor_group.rs @@ -1,9 +1,9 @@ -use crate::shared::{HelpMetadata}; +use crate::shared::models::internal::extract_command_path; +use crate::shared::HelpMetadata; use derive_builder::Builder; -use std::path::{Path, PathBuf}; use dev_scope_model::prelude::{ModelMetadata, V1AlphaDoctorGroup}; use dev_scope_model::ScopeModel; -use crate::shared::models::internal::extract_command_path; +use std::path::{Path, PathBuf}; #[derive(Debug, PartialEq, Clone, Builder)] #[builder(setter(into))] @@ -113,6 +113,7 @@ where #[derive(Debug, PartialEq, Clone, Builder)] #[builder(setter(into))] pub struct DoctorGroup { + pub full_name: String, pub metadata: ModelMetadata, pub requires: Vec, pub description: String, @@ -120,23 +121,32 @@ pub struct DoctorGroup { } impl HelpMetadata for DoctorGroup { - fn description(&self) -> &str { - &self.description + fn description(&self) -> String { + self.description.to_string() + } + + fn name(&self) -> String { + self.metadata.name.to_string() } - fn name(&self) -> &str { - &self.metadata.name + fn metadata(&self) -> &ModelMetadata { + &self.metadata + } + + fn full_name(&self) -> String { + self.full_name.to_string() } } impl TryFrom for DoctorGroup { - type Error = anyhow::Error; fn try_from(model: V1AlphaDoctorGroup) -> Result { - let containing_dir = Path::new(&model.containing_dir()); + let binding = model.containing_dir(); + let containing_dir = Path::new(&binding); let mut actions: Vec<_> = Default::default(); - for (count, spec_action) in model.spec.actions.into_iter().enumerate() { + for (count, spec_action) in model.spec.actions.iter().enumerate() { + let spec_action = spec_action.clone(); let help_text = spec_action .fix .as_ref() @@ -161,7 +171,7 @@ impl TryFrom for DoctorGroup { command: spec_action .check .commands - .map(|commands| DoctorGroupActionCommand::from((&containing_dir, commands))), + .map(|commands| DoctorGroupActionCommand::from((containing_dir, commands))), files: spec_action.check.paths.map(|paths| DoctorGroupCachePath { paths, base_path: containing_dir.parent().unwrap().to_path_buf(), @@ -171,8 +181,12 @@ impl TryFrom for DoctorGroup { } Ok(DoctorGroup { + full_name: model.full_name(), metadata: model.metadata, - description: model.spec.description.unwrap_or_else(|| "default".to_string()), + description: model + .spec + .description + .unwrap_or_else(|| "default".to_string()), actions, requires: model.spec.needs, }) @@ -187,60 +201,71 @@ mod tests { DoctorGroupActionFix, }; use crate::shared::prelude::DoctorGroupCachePath; + use dev_scope_model::prelude::{ + ModelMetadata, ModelMetadataAnnotations, ModelMetadataAnnotationsBuilder, + ModelMetadataBuilder, + }; + use predicates::prelude::*; use std::path::Path; - use dev_scope_model::prelude::ModelMetadata; #[test] fn parse_group_1() { - let text = include_str!("examples/group-1.yaml"); + let test_file = format!("{}/examples/group-1.yaml", env!("CARGO_MANIFEST_DIR")); + let text = std::fs::read_to_string(test_file).unwrap(); let path = Path::new("/foo/bar/.scope/file.yaml"); - let configs = parse_models_from_string(path, text).unwrap(); + let configs = parse_models_from_string(path, &text).unwrap(); assert_eq!(1, configs.len()); + + let dg = configs[0].get_doctor_group().unwrap(); + assert_eq!("foo", dg.metadata.name); assert_eq!( - configs[0].get_doctor_group().unwrap(), - DoctorGroup { - metadata: ModelMetadata::new("group-1"), - requires: vec!["bar".to_string()], - description: "Check your shell for basic functionality".to_string(), - actions: vec![ - DoctorGroupAction { - name: "1".to_string(), - required: false, - description: "foo1".to_string(), - fix: DoctorGroupActionFix { - command: Some(DoctorGroupActionCommand::from(vec![ - "/foo/bar/.scope/fix1.sh" - ])), - help_text: Some( - "There is a good way to fix this, maybe...".to_string() - ), - help_url: Some("https://go.example.com/fixit".to_string()), - }, - check: DoctorGroupActionCheck { - command: Some(DoctorGroupActionCommand::from(vec![ - "/foo/bar/.scope/foo1.sh" - ])), - files: Some(DoctorGroupCachePath::from(( - "/foo/bar", - vec!["flig/bar/**/*"] - ))) - } - }, - DoctorGroupAction { - name: "2".to_string(), - required: true, - description: "foo2".to_string(), - fix: DoctorGroupActionFix { - command: None, - help_text: None, - help_url: None, - }, - check: DoctorGroupActionCheck { - command: Some(DoctorGroupActionCommand::from(vec!["sleep infinity"])), - files: Some(DoctorGroupCachePath::from(("/foo/bar", vec!["*/*.txt"]))) - } - } - ] + "/foo/bar/.scope/file.yaml", + dg.metadata.annotations.file_path.unwrap() + ); + assert_eq!("/foo/bar/.scope", dg.metadata.annotations.file_dir.unwrap()); + assert_eq!("ScopeDoctorGroup/foo", dg.full_name); + assert_eq!(vec!["bar"], dg.requires); + assert_eq!("Check your shell for basic functionality", dg.description); + + assert_eq!( + dg.actions[0], + DoctorGroupAction { + name: "1".to_string(), + required: false, + description: "foo1".to_string(), + fix: DoctorGroupActionFix { + command: Some(DoctorGroupActionCommand::from(vec![ + "/foo/bar/.scope/fix1.sh" + ])), + help_text: Some("There is a good way to fix this, maybe...".to_string()), + help_url: Some("https://go.example.com/fixit".to_string()), + }, + check: DoctorGroupActionCheck { + command: Some(DoctorGroupActionCommand::from(vec![ + "/foo/bar/.scope/foo1.sh" + ])), + files: Some(DoctorGroupCachePath::from(( + "/foo/bar", + vec!["flig/bar/**/*"] + ))) + } + } + ); + assert_eq!( + dg.actions[1], + DoctorGroupAction { + name: "2".to_string(), + required: true, + description: "foo2".to_string(), + fix: DoctorGroupActionFix { + command: None, + help_text: None, + help_url: None, + }, + check: DoctorGroupActionCheck { + command: Some(DoctorGroupActionCommand::from(vec!["sleep infinity"])), + files: Some(DoctorGroupCachePath::from(("/foo/bar", vec!["*/*.txt"]))) + } } ); } diff --git a/scope/src/shared/models/internal/known_error.rs b/scope/src/shared/models/internal/known_error.rs index b616be6..2f9a956 100644 --- a/scope/src/shared/models/internal/known_error.rs +++ b/scope/src/shared/models/internal/known_error.rs @@ -1,12 +1,14 @@ use crate::shared::HelpMetadata; use derivative::Derivative; -use regex::Regex; use dev_scope_model::prelude::{ModelMetadata, V1AlphaKnownError}; +use dev_scope_model::ScopeModel; +use regex::Regex; #[derive(Derivative)] #[derivative(PartialEq)] #[derive(Debug, Clone)] pub struct KnownError { + pub full_name: String, pub metadata: ModelMetadata, pub description: String, pub pattern: String, @@ -16,12 +18,19 @@ pub struct KnownError { } impl HelpMetadata for KnownError { - fn description(&self) -> &str { - &self.description + fn description(&self) -> String { + self.description.to_string() + } + fn name(&self) -> String { + self.metadata.name.to_string() } - fn name(&self) -> &str { - &self.metadata.name + fn metadata(&self) -> &ModelMetadata { + &self.metadata + } + + fn full_name(&self) -> String { + self.full_name.to_string() } } @@ -31,6 +40,7 @@ impl TryFrom for KnownError { fn try_from(value: V1AlphaKnownError) -> Result { let regex = Regex::new(&value.spec.pattern)?; Ok(KnownError { + full_name: value.full_name(), metadata: value.metadata, pattern: value.spec.pattern, regex, @@ -44,6 +54,7 @@ impl TryFrom for KnownError { mod tests { use crate::shared::models::parse_models_from_string; use crate::shared::models::prelude::KnownError; + use dev_scope_model::prelude::ModelMetadata; use regex::Regex; use std::path::Path; @@ -61,11 +72,12 @@ spec: let path = Path::new("/foo/bar/file.yaml"); let configs = parse_models_from_string(path, text).unwrap(); assert_eq!(1, configs.len()); - assert_eq!(configs[0].get_known_error_spec().unwrap(), KnownError { - description: "Check if the word error is in the logs".to_string(), - help_text: "The command had an error, try reading the logs around there to find out what happened.".to_string(), - pattern: "error".to_string(), - regex: Regex::new("error").unwrap() - }); + let model = configs[0].get_known_error_spec().unwrap(); + + assert_eq!("error-exists", model.metadata.name); + assert_eq!("ScopeKnownError/error-exists", model.full_name); + assert_eq!("Check if the word error is in the logs", model.description); + assert_eq!("The command had an error, try reading the logs around there to find out what happened.", model.help_text); + assert_eq!("error", model.pattern); } } diff --git a/scope/src/shared/models/internal/mod.rs b/scope/src/shared/models/internal/mod.rs index d46d658..567a026 100644 --- a/scope/src/shared/models/internal/mod.rs +++ b/scope/src/shared/models/internal/mod.rs @@ -1,7 +1,14 @@ -use std::collections::VecDeque; -use std::path::Path; use crate::shared::prelude::*; +use anyhow::anyhow; +use dev_scope_model::prelude::{ + ModelRoot, V1AlphaDoctorGroup, V1AlphaKnownError, V1AlphaReportDefinition, + V1AlphaReportLocation, +}; +use dev_scope_model::InternalScopeModel; +use path_clean::PathClean; use serde_yaml::Value; +use std::collections::VecDeque; +use std::path::Path; mod doctor_group; mod known_error; @@ -19,38 +26,38 @@ pub mod prelude { #[derive(Debug, PartialEq)] pub enum ParsedConfig { - KnownError(ModelRoot), - ReportUpload(ModelRoot), - ReportDefinition(ModelRoot), - DoctorGroup(ModelRoot), + KnownError(KnownError), + ReportUpload(ReportUploadLocation), + ReportDefinition(ReportDefinition), + DoctorGroup(DoctorGroup), } #[cfg(test)] impl ParsedConfig { pub fn get_report_upload_spec(&self) -> Option { match self { - ParsedConfig::ReportUpload(root) => Some(root.spec.clone()), + ParsedConfig::ReportUpload(root) => Some(root.clone()), _ => None, } } pub fn get_report_def_spec(&self) -> Option { match self { - ParsedConfig::ReportDefinition(root) => Some(root.spec.clone()), + ParsedConfig::ReportDefinition(root) => Some(root.clone()), _ => None, } } pub fn get_known_error_spec(&self) -> Option { match self { - ParsedConfig::KnownError(root) => Some(root.spec.clone()), + ParsedConfig::KnownError(root) => Some(root.clone()), _ => None, } } pub fn get_doctor_group(&self) -> Option { match self { - ParsedConfig::DoctorGroup(root) => Some(root.spec.clone()), + ParsedConfig::DoctorGroup(root) => Some(root.clone()), _ => None, } } @@ -60,7 +67,23 @@ impl TryFrom> for ParsedConfig { type Error = anyhow::Error; fn try_from(value: ModelRoot) -> Result { - ParsedConfig::try_from(&value) + if let Ok(Some(known)) = V1AlphaDoctorGroup::known_type(&value) { + return Ok(ParsedConfig::DoctorGroup(DoctorGroup::try_from(known)?)); + } + if let Ok(Some(known)) = V1AlphaKnownError::known_type(&value) { + return Ok(ParsedConfig::KnownError(KnownError::try_from(known)?)); + } + if let Ok(Some(known)) = V1AlphaReportLocation::known_type(&value) { + return Ok(ParsedConfig::ReportUpload(ReportUploadLocation::try_from( + known, + )?)); + } + if let Ok(Some(known)) = V1AlphaReportDefinition::known_type(&value) { + return Ok(ParsedConfig::ReportDefinition(ReportDefinition::try_from( + known, + )?)); + } + Err(anyhow!("Error was know a known type")) } } @@ -87,12 +110,12 @@ fn test_extract_command_path() { let base_path = Path::new("/foo/bar"); assert_eq!( "/foo/bar/scripts/foo.sh", - crate::shared::models::v1alpha::extract_command_path(base_path, "./scripts/foo.sh") + extract_command_path(base_path, "./scripts/foo.sh") ); assert_eq!( "/scripts/foo.sh", - crate::shared::models::v1alpha::extract_command_path(base_path, "/scripts/foo.sh") + extract_command_path(base_path, "/scripts/foo.sh") ); - assert_eq!("foo", crate::shared::models::v1alpha::extract_command_path(base_path, "foo")); - assert_eq!("foo bar", crate::shared::models::v1alpha::extract_command_path(base_path, "foo bar")); + assert_eq!("foo", extract_command_path(base_path, "foo")); + assert_eq!("foo bar", extract_command_path(base_path, "foo bar")); } diff --git a/scope/src/shared/models/internal/report_definition.rs b/scope/src/shared/models/internal/report_definition.rs index a077824..f2cd1be 100644 --- a/scope/src/shared/models/internal/report_definition.rs +++ b/scope/src/shared/models/internal/report_definition.rs @@ -1,18 +1,40 @@ -use std::collections::BTreeMap; +use crate::prelude::{HelpMetadata, KnownError}; use dev_scope_model::prelude::{ModelMetadata, V1AlphaReportDefinition}; +use dev_scope_model::ScopeModel; +use std::collections::BTreeMap; #[derive(Debug, PartialEq, Clone)] pub struct ReportDefinition { + pub full_name: String, pub metadata: ModelMetadata, pub additional_data: BTreeMap, pub template: String, } +impl HelpMetadata for ReportDefinition { + fn description(&self) -> String { + format!("Create a template of an error for {}", self.metadata.name) + } + + fn name(&self) -> String { + self.metadata.name.to_string() + } + + fn metadata(&self) -> &ModelMetadata { + &self.metadata + } + + fn full_name(&self) -> String { + self.full_name.to_string() + } +} + impl TryFrom for ReportDefinition { type Error = anyhow::Error; fn try_from(value: V1AlphaReportDefinition) -> Result { Ok(ReportDefinition { + full_name: value.full_name(), metadata: value.metadata, template: value.spec.template.trim().to_string(), additional_data: value.spec.additional_data, @@ -22,8 +44,10 @@ impl TryFrom for ReportDefinition { #[cfg(test)] mod tests { + use std::collections::BTreeMap; use crate::shared::models::parse_models_from_string; use crate::shared::models::prelude::ReportDefinition; + use dev_scope_model::prelude::ModelMetadata; use std::path::Path; #[test] @@ -44,13 +68,14 @@ spec: let path = Path::new("/foo/bar/file.yaml"); let configs = parse_models_from_string(path, text).unwrap(); assert_eq!(1, configs.len()); + let model = configs[0].get_report_def_spec().unwrap(); + + assert_eq!("ScopeReportDefinition/report", model.full_name); + assert_eq!("report", model.metadata.name()); + assert_eq!("/foo/bar/file.yaml", model.metadata.annotations.file_path.unwrap()); + assert_eq!("hello bob", model.template); - assert_eq!( - configs[0].get_report_def_spec().unwrap(), - ReportDefinition { - template: "hello bob".to_string(), - additional_data: [("env".to_string(), "env".to_string())].into() - } - ); + let additional_data: BTreeMap = [("env".to_string(), "env".to_string())].into(); + assert_eq!(additional_data, model.additional_data); } -} \ No newline at end of file +} diff --git a/scope/src/shared/models/internal/upload_location.rs b/scope/src/shared/models/internal/upload_location.rs index aeb430c..47997d5 100644 --- a/scope/src/shared/models/internal/upload_location.rs +++ b/scope/src/shared/models/internal/upload_location.rs @@ -1,4 +1,6 @@ +use crate::prelude::{HelpMetadata, ReportDefinition}; use dev_scope_model::prelude::{ModelMetadata, V1AlphaReportLocation}; +use dev_scope_model::ScopeModel; #[derive(Debug, PartialEq, Clone)] pub enum ReportUploadLocationDestination { @@ -14,25 +16,50 @@ pub enum ReportUploadLocationDestination { #[derive(Debug, PartialEq, Clone)] pub struct ReportUploadLocation { pub metadata: ModelMetadata, + pub full_name: String, pub destination: ReportUploadLocationDestination, } +impl HelpMetadata for ReportUploadLocation { + fn description(&self) -> String { + format!("Upload resource {}", self.metadata.name) + } + + fn name(&self) -> String { + self.metadata.name.to_string() + } + + fn metadata(&self) -> &ModelMetadata { + &self.metadata + } + + fn full_name(&self) -> String { + self.full_name.to_string() + } +} + impl TryFrom for ReportUploadLocation { type Error = anyhow::Error; fn try_from(value: V1AlphaReportLocation) -> Result { let destination = match value.spec.destination { - dev_scope_model::prelude::ReportDestinationSpec::RustyPaste { url } => { - ReportUploadLocationDestination::RustyPaste { url } + dev_scope_model::prelude::ReportDestinationSpec::RustyPaste { ref url } => { + ReportUploadLocationDestination::RustyPaste { + url: url.to_string(), + } } - dev_scope_model::prelude::ReportDestinationSpec::GithubIssue(github_issue) => { + dev_scope_model::prelude::ReportDestinationSpec::GithubIssue(ref github_issue) => { ReportUploadLocationDestination::GithubIssue { - owner: github_issue.owner, - repo: github_issue.repo, - tags: github_issue.tags, + owner: github_issue.owner.to_string(), + repo: github_issue.repo.to_string(), + tags: github_issue.tags.clone(), } } }; - Ok(ReportUploadLocation { metadata: value.metadata, destination }) + Ok(ReportUploadLocation { + full_name: value.full_name(), + metadata: value.metadata, + destination, + }) } } diff --git a/scope/src/shared/models/mod.rs b/scope/src/shared/models/mod.rs index 55ab7fd..28d645e 100644 --- a/scope/src/shared/models/mod.rs +++ b/scope/src/shared/models/mod.rs @@ -3,8 +3,10 @@ use anyhow::anyhow; use serde::{Deserialize, Serialize}; use serde_yaml::Value; use std::collections::BTreeMap; +use std::path::Path; use derive_builder::Builder; +use dev_scope_model::prelude::ModelRoot; use strum::EnumString; mod internal; @@ -13,3 +15,19 @@ pub mod prelude { pub use super::internal::prelude::*; } +#[cfg(test)] +pub(crate) fn parse_models_from_string( + file_path: &std::path::Path, + input: &str, +) -> anyhow::Result> { + use serde_yaml::Deserializer; + + let mut models = Vec::new(); + for doc in Deserializer::from_str(input) { + if let Some(parsed_model) = crate::shared::config_load::parse_model(doc, file_path) { + models.push(parsed_model.try_into()?) + } + } + + Ok(models) +} diff --git a/scope/src/shared/report.rs b/scope/src/shared/report.rs index 117f9de..0cbf0b8 100644 --- a/scope/src/shared/report.rs +++ b/scope/src/shared/report.rs @@ -1,6 +1,6 @@ use super::capture::{CaptureOpts, OutputCapture}; use super::config_load::FoundConfig; -use super::models::prelude::{ReportUploadLocationDestination, ScopeModel}; +use super::models::prelude::ReportUploadLocationDestination; use super::prelude::OutputDestination; use anyhow::{anyhow, Result}; use minijinja::{context, Environment}; From 8003986f3bb7e404dd5b3a64b4014b9e2a2eab2c Mon Sep 17 00:00:00 2001 From: Ethan Hall Date: Sun, 3 Mar 2024 14:17:59 -0800 Subject: [PATCH 03/14] fmt and fix --- scope/src/doctor/tests.rs | 2 +- scope/src/shared/config_load.rs | 1 - scope/src/shared/mod.rs | 3 +-- scope/src/shared/models/internal/doctor_group.rs | 9 ++------- scope/src/shared/models/internal/known_error.rs | 4 +--- .../shared/models/internal/report_definition.rs | 15 +++++++++------ .../src/shared/models/internal/upload_location.rs | 2 +- scope/src/shared/models/mod.rs | 13 +------------ 8 files changed, 16 insertions(+), 33 deletions(-) diff --git a/scope/src/doctor/tests.rs b/scope/src/doctor/tests.rs index 95f38ae..968df7c 100644 --- a/scope/src/doctor/tests.rs +++ b/scope/src/doctor/tests.rs @@ -1,5 +1,5 @@ use crate::shared::prelude::{DoctorGroup, DoctorGroupAction, DoctorGroupBuilder}; -use dev_scope_model::prelude::{ModelMetadataAnnotations, ModelMetadataBuilder, ModelRootBuilder}; +use dev_scope_model::prelude::{ModelMetadataAnnotations, ModelMetadataBuilder}; use std::collections::BTreeMap; pub fn make_root_model_additional( diff --git a/scope/src/shared/config_load.rs b/scope/src/shared/config_load.rs index 3f3a176..b4f5d6e 100644 --- a/scope/src/shared/config_load.rs +++ b/scope/src/shared/config_load.rs @@ -7,7 +7,6 @@ use anyhow::{anyhow, Result}; use clap::{ArgGroup, Parser}; use colored::*; use dev_scope_model::prelude::{ModelMetadata, ModelRoot}; -use dev_scope_model::ScopeModel; use directories::{BaseDirs, UserDirs}; use itertools::Itertools; use serde::Deserialize; diff --git a/scope/src/shared/mod.rs b/scope/src/shared/mod.rs index 578bab9..e15557e 100644 --- a/scope/src/shared/mod.rs +++ b/scope/src/shared/mod.rs @@ -1,6 +1,5 @@ use colored::Colorize; -use dev_scope_model::prelude::{ModelMetadata, ModelRoot}; -use dev_scope_model::ScopeModel; +use dev_scope_model::prelude::ModelMetadata; use std::cmp::max; use std::path::Path; use tracing::info; diff --git a/scope/src/shared/models/internal/doctor_group.rs b/scope/src/shared/models/internal/doctor_group.rs index 9181a62..785326c 100644 --- a/scope/src/shared/models/internal/doctor_group.rs +++ b/scope/src/shared/models/internal/doctor_group.rs @@ -197,15 +197,10 @@ impl TryFrom for DoctorGroup { mod tests { use crate::shared::models::parse_models_from_string; use crate::shared::models::prelude::{ - DoctorGroup, DoctorGroupAction, DoctorGroupActionCheck, DoctorGroupActionCommand, - DoctorGroupActionFix, + DoctorGroupAction, DoctorGroupActionCheck, DoctorGroupActionCommand, DoctorGroupActionFix, }; use crate::shared::prelude::DoctorGroupCachePath; - use dev_scope_model::prelude::{ - ModelMetadata, ModelMetadataAnnotations, ModelMetadataAnnotationsBuilder, - ModelMetadataBuilder, - }; - use predicates::prelude::*; + use std::path::Path; #[test] diff --git a/scope/src/shared/models/internal/known_error.rs b/scope/src/shared/models/internal/known_error.rs index 2f9a956..b442c87 100644 --- a/scope/src/shared/models/internal/known_error.rs +++ b/scope/src/shared/models/internal/known_error.rs @@ -53,9 +53,7 @@ impl TryFrom for KnownError { #[cfg(test)] mod tests { use crate::shared::models::parse_models_from_string; - use crate::shared::models::prelude::KnownError; - use dev_scope_model::prelude::ModelMetadata; - use regex::Regex; + use std::path::Path; #[test] diff --git a/scope/src/shared/models/internal/report_definition.rs b/scope/src/shared/models/internal/report_definition.rs index f2cd1be..d954a8e 100644 --- a/scope/src/shared/models/internal/report_definition.rs +++ b/scope/src/shared/models/internal/report_definition.rs @@ -1,4 +1,4 @@ -use crate::prelude::{HelpMetadata, KnownError}; +use crate::prelude::HelpMetadata; use dev_scope_model::prelude::{ModelMetadata, V1AlphaReportDefinition}; use dev_scope_model::ScopeModel; use std::collections::BTreeMap; @@ -44,10 +44,9 @@ impl TryFrom for ReportDefinition { #[cfg(test)] mod tests { - use std::collections::BTreeMap; use crate::shared::models::parse_models_from_string; - use crate::shared::models::prelude::ReportDefinition; - use dev_scope_model::prelude::ModelMetadata; + use std::collections::BTreeMap; + use std::path::Path; #[test] @@ -72,10 +71,14 @@ spec: assert_eq!("ScopeReportDefinition/report", model.full_name); assert_eq!("report", model.metadata.name()); - assert_eq!("/foo/bar/file.yaml", model.metadata.annotations.file_path.unwrap()); + assert_eq!( + "/foo/bar/file.yaml", + model.metadata.annotations.file_path.unwrap() + ); assert_eq!("hello bob", model.template); - let additional_data: BTreeMap = [("env".to_string(), "env".to_string())].into(); + let additional_data: BTreeMap = + [("env".to_string(), "env".to_string())].into(); assert_eq!(additional_data, model.additional_data); } } diff --git a/scope/src/shared/models/internal/upload_location.rs b/scope/src/shared/models/internal/upload_location.rs index 47997d5..11b83be 100644 --- a/scope/src/shared/models/internal/upload_location.rs +++ b/scope/src/shared/models/internal/upload_location.rs @@ -1,4 +1,4 @@ -use crate::prelude::{HelpMetadata, ReportDefinition}; +use crate::prelude::HelpMetadata; use dev_scope_model::prelude::{ModelMetadata, V1AlphaReportLocation}; use dev_scope_model::ScopeModel; diff --git a/scope/src/shared/models/mod.rs b/scope/src/shared/models/mod.rs index 28d645e..92125cf 100644 --- a/scope/src/shared/models/mod.rs +++ b/scope/src/shared/models/mod.rs @@ -1,14 +1,3 @@ -use crate::shared::models::internal::ParsedConfig; -use anyhow::anyhow; -use serde::{Deserialize, Serialize}; -use serde_yaml::Value; -use std::collections::BTreeMap; -use std::path::Path; - -use derive_builder::Builder; -use dev_scope_model::prelude::ModelRoot; -use strum::EnumString; - mod internal; pub mod prelude { @@ -19,7 +8,7 @@ pub mod prelude { pub(crate) fn parse_models_from_string( file_path: &std::path::Path, input: &str, -) -> anyhow::Result> { +) -> anyhow::Result> { use serde_yaml::Deserializer; let mut models = Vec::new(); From 10586b6876bd3bd2dce93bb9927a51bbf96a4633 Mon Sep 17 00:00:00 2001 From: Ethan Hall Date: Sun, 3 Mar 2024 15:51:44 -0800 Subject: [PATCH 04/14] move description to metadata --- .../.scope/doctor-check-fix-in-scope.yaml | 2 +- examples/.scope/doctor-check-path-exists.yaml | 2 +- examples/.scope/doctor-group-1.yaml | 2 +- examples/.scope/doctor-setup.yaml | 2 +- examples/.scope/known-error.yaml | 2 +- scope-models/src/core.rs | 27 +++++++++++++--- scope-models/src/lib.rs | 18 ++++++----- scope-models/src/v1alpha/doctor_group.rs | 19 +++++++----- scope-models/src/v1alpha/known_error.rs | 19 +++++++----- scope-models/src/v1alpha/report_definition.rs | 18 +++++++---- scope-models/src/v1alpha/report_location.rs | 18 +++++++---- scope/src/analyze/cli.rs | 2 +- scope/src/bin/scope.rs | 31 +++---------------- scope/src/doctor/check.rs | 2 +- scope/src/doctor/commands/list.rs | 8 ++--- scope/src/shared/config_load.rs | 8 +++-- scope/src/shared/mod.rs | 27 +++++++--------- .../shared/models/internal/doctor_group.rs | 17 +--------- .../src/shared/models/internal/known_error.rs | 13 +------- .../models/internal/report_definition.rs | 11 +------ .../shared/models/internal/upload_location.rs | 11 +------ 21 files changed, 118 insertions(+), 141 deletions(-) diff --git a/examples/.scope/doctor-check-fix-in-scope.yaml b/examples/.scope/doctor-check-fix-in-scope.yaml index 674aa93..20a64f0 100644 --- a/examples/.scope/doctor-check-fix-in-scope.yaml +++ b/examples/.scope/doctor-check-fix-in-scope.yaml @@ -2,10 +2,10 @@ apiVersion: scope.github.com/v1alpha kind: ScopeDoctorCheck metadata: name: path-exists-fix-in-scope-dir + description: Check your shell for basic functionality spec: check: target: ./scripts/fail-first-call path-exists-fix-in-scope-dir fix: target: ./scripts/truey - description: Check your shell for basic functionality help: You're shell does not have a path env. Reload your shell. diff --git a/examples/.scope/doctor-check-path-exists.yaml b/examples/.scope/doctor-check-path-exists.yaml index a466f57..924cbf2 100644 --- a/examples/.scope/doctor-check-path-exists.yaml +++ b/examples/.scope/doctor-check-path-exists.yaml @@ -2,10 +2,10 @@ apiVersion: scope.github.com/v1alpha kind: ScopeDoctorCheck metadata: name: path-exists + description: Check your shell for basic functionality spec: check: target: ./scripts/fail-first-call path-exists fix: target: ../bin/truey - description: Check your shell for basic functionality help: You're shell does not have a path env. Reload your shell. diff --git a/examples/.scope/doctor-group-1.yaml b/examples/.scope/doctor-group-1.yaml index 64cfbe5..ec68519 100644 --- a/examples/.scope/doctor-group-1.yaml +++ b/examples/.scope/doctor-group-1.yaml @@ -2,8 +2,8 @@ apiVersion: scope.github.com/v1alpha kind: ScopeDoctorGroup metadata: name: group-1 -spec: description: Check your shell for basic functionality +spec: actions: - description: foo1 check: diff --git a/examples/.scope/doctor-setup.yaml b/examples/.scope/doctor-setup.yaml index 8295199..97a6b39 100644 --- a/examples/.scope/doctor-setup.yaml +++ b/examples/.scope/doctor-setup.yaml @@ -2,6 +2,7 @@ apiVersion: scope.github.com/v1alpha kind: ScopeDoctorSetup metadata: name: setup + description: You need to run bin/setup spec: cache: paths: @@ -9,4 +10,3 @@ spec: setup: exec: - ../bin/pip-install.sh - description: You need to run bin/setup \ No newline at end of file diff --git a/examples/.scope/known-error.yaml b/examples/.scope/known-error.yaml index f12dee7..0fcf1d7 100644 --- a/examples/.scope/known-error.yaml +++ b/examples/.scope/known-error.yaml @@ -2,7 +2,7 @@ apiVersion: scope.github.com/v1alpha kind: ScopeKnownError metadata: name: error-exists -spec: description: Check if the word error is in the logs +spec: pattern: error help: The command had an error, try reading the logs around there to find out what happened. \ No newline at end of file diff --git a/scope-models/src/core.rs b/scope-models/src/core.rs index 7fedc34..60cdccb 100644 --- a/scope-models/src/core.rs +++ b/scope-models/src/core.rs @@ -1,3 +1,4 @@ +use crate::{HelpMetadata, ScopeModel}; use derive_builder::Builder; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; @@ -24,6 +25,10 @@ impl ModelMetadata { self.name.to_string() } + pub fn description(&self) -> String { + self.description.to_string() + } + pub fn file_path(&self) -> String { match &self.annotations.file_path { Some(v) => v.to_string(), @@ -63,12 +68,18 @@ impl ModelMetadata { #[builder(setter(into))] pub struct ModelMetadata { pub name: String, + #[serde(default = "default_description")] + pub description: String, #[serde(default)] pub annotations: ModelMetadataAnnotations, #[serde(default)] pub labels: BTreeMap, } +fn default_description() -> String { + "Description not provided".to_string() +} + #[derive(Serialize, Deserialize, Debug, PartialEq, Clone, Builder)] #[builder(setter(into))] #[serde(rename_all = "camelCase")] @@ -79,7 +90,17 @@ pub struct ModelRoot { pub spec: V, } -impl crate::ScopeModel for ModelRoot { +impl HelpMetadata for ModelRoot { + fn metadata(&self) -> &ModelMetadata { + &self.metadata + } + + fn full_name(&self) -> String { + format!("{}/{}", self.kind, self.name()) + } +} + +impl ScopeModel for ModelRoot { fn api_version(&self) -> String { self.api_version.to_string() } @@ -88,10 +109,6 @@ impl crate::ScopeModel for ModelRoot { self.kind.to_string() } - fn metadata(&self) -> &ModelMetadata { - &self.metadata - } - fn spec(&self) -> &S { &self.spec } diff --git a/scope-models/src/lib.rs b/scope-models/src/lib.rs index 6bd5a8b..d184db0 100644 --- a/scope-models/src/lib.rs +++ b/scope-models/src/lib.rs @@ -10,14 +10,13 @@ mod v1alpha; pub mod prelude { pub use crate::core::*; pub use crate::v1alpha::prelude::*; + pub use crate::HelpMetadata; pub use crate::ScopeModel; } -pub trait ScopeModel { - fn api_version(&self) -> String; - fn kind(&self) -> String; +pub trait HelpMetadata { fn metadata(&self) -> &ModelMetadata; - fn spec(&self) -> &S; + fn full_name(&self) -> String; fn name(&self) -> &str { &self.metadata().name } @@ -27,15 +26,20 @@ pub trait ScopeModel { fn containing_dir(&self) -> String { self.metadata().containing_dir() } - fn exec_path(&self) -> String { self.metadata().exec_path() } - fn full_name(&self) -> String { - format!("{}/{}", self.kind(), self.name()) + fn description(&self) -> String { + self.metadata().description() } } +pub trait ScopeModel: HelpMetadata { + fn api_version(&self) -> String; + fn kind(&self) -> String; + fn spec(&self) -> &S; +} + pub trait InternalScopeModel: JsonSchema + Serialize + for<'a> Deserialize<'a> + ScopeModel where diff --git a/scope-models/src/v1alpha/doctor_group.rs b/scope-models/src/v1alpha/doctor_group.rs index 5138983..b68d368 100644 --- a/scope-models/src/v1alpha/doctor_group.rs +++ b/scope-models/src/v1alpha/doctor_group.rs @@ -1,7 +1,7 @@ use crate::core::ModelMetadata; use crate::v1alpha::V1AlphaApiVersion; -use crate::InternalScopeModel; +use crate::{HelpMetadata, InternalScopeModel, ScopeModel}; use derive_builder::Builder; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; @@ -46,7 +46,6 @@ fn doctor_group_action_required_default() -> bool { pub struct DoctorGroupSpec { #[serde(default)] pub needs: Vec, - pub description: Option, pub actions: Vec, } @@ -66,7 +65,17 @@ pub struct V1AlphaDoctorGroup { pub spec: DoctorGroupSpec, } -impl crate::ScopeModel for V1AlphaDoctorGroup { +impl HelpMetadata for V1AlphaDoctorGroup { + fn metadata(&self) -> &ModelMetadata { + &self.metadata + } + + fn full_name(&self) -> String { + format!("{}/{}", self.kind(), self.name()) + } +} + +impl ScopeModel for V1AlphaDoctorGroup { fn api_version(&self) -> String { Self::int_api_version() } @@ -75,10 +84,6 @@ impl crate::ScopeModel for V1AlphaDoctorGroup { Self::int_kind() } - fn metadata(&self) -> &ModelMetadata { - &self.metadata - } - fn spec(&self) -> &DoctorGroupSpec { &self.spec } diff --git a/scope-models/src/v1alpha/known_error.rs b/scope-models/src/v1alpha/known_error.rs index e1d55d7..8c88417 100644 --- a/scope-models/src/v1alpha/known_error.rs +++ b/scope-models/src/v1alpha/known_error.rs @@ -1,6 +1,6 @@ use crate::core::ModelMetadata; use crate::v1alpha::V1AlphaApiVersion; -use crate::InternalScopeModel; +use crate::{HelpMetadata, InternalScopeModel, ScopeModel}; use derive_builder::Builder; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; @@ -8,7 +8,6 @@ use serde::{Deserialize, Serialize}; #[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema)] #[serde(rename_all = "camelCase")] pub struct KnownErrorSpec { - pub description: String, pub help: String, pub pattern: String, } @@ -29,7 +28,17 @@ pub struct V1AlphaKnownError { pub spec: KnownErrorSpec, } -impl crate::ScopeModel for V1AlphaKnownError { +impl HelpMetadata for V1AlphaKnownError { + fn metadata(&self) -> &ModelMetadata { + &self.metadata + } + + fn full_name(&self) -> String { + format!("{}/{}", self.kind(), self.name()) + } +} + +impl ScopeModel for V1AlphaKnownError { fn api_version(&self) -> String { Self::int_api_version() } @@ -38,10 +47,6 @@ impl crate::ScopeModel for V1AlphaKnownError { Self::int_kind() } - fn metadata(&self) -> &ModelMetadata { - &self.metadata - } - fn spec(&self) -> &KnownErrorSpec { &self.spec } diff --git a/scope-models/src/v1alpha/report_definition.rs b/scope-models/src/v1alpha/report_definition.rs index 40ede3d..30608c6 100644 --- a/scope-models/src/v1alpha/report_definition.rs +++ b/scope-models/src/v1alpha/report_definition.rs @@ -3,7 +3,7 @@ use crate::core::ModelMetadata; use crate::v1alpha::V1AlphaApiVersion; use derive_builder::Builder; -use crate::InternalScopeModel; +use crate::{HelpMetadata, InternalScopeModel, ScopeModel}; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; use std::collections::BTreeMap; @@ -32,7 +32,17 @@ pub struct V1AlphaReportDefinition { pub spec: ReportDefinitionSpec, } -impl crate::ScopeModel for V1AlphaReportDefinition { +impl HelpMetadata for V1AlphaReportDefinition { + fn metadata(&self) -> &ModelMetadata { + &self.metadata + } + + fn full_name(&self) -> String { + format!("{}/{}", self.kind(), self.name()) + } +} + +impl ScopeModel for V1AlphaReportDefinition { fn api_version(&self) -> String { Self::int_api_version() } @@ -41,10 +51,6 @@ impl crate::ScopeModel for V1AlphaReportDefinition { Self::int_kind() } - fn metadata(&self) -> &ModelMetadata { - &self.metadata - } - fn spec(&self) -> &ReportDefinitionSpec { &self.spec } diff --git a/scope-models/src/v1alpha/report_location.rs b/scope-models/src/v1alpha/report_location.rs index addb7a0..a79627b 100644 --- a/scope-models/src/v1alpha/report_location.rs +++ b/scope-models/src/v1alpha/report_location.rs @@ -2,7 +2,7 @@ use crate::core::ModelMetadata; use crate::v1alpha::V1AlphaApiVersion; use derive_builder::Builder; -use crate::InternalScopeModel; +use crate::{HelpMetadata, InternalScopeModel, ScopeModel}; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; @@ -46,7 +46,17 @@ pub struct V1AlphaReportLocation { pub spec: ReportLocationSpec, } -impl crate::ScopeModel for V1AlphaReportLocation { +impl HelpMetadata for V1AlphaReportLocation { + fn metadata(&self) -> &ModelMetadata { + &self.metadata + } + + fn full_name(&self) -> String { + format!("{}/{}", self.kind(), self.name()) + } +} + +impl ScopeModel for V1AlphaReportLocation { fn api_version(&self) -> String { V1AlphaReportLocation::int_api_version() } @@ -55,10 +65,6 @@ impl crate::ScopeModel for V1AlphaReportLocation { V1AlphaReportLocation::int_kind() } - fn metadata(&self) -> &ModelMetadata { - &self.metadata - } - fn spec(&self) -> &ReportLocationSpec { &self.spec } diff --git a/scope/src/analyze/cli.rs b/scope/src/analyze/cli.rs index 5efcf27..d3a9366 100644 --- a/scope/src/analyze/cli.rs +++ b/scope/src/analyze/cli.rs @@ -1,8 +1,8 @@ use super::error::AnalyzeError; -use crate::prelude::HelpMetadata; use crate::shared::prelude::FoundConfig; use anyhow::Result; use clap::{Args, Subcommand}; +use dev_scope_model::HelpMetadata; use std::collections::BTreeMap; use std::path::PathBuf; use tokio::fs::File; diff --git a/scope/src/bin/scope.rs b/scope/src/bin/scope.rs index 8f3b67c..32aa611 100644 --- a/scope/src/bin/scope.rs +++ b/scope/src/bin/scope.rs @@ -141,30 +141,10 @@ lazy_static! { } fn show_config(found_config: &FoundConfig) -> Result<()> { - let mut extra_line = false; - if !found_config.doctor_group.is_empty() { - info!(target: "user", "Doctor Checks"); - let order = generate_doctor_list(found_config); - print_details(&found_config.working_dir, order); - extra_line = true; - } - - if !found_config.known_error.is_empty() { - if extra_line { - info!(target: "user", ""); - } + info!(target: "user", "Found Resources"); + print_details(&found_config.working_dir, &found_config.raw_config); - info!(target: "user", "Known Errors"); - print_details( - &found_config.working_dir, - found_config.known_error.values().collect(), - ); - extra_line = true; - } - - if extra_line { - info!(target: "user", ""); - } + info!(target: "user", ""); info!(target: "user", "Commands"); print_commands(found_config); Ok(()) @@ -195,11 +175,10 @@ fn print_commands(found_config: &FoundConfig) { let mut command_names: Vec<_> = command_map.keys().collect(); command_names.sort(); - info!(target: "user", "{:^20}{:^60}", "Name".white().bold(), "Description".white().bold()); - info!(target: "user", "{:^80}", str::repeat("-", 80)); + info!(target: "user", " {:20}{:60}", "Name".white().bold(), "Description".white().bold()); for command_name in command_names { let description = command_map.get(command_name.as_str()).unwrap(); - info!(target: "user", "{:^20} {:^60}", command_name.white().bold(), description); + info!(target: "user", "- {:20}{:60}", command_name, description); } } } diff --git a/scope/src/doctor/check.rs b/scope/src/doctor/check.rs index b2b9e3c..ebdcc13 100644 --- a/scope/src/doctor/check.rs +++ b/scope/src/doctor/check.rs @@ -7,9 +7,9 @@ use crate::shared::prelude::{ CaptureError, CaptureOpts, DoctorGroup, DoctorGroupAction, DoctorGroupActionCommand, DoctorGroupCachePath, ExecutionProvider, OutputDestination, }; -use crate::shared::HelpMetadata; use async_trait::async_trait; use derive_builder::Builder; +use dev_scope_model::HelpMetadata; use educe::Educe; use mockall::automock; use std::path::{Path, PathBuf}; diff --git a/scope/src/doctor/commands/list.rs b/scope/src/doctor/commands/list.rs index 33551ec..f129f08 100644 --- a/scope/src/doctor/commands/list.rs +++ b/scope/src/doctor/commands/list.rs @@ -11,12 +11,12 @@ pub struct DoctorListArgs {} pub async fn doctor_list(found_config: &FoundConfig, _args: &DoctorListArgs) -> Result<()> { info!(target: "user", "Available checks that will run"); - let order = generate_doctor_list(found_config); - print_details(&found_config.working_dir, order); + let order = generate_doctor_list(found_config).clone(); + print_details(&found_config.working_dir, &order); Ok(()) } -pub fn generate_doctor_list(found_config: &FoundConfig) -> Vec<&DoctorGroup> { +pub fn generate_doctor_list(found_config: &FoundConfig) -> Vec { let all_keys = BTreeSet::from_iter(found_config.doctor_group.keys().map(|x| x.to_string())); let all_paths = compute_group_order(&found_config.doctor_group, all_keys); @@ -31,6 +31,6 @@ pub fn generate_doctor_list(found_config: &FoundConfig) -> Vec<&DoctorGroup> { group_order .iter() - .map(|name| found_config.doctor_group.get(name).unwrap()) + .map(|name| found_config.doctor_group.get(name).unwrap().clone()) .collect() } diff --git a/scope/src/shared/config_load.rs b/scope/src/shared/config_load.rs index b4f5d6e..e3bf47c 100644 --- a/scope/src/shared/config_load.rs +++ b/scope/src/shared/config_load.rs @@ -1,4 +1,3 @@ -use crate::prelude::HelpMetadata; use crate::shared::models::prelude::{ DoctorGroup, KnownError, ParsedConfig, ReportDefinition, ReportUploadLocation, }; @@ -7,10 +6,12 @@ use anyhow::{anyhow, Result}; use clap::{ArgGroup, Parser}; use colored::*; use dev_scope_model::prelude::{ModelMetadata, ModelRoot}; +use dev_scope_model::{HelpMetadata, ScopeModel}; use directories::{BaseDirs, UserDirs}; use itertools::Itertools; use serde::Deserialize; use serde_yaml::{Deserializer, Value}; +use std::borrow::Cow; use std::collections::BTreeMap; use std::ffi::OsStr; use std::fs::{self, File}; @@ -141,7 +142,8 @@ impl FoundConfig { .map(|x| x.join("bin").display().to_string()) .join(":"); - let raw_config = load_all_config(&config_path).await; + let mut raw_config = load_all_config(&config_path).await; + raw_config.sort_by_key(|x| x.full_name()); let mut this = Self { working_dir, @@ -215,7 +217,7 @@ impl FoundConfig { } fn insert_if_absent(map: &mut BTreeMap, entry: T) { - let name = entry.name(); + let name = entry.name().to_string(); if map.contains_key(&name) { warn!(target: "user", "Duplicate {} found, dropping {} in {}", entry.full_name().to_string().bold(), entry.name().bold(), entry.metadata().file_path()); } else { diff --git a/scope/src/shared/mod.rs b/scope/src/shared/mod.rs index e15557e..9f9b5f1 100644 --- a/scope/src/shared/mod.rs +++ b/scope/src/shared/mod.rs @@ -1,5 +1,6 @@ use colored::Colorize; use dev_scope_model::prelude::ModelMetadata; +use dev_scope_model::HelpMetadata; use std::cmp::max; use std::path::Path; use tracing::info; @@ -15,13 +16,6 @@ mod report; pub const CONFIG_FILE_PATH_ENV: &str = "SCOPE_CONFIG_JSON"; pub const RUN_ID_ENV_VAR: &str = "SCOPE_RUN_ID"; -pub trait HelpMetadata { - fn description(&self) -> String; - fn name(&self) -> String; - fn metadata(&self) -> &ModelMetadata; - fn full_name(&self) -> String; -} - pub mod prelude { pub use super::capture::{ CaptureError, CaptureOpts, DefaultExecutionProvider, ExecutionProvider, @@ -32,7 +26,6 @@ pub mod prelude { pub use super::models::prelude::*; pub use super::print_details; pub use super::report::ReportBuilder; - pub use super::HelpMetadata; pub use super::{CONFIG_FILE_PATH_ENV, RUN_ID_ENV_VAR}; } @@ -40,22 +33,26 @@ pub(crate) fn convert_to_string(input: Vec<&str>) -> Vec { input.iter().map(|x| x.to_string()).collect() } -pub fn print_details(working_dir: &Path, config: Vec<&T>) +pub fn print_details(working_dir: &Path, config: &Vec) where T: HelpMetadata, { - let max_name_length = config.iter().map(|x| x.name().len()).max().unwrap_or(20); + let max_name_length = config + .iter() + .map(|x| x.full_name().len()) + .max() + .unwrap_or(20); let max_name_length = max(max_name_length, 20) + 2; - info!(target: "user", "{:max_name_length$}{:60}{}", "Name".white().bold(), "Description".white().bold(), "Path".white().bold()); - for check in config { - let mut description = check.description().to_string(); + info!(target: "user", " {:max_name_length$}{:60}{}", "Name".white().bold(), "Description".white().bold(), "Path".white().bold()); + for resource in config { + let mut description = resource.description().to_string(); if description.len() > 55 { description.truncate(55); description = format!("{}...", description); } - let mut loc = check.metadata().file_path(); + let mut loc = resource.metadata().file_path(); let diff_path = pathdiff::diff_paths(&loc, working_dir); if let Some(diff) = diff_path { loc = diff.display().to_string(); @@ -63,6 +60,6 @@ where loc = format!("...{}", loc.split_off(loc.len() - 35)); } - info!(target: "user", "{:max_name_length$}{:60}{}", check.name().white().bold(), description, loc); + info!(target: "user", "- {:max_name_length$}{:60}{}", resource.full_name(), description, loc); } } diff --git a/scope/src/shared/models/internal/doctor_group.rs b/scope/src/shared/models/internal/doctor_group.rs index 785326c..9036a63 100644 --- a/scope/src/shared/models/internal/doctor_group.rs +++ b/scope/src/shared/models/internal/doctor_group.rs @@ -1,8 +1,7 @@ use crate::shared::models::internal::extract_command_path; -use crate::shared::HelpMetadata; use derive_builder::Builder; use dev_scope_model::prelude::{ModelMetadata, V1AlphaDoctorGroup}; -use dev_scope_model::ScopeModel; +use dev_scope_model::{HelpMetadata, ScopeModel}; use std::path::{Path, PathBuf}; #[derive(Debug, PartialEq, Clone, Builder)] @@ -116,19 +115,10 @@ pub struct DoctorGroup { pub full_name: String, pub metadata: ModelMetadata, pub requires: Vec, - pub description: String, pub actions: Vec, } impl HelpMetadata for DoctorGroup { - fn description(&self) -> String { - self.description.to_string() - } - - fn name(&self) -> String { - self.metadata.name.to_string() - } - fn metadata(&self) -> &ModelMetadata { &self.metadata } @@ -183,10 +173,6 @@ impl TryFrom for DoctorGroup { Ok(DoctorGroup { full_name: model.full_name(), metadata: model.metadata, - description: model - .spec - .description - .unwrap_or_else(|| "default".to_string()), actions, requires: model.spec.needs, }) @@ -220,7 +206,6 @@ mod tests { assert_eq!("/foo/bar/.scope", dg.metadata.annotations.file_dir.unwrap()); assert_eq!("ScopeDoctorGroup/foo", dg.full_name); assert_eq!(vec!["bar"], dg.requires); - assert_eq!("Check your shell for basic functionality", dg.description); assert_eq!( dg.actions[0], diff --git a/scope/src/shared/models/internal/known_error.rs b/scope/src/shared/models/internal/known_error.rs index b442c87..4159e1b 100644 --- a/scope/src/shared/models/internal/known_error.rs +++ b/scope/src/shared/models/internal/known_error.rs @@ -1,7 +1,6 @@ -use crate::shared::HelpMetadata; use derivative::Derivative; use dev_scope_model::prelude::{ModelMetadata, V1AlphaKnownError}; -use dev_scope_model::ScopeModel; +use dev_scope_model::{HelpMetadata, ScopeModel}; use regex::Regex; #[derive(Derivative)] @@ -10,7 +9,6 @@ use regex::Regex; pub struct KnownError { pub full_name: String, pub metadata: ModelMetadata, - pub description: String, pub pattern: String, #[derivative(PartialEq = "ignore")] pub regex: Regex, @@ -18,13 +16,6 @@ pub struct KnownError { } impl HelpMetadata for KnownError { - fn description(&self) -> String { - self.description.to_string() - } - fn name(&self) -> String { - self.metadata.name.to_string() - } - fn metadata(&self) -> &ModelMetadata { &self.metadata } @@ -45,7 +36,6 @@ impl TryFrom for KnownError { pattern: value.spec.pattern, regex, help_text: value.spec.help, - description: value.spec.description, }) } } @@ -74,7 +64,6 @@ spec: assert_eq!("error-exists", model.metadata.name); assert_eq!("ScopeKnownError/error-exists", model.full_name); - assert_eq!("Check if the word error is in the logs", model.description); assert_eq!("The command had an error, try reading the logs around there to find out what happened.", model.help_text); assert_eq!("error", model.pattern); } diff --git a/scope/src/shared/models/internal/report_definition.rs b/scope/src/shared/models/internal/report_definition.rs index d954a8e..759d9fa 100644 --- a/scope/src/shared/models/internal/report_definition.rs +++ b/scope/src/shared/models/internal/report_definition.rs @@ -1,6 +1,5 @@ -use crate::prelude::HelpMetadata; use dev_scope_model::prelude::{ModelMetadata, V1AlphaReportDefinition}; -use dev_scope_model::ScopeModel; +use dev_scope_model::{HelpMetadata, ScopeModel}; use std::collections::BTreeMap; #[derive(Debug, PartialEq, Clone)] @@ -12,14 +11,6 @@ pub struct ReportDefinition { } impl HelpMetadata for ReportDefinition { - fn description(&self) -> String { - format!("Create a template of an error for {}", self.metadata.name) - } - - fn name(&self) -> String { - self.metadata.name.to_string() - } - fn metadata(&self) -> &ModelMetadata { &self.metadata } diff --git a/scope/src/shared/models/internal/upload_location.rs b/scope/src/shared/models/internal/upload_location.rs index 11b83be..49e656c 100644 --- a/scope/src/shared/models/internal/upload_location.rs +++ b/scope/src/shared/models/internal/upload_location.rs @@ -1,6 +1,5 @@ -use crate::prelude::HelpMetadata; use dev_scope_model::prelude::{ModelMetadata, V1AlphaReportLocation}; -use dev_scope_model::ScopeModel; +use dev_scope_model::HelpMetadata; #[derive(Debug, PartialEq, Clone)] pub enum ReportUploadLocationDestination { @@ -21,14 +20,6 @@ pub struct ReportUploadLocation { } impl HelpMetadata for ReportUploadLocation { - fn description(&self) -> String { - format!("Upload resource {}", self.metadata.name) - } - - fn name(&self) -> String { - self.metadata.name.to_string() - } - fn metadata(&self) -> &ModelMetadata { &self.metadata } From 67d507a98ebdd8b95b69e3ae1aea6d873017c40f Mon Sep 17 00:00:00 2001 From: Ethan Hall Date: Sun, 3 Mar 2024 16:42:02 -0800 Subject: [PATCH 05/14] update tests --- examples/.scope/doctor-check-path-exists.yaml | 11 ------ .../.scope/doctor-group-in-scope-dir.yaml | 15 ++++++++ examples/.scope/doctor-group-path-exists.yaml | 15 ++++++++ examples/.scope/doctor-group-setup.yaml | 13 +++++++ examples/.scope/doctor-setup.yaml | 12 ------- scope/src/bin/scope-intercept.rs | 1 + scope/src/doctor/commands/run.rs | 4 +++ scope/src/doctor/tests.rs | 2 +- scope/src/shared/config_load.rs | 4 +-- scope/src/shared/mod.rs | 2 +- .../shared/models/internal/doctor_group.rs | 2 +- .../src/shared/models/internal/known_error.rs | 2 +- .../models/internal/report_definition.rs | 2 +- scope/tests/integration_tests.rs | 36 +++++++++++++++---- 14 files changed, 85 insertions(+), 36 deletions(-) delete mode 100644 examples/.scope/doctor-check-path-exists.yaml create mode 100644 examples/.scope/doctor-group-in-scope-dir.yaml create mode 100644 examples/.scope/doctor-group-path-exists.yaml create mode 100644 examples/.scope/doctor-group-setup.yaml delete mode 100644 examples/.scope/doctor-setup.yaml diff --git a/examples/.scope/doctor-check-path-exists.yaml b/examples/.scope/doctor-check-path-exists.yaml deleted file mode 100644 index 924cbf2..0000000 --- a/examples/.scope/doctor-check-path-exists.yaml +++ /dev/null @@ -1,11 +0,0 @@ -apiVersion: scope.github.com/v1alpha -kind: ScopeDoctorCheck -metadata: - name: path-exists - description: Check your shell for basic functionality -spec: - check: - target: ./scripts/fail-first-call path-exists - fix: - target: ../bin/truey - help: You're shell does not have a path env. Reload your shell. diff --git a/examples/.scope/doctor-group-in-scope-dir.yaml b/examples/.scope/doctor-group-in-scope-dir.yaml new file mode 100644 index 0000000..4c90d9e --- /dev/null +++ b/examples/.scope/doctor-group-in-scope-dir.yaml @@ -0,0 +1,15 @@ +apiVersion: scope.github.com/v1alpha +kind: ScopeDoctorGroup +metadata: + name: path-exists-fix-in-scope-dir + description: Check your shell for basic functionality +spec: + actions: + - description: foo1 + help: You're shell does not have a path env. Reload your shell. + check: + commands: + - ./scripts/fail-first-call path-exists-fix-in-scope-dir + fix: + commands: + - ./scripts/truey diff --git a/examples/.scope/doctor-group-path-exists.yaml b/examples/.scope/doctor-group-path-exists.yaml new file mode 100644 index 0000000..44fadbd --- /dev/null +++ b/examples/.scope/doctor-group-path-exists.yaml @@ -0,0 +1,15 @@ +apiVersion: scope.github.com/v1alpha +kind: ScopeDoctorGroup +metadata: + name: path-exists + description: Check your shell for basic functionality +spec: + actions: + - description: foo1 + help: You're shell does not have a path env. Reload your shell. + check: + commands: + - ./scripts/fail-first-call path-exists + fix: + commands: + - ../bin/truey diff --git a/examples/.scope/doctor-group-setup.yaml b/examples/.scope/doctor-group-setup.yaml new file mode 100644 index 0000000..6cf0032 --- /dev/null +++ b/examples/.scope/doctor-group-setup.yaml @@ -0,0 +1,13 @@ +apiVersion: scope.github.com/v1alpha +kind: ScopeDoctorGroup +metadata: + name: setup + description: You need to run bin/setup +spec: + actions: + - check: + paths: + - '**/requirements.txt' + fix: + commands: + - ../bin/pip-install.sh diff --git a/examples/.scope/doctor-setup.yaml b/examples/.scope/doctor-setup.yaml deleted file mode 100644 index 97a6b39..0000000 --- a/examples/.scope/doctor-setup.yaml +++ /dev/null @@ -1,12 +0,0 @@ -apiVersion: scope.github.com/v1alpha -kind: ScopeDoctorSetup -metadata: - name: setup - description: You need to run bin/setup -spec: - cache: - paths: - - '**/requirements.txt' - setup: - exec: - - ../bin/pip-install.sh diff --git a/scope/src/bin/scope-intercept.rs b/scope/src/bin/scope-intercept.rs index 9df85d0..91e35e7 100644 --- a/scope/src/bin/scope-intercept.rs +++ b/scope/src/bin/scope-intercept.rs @@ -1,5 +1,6 @@ use clap::Parser; use dev_scope::prelude::*; +use dev_scope_model::HelpMetadata; use human_panic::setup_panic; use std::env; use tracing::{debug, enabled, error, info, warn, Level}; diff --git a/scope/src/doctor/commands/run.rs b/scope/src/doctor/commands/run.rs index 386a63a..79ee96a 100644 --- a/scope/src/doctor/commands/run.rs +++ b/scope/src/doctor/commands/run.rs @@ -84,6 +84,10 @@ pub async fn doctor_run(found_config: &FoundConfig, args: &DoctorRunArgs) -> Res let all_paths = compute_group_order(&found_config.doctor_group, desired_groups); + if all_paths.is_empty() { + warn!(target: "user", "Could not find any tasks to execute"); + } + let run_groups = RunGroups { group_actions: groups, all_paths, diff --git a/scope/src/doctor/tests.rs b/scope/src/doctor/tests.rs index 968df7c..39ef31f 100644 --- a/scope/src/doctor/tests.rs +++ b/scope/src/doctor/tests.rs @@ -14,13 +14,13 @@ where let mut binding = ModelMetadataBuilder::default(); let metadata_builder = binding .name("fake-name") + .description("a description") .annotations(ModelMetadataAnnotations::default()) .labels(BTreeMap::default()); let metadata = edit_meta(metadata_builder).build().unwrap(); let mut binding = DoctorGroupBuilder::default(); let group_builder = binding - .description("a description") .full_name("DoctorGroup/fake-name") .actions(actions) .metadata(metadata) diff --git a/scope/src/shared/config_load.rs b/scope/src/shared/config_load.rs index e3bf47c..0ebe149 100644 --- a/scope/src/shared/config_load.rs +++ b/scope/src/shared/config_load.rs @@ -6,12 +6,12 @@ use anyhow::{anyhow, Result}; use clap::{ArgGroup, Parser}; use colored::*; use dev_scope_model::prelude::{ModelMetadata, ModelRoot}; -use dev_scope_model::{HelpMetadata, ScopeModel}; +use dev_scope_model::HelpMetadata; use directories::{BaseDirs, UserDirs}; use itertools::Itertools; use serde::Deserialize; use serde_yaml::{Deserializer, Value}; -use std::borrow::Cow; + use std::collections::BTreeMap; use std::ffi::OsStr; use std::fs::{self, File}; diff --git a/scope/src/shared/mod.rs b/scope/src/shared/mod.rs index 9f9b5f1..4adb578 100644 --- a/scope/src/shared/mod.rs +++ b/scope/src/shared/mod.rs @@ -1,5 +1,5 @@ use colored::Colorize; -use dev_scope_model::prelude::ModelMetadata; + use dev_scope_model::HelpMetadata; use std::cmp::max; use std::path::Path; diff --git a/scope/src/shared/models/internal/doctor_group.rs b/scope/src/shared/models/internal/doctor_group.rs index 9036a63..3c43f74 100644 --- a/scope/src/shared/models/internal/doctor_group.rs +++ b/scope/src/shared/models/internal/doctor_group.rs @@ -1,7 +1,7 @@ use crate::shared::models::internal::extract_command_path; use derive_builder::Builder; use dev_scope_model::prelude::{ModelMetadata, V1AlphaDoctorGroup}; -use dev_scope_model::{HelpMetadata, ScopeModel}; +use dev_scope_model::HelpMetadata; use std::path::{Path, PathBuf}; #[derive(Debug, PartialEq, Clone, Builder)] diff --git a/scope/src/shared/models/internal/known_error.rs b/scope/src/shared/models/internal/known_error.rs index 4159e1b..aceacbc 100644 --- a/scope/src/shared/models/internal/known_error.rs +++ b/scope/src/shared/models/internal/known_error.rs @@ -1,6 +1,6 @@ use derivative::Derivative; use dev_scope_model::prelude::{ModelMetadata, V1AlphaKnownError}; -use dev_scope_model::{HelpMetadata, ScopeModel}; +use dev_scope_model::HelpMetadata; use regex::Regex; #[derive(Derivative)] diff --git a/scope/src/shared/models/internal/report_definition.rs b/scope/src/shared/models/internal/report_definition.rs index 759d9fa..820e3e4 100644 --- a/scope/src/shared/models/internal/report_definition.rs +++ b/scope/src/shared/models/internal/report_definition.rs @@ -1,5 +1,5 @@ use dev_scope_model::prelude::{ModelMetadata, V1AlphaReportDefinition}; -use dev_scope_model::{HelpMetadata, ScopeModel}; +use dev_scope_model::HelpMetadata; use std::collections::BTreeMap; #[derive(Debug, PartialEq, Clone)] diff --git a/scope/tests/integration_tests.rs b/scope/tests/integration_tests.rs index c844d73..fae9c33 100644 --- a/scope/tests/integration_tests.rs +++ b/scope/tests/integration_tests.rs @@ -24,9 +24,11 @@ fn test_list_reports_all_config() { result .success() - .stdout(predicate::str::contains("Doctor Checks")) - .stdout(predicate::str::contains("path-exists")) - .stdout(predicate::str::contains("error-exists")) + .stdout(predicate::str::contains("ScopeDoctorCheck/path-exists")) + .stdout(predicate::str::contains("ScopeKnownError/error-exists")) + .stdout(predicate::str::contains("ScopeDoctorGroup/group-1")) + .stdout(predicate::str::contains("ScopeReportDefinition/template")) + .stdout(predicate::str::contains("ScopeReportLocation/github")) .stdout(predicate::str::contains( "Check if the word error is in the logs", )) @@ -52,11 +54,10 @@ fn test_doctor_list() { result .success() - .stdout(predicate::str::contains("path-exists")) + .stdout(predicate::str::contains("ScopeDoctorGroup/group-1")) .stdout(predicate::str::contains( "Check your shell for basic functionality", - )) - .stdout(predicate::str::contains("setup")); + )); working_dir.close().unwrap(); } @@ -213,3 +214,26 @@ fn test_run_group_1() { )) .stdout(predicate::str::contains("Failed to write updated cache to disk").not()); } + +#[test] +fn test_no_tasks_found() { + let working_dir = setup_working_dir(); + + let mut cmd = Command::cargo_bin("scope").unwrap(); + let result = cmd + .current_dir(working_dir.path()) + .env("SCOPE_RUN_ID", "test_no_tasks_found") + .arg("doctor") + .arg("run") + .arg("--only=bogus-group") + .arg(&format!( + "--cache-dir={}/.cache", + working_dir.to_str().unwrap() + )) + .env("NO_COLOR", "1") + .assert(); + + result.success().stdout(predicate::str::contains( + "Could not find any tasks to execute", + )); +} From 0240d140d1f5e6772ebf6fe7d40c89c84e206f1d Mon Sep 17 00:00:00 2001 From: Ethan Hall Date: Sun, 3 Mar 2024 18:56:14 -0800 Subject: [PATCH 06/14] add validation and debugging --- Cargo.lock | 113 +++--------------- Cargo.toml | 12 ++ .../.scope/doctor-group-in-scope-dir.yaml | 2 +- examples/.scope/doctor-group-path-exists.yaml | 1 - examples/.scope/doctor-group-setup.yaml | 1 + scope-models/Cargo.toml | 21 ++-- scope-models/schema/merged.json | 54 +++++---- ...pha.com.github.scope.ScopeDoctorGroup.json | 55 +++++---- ...lpha.com.github.scope.ScopeKnownError.json | 55 +++++---- ...om.github.scope.ScopeReportDefinition.json | 55 +++++---- ....com.github.scope.ScopeReportLocation.json | 55 +++++---- scope-models/src/lib.rs | 25 +++- scope-models/src/v1alpha/doctor_group.rs | 5 + scope-models/src/v1alpha/known_error.rs | 2 + scope-models/src/v1alpha/report_definition.rs | 2 + scope-models/src/v1alpha/report_location.rs | 4 + scope/Cargo.toml | 18 +-- scope/tests/integration_tests.rs | 1 + 18 files changed, 240 insertions(+), 241 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ab384ec..aa2fe9f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -422,38 +422,14 @@ dependencies = [ "typenum", ] -[[package]] -name = "darling" -version = "0.14.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b750cb3417fd1b327431a470f388520309479ab0bf5e323505daf0290cd3850" -dependencies = [ - "darling_core 0.14.4", - "darling_macro 0.14.4", -] - [[package]] name = "darling" version = "0.20.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "54e36fcd13ed84ffdfda6f5be89b31287cbb80c439841fe69e04841435464391" dependencies = [ - "darling_core 0.20.8", - "darling_macro 0.20.8", -] - -[[package]] -name = "darling_core" -version = "0.14.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "109c1ca6e6b7f82cc233a97004ea8ed7ca123a9af07a8230878fcfda9b158bf0" -dependencies = [ - "fnv", - "ident_case", - "proc-macro2", - "quote", - "strsim", - "syn 1.0.109", + "darling_core", + "darling_macro", ] [[package]] @@ -470,24 +446,13 @@ dependencies = [ "syn 2.0.48", ] -[[package]] -name = "darling_macro" -version = "0.14.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4aab4dbc9f7611d8b55048a3a16d2d010c2c8334e46304b40ac1cc14bf3b48e" -dependencies = [ - "darling_core 0.14.4", - "quote", - "syn 1.0.109", -] - [[package]] name = "darling_macro" version = "0.20.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a668eda54683121533a393014d8692171709ff57a7d61f187b6e782719f8933f" dependencies = [ - "darling_core 0.20.8", + "darling_core", "quote", "syn 2.0.48", ] @@ -512,34 +477,13 @@ dependencies = [ "syn 1.0.109", ] -[[package]] -name = "derive_builder" -version = "0.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "660047478bc508c0fde22c868991eec0c40a63e48d610befef466d48e2bee574" -dependencies = [ - "derive_builder_macro 0.13.0", -] - [[package]] name = "derive_builder" version = "0.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0350b5cb0331628a5916d6c5c0b72e97393b8b6b03b47a9284f4e7f5a405ffd7" dependencies = [ - "derive_builder_macro 0.20.0", -] - -[[package]] -name = "derive_builder_core" -version = "0.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b217e6dd1011a54d12f3b920a411b5abd44b1716ecfe94f5f2f2f7b52e08ab7" -dependencies = [ - "darling 0.14.4", - "proc-macro2", - "quote", - "syn 1.0.109", + "derive_builder_macro", ] [[package]] @@ -548,29 +492,19 @@ version = "0.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d48cda787f839151732d396ac69e3473923d54312c070ee21e9effcaa8ca0b1d" dependencies = [ - "darling 0.20.8", + "darling", "proc-macro2", "quote", "syn 2.0.48", ] -[[package]] -name = "derive_builder_macro" -version = "0.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a5f77d7e20ac9153428f7ca14a88aba652adfc7a0ef0a06d654386310ef663b" -dependencies = [ - "derive_builder_core 0.13.0", - "syn 1.0.109", -] - [[package]] name = "derive_builder_macro" version = "0.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "206868b8242f27cecce124c19fd88157fbd0dd334df2587f36417bafbc85097b" dependencies = [ - "derive_builder_core 0.20.0", + "derive_builder_core", "syn 2.0.48", ] @@ -586,7 +520,7 @@ dependencies = [ "clap", "colored", "derivative", - "derive_builder 0.13.0", + "derive_builder", "dev-scope-model", "directories", "dotenv", @@ -597,6 +531,7 @@ dependencies = [ "inquire", "itertools", "json", + "jsonschema", "lazy_static", "minijinja", "mockall", @@ -607,11 +542,12 @@ dependencies = [ "predicates", "regex", "reqwest", + "schemars", "serde", "serde_json", "serde_yaml", "sha256", - "strum 0.25.0", + "strum", "thiserror", "time", "tokio", @@ -627,14 +563,15 @@ name = "dev-scope-model" version = "2024.2.6" dependencies = [ "anyhow", - "derive_builder 0.20.0", + "derive_builder", "jsonschema", "schemars", "serde", "serde_json", "serde_yaml", - "strum 0.26.1", + "strum", "thiserror", + "tracing", ] [[package]] @@ -2306,35 +2243,13 @@ version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" -[[package]] -name = "strum" -version = "0.25.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "290d54ea6f91c969195bdbcd7442c8c2a2ba87da8bf60a7ee86a235d4bc1e125" -dependencies = [ - "strum_macros 0.25.3", -] - [[package]] name = "strum" version = "0.26.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "723b93e8addf9aa965ebe2d11da6d7540fa2283fcea14b3371ff055f7ba13f5f" dependencies = [ - "strum_macros 0.26.1", -] - -[[package]] -name = "strum_macros" -version = "0.25.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23dc1fa9ac9c169a78ba62f0b841814b7abae11bdd047b9c58f893439e309ea0" -dependencies = [ - "heck", - "proc-macro2", - "quote", - "rustversion", - "syn 2.0.48", + "strum_macros", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 0395809..1a5cd75 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -23,6 +23,18 @@ pr-run-mode = "plan" # publish to homebrew publish-prereleases = true +[workspace.dependencies] +anyhow = "1.0.57" +thiserror = "1.0.30" +serde = { version = "1.0", features = ["derive"] } +serde_yaml = "0.9" +serde_json = "1.0" +schemars = "0.8" +derive_builder = "0.20" +strum = { version = "0.26", features = ["derive"] } +jsonschema = "0.17" +tracing = "0.1.34" + [workspace.metadata.dist.github-custom-runners] aarch64-unknown-linux-gnu = "buildjet-8vcpu-ubuntu-2204-arm" aarch64-unknown-linux-musl = "buildjet-8vcpu-ubuntu-2204-arm" diff --git a/examples/.scope/doctor-group-in-scope-dir.yaml b/examples/.scope/doctor-group-in-scope-dir.yaml index 4c90d9e..8785554 100644 --- a/examples/.scope/doctor-group-in-scope-dir.yaml +++ b/examples/.scope/doctor-group-in-scope-dir.yaml @@ -6,10 +6,10 @@ metadata: spec: actions: - description: foo1 - help: You're shell does not have a path env. Reload your shell. check: commands: - ./scripts/fail-first-call path-exists-fix-in-scope-dir fix: + helpText: You're shell does not have a path env. Reload your shell. commands: - ./scripts/truey diff --git a/examples/.scope/doctor-group-path-exists.yaml b/examples/.scope/doctor-group-path-exists.yaml index 44fadbd..b72667b 100644 --- a/examples/.scope/doctor-group-path-exists.yaml +++ b/examples/.scope/doctor-group-path-exists.yaml @@ -6,7 +6,6 @@ metadata: spec: actions: - description: foo1 - help: You're shell does not have a path env. Reload your shell. check: commands: - ./scripts/fail-first-call path-exists diff --git a/examples/.scope/doctor-group-setup.yaml b/examples/.scope/doctor-group-setup.yaml index 6cf0032..762168a 100644 --- a/examples/.scope/doctor-group-setup.yaml +++ b/examples/.scope/doctor-group-setup.yaml @@ -6,6 +6,7 @@ metadata: spec: actions: - check: + extra: not-defined paths: - '**/requirements.txt' fix: diff --git a/scope-models/Cargo.toml b/scope-models/Cargo.toml index fb4da5e..ebffef3 100644 --- a/scope-models/Cargo.toml +++ b/scope-models/Cargo.toml @@ -7,14 +7,15 @@ edition = "2021" dist = true [dependencies] -anyhow = "1.0.57" -thiserror = "1.0.30" -serde = { version = "1.0", features = ["derive"] } -serde_yaml = "0.9" -serde_json = "1.0" -schemars = "0.8" -derive_builder = "0.20" -strum = { version = "0.26", features = ["derive"] } +anyhow = { workspace = true } +thiserror = { workspace = true } +serde = {workspace = true} +serde_yaml = { workspace = true } +serde_json = { workspace = true } +schemars = { workspace = true } +derive_builder = { workspace = true } +strum = {workspace = true} +jsonschema = { workspace = true } +tracing = { workspace = true } -[dev-dependencies] -jsonschema = "0.17" \ No newline at end of file +[dev-dependencies] \ No newline at end of file diff --git a/scope-models/schema/merged.json b/scope-models/schema/merged.json index ccfed64..fd21237 100644 --- a/scope-models/schema/merged.json +++ b/scope-models/schema/merged.json @@ -41,7 +41,8 @@ }, "nullable": true } - } + }, + "additionalProperties": false }, "DoctorFixSpec": { "type": "object", @@ -69,7 +70,8 @@ ], "nullable": true } - } + }, + "additionalProperties": false }, "DoctorGroupActionSpec": { "type": "object", @@ -109,7 +111,8 @@ "default": true, "type": "boolean" } - } + }, + "additionalProperties": false }, "DoctorGroupKind": { "type": "string", @@ -129,13 +132,6 @@ "$ref": "#/definitions/DoctorGroupActionSpec" } }, - "description": { - "type": [ - "string", - "null" - ], - "nullable": true - }, "needs": { "default": [], "type": "array", @@ -143,7 +139,8 @@ "type": "string" } } - } + }, + "additionalProperties": false }, "KnownErrorKind": { "type": "string", @@ -154,21 +151,18 @@ "KnownErrorSpec": { "type": "object", "required": [ - "description", "help", "pattern" ], "properties": { - "description": { - "type": "string" - }, "help": { "type": "string" }, "pattern": { "type": "string" } - } + }, + "additionalProperties": false }, "ModelMetadata": { "type": "object", @@ -184,6 +178,10 @@ }, "$ref": "#/definitions/ModelMetadataAnnotations" }, + "description": { + "default": "Description not provided", + "type": "string" + }, "labels": { "default": {}, "type": "object", @@ -244,7 +242,8 @@ "template": { "type": "string" } - } + }, + "additionalProperties": false }, "ReportDestinationGithubIssueSpec": { "type": "object", @@ -266,7 +265,8 @@ "type": "string" } } - } + }, + "additionalProperties": false }, "ReportDestinationSpec": { "oneOf": [ @@ -285,7 +285,8 @@ "url": { "type": "string" } - } + }, + "additionalProperties": false } }, "additionalProperties": false @@ -319,7 +320,8 @@ "destination": { "$ref": "#/definitions/ReportDestinationSpec" } - } + }, + "additionalProperties": false }, "V1AlphaApiVersion": { "type": "string", @@ -348,7 +350,8 @@ "spec": { "$ref": "#/definitions/DoctorGroupSpec" } - } + }, + "additionalProperties": false }, "V1AlphaKnownError": { "type": "object", @@ -371,7 +374,8 @@ "spec": { "$ref": "#/definitions/KnownErrorSpec" } - } + }, + "additionalProperties": false }, "V1AlphaReportDefinition": { "type": "object", @@ -394,7 +398,8 @@ "spec": { "$ref": "#/definitions/ReportDefinitionSpec" } - } + }, + "additionalProperties": false }, "V1AlphaReportLocation": { "type": "object", @@ -417,7 +422,8 @@ "spec": { "$ref": "#/definitions/ReportLocationSpec" } - } + }, + "additionalProperties": false } } } \ No newline at end of file diff --git a/scope-models/schema/v1alpha.com.github.scope.ScopeDoctorGroup.json b/scope-models/schema/v1alpha.com.github.scope.ScopeDoctorGroup.json index 2b39a38..d594744 100644 --- a/scope-models/schema/v1alpha.com.github.scope.ScopeDoctorGroup.json +++ b/scope-models/schema/v1alpha.com.github.scope.ScopeDoctorGroup.json @@ -22,6 +22,7 @@ "$ref": "#/definitions/DoctorGroupSpec" } }, + "additionalProperties": false, "definitions": { "DoctorCheckSpec": { "type": "object", @@ -48,7 +49,8 @@ }, "nullable": true } - } + }, + "additionalProperties": false }, "DoctorFixSpec": { "type": "object", @@ -76,7 +78,8 @@ ], "nullable": true } - } + }, + "additionalProperties": false }, "DoctorGroupActionSpec": { "type": "object", @@ -116,7 +119,8 @@ "default": true, "type": "boolean" } - } + }, + "additionalProperties": false }, "DoctorGroupKind": { "type": "string", @@ -136,13 +140,6 @@ "$ref": "#/definitions/DoctorGroupActionSpec" } }, - "description": { - "type": [ - "string", - "null" - ], - "nullable": true - }, "needs": { "default": [], "type": "array", @@ -150,7 +147,8 @@ "type": "string" } } - } + }, + "additionalProperties": false }, "KnownErrorKind": { "type": "string", @@ -161,21 +159,18 @@ "KnownErrorSpec": { "type": "object", "required": [ - "description", "help", "pattern" ], "properties": { - "description": { - "type": "string" - }, "help": { "type": "string" }, "pattern": { "type": "string" } - } + }, + "additionalProperties": false }, "ModelMetadata": { "type": "object", @@ -191,6 +186,10 @@ }, "$ref": "#/definitions/ModelMetadataAnnotations" }, + "description": { + "default": "Description not provided", + "type": "string" + }, "labels": { "default": {}, "type": "object", @@ -251,7 +250,8 @@ "template": { "type": "string" } - } + }, + "additionalProperties": false }, "ReportDestinationGithubIssueSpec": { "type": "object", @@ -273,7 +273,8 @@ "type": "string" } } - } + }, + "additionalProperties": false }, "ReportDestinationSpec": { "oneOf": [ @@ -292,7 +293,8 @@ "url": { "type": "string" } - } + }, + "additionalProperties": false } }, "additionalProperties": false @@ -326,7 +328,8 @@ "destination": { "$ref": "#/definitions/ReportDestinationSpec" } - } + }, + "additionalProperties": false }, "V1AlphaApiVersion": { "type": "string", @@ -355,7 +358,8 @@ "spec": { "$ref": "#/definitions/DoctorGroupSpec" } - } + }, + "additionalProperties": false }, "V1AlphaKnownError": { "type": "object", @@ -378,7 +382,8 @@ "spec": { "$ref": "#/definitions/KnownErrorSpec" } - } + }, + "additionalProperties": false }, "V1AlphaReportDefinition": { "type": "object", @@ -401,7 +406,8 @@ "spec": { "$ref": "#/definitions/ReportDefinitionSpec" } - } + }, + "additionalProperties": false }, "V1AlphaReportLocation": { "type": "object", @@ -424,7 +430,8 @@ "spec": { "$ref": "#/definitions/ReportLocationSpec" } - } + }, + "additionalProperties": false } } } \ No newline at end of file diff --git a/scope-models/schema/v1alpha.com.github.scope.ScopeKnownError.json b/scope-models/schema/v1alpha.com.github.scope.ScopeKnownError.json index ebbffb4..26b4058 100644 --- a/scope-models/schema/v1alpha.com.github.scope.ScopeKnownError.json +++ b/scope-models/schema/v1alpha.com.github.scope.ScopeKnownError.json @@ -22,6 +22,7 @@ "$ref": "#/definitions/KnownErrorSpec" } }, + "additionalProperties": false, "definitions": { "DoctorCheckSpec": { "type": "object", @@ -48,7 +49,8 @@ }, "nullable": true } - } + }, + "additionalProperties": false }, "DoctorFixSpec": { "type": "object", @@ -76,7 +78,8 @@ ], "nullable": true } - } + }, + "additionalProperties": false }, "DoctorGroupActionSpec": { "type": "object", @@ -116,7 +119,8 @@ "default": true, "type": "boolean" } - } + }, + "additionalProperties": false }, "DoctorGroupKind": { "type": "string", @@ -136,13 +140,6 @@ "$ref": "#/definitions/DoctorGroupActionSpec" } }, - "description": { - "type": [ - "string", - "null" - ], - "nullable": true - }, "needs": { "default": [], "type": "array", @@ -150,7 +147,8 @@ "type": "string" } } - } + }, + "additionalProperties": false }, "KnownErrorKind": { "type": "string", @@ -161,21 +159,18 @@ "KnownErrorSpec": { "type": "object", "required": [ - "description", "help", "pattern" ], "properties": { - "description": { - "type": "string" - }, "help": { "type": "string" }, "pattern": { "type": "string" } - } + }, + "additionalProperties": false }, "ModelMetadata": { "type": "object", @@ -191,6 +186,10 @@ }, "$ref": "#/definitions/ModelMetadataAnnotations" }, + "description": { + "default": "Description not provided", + "type": "string" + }, "labels": { "default": {}, "type": "object", @@ -251,7 +250,8 @@ "template": { "type": "string" } - } + }, + "additionalProperties": false }, "ReportDestinationGithubIssueSpec": { "type": "object", @@ -273,7 +273,8 @@ "type": "string" } } - } + }, + "additionalProperties": false }, "ReportDestinationSpec": { "oneOf": [ @@ -292,7 +293,8 @@ "url": { "type": "string" } - } + }, + "additionalProperties": false } }, "additionalProperties": false @@ -326,7 +328,8 @@ "destination": { "$ref": "#/definitions/ReportDestinationSpec" } - } + }, + "additionalProperties": false }, "V1AlphaApiVersion": { "type": "string", @@ -355,7 +358,8 @@ "spec": { "$ref": "#/definitions/DoctorGroupSpec" } - } + }, + "additionalProperties": false }, "V1AlphaKnownError": { "type": "object", @@ -378,7 +382,8 @@ "spec": { "$ref": "#/definitions/KnownErrorSpec" } - } + }, + "additionalProperties": false }, "V1AlphaReportDefinition": { "type": "object", @@ -401,7 +406,8 @@ "spec": { "$ref": "#/definitions/ReportDefinitionSpec" } - } + }, + "additionalProperties": false }, "V1AlphaReportLocation": { "type": "object", @@ -424,7 +430,8 @@ "spec": { "$ref": "#/definitions/ReportLocationSpec" } - } + }, + "additionalProperties": false } } } \ No newline at end of file diff --git a/scope-models/schema/v1alpha.com.github.scope.ScopeReportDefinition.json b/scope-models/schema/v1alpha.com.github.scope.ScopeReportDefinition.json index 07497eb..7375068 100644 --- a/scope-models/schema/v1alpha.com.github.scope.ScopeReportDefinition.json +++ b/scope-models/schema/v1alpha.com.github.scope.ScopeReportDefinition.json @@ -22,6 +22,7 @@ "$ref": "#/definitions/ReportDefinitionSpec" } }, + "additionalProperties": false, "definitions": { "DoctorCheckSpec": { "type": "object", @@ -48,7 +49,8 @@ }, "nullable": true } - } + }, + "additionalProperties": false }, "DoctorFixSpec": { "type": "object", @@ -76,7 +78,8 @@ ], "nullable": true } - } + }, + "additionalProperties": false }, "DoctorGroupActionSpec": { "type": "object", @@ -116,7 +119,8 @@ "default": true, "type": "boolean" } - } + }, + "additionalProperties": false }, "DoctorGroupKind": { "type": "string", @@ -136,13 +140,6 @@ "$ref": "#/definitions/DoctorGroupActionSpec" } }, - "description": { - "type": [ - "string", - "null" - ], - "nullable": true - }, "needs": { "default": [], "type": "array", @@ -150,7 +147,8 @@ "type": "string" } } - } + }, + "additionalProperties": false }, "KnownErrorKind": { "type": "string", @@ -161,21 +159,18 @@ "KnownErrorSpec": { "type": "object", "required": [ - "description", "help", "pattern" ], "properties": { - "description": { - "type": "string" - }, "help": { "type": "string" }, "pattern": { "type": "string" } - } + }, + "additionalProperties": false }, "ModelMetadata": { "type": "object", @@ -191,6 +186,10 @@ }, "$ref": "#/definitions/ModelMetadataAnnotations" }, + "description": { + "default": "Description not provided", + "type": "string" + }, "labels": { "default": {}, "type": "object", @@ -251,7 +250,8 @@ "template": { "type": "string" } - } + }, + "additionalProperties": false }, "ReportDestinationGithubIssueSpec": { "type": "object", @@ -273,7 +273,8 @@ "type": "string" } } - } + }, + "additionalProperties": false }, "ReportDestinationSpec": { "oneOf": [ @@ -292,7 +293,8 @@ "url": { "type": "string" } - } + }, + "additionalProperties": false } }, "additionalProperties": false @@ -326,7 +328,8 @@ "destination": { "$ref": "#/definitions/ReportDestinationSpec" } - } + }, + "additionalProperties": false }, "V1AlphaApiVersion": { "type": "string", @@ -355,7 +358,8 @@ "spec": { "$ref": "#/definitions/DoctorGroupSpec" } - } + }, + "additionalProperties": false }, "V1AlphaKnownError": { "type": "object", @@ -378,7 +382,8 @@ "spec": { "$ref": "#/definitions/KnownErrorSpec" } - } + }, + "additionalProperties": false }, "V1AlphaReportDefinition": { "type": "object", @@ -401,7 +406,8 @@ "spec": { "$ref": "#/definitions/ReportDefinitionSpec" } - } + }, + "additionalProperties": false }, "V1AlphaReportLocation": { "type": "object", @@ -424,7 +430,8 @@ "spec": { "$ref": "#/definitions/ReportLocationSpec" } - } + }, + "additionalProperties": false } } } \ No newline at end of file diff --git a/scope-models/schema/v1alpha.com.github.scope.ScopeReportLocation.json b/scope-models/schema/v1alpha.com.github.scope.ScopeReportLocation.json index 4afdf1b..e9087e9 100644 --- a/scope-models/schema/v1alpha.com.github.scope.ScopeReportLocation.json +++ b/scope-models/schema/v1alpha.com.github.scope.ScopeReportLocation.json @@ -22,6 +22,7 @@ "$ref": "#/definitions/ReportLocationSpec" } }, + "additionalProperties": false, "definitions": { "DoctorCheckSpec": { "type": "object", @@ -48,7 +49,8 @@ }, "nullable": true } - } + }, + "additionalProperties": false }, "DoctorFixSpec": { "type": "object", @@ -76,7 +78,8 @@ ], "nullable": true } - } + }, + "additionalProperties": false }, "DoctorGroupActionSpec": { "type": "object", @@ -116,7 +119,8 @@ "default": true, "type": "boolean" } - } + }, + "additionalProperties": false }, "DoctorGroupKind": { "type": "string", @@ -136,13 +140,6 @@ "$ref": "#/definitions/DoctorGroupActionSpec" } }, - "description": { - "type": [ - "string", - "null" - ], - "nullable": true - }, "needs": { "default": [], "type": "array", @@ -150,7 +147,8 @@ "type": "string" } } - } + }, + "additionalProperties": false }, "KnownErrorKind": { "type": "string", @@ -161,21 +159,18 @@ "KnownErrorSpec": { "type": "object", "required": [ - "description", "help", "pattern" ], "properties": { - "description": { - "type": "string" - }, "help": { "type": "string" }, "pattern": { "type": "string" } - } + }, + "additionalProperties": false }, "ModelMetadata": { "type": "object", @@ -191,6 +186,10 @@ }, "$ref": "#/definitions/ModelMetadataAnnotations" }, + "description": { + "default": "Description not provided", + "type": "string" + }, "labels": { "default": {}, "type": "object", @@ -251,7 +250,8 @@ "template": { "type": "string" } - } + }, + "additionalProperties": false }, "ReportDestinationGithubIssueSpec": { "type": "object", @@ -273,7 +273,8 @@ "type": "string" } } - } + }, + "additionalProperties": false }, "ReportDestinationSpec": { "oneOf": [ @@ -292,7 +293,8 @@ "url": { "type": "string" } - } + }, + "additionalProperties": false } }, "additionalProperties": false @@ -326,7 +328,8 @@ "destination": { "$ref": "#/definitions/ReportDestinationSpec" } - } + }, + "additionalProperties": false }, "V1AlphaApiVersion": { "type": "string", @@ -355,7 +358,8 @@ "spec": { "$ref": "#/definitions/DoctorGroupSpec" } - } + }, + "additionalProperties": false }, "V1AlphaKnownError": { "type": "object", @@ -378,7 +382,8 @@ "spec": { "$ref": "#/definitions/KnownErrorSpec" } - } + }, + "additionalProperties": false }, "V1AlphaReportDefinition": { "type": "object", @@ -401,7 +406,8 @@ "spec": { "$ref": "#/definitions/ReportDefinitionSpec" } - } + }, + "additionalProperties": false }, "V1AlphaReportLocation": { "type": "object", @@ -424,7 +430,8 @@ "spec": { "$ref": "#/definitions/ReportLocationSpec" } - } + }, + "additionalProperties": false } } } \ No newline at end of file diff --git a/scope-models/src/lib.rs b/scope-models/src/lib.rs index d184db0..f0b0125 100644 --- a/scope-models/src/lib.rs +++ b/scope-models/src/lib.rs @@ -1,8 +1,10 @@ use crate::core::{ModelMetadata, ModelRoot}; +use anyhow::anyhow; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; use serde_yaml::Value; +use tracing::warn; mod core; mod v1alpha; @@ -52,11 +54,31 @@ where && Self::int_kind().to_lowercase() == input.kind.to_lowercase() { let value = serde_json::to_value(input)?; + if let Err(e) = Self::validate_resource(&value) { + warn!(target: "user", "Resource {} didn't match the schema for {}. {}", input.name(), Self::int_kind(), e); + } return Ok(Some(serde_json::from_value::(value)?)); } Ok(None) } + fn validate_resource(input: &serde_json::Value) -> anyhow::Result<()> { + let mut schema_gen = make_schema_generator(); + let schema = schema_gen.root_schema_for::(); + let schema_json = serde_json::to_value(&schema)?; + let compiled_schema = jsonschema::JSONSchema::compile(&schema_json) + .expect("internal json schema to be valid"); + if let Err(err_iter) = compiled_schema.validate(input) { + let mut errors = Vec::new(); + for err in err_iter { + errors.push(err.to_string()); + } + return Err(anyhow!(errors.join("\n"))); + }; + + Ok(()) + } + #[cfg(test)] fn examples() -> Vec; @@ -88,8 +110,7 @@ where } } -#[cfg(test)] -pub fn make_schema_generator() -> schemars::gen::SchemaGenerator { +pub(crate) fn make_schema_generator() -> schemars::gen::SchemaGenerator { let settings = schemars::gen::SchemaSettings::draft2019_09().with(|s| { s.option_nullable = true; }); diff --git a/scope-models/src/v1alpha/doctor_group.rs b/scope-models/src/v1alpha/doctor_group.rs index b68d368..f9d0e5b 100644 --- a/scope-models/src/v1alpha/doctor_group.rs +++ b/scope-models/src/v1alpha/doctor_group.rs @@ -8,6 +8,7 @@ use serde::{Deserialize, Serialize}; #[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema)] #[serde(rename_all = "camelCase")] +#[schemars(deny_unknown_fields)] pub struct DoctorCheckSpec { #[serde(default)] pub paths: Option>, @@ -17,6 +18,7 @@ pub struct DoctorCheckSpec { #[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema)] #[serde(rename_all = "camelCase")] +#[schemars(deny_unknown_fields)] pub struct DoctorFixSpec { #[serde(default)] pub commands: Vec, @@ -28,6 +30,7 @@ pub struct DoctorFixSpec { #[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema)] #[serde(rename_all = "camelCase")] +#[schemars(deny_unknown_fields)] pub struct DoctorGroupActionSpec { pub name: Option, pub description: Option, @@ -43,6 +46,7 @@ fn doctor_group_action_required_default() -> bool { #[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema)] #[serde(rename_all = "camelCase")] +#[schemars(deny_unknown_fields)] pub struct DoctorGroupSpec { #[serde(default)] pub needs: Vec, @@ -58,6 +62,7 @@ pub enum DoctorGroupKind { #[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Builder, JsonSchema)] #[builder(setter(into))] #[serde(rename_all = "camelCase")] +#[schemars(deny_unknown_fields)] pub struct V1AlphaDoctorGroup { pub api_version: V1AlphaApiVersion, pub kind: DoctorGroupKind, diff --git a/scope-models/src/v1alpha/known_error.rs b/scope-models/src/v1alpha/known_error.rs index 8c88417..c6bc7ca 100644 --- a/scope-models/src/v1alpha/known_error.rs +++ b/scope-models/src/v1alpha/known_error.rs @@ -7,6 +7,7 @@ use serde::{Deserialize, Serialize}; #[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema)] #[serde(rename_all = "camelCase")] +#[schemars(deny_unknown_fields)] pub struct KnownErrorSpec { pub help: String, pub pattern: String, @@ -21,6 +22,7 @@ pub enum KnownErrorKind { #[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Builder, JsonSchema)] #[builder(setter(into))] #[serde(rename_all = "camelCase")] +#[schemars(deny_unknown_fields)] pub struct V1AlphaKnownError { pub api_version: V1AlphaApiVersion, pub kind: KnownErrorKind, diff --git a/scope-models/src/v1alpha/report_definition.rs b/scope-models/src/v1alpha/report_definition.rs index 30608c6..a5d2382 100644 --- a/scope-models/src/v1alpha/report_definition.rs +++ b/scope-models/src/v1alpha/report_definition.rs @@ -10,6 +10,7 @@ use std::collections::BTreeMap; #[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Builder, JsonSchema)] #[serde(rename_all = "camelCase")] +#[schemars(deny_unknown_fields)] pub struct ReportDefinitionSpec { #[serde(default)] pub additional_data: BTreeMap, @@ -25,6 +26,7 @@ pub enum ReportDefinitionKind { #[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Builder, JsonSchema)] #[builder(setter(into))] #[serde(rename_all = "camelCase")] +#[schemars(deny_unknown_fields)] pub struct V1AlphaReportDefinition { pub api_version: V1AlphaApiVersion, pub kind: ReportDefinitionKind, diff --git a/scope-models/src/v1alpha/report_location.rs b/scope-models/src/v1alpha/report_location.rs index a79627b..584136f 100644 --- a/scope-models/src/v1alpha/report_location.rs +++ b/scope-models/src/v1alpha/report_location.rs @@ -8,6 +8,7 @@ use serde::{Deserialize, Serialize}; #[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema)] #[serde(rename_all = "camelCase")] +#[schemars(deny_unknown_fields)] pub struct ReportDestinationGithubIssueSpec { pub owner: String, pub repo: String, @@ -17,6 +18,7 @@ pub struct ReportDestinationGithubIssueSpec { #[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema)] #[serde(rename_all = "camelCase")] +#[schemars(deny_unknown_fields)] pub enum ReportDestinationSpec { RustyPaste { url: String }, GithubIssue(ReportDestinationGithubIssueSpec), @@ -24,6 +26,7 @@ pub enum ReportDestinationSpec { #[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema)] #[serde(rename_all = "camelCase")] +#[schemars(deny_unknown_fields)] pub struct ReportLocationSpec { #[serde(with = "serde_yaml::with::singleton_map")] #[schemars(with = "ReportDestinationSpec")] @@ -39,6 +42,7 @@ pub enum ReportLocationKind { #[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Builder, JsonSchema)] #[builder(setter(into))] #[serde(rename_all = "camelCase")] +#[schemars(deny_unknown_fields)] pub struct V1AlphaReportLocation { pub api_version: V1AlphaApiVersion, pub kind: ReportLocationKind, diff --git a/scope/Cargo.toml b/scope/Cargo.toml index 2a4f0f0..7ec8865 100644 --- a/scope/Cargo.toml +++ b/scope/Cargo.toml @@ -26,9 +26,6 @@ name = "scope-intercept" dev-scope-model = { path = "../scope-models" } clap = { version = "4.4.11", features = ["derive", "env"]} human-panic = "1.0.3" -anyhow = "1.0.57" -thiserror = "1.0.30" -tracing = "0.1.34" tokio = { version = "1", features = ["full"] } dotenv = "0.15.0" colored = "2.0.0" @@ -40,26 +37,31 @@ tracing-subscriber = { version = "0.3", features = ["time", "json", "local-time" tracing-appender = "0.2.2" chrono = "0.4" nanoid = "0.4" -serde = { version = "1.0", features = ["derive"] } -serde_yaml = "0.9" -serde_json = "1.0" directories = "5" derivative = "2" reqwest = { version = "0.11", features = ["multipart", "rustls-tls", "hyper-tls", "native-tls-vendored" ] } time = { version = "0.3", features = ["macros", "formatting", "local-offset"] } json = "0.12" minijinja = "1.0" -strum = { version = "0.25", features = ["derive"] } itertools = { version = "0.12", features = [] } path-clean = "1.0.1" async-trait = "0.1.77" mockall = "0.12.1" -derive_builder = "0.13.0" pathdiff = "0.2.1" glob = "0.3" educe = "0.5.11" petgraph = "0.6.4" sha256 = "1.5.0" +anyhow = { workspace = true } +thiserror = { workspace = true } +serde = {workspace = true} +serde_yaml = { workspace = true } +serde_json = { workspace = true } +schemars = { workspace = true } +derive_builder = { workspace = true } +strum = {workspace = true} +jsonschema = { workspace = true } +tracing = { workspace = true } [dev-dependencies] assert_cmd = "2.0.12" diff --git a/scope/tests/integration_tests.rs b/scope/tests/integration_tests.rs index fae9c33..320a6d1 100644 --- a/scope/tests/integration_tests.rs +++ b/scope/tests/integration_tests.rs @@ -34,6 +34,7 @@ fn test_list_reports_all_config() { )) .stdout(predicate::str::contains("setup")) .stdout(predicate::str::contains(".scope/known-error.yaml")) + .stdout(predicate::str::contains("Resource setup didn't match the schema for ScopeDoctorGroup. Additional properties are not allowed ('extra' was unexpected)")) .stdout( predicate::str::is_match(r"bar\s+External sub-command, run `scope bar` for help") .unwrap(), From 9156b3a71c71b15a2beaf76d10c54449fa98570c Mon Sep 17 00:00:00 2001 From: Ethan Hall Date: Sun, 3 Mar 2024 19:14:00 -0800 Subject: [PATCH 07/14] merge things --- Cargo.lock | 17 - Cargo.toml | 13 +- scope-models/Cargo.toml | 21 - scope-models/schema/merged.json | 429 ----------------- ...pha.com.github.scope.ScopeDoctorGroup.json | 437 ------------------ ...lpha.com.github.scope.ScopeKnownError.json | 437 ------------------ ...om.github.scope.ScopeReportDefinition.json | 437 ------------------ ....com.github.scope.ScopeReportLocation.json | 437 ------------------ scope/Cargo.toml | 21 +- .../examples/v1alpha/DoctorGroup.yaml | 0 .../examples/v1alpha/KnownError.yaml | 0 .../examples/v1alpha/ReportDefinition.yaml | 0 .../v1alpha/ReportLocation.github.yaml | 0 .../v1alpha/ReportLocation.rustyPaste.yaml | 0 scope/src/analyze/cli.rs | 2 +- scope/src/bin/scope-intercept.rs | 1 - scope/src/doctor/check.rs | 2 +- scope/src/doctor/tests.rs | 2 +- scope/src/lib.rs | 2 + .../src => scope/src/models}/core.rs | 2 +- .../src/lib.rs => scope/src/models/mod.rs | 15 +- .../src/models}/v1alpha/doctor_group.rs | 6 +- .../src/models}/v1alpha/known_error.rs | 6 +- .../src => scope/src/models}/v1alpha/mod.rs | 0 .../src/models}/v1alpha/report_definition.rs | 6 +- .../src/models}/v1alpha/report_location.rs | 7 +- scope/src/shared/config_load.rs | 4 +- scope/src/shared/mod.rs | 2 +- .../shared/models/internal/doctor_group.rs | 4 +- .../src/shared/models/internal/known_error.rs | 4 +- scope/src/shared/models/internal/mod.rs | 8 +- .../models/internal/report_definition.rs | 4 +- .../shared/models/internal/upload_location.rs | 8 +- 33 files changed, 53 insertions(+), 2281 deletions(-) delete mode 100644 scope-models/Cargo.toml delete mode 100644 scope-models/schema/merged.json delete mode 100644 scope-models/schema/v1alpha.com.github.scope.ScopeDoctorGroup.json delete mode 100644 scope-models/schema/v1alpha.com.github.scope.ScopeKnownError.json delete mode 100644 scope-models/schema/v1alpha.com.github.scope.ScopeReportDefinition.json delete mode 100644 scope-models/schema/v1alpha.com.github.scope.ScopeReportLocation.json rename {scope-models => scope}/examples/v1alpha/DoctorGroup.yaml (100%) rename {scope-models => scope}/examples/v1alpha/KnownError.yaml (100%) rename {scope-models => scope}/examples/v1alpha/ReportDefinition.yaml (100%) rename {scope-models => scope}/examples/v1alpha/ReportLocation.github.yaml (100%) rename {scope-models => scope}/examples/v1alpha/ReportLocation.rustyPaste.yaml (100%) rename {scope-models/src => scope/src/models}/core.rs (98%) rename scope-models/src/lib.rs => scope/src/models/mod.rs (94%) rename {scope-models/src => scope/src/models}/v1alpha/doctor_group.rs (94%) rename {scope-models/src => scope/src/models}/v1alpha/known_error.rs (91%) rename {scope-models/src => scope/src/models}/v1alpha/mod.rs (100%) rename {scope-models/src => scope/src/models}/v1alpha/report_definition.rs (92%) rename {scope-models/src => scope/src/models}/v1alpha/report_location.rs (94%) diff --git a/Cargo.lock b/Cargo.lock index aa2fe9f..6db2b84 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -521,7 +521,6 @@ dependencies = [ "colored", "derivative", "derive_builder", - "dev-scope-model", "directories", "dotenv", "educe", @@ -558,22 +557,6 @@ dependencies = [ "which", ] -[[package]] -name = "dev-scope-model" -version = "2024.2.6" -dependencies = [ - "anyhow", - "derive_builder", - "jsonschema", - "schemars", - "serde", - "serde_json", - "serde_yaml", - "strum", - "thiserror", - "tracing", -] - [[package]] name = "difflib" version = "0.4.0" diff --git a/Cargo.toml b/Cargo.toml index 1a5cd75..8da6aa5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,5 +1,5 @@ [workspace] -members = ["scope", "scope-models"] +members = ["scope"] resolver = "2" # Config for 'cargo dist' @@ -23,17 +23,6 @@ pr-run-mode = "plan" # publish to homebrew publish-prereleases = true -[workspace.dependencies] -anyhow = "1.0.57" -thiserror = "1.0.30" -serde = { version = "1.0", features = ["derive"] } -serde_yaml = "0.9" -serde_json = "1.0" -schemars = "0.8" -derive_builder = "0.20" -strum = { version = "0.26", features = ["derive"] } -jsonschema = "0.17" -tracing = "0.1.34" [workspace.metadata.dist.github-custom-runners] aarch64-unknown-linux-gnu = "buildjet-8vcpu-ubuntu-2204-arm" diff --git a/scope-models/Cargo.toml b/scope-models/Cargo.toml deleted file mode 100644 index ebffef3..0000000 --- a/scope-models/Cargo.toml +++ /dev/null @@ -1,21 +0,0 @@ -[package] -name = "dev-scope-model" -version = "2024.2.6" -edition = "2021" - -[package.metadata.dist] -dist = true - -[dependencies] -anyhow = { workspace = true } -thiserror = { workspace = true } -serde = {workspace = true} -serde_yaml = { workspace = true } -serde_json = { workspace = true } -schemars = { workspace = true } -derive_builder = { workspace = true } -strum = {workspace = true} -jsonschema = { workspace = true } -tracing = { workspace = true } - -[dev-dependencies] \ No newline at end of file diff --git a/scope-models/schema/merged.json b/scope-models/schema/merged.json deleted file mode 100644 index fd21237..0000000 --- a/scope-models/schema/merged.json +++ /dev/null @@ -1,429 +0,0 @@ -{ - "$schema": "https://json-schema.org/draft/2019-09/schema", - "title": "ScopeTypes", - "anyOf": [ - { - "$ref": "#/definitions/V1AlphaReportLocation" - }, - { - "$ref": "#/definitions/V1AlphaReportDefinition" - }, - { - "$ref": "#/definitions/V1AlphaKnownError" - }, - { - "$ref": "#/definitions/V1AlphaDoctorGroup" - } - ], - "definitions": { - "DoctorCheckSpec": { - "type": "object", - "properties": { - "commands": { - "default": null, - "type": [ - "array", - "null" - ], - "items": { - "type": "string" - }, - "nullable": true - }, - "paths": { - "default": null, - "type": [ - "array", - "null" - ], - "items": { - "type": "string" - }, - "nullable": true - } - }, - "additionalProperties": false - }, - "DoctorFixSpec": { - "type": "object", - "properties": { - "commands": { - "default": [], - "type": "array", - "items": { - "type": "string" - } - }, - "helpText": { - "default": null, - "type": [ - "string", - "null" - ], - "nullable": true - }, - "helpUrl": { - "default": null, - "type": [ - "string", - "null" - ], - "nullable": true - } - }, - "additionalProperties": false - }, - "DoctorGroupActionSpec": { - "type": "object", - "required": [ - "check" - ], - "properties": { - "check": { - "$ref": "#/definitions/DoctorCheckSpec" - }, - "description": { - "type": [ - "string", - "null" - ], - "nullable": true - }, - "fix": { - "anyOf": [ - { - "$ref": "#/definitions/DoctorFixSpec" - }, - { - "type": "null" - } - ], - "nullable": true - }, - "name": { - "type": [ - "string", - "null" - ], - "nullable": true - }, - "required": { - "default": true, - "type": "boolean" - } - }, - "additionalProperties": false - }, - "DoctorGroupKind": { - "type": "string", - "enum": [ - "ScopeDoctorGroup" - ] - }, - "DoctorGroupSpec": { - "type": "object", - "required": [ - "actions" - ], - "properties": { - "actions": { - "type": "array", - "items": { - "$ref": "#/definitions/DoctorGroupActionSpec" - } - }, - "needs": { - "default": [], - "type": "array", - "items": { - "type": "string" - } - } - }, - "additionalProperties": false - }, - "KnownErrorKind": { - "type": "string", - "enum": [ - "ScopeKnownError" - ] - }, - "KnownErrorSpec": { - "type": "object", - "required": [ - "help", - "pattern" - ], - "properties": { - "help": { - "type": "string" - }, - "pattern": { - "type": "string" - } - }, - "additionalProperties": false - }, - "ModelMetadata": { - "type": "object", - "required": [ - "name" - ], - "properties": { - "annotations": { - "default": { - "scope.github.com/bin-path": null, - "scope.github.com/file-dir": null, - "scope.github.com/file-path": null - }, - "$ref": "#/definitions/ModelMetadataAnnotations" - }, - "description": { - "default": "Description not provided", - "type": "string" - }, - "labels": { - "default": {}, - "type": "object", - "additionalProperties": { - "type": "string" - } - }, - "name": { - "type": "string" - } - } - }, - "ModelMetadataAnnotations": { - "type": "object", - "properties": { - "scope.github.com/bin-path": { - "type": [ - "string", - "null" - ], - "nullable": true - }, - "scope.github.com/file-dir": { - "type": [ - "string", - "null" - ], - "nullable": true - }, - "scope.github.com/file-path": { - "type": [ - "string", - "null" - ], - "nullable": true - } - } - }, - "ReportDefinitionKind": { - "type": "string", - "enum": [ - "ScopeReportDefinition" - ] - }, - "ReportDefinitionSpec": { - "type": "object", - "required": [ - "template" - ], - "properties": { - "additionalData": { - "default": {}, - "type": "object", - "additionalProperties": { - "type": "string" - } - }, - "template": { - "type": "string" - } - }, - "additionalProperties": false - }, - "ReportDestinationGithubIssueSpec": { - "type": "object", - "required": [ - "owner", - "repo" - ], - "properties": { - "owner": { - "type": "string" - }, - "repo": { - "type": "string" - }, - "tags": { - "default": [], - "type": "array", - "items": { - "type": "string" - } - } - }, - "additionalProperties": false - }, - "ReportDestinationSpec": { - "oneOf": [ - { - "type": "object", - "required": [ - "rustyPaste" - ], - "properties": { - "rustyPaste": { - "type": "object", - "required": [ - "url" - ], - "properties": { - "url": { - "type": "string" - } - }, - "additionalProperties": false - } - }, - "additionalProperties": false - }, - { - "type": "object", - "required": [ - "githubIssue" - ], - "properties": { - "githubIssue": { - "$ref": "#/definitions/ReportDestinationGithubIssueSpec" - } - }, - "additionalProperties": false - } - ] - }, - "ReportLocationKind": { - "type": "string", - "enum": [ - "ScopeReportLocation" - ] - }, - "ReportLocationSpec": { - "type": "object", - "required": [ - "destination" - ], - "properties": { - "destination": { - "$ref": "#/definitions/ReportDestinationSpec" - } - }, - "additionalProperties": false - }, - "V1AlphaApiVersion": { - "type": "string", - "enum": [ - "scope.github.com/v1alpha" - ] - }, - "V1AlphaDoctorGroup": { - "type": "object", - "required": [ - "apiVersion", - "kind", - "metadata", - "spec" - ], - "properties": { - "apiVersion": { - "$ref": "#/definitions/V1AlphaApiVersion" - }, - "kind": { - "$ref": "#/definitions/DoctorGroupKind" - }, - "metadata": { - "$ref": "#/definitions/ModelMetadata" - }, - "spec": { - "$ref": "#/definitions/DoctorGroupSpec" - } - }, - "additionalProperties": false - }, - "V1AlphaKnownError": { - "type": "object", - "required": [ - "apiVersion", - "kind", - "metadata", - "spec" - ], - "properties": { - "apiVersion": { - "$ref": "#/definitions/V1AlphaApiVersion" - }, - "kind": { - "$ref": "#/definitions/KnownErrorKind" - }, - "metadata": { - "$ref": "#/definitions/ModelMetadata" - }, - "spec": { - "$ref": "#/definitions/KnownErrorSpec" - } - }, - "additionalProperties": false - }, - "V1AlphaReportDefinition": { - "type": "object", - "required": [ - "apiVersion", - "kind", - "metadata", - "spec" - ], - "properties": { - "apiVersion": { - "$ref": "#/definitions/V1AlphaApiVersion" - }, - "kind": { - "$ref": "#/definitions/ReportDefinitionKind" - }, - "metadata": { - "$ref": "#/definitions/ModelMetadata" - }, - "spec": { - "$ref": "#/definitions/ReportDefinitionSpec" - } - }, - "additionalProperties": false - }, - "V1AlphaReportLocation": { - "type": "object", - "required": [ - "apiVersion", - "kind", - "metadata", - "spec" - ], - "properties": { - "apiVersion": { - "$ref": "#/definitions/V1AlphaApiVersion" - }, - "kind": { - "$ref": "#/definitions/ReportLocationKind" - }, - "metadata": { - "$ref": "#/definitions/ModelMetadata" - }, - "spec": { - "$ref": "#/definitions/ReportLocationSpec" - } - }, - "additionalProperties": false - } - } -} \ No newline at end of file diff --git a/scope-models/schema/v1alpha.com.github.scope.ScopeDoctorGroup.json b/scope-models/schema/v1alpha.com.github.scope.ScopeDoctorGroup.json deleted file mode 100644 index d594744..0000000 --- a/scope-models/schema/v1alpha.com.github.scope.ScopeDoctorGroup.json +++ /dev/null @@ -1,437 +0,0 @@ -{ - "$schema": "https://json-schema.org/draft/2019-09/schema", - "title": "V1AlphaDoctorGroup", - "type": "object", - "required": [ - "apiVersion", - "kind", - "metadata", - "spec" - ], - "properties": { - "apiVersion": { - "$ref": "#/definitions/V1AlphaApiVersion" - }, - "kind": { - "$ref": "#/definitions/DoctorGroupKind" - }, - "metadata": { - "$ref": "#/definitions/ModelMetadata" - }, - "spec": { - "$ref": "#/definitions/DoctorGroupSpec" - } - }, - "additionalProperties": false, - "definitions": { - "DoctorCheckSpec": { - "type": "object", - "properties": { - "commands": { - "default": null, - "type": [ - "array", - "null" - ], - "items": { - "type": "string" - }, - "nullable": true - }, - "paths": { - "default": null, - "type": [ - "array", - "null" - ], - "items": { - "type": "string" - }, - "nullable": true - } - }, - "additionalProperties": false - }, - "DoctorFixSpec": { - "type": "object", - "properties": { - "commands": { - "default": [], - "type": "array", - "items": { - "type": "string" - } - }, - "helpText": { - "default": null, - "type": [ - "string", - "null" - ], - "nullable": true - }, - "helpUrl": { - "default": null, - "type": [ - "string", - "null" - ], - "nullable": true - } - }, - "additionalProperties": false - }, - "DoctorGroupActionSpec": { - "type": "object", - "required": [ - "check" - ], - "properties": { - "check": { - "$ref": "#/definitions/DoctorCheckSpec" - }, - "description": { - "type": [ - "string", - "null" - ], - "nullable": true - }, - "fix": { - "anyOf": [ - { - "$ref": "#/definitions/DoctorFixSpec" - }, - { - "type": "null" - } - ], - "nullable": true - }, - "name": { - "type": [ - "string", - "null" - ], - "nullable": true - }, - "required": { - "default": true, - "type": "boolean" - } - }, - "additionalProperties": false - }, - "DoctorGroupKind": { - "type": "string", - "enum": [ - "ScopeDoctorGroup" - ] - }, - "DoctorGroupSpec": { - "type": "object", - "required": [ - "actions" - ], - "properties": { - "actions": { - "type": "array", - "items": { - "$ref": "#/definitions/DoctorGroupActionSpec" - } - }, - "needs": { - "default": [], - "type": "array", - "items": { - "type": "string" - } - } - }, - "additionalProperties": false - }, - "KnownErrorKind": { - "type": "string", - "enum": [ - "ScopeKnownError" - ] - }, - "KnownErrorSpec": { - "type": "object", - "required": [ - "help", - "pattern" - ], - "properties": { - "help": { - "type": "string" - }, - "pattern": { - "type": "string" - } - }, - "additionalProperties": false - }, - "ModelMetadata": { - "type": "object", - "required": [ - "name" - ], - "properties": { - "annotations": { - "default": { - "scope.github.com/bin-path": null, - "scope.github.com/file-dir": null, - "scope.github.com/file-path": null - }, - "$ref": "#/definitions/ModelMetadataAnnotations" - }, - "description": { - "default": "Description not provided", - "type": "string" - }, - "labels": { - "default": {}, - "type": "object", - "additionalProperties": { - "type": "string" - } - }, - "name": { - "type": "string" - } - } - }, - "ModelMetadataAnnotations": { - "type": "object", - "properties": { - "scope.github.com/bin-path": { - "type": [ - "string", - "null" - ], - "nullable": true - }, - "scope.github.com/file-dir": { - "type": [ - "string", - "null" - ], - "nullable": true - }, - "scope.github.com/file-path": { - "type": [ - "string", - "null" - ], - "nullable": true - } - } - }, - "ReportDefinitionKind": { - "type": "string", - "enum": [ - "ScopeReportDefinition" - ] - }, - "ReportDefinitionSpec": { - "type": "object", - "required": [ - "template" - ], - "properties": { - "additionalData": { - "default": {}, - "type": "object", - "additionalProperties": { - "type": "string" - } - }, - "template": { - "type": "string" - } - }, - "additionalProperties": false - }, - "ReportDestinationGithubIssueSpec": { - "type": "object", - "required": [ - "owner", - "repo" - ], - "properties": { - "owner": { - "type": "string" - }, - "repo": { - "type": "string" - }, - "tags": { - "default": [], - "type": "array", - "items": { - "type": "string" - } - } - }, - "additionalProperties": false - }, - "ReportDestinationSpec": { - "oneOf": [ - { - "type": "object", - "required": [ - "rustyPaste" - ], - "properties": { - "rustyPaste": { - "type": "object", - "required": [ - "url" - ], - "properties": { - "url": { - "type": "string" - } - }, - "additionalProperties": false - } - }, - "additionalProperties": false - }, - { - "type": "object", - "required": [ - "githubIssue" - ], - "properties": { - "githubIssue": { - "$ref": "#/definitions/ReportDestinationGithubIssueSpec" - } - }, - "additionalProperties": false - } - ] - }, - "ReportLocationKind": { - "type": "string", - "enum": [ - "ScopeReportLocation" - ] - }, - "ReportLocationSpec": { - "type": "object", - "required": [ - "destination" - ], - "properties": { - "destination": { - "$ref": "#/definitions/ReportDestinationSpec" - } - }, - "additionalProperties": false - }, - "V1AlphaApiVersion": { - "type": "string", - "enum": [ - "scope.github.com/v1alpha" - ] - }, - "V1AlphaDoctorGroup": { - "type": "object", - "required": [ - "apiVersion", - "kind", - "metadata", - "spec" - ], - "properties": { - "apiVersion": { - "$ref": "#/definitions/V1AlphaApiVersion" - }, - "kind": { - "$ref": "#/definitions/DoctorGroupKind" - }, - "metadata": { - "$ref": "#/definitions/ModelMetadata" - }, - "spec": { - "$ref": "#/definitions/DoctorGroupSpec" - } - }, - "additionalProperties": false - }, - "V1AlphaKnownError": { - "type": "object", - "required": [ - "apiVersion", - "kind", - "metadata", - "spec" - ], - "properties": { - "apiVersion": { - "$ref": "#/definitions/V1AlphaApiVersion" - }, - "kind": { - "$ref": "#/definitions/KnownErrorKind" - }, - "metadata": { - "$ref": "#/definitions/ModelMetadata" - }, - "spec": { - "$ref": "#/definitions/KnownErrorSpec" - } - }, - "additionalProperties": false - }, - "V1AlphaReportDefinition": { - "type": "object", - "required": [ - "apiVersion", - "kind", - "metadata", - "spec" - ], - "properties": { - "apiVersion": { - "$ref": "#/definitions/V1AlphaApiVersion" - }, - "kind": { - "$ref": "#/definitions/ReportDefinitionKind" - }, - "metadata": { - "$ref": "#/definitions/ModelMetadata" - }, - "spec": { - "$ref": "#/definitions/ReportDefinitionSpec" - } - }, - "additionalProperties": false - }, - "V1AlphaReportLocation": { - "type": "object", - "required": [ - "apiVersion", - "kind", - "metadata", - "spec" - ], - "properties": { - "apiVersion": { - "$ref": "#/definitions/V1AlphaApiVersion" - }, - "kind": { - "$ref": "#/definitions/ReportLocationKind" - }, - "metadata": { - "$ref": "#/definitions/ModelMetadata" - }, - "spec": { - "$ref": "#/definitions/ReportLocationSpec" - } - }, - "additionalProperties": false - } - } -} \ No newline at end of file diff --git a/scope-models/schema/v1alpha.com.github.scope.ScopeKnownError.json b/scope-models/schema/v1alpha.com.github.scope.ScopeKnownError.json deleted file mode 100644 index 26b4058..0000000 --- a/scope-models/schema/v1alpha.com.github.scope.ScopeKnownError.json +++ /dev/null @@ -1,437 +0,0 @@ -{ - "$schema": "https://json-schema.org/draft/2019-09/schema", - "title": "V1AlphaKnownError", - "type": "object", - "required": [ - "apiVersion", - "kind", - "metadata", - "spec" - ], - "properties": { - "apiVersion": { - "$ref": "#/definitions/V1AlphaApiVersion" - }, - "kind": { - "$ref": "#/definitions/KnownErrorKind" - }, - "metadata": { - "$ref": "#/definitions/ModelMetadata" - }, - "spec": { - "$ref": "#/definitions/KnownErrorSpec" - } - }, - "additionalProperties": false, - "definitions": { - "DoctorCheckSpec": { - "type": "object", - "properties": { - "commands": { - "default": null, - "type": [ - "array", - "null" - ], - "items": { - "type": "string" - }, - "nullable": true - }, - "paths": { - "default": null, - "type": [ - "array", - "null" - ], - "items": { - "type": "string" - }, - "nullable": true - } - }, - "additionalProperties": false - }, - "DoctorFixSpec": { - "type": "object", - "properties": { - "commands": { - "default": [], - "type": "array", - "items": { - "type": "string" - } - }, - "helpText": { - "default": null, - "type": [ - "string", - "null" - ], - "nullable": true - }, - "helpUrl": { - "default": null, - "type": [ - "string", - "null" - ], - "nullable": true - } - }, - "additionalProperties": false - }, - "DoctorGroupActionSpec": { - "type": "object", - "required": [ - "check" - ], - "properties": { - "check": { - "$ref": "#/definitions/DoctorCheckSpec" - }, - "description": { - "type": [ - "string", - "null" - ], - "nullable": true - }, - "fix": { - "anyOf": [ - { - "$ref": "#/definitions/DoctorFixSpec" - }, - { - "type": "null" - } - ], - "nullable": true - }, - "name": { - "type": [ - "string", - "null" - ], - "nullable": true - }, - "required": { - "default": true, - "type": "boolean" - } - }, - "additionalProperties": false - }, - "DoctorGroupKind": { - "type": "string", - "enum": [ - "ScopeDoctorGroup" - ] - }, - "DoctorGroupSpec": { - "type": "object", - "required": [ - "actions" - ], - "properties": { - "actions": { - "type": "array", - "items": { - "$ref": "#/definitions/DoctorGroupActionSpec" - } - }, - "needs": { - "default": [], - "type": "array", - "items": { - "type": "string" - } - } - }, - "additionalProperties": false - }, - "KnownErrorKind": { - "type": "string", - "enum": [ - "ScopeKnownError" - ] - }, - "KnownErrorSpec": { - "type": "object", - "required": [ - "help", - "pattern" - ], - "properties": { - "help": { - "type": "string" - }, - "pattern": { - "type": "string" - } - }, - "additionalProperties": false - }, - "ModelMetadata": { - "type": "object", - "required": [ - "name" - ], - "properties": { - "annotations": { - "default": { - "scope.github.com/bin-path": null, - "scope.github.com/file-dir": null, - "scope.github.com/file-path": null - }, - "$ref": "#/definitions/ModelMetadataAnnotations" - }, - "description": { - "default": "Description not provided", - "type": "string" - }, - "labels": { - "default": {}, - "type": "object", - "additionalProperties": { - "type": "string" - } - }, - "name": { - "type": "string" - } - } - }, - "ModelMetadataAnnotations": { - "type": "object", - "properties": { - "scope.github.com/bin-path": { - "type": [ - "string", - "null" - ], - "nullable": true - }, - "scope.github.com/file-dir": { - "type": [ - "string", - "null" - ], - "nullable": true - }, - "scope.github.com/file-path": { - "type": [ - "string", - "null" - ], - "nullable": true - } - } - }, - "ReportDefinitionKind": { - "type": "string", - "enum": [ - "ScopeReportDefinition" - ] - }, - "ReportDefinitionSpec": { - "type": "object", - "required": [ - "template" - ], - "properties": { - "additionalData": { - "default": {}, - "type": "object", - "additionalProperties": { - "type": "string" - } - }, - "template": { - "type": "string" - } - }, - "additionalProperties": false - }, - "ReportDestinationGithubIssueSpec": { - "type": "object", - "required": [ - "owner", - "repo" - ], - "properties": { - "owner": { - "type": "string" - }, - "repo": { - "type": "string" - }, - "tags": { - "default": [], - "type": "array", - "items": { - "type": "string" - } - } - }, - "additionalProperties": false - }, - "ReportDestinationSpec": { - "oneOf": [ - { - "type": "object", - "required": [ - "rustyPaste" - ], - "properties": { - "rustyPaste": { - "type": "object", - "required": [ - "url" - ], - "properties": { - "url": { - "type": "string" - } - }, - "additionalProperties": false - } - }, - "additionalProperties": false - }, - { - "type": "object", - "required": [ - "githubIssue" - ], - "properties": { - "githubIssue": { - "$ref": "#/definitions/ReportDestinationGithubIssueSpec" - } - }, - "additionalProperties": false - } - ] - }, - "ReportLocationKind": { - "type": "string", - "enum": [ - "ScopeReportLocation" - ] - }, - "ReportLocationSpec": { - "type": "object", - "required": [ - "destination" - ], - "properties": { - "destination": { - "$ref": "#/definitions/ReportDestinationSpec" - } - }, - "additionalProperties": false - }, - "V1AlphaApiVersion": { - "type": "string", - "enum": [ - "scope.github.com/v1alpha" - ] - }, - "V1AlphaDoctorGroup": { - "type": "object", - "required": [ - "apiVersion", - "kind", - "metadata", - "spec" - ], - "properties": { - "apiVersion": { - "$ref": "#/definitions/V1AlphaApiVersion" - }, - "kind": { - "$ref": "#/definitions/DoctorGroupKind" - }, - "metadata": { - "$ref": "#/definitions/ModelMetadata" - }, - "spec": { - "$ref": "#/definitions/DoctorGroupSpec" - } - }, - "additionalProperties": false - }, - "V1AlphaKnownError": { - "type": "object", - "required": [ - "apiVersion", - "kind", - "metadata", - "spec" - ], - "properties": { - "apiVersion": { - "$ref": "#/definitions/V1AlphaApiVersion" - }, - "kind": { - "$ref": "#/definitions/KnownErrorKind" - }, - "metadata": { - "$ref": "#/definitions/ModelMetadata" - }, - "spec": { - "$ref": "#/definitions/KnownErrorSpec" - } - }, - "additionalProperties": false - }, - "V1AlphaReportDefinition": { - "type": "object", - "required": [ - "apiVersion", - "kind", - "metadata", - "spec" - ], - "properties": { - "apiVersion": { - "$ref": "#/definitions/V1AlphaApiVersion" - }, - "kind": { - "$ref": "#/definitions/ReportDefinitionKind" - }, - "metadata": { - "$ref": "#/definitions/ModelMetadata" - }, - "spec": { - "$ref": "#/definitions/ReportDefinitionSpec" - } - }, - "additionalProperties": false - }, - "V1AlphaReportLocation": { - "type": "object", - "required": [ - "apiVersion", - "kind", - "metadata", - "spec" - ], - "properties": { - "apiVersion": { - "$ref": "#/definitions/V1AlphaApiVersion" - }, - "kind": { - "$ref": "#/definitions/ReportLocationKind" - }, - "metadata": { - "$ref": "#/definitions/ModelMetadata" - }, - "spec": { - "$ref": "#/definitions/ReportLocationSpec" - } - }, - "additionalProperties": false - } - } -} \ No newline at end of file diff --git a/scope-models/schema/v1alpha.com.github.scope.ScopeReportDefinition.json b/scope-models/schema/v1alpha.com.github.scope.ScopeReportDefinition.json deleted file mode 100644 index 7375068..0000000 --- a/scope-models/schema/v1alpha.com.github.scope.ScopeReportDefinition.json +++ /dev/null @@ -1,437 +0,0 @@ -{ - "$schema": "https://json-schema.org/draft/2019-09/schema", - "title": "V1AlphaReportDefinition", - "type": "object", - "required": [ - "apiVersion", - "kind", - "metadata", - "spec" - ], - "properties": { - "apiVersion": { - "$ref": "#/definitions/V1AlphaApiVersion" - }, - "kind": { - "$ref": "#/definitions/ReportDefinitionKind" - }, - "metadata": { - "$ref": "#/definitions/ModelMetadata" - }, - "spec": { - "$ref": "#/definitions/ReportDefinitionSpec" - } - }, - "additionalProperties": false, - "definitions": { - "DoctorCheckSpec": { - "type": "object", - "properties": { - "commands": { - "default": null, - "type": [ - "array", - "null" - ], - "items": { - "type": "string" - }, - "nullable": true - }, - "paths": { - "default": null, - "type": [ - "array", - "null" - ], - "items": { - "type": "string" - }, - "nullable": true - } - }, - "additionalProperties": false - }, - "DoctorFixSpec": { - "type": "object", - "properties": { - "commands": { - "default": [], - "type": "array", - "items": { - "type": "string" - } - }, - "helpText": { - "default": null, - "type": [ - "string", - "null" - ], - "nullable": true - }, - "helpUrl": { - "default": null, - "type": [ - "string", - "null" - ], - "nullable": true - } - }, - "additionalProperties": false - }, - "DoctorGroupActionSpec": { - "type": "object", - "required": [ - "check" - ], - "properties": { - "check": { - "$ref": "#/definitions/DoctorCheckSpec" - }, - "description": { - "type": [ - "string", - "null" - ], - "nullable": true - }, - "fix": { - "anyOf": [ - { - "$ref": "#/definitions/DoctorFixSpec" - }, - { - "type": "null" - } - ], - "nullable": true - }, - "name": { - "type": [ - "string", - "null" - ], - "nullable": true - }, - "required": { - "default": true, - "type": "boolean" - } - }, - "additionalProperties": false - }, - "DoctorGroupKind": { - "type": "string", - "enum": [ - "ScopeDoctorGroup" - ] - }, - "DoctorGroupSpec": { - "type": "object", - "required": [ - "actions" - ], - "properties": { - "actions": { - "type": "array", - "items": { - "$ref": "#/definitions/DoctorGroupActionSpec" - } - }, - "needs": { - "default": [], - "type": "array", - "items": { - "type": "string" - } - } - }, - "additionalProperties": false - }, - "KnownErrorKind": { - "type": "string", - "enum": [ - "ScopeKnownError" - ] - }, - "KnownErrorSpec": { - "type": "object", - "required": [ - "help", - "pattern" - ], - "properties": { - "help": { - "type": "string" - }, - "pattern": { - "type": "string" - } - }, - "additionalProperties": false - }, - "ModelMetadata": { - "type": "object", - "required": [ - "name" - ], - "properties": { - "annotations": { - "default": { - "scope.github.com/bin-path": null, - "scope.github.com/file-dir": null, - "scope.github.com/file-path": null - }, - "$ref": "#/definitions/ModelMetadataAnnotations" - }, - "description": { - "default": "Description not provided", - "type": "string" - }, - "labels": { - "default": {}, - "type": "object", - "additionalProperties": { - "type": "string" - } - }, - "name": { - "type": "string" - } - } - }, - "ModelMetadataAnnotations": { - "type": "object", - "properties": { - "scope.github.com/bin-path": { - "type": [ - "string", - "null" - ], - "nullable": true - }, - "scope.github.com/file-dir": { - "type": [ - "string", - "null" - ], - "nullable": true - }, - "scope.github.com/file-path": { - "type": [ - "string", - "null" - ], - "nullable": true - } - } - }, - "ReportDefinitionKind": { - "type": "string", - "enum": [ - "ScopeReportDefinition" - ] - }, - "ReportDefinitionSpec": { - "type": "object", - "required": [ - "template" - ], - "properties": { - "additionalData": { - "default": {}, - "type": "object", - "additionalProperties": { - "type": "string" - } - }, - "template": { - "type": "string" - } - }, - "additionalProperties": false - }, - "ReportDestinationGithubIssueSpec": { - "type": "object", - "required": [ - "owner", - "repo" - ], - "properties": { - "owner": { - "type": "string" - }, - "repo": { - "type": "string" - }, - "tags": { - "default": [], - "type": "array", - "items": { - "type": "string" - } - } - }, - "additionalProperties": false - }, - "ReportDestinationSpec": { - "oneOf": [ - { - "type": "object", - "required": [ - "rustyPaste" - ], - "properties": { - "rustyPaste": { - "type": "object", - "required": [ - "url" - ], - "properties": { - "url": { - "type": "string" - } - }, - "additionalProperties": false - } - }, - "additionalProperties": false - }, - { - "type": "object", - "required": [ - "githubIssue" - ], - "properties": { - "githubIssue": { - "$ref": "#/definitions/ReportDestinationGithubIssueSpec" - } - }, - "additionalProperties": false - } - ] - }, - "ReportLocationKind": { - "type": "string", - "enum": [ - "ScopeReportLocation" - ] - }, - "ReportLocationSpec": { - "type": "object", - "required": [ - "destination" - ], - "properties": { - "destination": { - "$ref": "#/definitions/ReportDestinationSpec" - } - }, - "additionalProperties": false - }, - "V1AlphaApiVersion": { - "type": "string", - "enum": [ - "scope.github.com/v1alpha" - ] - }, - "V1AlphaDoctorGroup": { - "type": "object", - "required": [ - "apiVersion", - "kind", - "metadata", - "spec" - ], - "properties": { - "apiVersion": { - "$ref": "#/definitions/V1AlphaApiVersion" - }, - "kind": { - "$ref": "#/definitions/DoctorGroupKind" - }, - "metadata": { - "$ref": "#/definitions/ModelMetadata" - }, - "spec": { - "$ref": "#/definitions/DoctorGroupSpec" - } - }, - "additionalProperties": false - }, - "V1AlphaKnownError": { - "type": "object", - "required": [ - "apiVersion", - "kind", - "metadata", - "spec" - ], - "properties": { - "apiVersion": { - "$ref": "#/definitions/V1AlphaApiVersion" - }, - "kind": { - "$ref": "#/definitions/KnownErrorKind" - }, - "metadata": { - "$ref": "#/definitions/ModelMetadata" - }, - "spec": { - "$ref": "#/definitions/KnownErrorSpec" - } - }, - "additionalProperties": false - }, - "V1AlphaReportDefinition": { - "type": "object", - "required": [ - "apiVersion", - "kind", - "metadata", - "spec" - ], - "properties": { - "apiVersion": { - "$ref": "#/definitions/V1AlphaApiVersion" - }, - "kind": { - "$ref": "#/definitions/ReportDefinitionKind" - }, - "metadata": { - "$ref": "#/definitions/ModelMetadata" - }, - "spec": { - "$ref": "#/definitions/ReportDefinitionSpec" - } - }, - "additionalProperties": false - }, - "V1AlphaReportLocation": { - "type": "object", - "required": [ - "apiVersion", - "kind", - "metadata", - "spec" - ], - "properties": { - "apiVersion": { - "$ref": "#/definitions/V1AlphaApiVersion" - }, - "kind": { - "$ref": "#/definitions/ReportLocationKind" - }, - "metadata": { - "$ref": "#/definitions/ModelMetadata" - }, - "spec": { - "$ref": "#/definitions/ReportLocationSpec" - } - }, - "additionalProperties": false - } - } -} \ No newline at end of file diff --git a/scope-models/schema/v1alpha.com.github.scope.ScopeReportLocation.json b/scope-models/schema/v1alpha.com.github.scope.ScopeReportLocation.json deleted file mode 100644 index e9087e9..0000000 --- a/scope-models/schema/v1alpha.com.github.scope.ScopeReportLocation.json +++ /dev/null @@ -1,437 +0,0 @@ -{ - "$schema": "https://json-schema.org/draft/2019-09/schema", - "title": "V1AlphaReportLocation", - "type": "object", - "required": [ - "apiVersion", - "kind", - "metadata", - "spec" - ], - "properties": { - "apiVersion": { - "$ref": "#/definitions/V1AlphaApiVersion" - }, - "kind": { - "$ref": "#/definitions/ReportLocationKind" - }, - "metadata": { - "$ref": "#/definitions/ModelMetadata" - }, - "spec": { - "$ref": "#/definitions/ReportLocationSpec" - } - }, - "additionalProperties": false, - "definitions": { - "DoctorCheckSpec": { - "type": "object", - "properties": { - "commands": { - "default": null, - "type": [ - "array", - "null" - ], - "items": { - "type": "string" - }, - "nullable": true - }, - "paths": { - "default": null, - "type": [ - "array", - "null" - ], - "items": { - "type": "string" - }, - "nullable": true - } - }, - "additionalProperties": false - }, - "DoctorFixSpec": { - "type": "object", - "properties": { - "commands": { - "default": [], - "type": "array", - "items": { - "type": "string" - } - }, - "helpText": { - "default": null, - "type": [ - "string", - "null" - ], - "nullable": true - }, - "helpUrl": { - "default": null, - "type": [ - "string", - "null" - ], - "nullable": true - } - }, - "additionalProperties": false - }, - "DoctorGroupActionSpec": { - "type": "object", - "required": [ - "check" - ], - "properties": { - "check": { - "$ref": "#/definitions/DoctorCheckSpec" - }, - "description": { - "type": [ - "string", - "null" - ], - "nullable": true - }, - "fix": { - "anyOf": [ - { - "$ref": "#/definitions/DoctorFixSpec" - }, - { - "type": "null" - } - ], - "nullable": true - }, - "name": { - "type": [ - "string", - "null" - ], - "nullable": true - }, - "required": { - "default": true, - "type": "boolean" - } - }, - "additionalProperties": false - }, - "DoctorGroupKind": { - "type": "string", - "enum": [ - "ScopeDoctorGroup" - ] - }, - "DoctorGroupSpec": { - "type": "object", - "required": [ - "actions" - ], - "properties": { - "actions": { - "type": "array", - "items": { - "$ref": "#/definitions/DoctorGroupActionSpec" - } - }, - "needs": { - "default": [], - "type": "array", - "items": { - "type": "string" - } - } - }, - "additionalProperties": false - }, - "KnownErrorKind": { - "type": "string", - "enum": [ - "ScopeKnownError" - ] - }, - "KnownErrorSpec": { - "type": "object", - "required": [ - "help", - "pattern" - ], - "properties": { - "help": { - "type": "string" - }, - "pattern": { - "type": "string" - } - }, - "additionalProperties": false - }, - "ModelMetadata": { - "type": "object", - "required": [ - "name" - ], - "properties": { - "annotations": { - "default": { - "scope.github.com/bin-path": null, - "scope.github.com/file-dir": null, - "scope.github.com/file-path": null - }, - "$ref": "#/definitions/ModelMetadataAnnotations" - }, - "description": { - "default": "Description not provided", - "type": "string" - }, - "labels": { - "default": {}, - "type": "object", - "additionalProperties": { - "type": "string" - } - }, - "name": { - "type": "string" - } - } - }, - "ModelMetadataAnnotations": { - "type": "object", - "properties": { - "scope.github.com/bin-path": { - "type": [ - "string", - "null" - ], - "nullable": true - }, - "scope.github.com/file-dir": { - "type": [ - "string", - "null" - ], - "nullable": true - }, - "scope.github.com/file-path": { - "type": [ - "string", - "null" - ], - "nullable": true - } - } - }, - "ReportDefinitionKind": { - "type": "string", - "enum": [ - "ScopeReportDefinition" - ] - }, - "ReportDefinitionSpec": { - "type": "object", - "required": [ - "template" - ], - "properties": { - "additionalData": { - "default": {}, - "type": "object", - "additionalProperties": { - "type": "string" - } - }, - "template": { - "type": "string" - } - }, - "additionalProperties": false - }, - "ReportDestinationGithubIssueSpec": { - "type": "object", - "required": [ - "owner", - "repo" - ], - "properties": { - "owner": { - "type": "string" - }, - "repo": { - "type": "string" - }, - "tags": { - "default": [], - "type": "array", - "items": { - "type": "string" - } - } - }, - "additionalProperties": false - }, - "ReportDestinationSpec": { - "oneOf": [ - { - "type": "object", - "required": [ - "rustyPaste" - ], - "properties": { - "rustyPaste": { - "type": "object", - "required": [ - "url" - ], - "properties": { - "url": { - "type": "string" - } - }, - "additionalProperties": false - } - }, - "additionalProperties": false - }, - { - "type": "object", - "required": [ - "githubIssue" - ], - "properties": { - "githubIssue": { - "$ref": "#/definitions/ReportDestinationGithubIssueSpec" - } - }, - "additionalProperties": false - } - ] - }, - "ReportLocationKind": { - "type": "string", - "enum": [ - "ScopeReportLocation" - ] - }, - "ReportLocationSpec": { - "type": "object", - "required": [ - "destination" - ], - "properties": { - "destination": { - "$ref": "#/definitions/ReportDestinationSpec" - } - }, - "additionalProperties": false - }, - "V1AlphaApiVersion": { - "type": "string", - "enum": [ - "scope.github.com/v1alpha" - ] - }, - "V1AlphaDoctorGroup": { - "type": "object", - "required": [ - "apiVersion", - "kind", - "metadata", - "spec" - ], - "properties": { - "apiVersion": { - "$ref": "#/definitions/V1AlphaApiVersion" - }, - "kind": { - "$ref": "#/definitions/DoctorGroupKind" - }, - "metadata": { - "$ref": "#/definitions/ModelMetadata" - }, - "spec": { - "$ref": "#/definitions/DoctorGroupSpec" - } - }, - "additionalProperties": false - }, - "V1AlphaKnownError": { - "type": "object", - "required": [ - "apiVersion", - "kind", - "metadata", - "spec" - ], - "properties": { - "apiVersion": { - "$ref": "#/definitions/V1AlphaApiVersion" - }, - "kind": { - "$ref": "#/definitions/KnownErrorKind" - }, - "metadata": { - "$ref": "#/definitions/ModelMetadata" - }, - "spec": { - "$ref": "#/definitions/KnownErrorSpec" - } - }, - "additionalProperties": false - }, - "V1AlphaReportDefinition": { - "type": "object", - "required": [ - "apiVersion", - "kind", - "metadata", - "spec" - ], - "properties": { - "apiVersion": { - "$ref": "#/definitions/V1AlphaApiVersion" - }, - "kind": { - "$ref": "#/definitions/ReportDefinitionKind" - }, - "metadata": { - "$ref": "#/definitions/ModelMetadata" - }, - "spec": { - "$ref": "#/definitions/ReportDefinitionSpec" - } - }, - "additionalProperties": false - }, - "V1AlphaReportLocation": { - "type": "object", - "required": [ - "apiVersion", - "kind", - "metadata", - "spec" - ], - "properties": { - "apiVersion": { - "$ref": "#/definitions/V1AlphaApiVersion" - }, - "kind": { - "$ref": "#/definitions/ReportLocationKind" - }, - "metadata": { - "$ref": "#/definitions/ModelMetadata" - }, - "spec": { - "$ref": "#/definitions/ReportLocationSpec" - } - }, - "additionalProperties": false - } - } -} \ No newline at end of file diff --git a/scope/Cargo.toml b/scope/Cargo.toml index 7ec8865..426eb4d 100644 --- a/scope/Cargo.toml +++ b/scope/Cargo.toml @@ -23,7 +23,6 @@ name = "scope" name = "scope-intercept" [dependencies] -dev-scope-model = { path = "../scope-models" } clap = { version = "4.4.11", features = ["derive", "env"]} human-panic = "1.0.3" tokio = { version = "1", features = ["full"] } @@ -52,16 +51,16 @@ glob = "0.3" educe = "0.5.11" petgraph = "0.6.4" sha256 = "1.5.0" -anyhow = { workspace = true } -thiserror = { workspace = true } -serde = {workspace = true} -serde_yaml = { workspace = true } -serde_json = { workspace = true } -schemars = { workspace = true } -derive_builder = { workspace = true } -strum = {workspace = true} -jsonschema = { workspace = true } -tracing = { workspace = true } +anyhow = "1.0.57" +thiserror = "1.0.30" +serde = { version = "1.0", features = ["derive"] } +serde_yaml = "0.9" +serde_json = "1.0" +schemars = "0.8" +derive_builder = "0.20" +strum = { version = "0.26", features = ["derive"] } +jsonschema = "0.17" +tracing = "0.1.34" [dev-dependencies] assert_cmd = "2.0.12" diff --git a/scope-models/examples/v1alpha/DoctorGroup.yaml b/scope/examples/v1alpha/DoctorGroup.yaml similarity index 100% rename from scope-models/examples/v1alpha/DoctorGroup.yaml rename to scope/examples/v1alpha/DoctorGroup.yaml diff --git a/scope-models/examples/v1alpha/KnownError.yaml b/scope/examples/v1alpha/KnownError.yaml similarity index 100% rename from scope-models/examples/v1alpha/KnownError.yaml rename to scope/examples/v1alpha/KnownError.yaml diff --git a/scope-models/examples/v1alpha/ReportDefinition.yaml b/scope/examples/v1alpha/ReportDefinition.yaml similarity index 100% rename from scope-models/examples/v1alpha/ReportDefinition.yaml rename to scope/examples/v1alpha/ReportDefinition.yaml diff --git a/scope-models/examples/v1alpha/ReportLocation.github.yaml b/scope/examples/v1alpha/ReportLocation.github.yaml similarity index 100% rename from scope-models/examples/v1alpha/ReportLocation.github.yaml rename to scope/examples/v1alpha/ReportLocation.github.yaml diff --git a/scope-models/examples/v1alpha/ReportLocation.rustyPaste.yaml b/scope/examples/v1alpha/ReportLocation.rustyPaste.yaml similarity index 100% rename from scope-models/examples/v1alpha/ReportLocation.rustyPaste.yaml rename to scope/examples/v1alpha/ReportLocation.rustyPaste.yaml diff --git a/scope/src/analyze/cli.rs b/scope/src/analyze/cli.rs index d3a9366..be4534f 100644 --- a/scope/src/analyze/cli.rs +++ b/scope/src/analyze/cli.rs @@ -1,8 +1,8 @@ use super::error::AnalyzeError; +use crate::models::HelpMetadata; use crate::shared::prelude::FoundConfig; use anyhow::Result; use clap::{Args, Subcommand}; -use dev_scope_model::HelpMetadata; use std::collections::BTreeMap; use std::path::PathBuf; use tokio::fs::File; diff --git a/scope/src/bin/scope-intercept.rs b/scope/src/bin/scope-intercept.rs index 91e35e7..9df85d0 100644 --- a/scope/src/bin/scope-intercept.rs +++ b/scope/src/bin/scope-intercept.rs @@ -1,6 +1,5 @@ use clap::Parser; use dev_scope::prelude::*; -use dev_scope_model::HelpMetadata; use human_panic::setup_panic; use std::env; use tracing::{debug, enabled, error, info, warn, Level}; diff --git a/scope/src/doctor/check.rs b/scope/src/doctor/check.rs index ebdcc13..e255448 100644 --- a/scope/src/doctor/check.rs +++ b/scope/src/doctor/check.rs @@ -3,13 +3,13 @@ use anyhow::Result; use std::cmp; use std::cmp::max; +use crate::models::HelpMetadata; use crate::shared::prelude::{ CaptureError, CaptureOpts, DoctorGroup, DoctorGroupAction, DoctorGroupActionCommand, DoctorGroupCachePath, ExecutionProvider, OutputDestination, }; use async_trait::async_trait; use derive_builder::Builder; -use dev_scope_model::HelpMetadata; use educe::Educe; use mockall::automock; use std::path::{Path, PathBuf}; diff --git a/scope/src/doctor/tests.rs b/scope/src/doctor/tests.rs index 39ef31f..393ff99 100644 --- a/scope/src/doctor/tests.rs +++ b/scope/src/doctor/tests.rs @@ -1,5 +1,5 @@ +use crate::models::prelude::{ModelMetadataAnnotations, ModelMetadataBuilder}; use crate::shared::prelude::{DoctorGroup, DoctorGroupAction, DoctorGroupBuilder}; -use dev_scope_model::prelude::{ModelMetadataAnnotations, ModelMetadataBuilder}; use std::collections::BTreeMap; pub fn make_root_model_additional( diff --git a/scope/src/lib.rs b/scope/src/lib.rs index 2f7327c..beac3b8 100644 --- a/scope/src/lib.rs +++ b/scope/src/lib.rs @@ -1,11 +1,13 @@ pub mod analyze; pub mod doctor; +pub mod models; pub mod report; pub mod shared; pub mod prelude { pub use crate::analyze::prelude::*; pub use crate::doctor::prelude::*; + pub use crate::models::prelude::*; pub use crate::report::prelude::*; pub use crate::shared::prelude::*; } diff --git a/scope-models/src/core.rs b/scope/src/models/core.rs similarity index 98% rename from scope-models/src/core.rs rename to scope/src/models/core.rs index 60cdccb..0671daa 100644 --- a/scope-models/src/core.rs +++ b/scope/src/models/core.rs @@ -1,4 +1,4 @@ -use crate::{HelpMetadata, ScopeModel}; +use crate::models::{HelpMetadata, ScopeModel}; use derive_builder::Builder; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; diff --git a/scope-models/src/lib.rs b/scope/src/models/mod.rs similarity index 94% rename from scope-models/src/lib.rs rename to scope/src/models/mod.rs index f0b0125..516195f 100644 --- a/scope-models/src/lib.rs +++ b/scope/src/models/mod.rs @@ -1,4 +1,4 @@ -use crate::core::{ModelMetadata, ModelRoot}; +use crate::models::core::{ModelMetadata, ModelRoot}; use anyhow::anyhow; use schemars::JsonSchema; @@ -10,10 +10,9 @@ mod core; mod v1alpha; pub mod prelude { - pub use crate::core::*; - pub use crate::v1alpha::prelude::*; - pub use crate::HelpMetadata; - pub use crate::ScopeModel; + pub use crate::models::core::*; + pub use crate::models::v1alpha::prelude::*; + pub use crate::models::{HelpMetadata, ScopeModel}; } pub trait HelpMetadata { @@ -148,8 +147,8 @@ where #[cfg(test)] mod schema_gen { - use crate::v1alpha::prelude::*; - use crate::InternalScopeModel; + use crate::models::v1alpha::prelude::*; + use crate::models::InternalScopeModel; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; @@ -169,7 +168,7 @@ mod schema_gen { std::fs::remove_dir_all(&out_dir).unwrap(); std::fs::create_dir_all(&out_dir).unwrap(); - let mut schema_gen = crate::make_schema_generator(); + let mut schema_gen = crate::models::make_schema_generator(); let merged_schema = schema_gen.root_schema_for::(); let merged_schema_json = serde_json::to_string_pretty(&merged_schema).unwrap(); std::fs::write(format!("{}/merged.json", out_dir), &merged_schema_json).unwrap(); diff --git a/scope-models/src/v1alpha/doctor_group.rs b/scope/src/models/v1alpha/doctor_group.rs similarity index 94% rename from scope-models/src/v1alpha/doctor_group.rs rename to scope/src/models/v1alpha/doctor_group.rs index f9d0e5b..a5a626a 100644 --- a/scope-models/src/v1alpha/doctor_group.rs +++ b/scope/src/models/v1alpha/doctor_group.rs @@ -1,7 +1,7 @@ -use crate::core::ModelMetadata; +use crate::models::core::ModelMetadata; -use crate::v1alpha::V1AlphaApiVersion; -use crate::{HelpMetadata, InternalScopeModel, ScopeModel}; +use crate::models::v1alpha::V1AlphaApiVersion; +use crate::models::{HelpMetadata, InternalScopeModel, ScopeModel}; use derive_builder::Builder; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; diff --git a/scope-models/src/v1alpha/known_error.rs b/scope/src/models/v1alpha/known_error.rs similarity index 91% rename from scope-models/src/v1alpha/known_error.rs rename to scope/src/models/v1alpha/known_error.rs index c6bc7ca..e3286bc 100644 --- a/scope-models/src/v1alpha/known_error.rs +++ b/scope/src/models/v1alpha/known_error.rs @@ -1,6 +1,6 @@ -use crate::core::ModelMetadata; -use crate::v1alpha::V1AlphaApiVersion; -use crate::{HelpMetadata, InternalScopeModel, ScopeModel}; +use crate::models::core::ModelMetadata; +use crate::models::v1alpha::V1AlphaApiVersion; +use crate::models::{HelpMetadata, InternalScopeModel, ScopeModel}; use derive_builder::Builder; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; diff --git a/scope-models/src/v1alpha/mod.rs b/scope/src/models/v1alpha/mod.rs similarity index 100% rename from scope-models/src/v1alpha/mod.rs rename to scope/src/models/v1alpha/mod.rs diff --git a/scope-models/src/v1alpha/report_definition.rs b/scope/src/models/v1alpha/report_definition.rs similarity index 92% rename from scope-models/src/v1alpha/report_definition.rs rename to scope/src/models/v1alpha/report_definition.rs index a5d2382..5ce58c2 100644 --- a/scope-models/src/v1alpha/report_definition.rs +++ b/scope/src/models/v1alpha/report_definition.rs @@ -1,9 +1,9 @@ -use crate::core::ModelMetadata; +use crate::models::core::ModelMetadata; -use crate::v1alpha::V1AlphaApiVersion; +use crate::models::v1alpha::V1AlphaApiVersion; use derive_builder::Builder; -use crate::{HelpMetadata, InternalScopeModel, ScopeModel}; +use crate::models::{HelpMetadata, InternalScopeModel, ScopeModel}; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; use std::collections::BTreeMap; diff --git a/scope-models/src/v1alpha/report_location.rs b/scope/src/models/v1alpha/report_location.rs similarity index 94% rename from scope-models/src/v1alpha/report_location.rs rename to scope/src/models/v1alpha/report_location.rs index 584136f..25bdd68 100644 --- a/scope-models/src/v1alpha/report_location.rs +++ b/scope/src/models/v1alpha/report_location.rs @@ -1,8 +1,7 @@ -use crate::core::ModelMetadata; -use crate::v1alpha::V1AlphaApiVersion; +use crate::models::core::ModelMetadata; +use crate::models::v1alpha::V1AlphaApiVersion; +use crate::models::{HelpMetadata, InternalScopeModel, ScopeModel}; use derive_builder::Builder; - -use crate::{HelpMetadata, InternalScopeModel, ScopeModel}; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; diff --git a/scope/src/shared/config_load.rs b/scope/src/shared/config_load.rs index 0ebe149..33a88c2 100644 --- a/scope/src/shared/config_load.rs +++ b/scope/src/shared/config_load.rs @@ -1,3 +1,5 @@ +use crate::models::prelude::{ModelMetadata, ModelRoot}; +use crate::models::HelpMetadata; use crate::shared::models::prelude::{ DoctorGroup, KnownError, ParsedConfig, ReportDefinition, ReportUploadLocation, }; @@ -5,8 +7,6 @@ use crate::shared::RUN_ID_ENV_VAR; use anyhow::{anyhow, Result}; use clap::{ArgGroup, Parser}; use colored::*; -use dev_scope_model::prelude::{ModelMetadata, ModelRoot}; -use dev_scope_model::HelpMetadata; use directories::{BaseDirs, UserDirs}; use itertools::Itertools; use serde::Deserialize; diff --git a/scope/src/shared/mod.rs b/scope/src/shared/mod.rs index 4adb578..12f3a47 100644 --- a/scope/src/shared/mod.rs +++ b/scope/src/shared/mod.rs @@ -1,6 +1,6 @@ use colored::Colorize; -use dev_scope_model::HelpMetadata; +use crate::models::HelpMetadata; use std::cmp::max; use std::path::Path; use tracing::info; diff --git a/scope/src/shared/models/internal/doctor_group.rs b/scope/src/shared/models/internal/doctor_group.rs index 3c43f74..87e04e7 100644 --- a/scope/src/shared/models/internal/doctor_group.rs +++ b/scope/src/shared/models/internal/doctor_group.rs @@ -1,7 +1,7 @@ +use crate::models::prelude::{ModelMetadata, V1AlphaDoctorGroup}; +use crate::models::HelpMetadata; use crate::shared::models::internal::extract_command_path; use derive_builder::Builder; -use dev_scope_model::prelude::{ModelMetadata, V1AlphaDoctorGroup}; -use dev_scope_model::HelpMetadata; use std::path::{Path, PathBuf}; #[derive(Debug, PartialEq, Clone, Builder)] diff --git a/scope/src/shared/models/internal/known_error.rs b/scope/src/shared/models/internal/known_error.rs index aceacbc..19c6f26 100644 --- a/scope/src/shared/models/internal/known_error.rs +++ b/scope/src/shared/models/internal/known_error.rs @@ -1,6 +1,6 @@ +use crate::models::prelude::{ModelMetadata, V1AlphaKnownError}; +use crate::models::HelpMetadata; use derivative::Derivative; -use dev_scope_model::prelude::{ModelMetadata, V1AlphaKnownError}; -use dev_scope_model::HelpMetadata; use regex::Regex; #[derive(Derivative)] diff --git a/scope/src/shared/models/internal/mod.rs b/scope/src/shared/models/internal/mod.rs index 567a026..ef81d0f 100644 --- a/scope/src/shared/models/internal/mod.rs +++ b/scope/src/shared/models/internal/mod.rs @@ -1,10 +1,10 @@ -use crate::shared::prelude::*; -use anyhow::anyhow; -use dev_scope_model::prelude::{ +use crate::models::prelude::{ ModelRoot, V1AlphaDoctorGroup, V1AlphaKnownError, V1AlphaReportDefinition, V1AlphaReportLocation, }; -use dev_scope_model::InternalScopeModel; +use crate::models::InternalScopeModel; +use crate::shared::prelude::*; +use anyhow::anyhow; use path_clean::PathClean; use serde_yaml::Value; use std::collections::VecDeque; diff --git a/scope/src/shared/models/internal/report_definition.rs b/scope/src/shared/models/internal/report_definition.rs index 820e3e4..cdb1c7b 100644 --- a/scope/src/shared/models/internal/report_definition.rs +++ b/scope/src/shared/models/internal/report_definition.rs @@ -1,5 +1,5 @@ -use dev_scope_model::prelude::{ModelMetadata, V1AlphaReportDefinition}; -use dev_scope_model::HelpMetadata; +use crate::models::prelude::{ModelMetadata, V1AlphaReportDefinition}; +use crate::models::HelpMetadata; use std::collections::BTreeMap; #[derive(Debug, PartialEq, Clone)] diff --git a/scope/src/shared/models/internal/upload_location.rs b/scope/src/shared/models/internal/upload_location.rs index 49e656c..4466bb5 100644 --- a/scope/src/shared/models/internal/upload_location.rs +++ b/scope/src/shared/models/internal/upload_location.rs @@ -1,5 +1,5 @@ -use dev_scope_model::prelude::{ModelMetadata, V1AlphaReportLocation}; -use dev_scope_model::HelpMetadata; +use crate::models::prelude::{ModelMetadata, V1AlphaReportLocation}; +use crate::models::HelpMetadata; #[derive(Debug, PartialEq, Clone)] pub enum ReportUploadLocationDestination { @@ -34,12 +34,12 @@ impl TryFrom for ReportUploadLocation { fn try_from(value: V1AlphaReportLocation) -> Result { let destination = match value.spec.destination { - dev_scope_model::prelude::ReportDestinationSpec::RustyPaste { ref url } => { + crate::models::prelude::ReportDestinationSpec::RustyPaste { ref url } => { ReportUploadLocationDestination::RustyPaste { url: url.to_string(), } } - dev_scope_model::prelude::ReportDestinationSpec::GithubIssue(ref github_issue) => { + crate::models::prelude::ReportDestinationSpec::GithubIssue(ref github_issue) => { ReportUploadLocationDestination::GithubIssue { owner: github_issue.owner.to_string(), repo: github_issue.repo.to_string(), From c6bad5f88dccb2f7ed985d37808d01482f45112c Mon Sep 17 00:00:00 2001 From: Ethan Hall Date: Sun, 3 Mar 2024 19:28:44 -0800 Subject: [PATCH 08/14] working on docs --- docs/docs/models/ScopeDoctorCheck.md | 49 -- ...opeDoctorGroup.md => ScopeDoctorGroup.mdx} | 6 + docs/docs/models/ScopeDoctorSetup.md | 46 -- docs/docusaurus.config.ts | 2 + docs/package.json | 1 + docs/tsconfig.json | 4 +- docs/yarn.lock | 111 ++++- scope/schema/merged.json | 429 +++++++++++++++++ ...pha.com.github.scope.ScopeDoctorGroup.json | 437 ++++++++++++++++++ ...lpha.com.github.scope.ScopeKnownError.json | 437 ++++++++++++++++++ ...om.github.scope.ScopeReportDefinition.json | 437 ++++++++++++++++++ ....com.github.scope.ScopeReportLocation.json | 437 ++++++++++++++++++ scope/src/models/mod.rs | 2 +- 13 files changed, 2298 insertions(+), 100 deletions(-) delete mode 100644 docs/docs/models/ScopeDoctorCheck.md rename docs/docs/models/{ScopeDoctorGroup.md => ScopeDoctorGroup.mdx} (93%) delete mode 100644 docs/docs/models/ScopeDoctorSetup.md create mode 100644 scope/schema/merged.json create mode 100644 scope/schema/v1alpha.com.github.scope.ScopeDoctorGroup.json create mode 100644 scope/schema/v1alpha.com.github.scope.ScopeKnownError.json create mode 100644 scope/schema/v1alpha.com.github.scope.ScopeReportDefinition.json create mode 100644 scope/schema/v1alpha.com.github.scope.ScopeReportLocation.json diff --git a/docs/docs/models/ScopeDoctorCheck.md b/docs/docs/models/ScopeDoctorCheck.md deleted file mode 100644 index faf465d..0000000 --- a/docs/docs/models/ScopeDoctorCheck.md +++ /dev/null @@ -1,49 +0,0 @@ ---- -sidebar_position: 10 ---- - -# ScopeDoctorCheck - -**Deprecated**, use [ScopeDoctorGroup](./ScopeDoctorGroup.md) instead. -Scope will translate this file to a Group when running internally. - -Looking at `doctor-check-path-exists.yaml` in the example folder. - -```yaml -apiVersion: scope.github.com/v1alpha -kind: ScopeDoctorCheck -metadata: - name: path-exists -spec: - # order: 100 # default value - check: - target: scripts/does-path-env-exist.sh - fix: - target: ../bin/truey - description: Check your shell for basic functionality - help: Your shell does not have a path env. Reload your shell. -``` - -The kind is `ScopeDoctorCheck`, letting scope know that this is a Check instruction. - -## Exit Codes - -Depending on the exit code, different effects will happen - -| Exit Code | Check Effect | Fix Effect | -|-------------|--------------------------------------------------------------------|--------------------------------------------| -| `0` | No work needed | Fix was successful | -| `1 - 99` | Work required | Fix ran, but failed | -| `100+` | Work is required, but fix should not run. Do not run other checks. | Fix ran, failed, and execution should stop | - -## Schema - -- `.spec.check.target` is a script to run, used to check if the system is working. If the script exits 0, that indicates success. Otherwise, that something is wrong. The scripts are relative to the folder containing spec file. If this file was at `$HOME/workspace/example/.scope/check.yaml` the command to run would be `$HOME/workspace/example/.scope/scripts/does-path-env-exist.sh` - -- `.spec.fix.target` is an optional command to run when the check fails. If provided, the fix will automatically run. - -- `.spec.description` is a useful description of the setup, used when listing what's available. - -- `.spec.help` text to provide to the user when the check fails, and if the fix fails. - -- `.spec.order` a number, defaulting to 100, that will change the order the step is run in. The lower the number, the earlier the step will be run. diff --git a/docs/docs/models/ScopeDoctorGroup.md b/docs/docs/models/ScopeDoctorGroup.mdx similarity index 93% rename from docs/docs/models/ScopeDoctorGroup.md rename to docs/docs/models/ScopeDoctorGroup.mdx index eb3cf44..2b14263 100644 --- a/docs/docs/models/ScopeDoctorGroup.md +++ b/docs/docs/models/ScopeDoctorGroup.mdx @@ -1,3 +1,7 @@ +import CodeBlock from '@theme/CodeBlock'; +import Schema from "@site/static/schemas/mySuperSchema.json"; +import JSONSchemaViewer from "@theme/JSONSchemaViewer"; + --- sidebar_position: 1 --- @@ -47,6 +51,8 @@ spec: - yarn install ``` + + In the example above, there are two actions, the first ensures that node is operational. ## Actions diff --git a/docs/docs/models/ScopeDoctorSetup.md b/docs/docs/models/ScopeDoctorSetup.md deleted file mode 100644 index 2d2f2ec..0000000 --- a/docs/docs/models/ScopeDoctorSetup.md +++ /dev/null @@ -1,46 +0,0 @@ ---- -sidebar_position: 11 ---- - -# ScopeDoctorSetup - -**Deprecated**, use [ScopeDoctorGroup](./ScopeDoctorGroup.md) instead. -Scope will translate this file to a Group when running internally. - -```yaml -apiVersion: scope.github.com/v1alpha -kind: ScopeDoctorSetup -metadata: - name: setup -spec: - # order: 100 # default value - cache: - paths: - - '**/requirements.txt' - setup: - exec: - - ../bin/pip-install.sh - description: You need to run bin/setup -``` - -The kind is `ScopeDoctorSetup`, letting scope know that this is a Setup instruction. - -## Exit Codes - -Depending on the exit code, different effects will happen - -| Exit Code | Setup | -|-------------|----------------------------------------------------| -| `0` | Fix was successful | -| `1 - 99` | Fix ran, but failed, other steps should still run. | -| `100+` | Fix ran, failed, and execution should stop | - -## Schema - -- `.spec.cache.paths` is an array of `globstar` files that will be used to check for changes. These paths are relative to the "project dir". If this file was at `$HOME/workspace/example/.scope/doctor-setup.yaml` the project dir would be `$HOME/workspace/example`. For this example, the search glob would be `$HOME/workspace/example/**/requirements.txt`. - -- `.spec.setup.exec` is an array of commands to run when the cache is "busted". The scripts are relative to the folder containing spec file. If this file was at `$HOME/workspace/example/.scope/doctor-setup.yaml` the command to run would be `$HOME/workspace/example/.scope/../bin/pip-install.sh` - -- `.spec.description` is a useful description of the setup, used when listing what's available. - -- `.spec.order` a number, defaulting to 100, that will change the order the step is run in. The lower the number, the earlier the step will be run. diff --git a/docs/docusaurus.config.ts b/docs/docusaurus.config.ts index d8e0327..7e8a5cd 100644 --- a/docs/docusaurus.config.ts +++ b/docs/docusaurus.config.ts @@ -47,6 +47,8 @@ const config: Config = { } satisfies Preset.Options, ], ], + // Allows use of @theme/JSONSchemaEditor or @theme/JSONSchemaViewer + themes: ["docusaurus-json-schema-plugin"], themeConfig: { colorMode: { diff --git a/docs/package.json b/docs/package.json index 441a9ac..af3e282 100644 --- a/docs/package.json +++ b/docs/package.json @@ -19,6 +19,7 @@ "@docusaurus/preset-classic": "3.1.0", "@mdx-js/react": "^3.0.0", "clsx": "^2.0.0", + "docusaurus-json-schema-plugin": "^1.11.0", "prism-react-renderer": "^2.3.0", "react": "^18.0.0", "react-dom": "^18.0.0" diff --git a/docs/tsconfig.json b/docs/tsconfig.json index 314eab8..24386fe 100644 --- a/docs/tsconfig.json +++ b/docs/tsconfig.json @@ -2,6 +2,8 @@ // This file is not used in compilation. It is here just for a nice editor experience. "extends": "@docusaurus/tsconfig", "compilerOptions": { - "baseUrl": "." + "baseUrl": ".", + "resolveJsonModule": true, + "types": ["node", "@docusaurus/module-type-aliases", "@docusaurus/theme-classic", "docusaurus-json-schema-plugin"] } } diff --git a/docs/yarn.lock b/docs/yarn.lock index 7169dee..82e9f67 100644 --- a/docs/yarn.lock +++ b/docs/yarn.lock @@ -1855,6 +1855,52 @@ p-map "^4.0.0" webpack-sources "^3.2.2" +"@stoplight/json-ref-resolver@^3.1.5": + version "3.1.6" + resolved "https://registry.yarnpkg.com/@stoplight/json-ref-resolver/-/json-ref-resolver-3.1.6.tgz#dcf8724472b7d54e8e8952510f39b8ee901dcf56" + integrity sha512-YNcWv3R3n3U6iQYBsFOiWSuRGE5su1tJSiX6pAPRVk7dP0L7lqCteXGzuVRQ0gMZqUl8v1P0+fAKxF6PLo9B5A== + dependencies: + "@stoplight/json" "^3.21.0" + "@stoplight/path" "^1.3.2" + "@stoplight/types" "^12.3.0 || ^13.0.0" + "@types/urijs" "^1.19.19" + dependency-graph "~0.11.0" + fast-memoize "^2.5.2" + immer "^9.0.6" + lodash "^4.17.21" + tslib "^2.6.0" + urijs "^1.19.11" + +"@stoplight/json@^3.21.0": + version "3.21.0" + resolved "https://registry.yarnpkg.com/@stoplight/json/-/json-3.21.0.tgz#c0dff9c478f3365d7946cb6e34c17cc2fa84250b" + integrity sha512-5O0apqJ/t4sIevXCO3SBN9AHCEKKR/Zb4gaj7wYe5863jme9g02Q0n/GhM7ZCALkL+vGPTe4ZzTETP8TFtsw3g== + dependencies: + "@stoplight/ordered-object-literal" "^1.0.3" + "@stoplight/path" "^1.3.2" + "@stoplight/types" "^13.6.0" + jsonc-parser "~2.2.1" + lodash "^4.17.21" + safe-stable-stringify "^1.1" + +"@stoplight/ordered-object-literal@^1.0.3": + version "1.0.5" + resolved "https://registry.yarnpkg.com/@stoplight/ordered-object-literal/-/ordered-object-literal-1.0.5.tgz#06689095a4f1a53e9d9a5f0055f707c387af966a" + integrity sha512-COTiuCU5bgMUtbIFBuyyh2/yVVzlr5Om0v5utQDgBCuQUOPgU1DwoffkTfg4UBQOvByi5foF4w4T+H9CoRe5wg== + +"@stoplight/path@^1.3.2": + version "1.3.2" + resolved "https://registry.yarnpkg.com/@stoplight/path/-/path-1.3.2.tgz#96e591496b72fde0f0cdae01a61d64f065bd9ede" + integrity sha512-lyIc6JUlUA8Ve5ELywPC8I2Sdnh1zc1zmbYgVarhXIp9YeAB0ReeqmGEOWNtlHkbP2DAA1AL65Wfn2ncjK/jtQ== + +"@stoplight/types@^12.3.0 || ^13.0.0", "@stoplight/types@^13.6.0": + version "13.20.0" + resolved "https://registry.yarnpkg.com/@stoplight/types/-/types-13.20.0.tgz#d42682f1e3a14a3c60bdf0df08bff4023518763d" + integrity sha512-2FNTv05If7ib79VPDA/r9eUet76jewXFH2y2K5vuge6SXbRHtWBhcaRmu+6QpF4/WRNoJj5XYRSwLGXDxysBGA== + dependencies: + "@types/json-schema" "^7.0.4" + utility-types "^3.10.0" + "@svgr/babel-plugin-add-jsx-attribute@^6.5.1": version "6.5.1" resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-add-jsx-attribute/-/babel-plugin-add-jsx-attribute-6.5.1.tgz#74a5d648bd0347bda99d82409d87b8ca80b9a1ba" @@ -2292,6 +2338,11 @@ resolved "https://registry.yarnpkg.com/@types/unist/-/unist-2.0.10.tgz#04ffa7f406ab628f7f7e97ca23e290cd8ab15efc" integrity sha512-IfYcSBWE3hLpBg8+X2SEa8LVkJdJEkT2Ese2aaLs3ptGdVtABxndrMaxuFlQ1qdFf9Q5rDvDpxI3WwgvKFAsQA== +"@types/urijs@^1.19.19": + version "1.19.25" + resolved "https://registry.yarnpkg.com/@types/urijs/-/urijs-1.19.25.tgz#ac92b53e674c3b108decdbe88dc5f444a2f42f6a" + integrity sha512-XOfUup9r3Y06nFAZh3WvO0rBU4OtlfPB/vgxpjg+NRdGU6CN6djdc6OEiH+PcqHCY6eFLo9Ista73uarf4gnBg== + "@types/ws@^8.5.5": version "8.5.10" resolved "https://registry.yarnpkg.com/@types/ws/-/ws-8.5.10.tgz#4acfb517970853fa6574a3a6886791d04a396787" @@ -3520,6 +3571,11 @@ depd@~1.1.2: resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9" integrity sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ== +dependency-graph@~0.11.0: + version "0.11.0" + resolved "https://registry.yarnpkg.com/dependency-graph/-/dependency-graph-0.11.0.tgz#ac0ce7ed68a54da22165a85e97a01d53f5eb2e27" + integrity sha512-JeMq7fEshyepOWDfcfHK06N3MhyPhz++vtqWhMT5O9A3K42rdsEDpfdVqjaqaAhsw6a+ZqeDvQVtD0hFHQWrzg== + dequal@^2.0.0: version "2.0.3" resolved "https://registry.yarnpkg.com/dequal/-/dequal-2.0.3.tgz#2644214f1997d39ed0ee0ece72335490a7ac67be" @@ -3572,6 +3628,16 @@ dns-packet@^5.2.2: dependencies: "@leichtgewicht/ip-codec" "^2.0.1" +docusaurus-json-schema-plugin@^1.11.0: + version "1.11.0" + resolved "https://registry.yarnpkg.com/docusaurus-json-schema-plugin/-/docusaurus-json-schema-plugin-1.11.0.tgz#85bc1d8899163683e3207dbe7a5504079932791a" + integrity sha512-Nd2WCoO4+Ke0fDOltdlaLwGmseCRMBuDxZd+QsaPCwJbogvNggBIEqFwFpRxlW+rIOTqB7ayeZ0jS0SFHn27fA== + dependencies: + "@stoplight/json-ref-resolver" "^3.1.5" + monaco-editor "^0.44.0" + monaco-editor-webpack-plugin "^7.0.1" + react-monaco-editor "^0.55.0" + dom-converter@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/dom-converter/-/dom-converter-0.2.0.tgz#6721a9daee2e293682955b6afe416771627bb768" @@ -3961,6 +4027,11 @@ fast-json-stable-stringify@^2.0.0: resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== +fast-memoize@^2.5.2: + version "2.5.2" + resolved "https://registry.yarnpkg.com/fast-memoize/-/fast-memoize-2.5.2.tgz#79e3bb6a4ec867ea40ba0e7146816f6cdce9b57e" + integrity sha512-Ue0LwpDYErFbmNnZSF0UH6eImUwDmogUO1jyE+JbN2gsQz/jICm1Ve7t9QT0rNSsfJt+Hs4/S3GnsDVjL4HVrw== + fast-url-parser@1.1.3: version "1.1.3" resolved "https://registry.yarnpkg.com/fast-url-parser/-/fast-url-parser-1.1.3.tgz#f4af3ea9f34d8a271cf58ad2b3759f431f0b318d" @@ -4678,7 +4749,7 @@ image-size@^1.0.2: dependencies: queue "6.0.2" -immer@^9.0.7: +immer@^9.0.6, immer@^9.0.7: version "9.0.21" resolved "https://registry.yarnpkg.com/immer/-/immer-9.0.21.tgz#1e025ea31a40f24fb064f1fef23e931496330176" integrity sha512-bc4NBHqOqSfRW7POMkHd51LvClaeMXpm8dx0e8oE2GORbq5aRK7Bxl4FyzVLdGtLmvLKL7BTDBG5ACQm4HWjTA== @@ -5068,6 +5139,11 @@ json5@^2.1.2, json5@^2.2.3: resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.3.tgz#78cd6f1a19bdc12b73db5ad0c61efd66c1e29283" integrity sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg== +jsonc-parser@~2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/jsonc-parser/-/jsonc-parser-2.2.1.tgz#db73cd59d78cce28723199466b2a03d1be1df2bc" + integrity sha512-o6/yDBYccGvTz1+QFevz6l6OBZ2+fMVu2JZ9CIhzsYRX4mjaK5IyX9eldUdCmga16zlgQxyrj5pt9kzuj2C02w== + jsonfile@^6.0.1: version "6.1.0" resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-6.1.0.tgz#bc55b2634793c679ec6403094eb13698a6ec0aae" @@ -5129,7 +5205,7 @@ loader-runner@^4.2.0: resolved "https://registry.yarnpkg.com/loader-runner/-/loader-runner-4.3.0.tgz#c1b4a163b99f614830353b16755e7149ac2314e1" integrity sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg== -loader-utils@^2.0.0: +loader-utils@^2.0.0, loader-utils@^2.0.2: version "2.0.4" resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-2.0.4.tgz#8b5cb38b5c34a9a018ee1fc0e6a066d1dfcc528c" integrity sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw== @@ -5979,6 +6055,18 @@ minimist@^1.2.0: resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c" integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA== +monaco-editor-webpack-plugin@^7.0.1: + version "7.1.0" + resolved "https://registry.yarnpkg.com/monaco-editor-webpack-plugin/-/monaco-editor-webpack-plugin-7.1.0.tgz#16f265c2b5dbb5fe08681b6b3b7d00d3c5b2ee97" + integrity sha512-ZjnGINHN963JQkFqjjcBtn1XBtUATDZBMgNQhDQwd78w2ukRhFXAPNgWuacaQiDZsUr4h1rWv5Mv6eriKuOSzA== + dependencies: + loader-utils "^2.0.2" + +monaco-editor@^0.44.0: + version "0.44.0" + resolved "https://registry.yarnpkg.com/monaco-editor/-/monaco-editor-0.44.0.tgz#3c0fe3655923bbf7dd647057302070b5095b6c59" + integrity sha512-5SmjNStN6bSuSE5WPT2ZV+iYn1/yI9sd4Igtk23ChvqB7kDk9lZbB9F5frsuvpB+2njdIeGGFf2G4gbE6rCC9Q== + mrmime@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/mrmime/-/mrmime-2.0.0.tgz#151082a6e06e59a9a39b46b3e14d5cfe92b3abb4" @@ -6727,7 +6815,7 @@ prompts@^2.4.2: kleur "^3.0.3" sisteransi "^1.0.5" -prop-types@^15.6.2, prop-types@^15.7.2: +prop-types@^15.6.2, prop-types@^15.7.2, prop-types@^15.8.1: version "15.8.1" resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.8.1.tgz#67d87bf1a694f48435cf332c24af10214a3140b5" integrity sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg== @@ -6917,6 +7005,13 @@ react-loadable-ssr-addon-v5-slorber@^1.0.1: dependencies: "@babel/runtime" "^7.10.3" +react-monaco-editor@^0.55.0: + version "0.55.0" + resolved "https://registry.yarnpkg.com/react-monaco-editor/-/react-monaco-editor-0.55.0.tgz#8933e8acc28e177b8b2aaf23593716b8cebf27a8" + integrity sha512-GdEP0Q3Rn1dczfKEEyY08Nes5plWwIYU4sWRBQO0+jsQWQsKMHKCC6+hPRwR7G/4aA3V/iU9jSmWPzVJYMVFSQ== + dependencies: + prop-types "^15.8.1" + react-router-config@^5.1.1: version "5.1.1" resolved "https://registry.yarnpkg.com/react-router-config/-/react-router-config-5.1.1.tgz#0f4263d1a80c6b2dc7b9c1902c9526478194a988" @@ -7265,6 +7360,11 @@ safe-buffer@5.2.1, safe-buffer@>=5.1.0, safe-buffer@^5.1.0, safe-buffer@~5.2.0: resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== +safe-stable-stringify@^1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/safe-stable-stringify/-/safe-stable-stringify-1.1.1.tgz#c8a220ab525cd94e60ebf47ddc404d610dc5d84a" + integrity sha512-ERq4hUjKDbJfE4+XtZLFPCDi8Vb1JqaxAPTxWFLBx8XcAlf9Bda/ZJdVezs/NAfsMQScyIlUMx+Yeu7P7rx5jw== + "safer-buffer@>= 2.1.2 < 3": version "2.1.2" resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" @@ -8040,6 +8140,11 @@ uri-js@^4.2.2: dependencies: punycode "^2.1.0" +urijs@^1.19.11: + version "1.19.11" + resolved "https://registry.yarnpkg.com/urijs/-/urijs-1.19.11.tgz#204b0d6b605ae80bea54bea39280cdb7c9f923cc" + integrity sha512-HXgFDgDommxn5/bIv0cnQZsPhHDA90NPHD6+c/v21U5+Sx5hoP8+dP9IZXBU1gIfvdRfhG8cel9QNPeionfcCQ== + url-loader@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/url-loader/-/url-loader-4.1.1.tgz#28505e905cae158cf07c92ca622d7f237e70a4e2" diff --git a/scope/schema/merged.json b/scope/schema/merged.json new file mode 100644 index 0000000..fd21237 --- /dev/null +++ b/scope/schema/merged.json @@ -0,0 +1,429 @@ +{ + "$schema": "https://json-schema.org/draft/2019-09/schema", + "title": "ScopeTypes", + "anyOf": [ + { + "$ref": "#/definitions/V1AlphaReportLocation" + }, + { + "$ref": "#/definitions/V1AlphaReportDefinition" + }, + { + "$ref": "#/definitions/V1AlphaKnownError" + }, + { + "$ref": "#/definitions/V1AlphaDoctorGroup" + } + ], + "definitions": { + "DoctorCheckSpec": { + "type": "object", + "properties": { + "commands": { + "default": null, + "type": [ + "array", + "null" + ], + "items": { + "type": "string" + }, + "nullable": true + }, + "paths": { + "default": null, + "type": [ + "array", + "null" + ], + "items": { + "type": "string" + }, + "nullable": true + } + }, + "additionalProperties": false + }, + "DoctorFixSpec": { + "type": "object", + "properties": { + "commands": { + "default": [], + "type": "array", + "items": { + "type": "string" + } + }, + "helpText": { + "default": null, + "type": [ + "string", + "null" + ], + "nullable": true + }, + "helpUrl": { + "default": null, + "type": [ + "string", + "null" + ], + "nullable": true + } + }, + "additionalProperties": false + }, + "DoctorGroupActionSpec": { + "type": "object", + "required": [ + "check" + ], + "properties": { + "check": { + "$ref": "#/definitions/DoctorCheckSpec" + }, + "description": { + "type": [ + "string", + "null" + ], + "nullable": true + }, + "fix": { + "anyOf": [ + { + "$ref": "#/definitions/DoctorFixSpec" + }, + { + "type": "null" + } + ], + "nullable": true + }, + "name": { + "type": [ + "string", + "null" + ], + "nullable": true + }, + "required": { + "default": true, + "type": "boolean" + } + }, + "additionalProperties": false + }, + "DoctorGroupKind": { + "type": "string", + "enum": [ + "ScopeDoctorGroup" + ] + }, + "DoctorGroupSpec": { + "type": "object", + "required": [ + "actions" + ], + "properties": { + "actions": { + "type": "array", + "items": { + "$ref": "#/definitions/DoctorGroupActionSpec" + } + }, + "needs": { + "default": [], + "type": "array", + "items": { + "type": "string" + } + } + }, + "additionalProperties": false + }, + "KnownErrorKind": { + "type": "string", + "enum": [ + "ScopeKnownError" + ] + }, + "KnownErrorSpec": { + "type": "object", + "required": [ + "help", + "pattern" + ], + "properties": { + "help": { + "type": "string" + }, + "pattern": { + "type": "string" + } + }, + "additionalProperties": false + }, + "ModelMetadata": { + "type": "object", + "required": [ + "name" + ], + "properties": { + "annotations": { + "default": { + "scope.github.com/bin-path": null, + "scope.github.com/file-dir": null, + "scope.github.com/file-path": null + }, + "$ref": "#/definitions/ModelMetadataAnnotations" + }, + "description": { + "default": "Description not provided", + "type": "string" + }, + "labels": { + "default": {}, + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "name": { + "type": "string" + } + } + }, + "ModelMetadataAnnotations": { + "type": "object", + "properties": { + "scope.github.com/bin-path": { + "type": [ + "string", + "null" + ], + "nullable": true + }, + "scope.github.com/file-dir": { + "type": [ + "string", + "null" + ], + "nullable": true + }, + "scope.github.com/file-path": { + "type": [ + "string", + "null" + ], + "nullable": true + } + } + }, + "ReportDefinitionKind": { + "type": "string", + "enum": [ + "ScopeReportDefinition" + ] + }, + "ReportDefinitionSpec": { + "type": "object", + "required": [ + "template" + ], + "properties": { + "additionalData": { + "default": {}, + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "template": { + "type": "string" + } + }, + "additionalProperties": false + }, + "ReportDestinationGithubIssueSpec": { + "type": "object", + "required": [ + "owner", + "repo" + ], + "properties": { + "owner": { + "type": "string" + }, + "repo": { + "type": "string" + }, + "tags": { + "default": [], + "type": "array", + "items": { + "type": "string" + } + } + }, + "additionalProperties": false + }, + "ReportDestinationSpec": { + "oneOf": [ + { + "type": "object", + "required": [ + "rustyPaste" + ], + "properties": { + "rustyPaste": { + "type": "object", + "required": [ + "url" + ], + "properties": { + "url": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "githubIssue" + ], + "properties": { + "githubIssue": { + "$ref": "#/definitions/ReportDestinationGithubIssueSpec" + } + }, + "additionalProperties": false + } + ] + }, + "ReportLocationKind": { + "type": "string", + "enum": [ + "ScopeReportLocation" + ] + }, + "ReportLocationSpec": { + "type": "object", + "required": [ + "destination" + ], + "properties": { + "destination": { + "$ref": "#/definitions/ReportDestinationSpec" + } + }, + "additionalProperties": false + }, + "V1AlphaApiVersion": { + "type": "string", + "enum": [ + "scope.github.com/v1alpha" + ] + }, + "V1AlphaDoctorGroup": { + "type": "object", + "required": [ + "apiVersion", + "kind", + "metadata", + "spec" + ], + "properties": { + "apiVersion": { + "$ref": "#/definitions/V1AlphaApiVersion" + }, + "kind": { + "$ref": "#/definitions/DoctorGroupKind" + }, + "metadata": { + "$ref": "#/definitions/ModelMetadata" + }, + "spec": { + "$ref": "#/definitions/DoctorGroupSpec" + } + }, + "additionalProperties": false + }, + "V1AlphaKnownError": { + "type": "object", + "required": [ + "apiVersion", + "kind", + "metadata", + "spec" + ], + "properties": { + "apiVersion": { + "$ref": "#/definitions/V1AlphaApiVersion" + }, + "kind": { + "$ref": "#/definitions/KnownErrorKind" + }, + "metadata": { + "$ref": "#/definitions/ModelMetadata" + }, + "spec": { + "$ref": "#/definitions/KnownErrorSpec" + } + }, + "additionalProperties": false + }, + "V1AlphaReportDefinition": { + "type": "object", + "required": [ + "apiVersion", + "kind", + "metadata", + "spec" + ], + "properties": { + "apiVersion": { + "$ref": "#/definitions/V1AlphaApiVersion" + }, + "kind": { + "$ref": "#/definitions/ReportDefinitionKind" + }, + "metadata": { + "$ref": "#/definitions/ModelMetadata" + }, + "spec": { + "$ref": "#/definitions/ReportDefinitionSpec" + } + }, + "additionalProperties": false + }, + "V1AlphaReportLocation": { + "type": "object", + "required": [ + "apiVersion", + "kind", + "metadata", + "spec" + ], + "properties": { + "apiVersion": { + "$ref": "#/definitions/V1AlphaApiVersion" + }, + "kind": { + "$ref": "#/definitions/ReportLocationKind" + }, + "metadata": { + "$ref": "#/definitions/ModelMetadata" + }, + "spec": { + "$ref": "#/definitions/ReportLocationSpec" + } + }, + "additionalProperties": false + } + } +} \ No newline at end of file diff --git a/scope/schema/v1alpha.com.github.scope.ScopeDoctorGroup.json b/scope/schema/v1alpha.com.github.scope.ScopeDoctorGroup.json new file mode 100644 index 0000000..d594744 --- /dev/null +++ b/scope/schema/v1alpha.com.github.scope.ScopeDoctorGroup.json @@ -0,0 +1,437 @@ +{ + "$schema": "https://json-schema.org/draft/2019-09/schema", + "title": "V1AlphaDoctorGroup", + "type": "object", + "required": [ + "apiVersion", + "kind", + "metadata", + "spec" + ], + "properties": { + "apiVersion": { + "$ref": "#/definitions/V1AlphaApiVersion" + }, + "kind": { + "$ref": "#/definitions/DoctorGroupKind" + }, + "metadata": { + "$ref": "#/definitions/ModelMetadata" + }, + "spec": { + "$ref": "#/definitions/DoctorGroupSpec" + } + }, + "additionalProperties": false, + "definitions": { + "DoctorCheckSpec": { + "type": "object", + "properties": { + "commands": { + "default": null, + "type": [ + "array", + "null" + ], + "items": { + "type": "string" + }, + "nullable": true + }, + "paths": { + "default": null, + "type": [ + "array", + "null" + ], + "items": { + "type": "string" + }, + "nullable": true + } + }, + "additionalProperties": false + }, + "DoctorFixSpec": { + "type": "object", + "properties": { + "commands": { + "default": [], + "type": "array", + "items": { + "type": "string" + } + }, + "helpText": { + "default": null, + "type": [ + "string", + "null" + ], + "nullable": true + }, + "helpUrl": { + "default": null, + "type": [ + "string", + "null" + ], + "nullable": true + } + }, + "additionalProperties": false + }, + "DoctorGroupActionSpec": { + "type": "object", + "required": [ + "check" + ], + "properties": { + "check": { + "$ref": "#/definitions/DoctorCheckSpec" + }, + "description": { + "type": [ + "string", + "null" + ], + "nullable": true + }, + "fix": { + "anyOf": [ + { + "$ref": "#/definitions/DoctorFixSpec" + }, + { + "type": "null" + } + ], + "nullable": true + }, + "name": { + "type": [ + "string", + "null" + ], + "nullable": true + }, + "required": { + "default": true, + "type": "boolean" + } + }, + "additionalProperties": false + }, + "DoctorGroupKind": { + "type": "string", + "enum": [ + "ScopeDoctorGroup" + ] + }, + "DoctorGroupSpec": { + "type": "object", + "required": [ + "actions" + ], + "properties": { + "actions": { + "type": "array", + "items": { + "$ref": "#/definitions/DoctorGroupActionSpec" + } + }, + "needs": { + "default": [], + "type": "array", + "items": { + "type": "string" + } + } + }, + "additionalProperties": false + }, + "KnownErrorKind": { + "type": "string", + "enum": [ + "ScopeKnownError" + ] + }, + "KnownErrorSpec": { + "type": "object", + "required": [ + "help", + "pattern" + ], + "properties": { + "help": { + "type": "string" + }, + "pattern": { + "type": "string" + } + }, + "additionalProperties": false + }, + "ModelMetadata": { + "type": "object", + "required": [ + "name" + ], + "properties": { + "annotations": { + "default": { + "scope.github.com/bin-path": null, + "scope.github.com/file-dir": null, + "scope.github.com/file-path": null + }, + "$ref": "#/definitions/ModelMetadataAnnotations" + }, + "description": { + "default": "Description not provided", + "type": "string" + }, + "labels": { + "default": {}, + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "name": { + "type": "string" + } + } + }, + "ModelMetadataAnnotations": { + "type": "object", + "properties": { + "scope.github.com/bin-path": { + "type": [ + "string", + "null" + ], + "nullable": true + }, + "scope.github.com/file-dir": { + "type": [ + "string", + "null" + ], + "nullable": true + }, + "scope.github.com/file-path": { + "type": [ + "string", + "null" + ], + "nullable": true + } + } + }, + "ReportDefinitionKind": { + "type": "string", + "enum": [ + "ScopeReportDefinition" + ] + }, + "ReportDefinitionSpec": { + "type": "object", + "required": [ + "template" + ], + "properties": { + "additionalData": { + "default": {}, + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "template": { + "type": "string" + } + }, + "additionalProperties": false + }, + "ReportDestinationGithubIssueSpec": { + "type": "object", + "required": [ + "owner", + "repo" + ], + "properties": { + "owner": { + "type": "string" + }, + "repo": { + "type": "string" + }, + "tags": { + "default": [], + "type": "array", + "items": { + "type": "string" + } + } + }, + "additionalProperties": false + }, + "ReportDestinationSpec": { + "oneOf": [ + { + "type": "object", + "required": [ + "rustyPaste" + ], + "properties": { + "rustyPaste": { + "type": "object", + "required": [ + "url" + ], + "properties": { + "url": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "githubIssue" + ], + "properties": { + "githubIssue": { + "$ref": "#/definitions/ReportDestinationGithubIssueSpec" + } + }, + "additionalProperties": false + } + ] + }, + "ReportLocationKind": { + "type": "string", + "enum": [ + "ScopeReportLocation" + ] + }, + "ReportLocationSpec": { + "type": "object", + "required": [ + "destination" + ], + "properties": { + "destination": { + "$ref": "#/definitions/ReportDestinationSpec" + } + }, + "additionalProperties": false + }, + "V1AlphaApiVersion": { + "type": "string", + "enum": [ + "scope.github.com/v1alpha" + ] + }, + "V1AlphaDoctorGroup": { + "type": "object", + "required": [ + "apiVersion", + "kind", + "metadata", + "spec" + ], + "properties": { + "apiVersion": { + "$ref": "#/definitions/V1AlphaApiVersion" + }, + "kind": { + "$ref": "#/definitions/DoctorGroupKind" + }, + "metadata": { + "$ref": "#/definitions/ModelMetadata" + }, + "spec": { + "$ref": "#/definitions/DoctorGroupSpec" + } + }, + "additionalProperties": false + }, + "V1AlphaKnownError": { + "type": "object", + "required": [ + "apiVersion", + "kind", + "metadata", + "spec" + ], + "properties": { + "apiVersion": { + "$ref": "#/definitions/V1AlphaApiVersion" + }, + "kind": { + "$ref": "#/definitions/KnownErrorKind" + }, + "metadata": { + "$ref": "#/definitions/ModelMetadata" + }, + "spec": { + "$ref": "#/definitions/KnownErrorSpec" + } + }, + "additionalProperties": false + }, + "V1AlphaReportDefinition": { + "type": "object", + "required": [ + "apiVersion", + "kind", + "metadata", + "spec" + ], + "properties": { + "apiVersion": { + "$ref": "#/definitions/V1AlphaApiVersion" + }, + "kind": { + "$ref": "#/definitions/ReportDefinitionKind" + }, + "metadata": { + "$ref": "#/definitions/ModelMetadata" + }, + "spec": { + "$ref": "#/definitions/ReportDefinitionSpec" + } + }, + "additionalProperties": false + }, + "V1AlphaReportLocation": { + "type": "object", + "required": [ + "apiVersion", + "kind", + "metadata", + "spec" + ], + "properties": { + "apiVersion": { + "$ref": "#/definitions/V1AlphaApiVersion" + }, + "kind": { + "$ref": "#/definitions/ReportLocationKind" + }, + "metadata": { + "$ref": "#/definitions/ModelMetadata" + }, + "spec": { + "$ref": "#/definitions/ReportLocationSpec" + } + }, + "additionalProperties": false + } + } +} \ No newline at end of file diff --git a/scope/schema/v1alpha.com.github.scope.ScopeKnownError.json b/scope/schema/v1alpha.com.github.scope.ScopeKnownError.json new file mode 100644 index 0000000..26b4058 --- /dev/null +++ b/scope/schema/v1alpha.com.github.scope.ScopeKnownError.json @@ -0,0 +1,437 @@ +{ + "$schema": "https://json-schema.org/draft/2019-09/schema", + "title": "V1AlphaKnownError", + "type": "object", + "required": [ + "apiVersion", + "kind", + "metadata", + "spec" + ], + "properties": { + "apiVersion": { + "$ref": "#/definitions/V1AlphaApiVersion" + }, + "kind": { + "$ref": "#/definitions/KnownErrorKind" + }, + "metadata": { + "$ref": "#/definitions/ModelMetadata" + }, + "spec": { + "$ref": "#/definitions/KnownErrorSpec" + } + }, + "additionalProperties": false, + "definitions": { + "DoctorCheckSpec": { + "type": "object", + "properties": { + "commands": { + "default": null, + "type": [ + "array", + "null" + ], + "items": { + "type": "string" + }, + "nullable": true + }, + "paths": { + "default": null, + "type": [ + "array", + "null" + ], + "items": { + "type": "string" + }, + "nullable": true + } + }, + "additionalProperties": false + }, + "DoctorFixSpec": { + "type": "object", + "properties": { + "commands": { + "default": [], + "type": "array", + "items": { + "type": "string" + } + }, + "helpText": { + "default": null, + "type": [ + "string", + "null" + ], + "nullable": true + }, + "helpUrl": { + "default": null, + "type": [ + "string", + "null" + ], + "nullable": true + } + }, + "additionalProperties": false + }, + "DoctorGroupActionSpec": { + "type": "object", + "required": [ + "check" + ], + "properties": { + "check": { + "$ref": "#/definitions/DoctorCheckSpec" + }, + "description": { + "type": [ + "string", + "null" + ], + "nullable": true + }, + "fix": { + "anyOf": [ + { + "$ref": "#/definitions/DoctorFixSpec" + }, + { + "type": "null" + } + ], + "nullable": true + }, + "name": { + "type": [ + "string", + "null" + ], + "nullable": true + }, + "required": { + "default": true, + "type": "boolean" + } + }, + "additionalProperties": false + }, + "DoctorGroupKind": { + "type": "string", + "enum": [ + "ScopeDoctorGroup" + ] + }, + "DoctorGroupSpec": { + "type": "object", + "required": [ + "actions" + ], + "properties": { + "actions": { + "type": "array", + "items": { + "$ref": "#/definitions/DoctorGroupActionSpec" + } + }, + "needs": { + "default": [], + "type": "array", + "items": { + "type": "string" + } + } + }, + "additionalProperties": false + }, + "KnownErrorKind": { + "type": "string", + "enum": [ + "ScopeKnownError" + ] + }, + "KnownErrorSpec": { + "type": "object", + "required": [ + "help", + "pattern" + ], + "properties": { + "help": { + "type": "string" + }, + "pattern": { + "type": "string" + } + }, + "additionalProperties": false + }, + "ModelMetadata": { + "type": "object", + "required": [ + "name" + ], + "properties": { + "annotations": { + "default": { + "scope.github.com/bin-path": null, + "scope.github.com/file-dir": null, + "scope.github.com/file-path": null + }, + "$ref": "#/definitions/ModelMetadataAnnotations" + }, + "description": { + "default": "Description not provided", + "type": "string" + }, + "labels": { + "default": {}, + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "name": { + "type": "string" + } + } + }, + "ModelMetadataAnnotations": { + "type": "object", + "properties": { + "scope.github.com/bin-path": { + "type": [ + "string", + "null" + ], + "nullable": true + }, + "scope.github.com/file-dir": { + "type": [ + "string", + "null" + ], + "nullable": true + }, + "scope.github.com/file-path": { + "type": [ + "string", + "null" + ], + "nullable": true + } + } + }, + "ReportDefinitionKind": { + "type": "string", + "enum": [ + "ScopeReportDefinition" + ] + }, + "ReportDefinitionSpec": { + "type": "object", + "required": [ + "template" + ], + "properties": { + "additionalData": { + "default": {}, + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "template": { + "type": "string" + } + }, + "additionalProperties": false + }, + "ReportDestinationGithubIssueSpec": { + "type": "object", + "required": [ + "owner", + "repo" + ], + "properties": { + "owner": { + "type": "string" + }, + "repo": { + "type": "string" + }, + "tags": { + "default": [], + "type": "array", + "items": { + "type": "string" + } + } + }, + "additionalProperties": false + }, + "ReportDestinationSpec": { + "oneOf": [ + { + "type": "object", + "required": [ + "rustyPaste" + ], + "properties": { + "rustyPaste": { + "type": "object", + "required": [ + "url" + ], + "properties": { + "url": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "githubIssue" + ], + "properties": { + "githubIssue": { + "$ref": "#/definitions/ReportDestinationGithubIssueSpec" + } + }, + "additionalProperties": false + } + ] + }, + "ReportLocationKind": { + "type": "string", + "enum": [ + "ScopeReportLocation" + ] + }, + "ReportLocationSpec": { + "type": "object", + "required": [ + "destination" + ], + "properties": { + "destination": { + "$ref": "#/definitions/ReportDestinationSpec" + } + }, + "additionalProperties": false + }, + "V1AlphaApiVersion": { + "type": "string", + "enum": [ + "scope.github.com/v1alpha" + ] + }, + "V1AlphaDoctorGroup": { + "type": "object", + "required": [ + "apiVersion", + "kind", + "metadata", + "spec" + ], + "properties": { + "apiVersion": { + "$ref": "#/definitions/V1AlphaApiVersion" + }, + "kind": { + "$ref": "#/definitions/DoctorGroupKind" + }, + "metadata": { + "$ref": "#/definitions/ModelMetadata" + }, + "spec": { + "$ref": "#/definitions/DoctorGroupSpec" + } + }, + "additionalProperties": false + }, + "V1AlphaKnownError": { + "type": "object", + "required": [ + "apiVersion", + "kind", + "metadata", + "spec" + ], + "properties": { + "apiVersion": { + "$ref": "#/definitions/V1AlphaApiVersion" + }, + "kind": { + "$ref": "#/definitions/KnownErrorKind" + }, + "metadata": { + "$ref": "#/definitions/ModelMetadata" + }, + "spec": { + "$ref": "#/definitions/KnownErrorSpec" + } + }, + "additionalProperties": false + }, + "V1AlphaReportDefinition": { + "type": "object", + "required": [ + "apiVersion", + "kind", + "metadata", + "spec" + ], + "properties": { + "apiVersion": { + "$ref": "#/definitions/V1AlphaApiVersion" + }, + "kind": { + "$ref": "#/definitions/ReportDefinitionKind" + }, + "metadata": { + "$ref": "#/definitions/ModelMetadata" + }, + "spec": { + "$ref": "#/definitions/ReportDefinitionSpec" + } + }, + "additionalProperties": false + }, + "V1AlphaReportLocation": { + "type": "object", + "required": [ + "apiVersion", + "kind", + "metadata", + "spec" + ], + "properties": { + "apiVersion": { + "$ref": "#/definitions/V1AlphaApiVersion" + }, + "kind": { + "$ref": "#/definitions/ReportLocationKind" + }, + "metadata": { + "$ref": "#/definitions/ModelMetadata" + }, + "spec": { + "$ref": "#/definitions/ReportLocationSpec" + } + }, + "additionalProperties": false + } + } +} \ No newline at end of file diff --git a/scope/schema/v1alpha.com.github.scope.ScopeReportDefinition.json b/scope/schema/v1alpha.com.github.scope.ScopeReportDefinition.json new file mode 100644 index 0000000..7375068 --- /dev/null +++ b/scope/schema/v1alpha.com.github.scope.ScopeReportDefinition.json @@ -0,0 +1,437 @@ +{ + "$schema": "https://json-schema.org/draft/2019-09/schema", + "title": "V1AlphaReportDefinition", + "type": "object", + "required": [ + "apiVersion", + "kind", + "metadata", + "spec" + ], + "properties": { + "apiVersion": { + "$ref": "#/definitions/V1AlphaApiVersion" + }, + "kind": { + "$ref": "#/definitions/ReportDefinitionKind" + }, + "metadata": { + "$ref": "#/definitions/ModelMetadata" + }, + "spec": { + "$ref": "#/definitions/ReportDefinitionSpec" + } + }, + "additionalProperties": false, + "definitions": { + "DoctorCheckSpec": { + "type": "object", + "properties": { + "commands": { + "default": null, + "type": [ + "array", + "null" + ], + "items": { + "type": "string" + }, + "nullable": true + }, + "paths": { + "default": null, + "type": [ + "array", + "null" + ], + "items": { + "type": "string" + }, + "nullable": true + } + }, + "additionalProperties": false + }, + "DoctorFixSpec": { + "type": "object", + "properties": { + "commands": { + "default": [], + "type": "array", + "items": { + "type": "string" + } + }, + "helpText": { + "default": null, + "type": [ + "string", + "null" + ], + "nullable": true + }, + "helpUrl": { + "default": null, + "type": [ + "string", + "null" + ], + "nullable": true + } + }, + "additionalProperties": false + }, + "DoctorGroupActionSpec": { + "type": "object", + "required": [ + "check" + ], + "properties": { + "check": { + "$ref": "#/definitions/DoctorCheckSpec" + }, + "description": { + "type": [ + "string", + "null" + ], + "nullable": true + }, + "fix": { + "anyOf": [ + { + "$ref": "#/definitions/DoctorFixSpec" + }, + { + "type": "null" + } + ], + "nullable": true + }, + "name": { + "type": [ + "string", + "null" + ], + "nullable": true + }, + "required": { + "default": true, + "type": "boolean" + } + }, + "additionalProperties": false + }, + "DoctorGroupKind": { + "type": "string", + "enum": [ + "ScopeDoctorGroup" + ] + }, + "DoctorGroupSpec": { + "type": "object", + "required": [ + "actions" + ], + "properties": { + "actions": { + "type": "array", + "items": { + "$ref": "#/definitions/DoctorGroupActionSpec" + } + }, + "needs": { + "default": [], + "type": "array", + "items": { + "type": "string" + } + } + }, + "additionalProperties": false + }, + "KnownErrorKind": { + "type": "string", + "enum": [ + "ScopeKnownError" + ] + }, + "KnownErrorSpec": { + "type": "object", + "required": [ + "help", + "pattern" + ], + "properties": { + "help": { + "type": "string" + }, + "pattern": { + "type": "string" + } + }, + "additionalProperties": false + }, + "ModelMetadata": { + "type": "object", + "required": [ + "name" + ], + "properties": { + "annotations": { + "default": { + "scope.github.com/bin-path": null, + "scope.github.com/file-dir": null, + "scope.github.com/file-path": null + }, + "$ref": "#/definitions/ModelMetadataAnnotations" + }, + "description": { + "default": "Description not provided", + "type": "string" + }, + "labels": { + "default": {}, + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "name": { + "type": "string" + } + } + }, + "ModelMetadataAnnotations": { + "type": "object", + "properties": { + "scope.github.com/bin-path": { + "type": [ + "string", + "null" + ], + "nullable": true + }, + "scope.github.com/file-dir": { + "type": [ + "string", + "null" + ], + "nullable": true + }, + "scope.github.com/file-path": { + "type": [ + "string", + "null" + ], + "nullable": true + } + } + }, + "ReportDefinitionKind": { + "type": "string", + "enum": [ + "ScopeReportDefinition" + ] + }, + "ReportDefinitionSpec": { + "type": "object", + "required": [ + "template" + ], + "properties": { + "additionalData": { + "default": {}, + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "template": { + "type": "string" + } + }, + "additionalProperties": false + }, + "ReportDestinationGithubIssueSpec": { + "type": "object", + "required": [ + "owner", + "repo" + ], + "properties": { + "owner": { + "type": "string" + }, + "repo": { + "type": "string" + }, + "tags": { + "default": [], + "type": "array", + "items": { + "type": "string" + } + } + }, + "additionalProperties": false + }, + "ReportDestinationSpec": { + "oneOf": [ + { + "type": "object", + "required": [ + "rustyPaste" + ], + "properties": { + "rustyPaste": { + "type": "object", + "required": [ + "url" + ], + "properties": { + "url": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "githubIssue" + ], + "properties": { + "githubIssue": { + "$ref": "#/definitions/ReportDestinationGithubIssueSpec" + } + }, + "additionalProperties": false + } + ] + }, + "ReportLocationKind": { + "type": "string", + "enum": [ + "ScopeReportLocation" + ] + }, + "ReportLocationSpec": { + "type": "object", + "required": [ + "destination" + ], + "properties": { + "destination": { + "$ref": "#/definitions/ReportDestinationSpec" + } + }, + "additionalProperties": false + }, + "V1AlphaApiVersion": { + "type": "string", + "enum": [ + "scope.github.com/v1alpha" + ] + }, + "V1AlphaDoctorGroup": { + "type": "object", + "required": [ + "apiVersion", + "kind", + "metadata", + "spec" + ], + "properties": { + "apiVersion": { + "$ref": "#/definitions/V1AlphaApiVersion" + }, + "kind": { + "$ref": "#/definitions/DoctorGroupKind" + }, + "metadata": { + "$ref": "#/definitions/ModelMetadata" + }, + "spec": { + "$ref": "#/definitions/DoctorGroupSpec" + } + }, + "additionalProperties": false + }, + "V1AlphaKnownError": { + "type": "object", + "required": [ + "apiVersion", + "kind", + "metadata", + "spec" + ], + "properties": { + "apiVersion": { + "$ref": "#/definitions/V1AlphaApiVersion" + }, + "kind": { + "$ref": "#/definitions/KnownErrorKind" + }, + "metadata": { + "$ref": "#/definitions/ModelMetadata" + }, + "spec": { + "$ref": "#/definitions/KnownErrorSpec" + } + }, + "additionalProperties": false + }, + "V1AlphaReportDefinition": { + "type": "object", + "required": [ + "apiVersion", + "kind", + "metadata", + "spec" + ], + "properties": { + "apiVersion": { + "$ref": "#/definitions/V1AlphaApiVersion" + }, + "kind": { + "$ref": "#/definitions/ReportDefinitionKind" + }, + "metadata": { + "$ref": "#/definitions/ModelMetadata" + }, + "spec": { + "$ref": "#/definitions/ReportDefinitionSpec" + } + }, + "additionalProperties": false + }, + "V1AlphaReportLocation": { + "type": "object", + "required": [ + "apiVersion", + "kind", + "metadata", + "spec" + ], + "properties": { + "apiVersion": { + "$ref": "#/definitions/V1AlphaApiVersion" + }, + "kind": { + "$ref": "#/definitions/ReportLocationKind" + }, + "metadata": { + "$ref": "#/definitions/ModelMetadata" + }, + "spec": { + "$ref": "#/definitions/ReportLocationSpec" + } + }, + "additionalProperties": false + } + } +} \ No newline at end of file diff --git a/scope/schema/v1alpha.com.github.scope.ScopeReportLocation.json b/scope/schema/v1alpha.com.github.scope.ScopeReportLocation.json new file mode 100644 index 0000000..e9087e9 --- /dev/null +++ b/scope/schema/v1alpha.com.github.scope.ScopeReportLocation.json @@ -0,0 +1,437 @@ +{ + "$schema": "https://json-schema.org/draft/2019-09/schema", + "title": "V1AlphaReportLocation", + "type": "object", + "required": [ + "apiVersion", + "kind", + "metadata", + "spec" + ], + "properties": { + "apiVersion": { + "$ref": "#/definitions/V1AlphaApiVersion" + }, + "kind": { + "$ref": "#/definitions/ReportLocationKind" + }, + "metadata": { + "$ref": "#/definitions/ModelMetadata" + }, + "spec": { + "$ref": "#/definitions/ReportLocationSpec" + } + }, + "additionalProperties": false, + "definitions": { + "DoctorCheckSpec": { + "type": "object", + "properties": { + "commands": { + "default": null, + "type": [ + "array", + "null" + ], + "items": { + "type": "string" + }, + "nullable": true + }, + "paths": { + "default": null, + "type": [ + "array", + "null" + ], + "items": { + "type": "string" + }, + "nullable": true + } + }, + "additionalProperties": false + }, + "DoctorFixSpec": { + "type": "object", + "properties": { + "commands": { + "default": [], + "type": "array", + "items": { + "type": "string" + } + }, + "helpText": { + "default": null, + "type": [ + "string", + "null" + ], + "nullable": true + }, + "helpUrl": { + "default": null, + "type": [ + "string", + "null" + ], + "nullable": true + } + }, + "additionalProperties": false + }, + "DoctorGroupActionSpec": { + "type": "object", + "required": [ + "check" + ], + "properties": { + "check": { + "$ref": "#/definitions/DoctorCheckSpec" + }, + "description": { + "type": [ + "string", + "null" + ], + "nullable": true + }, + "fix": { + "anyOf": [ + { + "$ref": "#/definitions/DoctorFixSpec" + }, + { + "type": "null" + } + ], + "nullable": true + }, + "name": { + "type": [ + "string", + "null" + ], + "nullable": true + }, + "required": { + "default": true, + "type": "boolean" + } + }, + "additionalProperties": false + }, + "DoctorGroupKind": { + "type": "string", + "enum": [ + "ScopeDoctorGroup" + ] + }, + "DoctorGroupSpec": { + "type": "object", + "required": [ + "actions" + ], + "properties": { + "actions": { + "type": "array", + "items": { + "$ref": "#/definitions/DoctorGroupActionSpec" + } + }, + "needs": { + "default": [], + "type": "array", + "items": { + "type": "string" + } + } + }, + "additionalProperties": false + }, + "KnownErrorKind": { + "type": "string", + "enum": [ + "ScopeKnownError" + ] + }, + "KnownErrorSpec": { + "type": "object", + "required": [ + "help", + "pattern" + ], + "properties": { + "help": { + "type": "string" + }, + "pattern": { + "type": "string" + } + }, + "additionalProperties": false + }, + "ModelMetadata": { + "type": "object", + "required": [ + "name" + ], + "properties": { + "annotations": { + "default": { + "scope.github.com/bin-path": null, + "scope.github.com/file-dir": null, + "scope.github.com/file-path": null + }, + "$ref": "#/definitions/ModelMetadataAnnotations" + }, + "description": { + "default": "Description not provided", + "type": "string" + }, + "labels": { + "default": {}, + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "name": { + "type": "string" + } + } + }, + "ModelMetadataAnnotations": { + "type": "object", + "properties": { + "scope.github.com/bin-path": { + "type": [ + "string", + "null" + ], + "nullable": true + }, + "scope.github.com/file-dir": { + "type": [ + "string", + "null" + ], + "nullable": true + }, + "scope.github.com/file-path": { + "type": [ + "string", + "null" + ], + "nullable": true + } + } + }, + "ReportDefinitionKind": { + "type": "string", + "enum": [ + "ScopeReportDefinition" + ] + }, + "ReportDefinitionSpec": { + "type": "object", + "required": [ + "template" + ], + "properties": { + "additionalData": { + "default": {}, + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "template": { + "type": "string" + } + }, + "additionalProperties": false + }, + "ReportDestinationGithubIssueSpec": { + "type": "object", + "required": [ + "owner", + "repo" + ], + "properties": { + "owner": { + "type": "string" + }, + "repo": { + "type": "string" + }, + "tags": { + "default": [], + "type": "array", + "items": { + "type": "string" + } + } + }, + "additionalProperties": false + }, + "ReportDestinationSpec": { + "oneOf": [ + { + "type": "object", + "required": [ + "rustyPaste" + ], + "properties": { + "rustyPaste": { + "type": "object", + "required": [ + "url" + ], + "properties": { + "url": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "githubIssue" + ], + "properties": { + "githubIssue": { + "$ref": "#/definitions/ReportDestinationGithubIssueSpec" + } + }, + "additionalProperties": false + } + ] + }, + "ReportLocationKind": { + "type": "string", + "enum": [ + "ScopeReportLocation" + ] + }, + "ReportLocationSpec": { + "type": "object", + "required": [ + "destination" + ], + "properties": { + "destination": { + "$ref": "#/definitions/ReportDestinationSpec" + } + }, + "additionalProperties": false + }, + "V1AlphaApiVersion": { + "type": "string", + "enum": [ + "scope.github.com/v1alpha" + ] + }, + "V1AlphaDoctorGroup": { + "type": "object", + "required": [ + "apiVersion", + "kind", + "metadata", + "spec" + ], + "properties": { + "apiVersion": { + "$ref": "#/definitions/V1AlphaApiVersion" + }, + "kind": { + "$ref": "#/definitions/DoctorGroupKind" + }, + "metadata": { + "$ref": "#/definitions/ModelMetadata" + }, + "spec": { + "$ref": "#/definitions/DoctorGroupSpec" + } + }, + "additionalProperties": false + }, + "V1AlphaKnownError": { + "type": "object", + "required": [ + "apiVersion", + "kind", + "metadata", + "spec" + ], + "properties": { + "apiVersion": { + "$ref": "#/definitions/V1AlphaApiVersion" + }, + "kind": { + "$ref": "#/definitions/KnownErrorKind" + }, + "metadata": { + "$ref": "#/definitions/ModelMetadata" + }, + "spec": { + "$ref": "#/definitions/KnownErrorSpec" + } + }, + "additionalProperties": false + }, + "V1AlphaReportDefinition": { + "type": "object", + "required": [ + "apiVersion", + "kind", + "metadata", + "spec" + ], + "properties": { + "apiVersion": { + "$ref": "#/definitions/V1AlphaApiVersion" + }, + "kind": { + "$ref": "#/definitions/ReportDefinitionKind" + }, + "metadata": { + "$ref": "#/definitions/ModelMetadata" + }, + "spec": { + "$ref": "#/definitions/ReportDefinitionSpec" + } + }, + "additionalProperties": false + }, + "V1AlphaReportLocation": { + "type": "object", + "required": [ + "apiVersion", + "kind", + "metadata", + "spec" + ], + "properties": { + "apiVersion": { + "$ref": "#/definitions/V1AlphaApiVersion" + }, + "kind": { + "$ref": "#/definitions/ReportLocationKind" + }, + "metadata": { + "$ref": "#/definitions/ModelMetadata" + }, + "spec": { + "$ref": "#/definitions/ReportLocationSpec" + } + }, + "additionalProperties": false + } + } +} \ No newline at end of file diff --git a/scope/src/models/mod.rs b/scope/src/models/mod.rs index 516195f..05d068e 100644 --- a/scope/src/models/mod.rs +++ b/scope/src/models/mod.rs @@ -165,7 +165,7 @@ mod schema_gen { #[test] fn create_and_validate_schemas() { let out_dir = format!("{}/schema", env!("CARGO_MANIFEST_DIR")); - std::fs::remove_dir_all(&out_dir).unwrap(); + std::fs::remove_dir_all(&out_dir).ok(); std::fs::create_dir_all(&out_dir).unwrap(); let mut schema_gen = crate::models::make_schema_generator(); From a8c359d0e89f3c83f15cc57e99d74a0cee1d1089 Mon Sep 17 00:00:00 2001 From: Ethan Hall Date: Mon, 4 Mar 2024 20:01:49 -0800 Subject: [PATCH 09/14] add docs --- docs/docs/commands/analyze/analyze-logs.md | 2 +- docs/docs/commands/doctor.md | 11 +- docs/docs/commands/index.md | 31 +++-- docs/docs/commands/report.md | 4 +- docs/docs/intro.md | 2 +- docs/docs/models/ScopeDoctorGroup.mdx | 30 +++-- docs/docs/models/ScopeKnownError.md | 21 ---- docs/docs/models/ScopeKnownError.mdx | 33 ++++++ docs/docs/models/ScopeReportDefinition.md | 31 ----- docs/docs/models/ScopeReportDefinition.mdx | 43 +++++++ ...ortLocation.md => ScopeReportLocation.mdx} | 19 ++- docs/docusaurus.config.ts | 2 + docs/static/schema | 1 + scope/schema/merged.json | 104 ++++++++++++----- ...pha.com.github.scope.ScopeDoctorGroup.json | 109 +++++++++++++----- ...lpha.com.github.scope.ScopeKnownError.json | 109 +++++++++++++----- ...om.github.scope.ScopeReportDefinition.json | 109 +++++++++++++----- ....com.github.scope.ScopeReportLocation.json | 109 +++++++++++++----- scope/src/models/core.rs | 14 +++ scope/src/models/v1alpha/doctor_group.rs | 42 +++++++ scope/src/models/v1alpha/known_error.rs | 12 ++ scope/src/models/v1alpha/mod.rs | 2 + scope/src/models/v1alpha/report_definition.rs | 15 +++ scope/src/models/v1alpha/report_location.rs | 26 ++++- .../shared/models/internal/upload_location.rs | 4 +- 25 files changed, 665 insertions(+), 220 deletions(-) delete mode 100644 docs/docs/models/ScopeKnownError.md create mode 100644 docs/docs/models/ScopeKnownError.mdx delete mode 100644 docs/docs/models/ScopeReportDefinition.md create mode 100644 docs/docs/models/ScopeReportDefinition.mdx rename docs/docs/models/{ScopeReportLocation.md => ScopeReportLocation.mdx} (59%) create mode 120000 docs/static/schema diff --git a/docs/docs/commands/analyze/analyze-logs.md b/docs/docs/commands/analyze/analyze-logs.md index 7dc7460..3689c26 100644 --- a/docs/docs/commands/analyze/analyze-logs.md +++ b/docs/docs/commands/analyze/analyze-logs.md @@ -4,6 +4,6 @@ sidebar_position: 1 # Analyze Logs -`scope analyze logs` allows the user to provide a log file, or stdin. The file is parsed, and matches against the [ScopeKnownError](../../models/ScopeKnownError.md)'s. +`scope analyze logs` allows the user to provide a log file, or stdin. The file is parsed, and matches against the [ScopeKnownError](../../models/ScopeKnownError.mdx)'s. Once all the known errors are matched, the search will stop. \ No newline at end of file diff --git a/docs/docs/commands/doctor.md b/docs/docs/commands/doctor.md index 9bade8d..31b0d65 100644 --- a/docs/docs/commands/doctor.md +++ b/docs/docs/commands/doctor.md @@ -41,4 +41,13 @@ Options: ## `list` -Will print out all doctor checks available. \ No newline at end of file +Will print out all doctor checks available, in the order `run` will execute. + +```text + INFO Available checks that will run + INFO Name Description Path + INFO - ScopeDoctorGroup/setup You need to run bin/setup .scope/doctor-group-setup.yaml + INFO - ScopeDoctorGroup/path-exists-fix-in-scope-dir Check your shell for basic functionality .scope/doctor-group-in-scope-dir.yaml + INFO - ScopeDoctorGroup/path-exists Check your shell for basic functionality .scope/doctor-group-path-exists.yaml + INFO - ScopeDoctorGroup/group-1 Check your shell for basic functionality .scope/doctor-group-1.yaml +``` \ No newline at end of file diff --git a/docs/docs/commands/index.md b/docs/docs/commands/index.md index 3a5e7b9..aca7d5e 100644 --- a/docs/docs/commands/index.md +++ b/docs/docs/commands/index.md @@ -16,14 +16,29 @@ Additionally, there is `list` that will output all the found configuration. Here is an example output of `scope list` run from the `examples/` directory. ```text -17:47:57 INFO Commands -17:47:57 INFO Name Description -17:47:57 INFO -------------------------------------------------------------------------------- -17:47:57 INFO bar External sub-command, run `scope bar` for help -17:47:57 INFO doctor Run checks that will "checkup" your machine -17:47:57 INFO foo External sub-command, run `scope foo` for help -17:47:57 INFO list List the found config files, and resources detected -17:47:57 INFO report Generate a bug report based from a command that was ran + INFO Found Resources + INFO Name Description Path + INFO - ScopeDoctorCheck/path-exists-fix-in-scope-dir Check your shell for basic functionality .scope/doctor-check-fix-in-scope.yaml + INFO - ScopeDoctorGroup/group-1 Check your shell for basic functionality .scope/doctor-group-1.yaml + INFO - ScopeDoctorGroup/path-exists Check your shell for basic functionality .scope/doctor-group-path-exists.yaml + INFO - ScopeDoctorGroup/path-exists-fix-in-scope-dir Check your shell for basic functionality .scope/doctor-group-in-scope-dir.yaml + INFO - ScopeDoctorGroup/setup You need to run bin/setup .scope/doctor-group-setup.yaml + INFO - ScopeKnownError/error-exists Check if the word error is in the logs .scope/known-error.yaml + INFO - ScopeReportDefinition/template Description not provided .scope/report.yaml + INFO - ScopeReportLocation/github Description not provided .scope/report.yaml + INFO - ScopeReportLocation/report Description not provided .scope/report.yaml + INFO + INFO Commands + INFO Name Description + INFO - analyze Analyze logs, output, etc for known errors + INFO - bar External sub-command, run `scope bar` for help + INFO - doctor Run checks that will "checkup" your machine + INFO - foo External sub-command, run `scope foo` for help + INFO - intercept External sub-command, run `scope intercept` for help + INFO - list List the found config files, and resources detected + INFO - report Generate a bug report based from a command that was ran + INFO - version Print version info and exit + ``` Under the `Commands` section, notice two additional commands: diff --git a/docs/docs/commands/report.md b/docs/docs/commands/report.md index 21f3b7d..5ccff91 100644 --- a/docs/docs/commands/report.md +++ b/docs/docs/commands/report.md @@ -8,8 +8,8 @@ sidebar_position: 2 To build a bug report, two different files are used: -- [ScopeReportDefinition](../models/ScopeReportDefinition.md) - is used to define what to include in the bug report. There can only be one report definition at one time. -- [ScopeReportLocation](../models/ScopeReportLocation.md) - defines where to upload reports to. +- [ScopeReportDefinition](../models/ScopeReportDefinition.mdx) - is used to define what to include in the bug report. There can only be one report definition at one time. +- [ScopeReportLocation](../models/ScopeReportLocation.mdx) - defines where to upload reports to. When reporting a bug, scope will auto redact well known keys and patterns to reduce sharing private information. diff --git a/docs/docs/intro.md b/docs/docs/intro.md index 69ce941..aad41d0 100644 --- a/docs/docs/intro.md +++ b/docs/docs/intro.md @@ -8,7 +8,7 @@ Scope allows teams to define development config for engineers. Scope is a tool f The config falls into three major categories: - [Local setup](./commands/doctor.md) -- [Error debugging locally](models/ScopeKnownError.md) +- [Error debugging locally](models/ScopeKnownError.mdx) - [Generate great bug reports](./commands/report.md) ## Config diff --git a/docs/docs/models/ScopeDoctorGroup.mdx b/docs/docs/models/ScopeDoctorGroup.mdx index 2b14263..661a95a 100644 --- a/docs/docs/models/ScopeDoctorGroup.mdx +++ b/docs/docs/models/ScopeDoctorGroup.mdx @@ -1,11 +1,13 @@ -import CodeBlock from '@theme/CodeBlock'; -import Schema from "@site/static/schemas/mySuperSchema.json"; -import JSONSchemaViewer from "@theme/JSONSchemaViewer"; - --- sidebar_position: 1 --- +import CodeBlock from '@theme/CodeBlock'; +import Schema from "../../static//schema/v1alpha.com.github.scope.ScopeDoctorGroup.json"; +import JSONSchemaViewer from "@theme/JSONSchemaViewer"; +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + # ScopeDoctorGroup A "group" is a set of operations that should be preformed as part of solving a problem. @@ -51,8 +53,6 @@ spec: - yarn install ``` - - In the example above, there are two actions, the first ensures that node is operational. ## Actions @@ -75,13 +75,11 @@ To target a script relative to the group it must start with `.`, and giving a re ## Schema -- `.spec.action` a series of steps to check and fix for the group. -- `.spec.needs[]` an array of names required before this group can run. -- `.spec.action[].name` a short name to refer to the action -- `.spec.action[].required` default true, when true action failing check & fix will stop all execution. -- `.spec.action[].check.paths` A list of globs to check for a change. -- `.spec.action[].check.commands` A list of commands to execute, using the exit code to determine if changes are needed. -- `.spec.action[].fix.commands` A list of commands to execute, attempting to resolve issues detected by the action. -- `.spec.action[].fix.helpText` Text to display to the user if this action fails. -- `.spec.action[].fix.helpUrl` A URL to provide to the user in case of an error in this action. -- `.spec.description` is a useful description of the setup, used when listing what's available. + + + + + + {JSON.stringify(Schema, null, 2)} + + diff --git a/docs/docs/models/ScopeKnownError.md b/docs/docs/models/ScopeKnownError.md deleted file mode 100644 index e539875..0000000 --- a/docs/docs/models/ScopeKnownError.md +++ /dev/null @@ -1,21 +0,0 @@ ---- -sidebar_position: 3 ---- - -# ScopeKnownError - -```yaml -apiVersion: scope.github.com/v1alpha -kind: ScopeKnownError -metadata: - name: error-exists -spec: - description: Check if the word error is in the logs - pattern: error - help: The command had an error, try reading the logs around there to find out what happened. -``` - -## Schema - -- `.spec.pattern` is a Regex that will be run over stdout and stderr to search for a known error. -- `.spec.help` is the description given when the pattern matches diff --git a/docs/docs/models/ScopeKnownError.mdx b/docs/docs/models/ScopeKnownError.mdx new file mode 100644 index 0000000..2fe94c1 --- /dev/null +++ b/docs/docs/models/ScopeKnownError.mdx @@ -0,0 +1,33 @@ +--- +sidebar_position: 2 +--- + +import CodeBlock from '@theme/CodeBlock'; +import Schema from "../../static/schema/v1alpha.com.github.scope.ScopeKnownError.json"; +import JSONSchemaViewer from "@theme/JSONSchemaViewer"; +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +# ScopeKnownError + +```yaml +apiVersion: scope.github.com/v1alpha +kind: ScopeKnownError +metadata: + name: error-exists +spec: + description: Check if the word error is in the logs + pattern: error + help: The command had an error, try reading the logs around there to find out what happened. +``` + +## Schema + + + + + + + {JSON.stringify(Schema, null, 2)} + + \ No newline at end of file diff --git a/docs/docs/models/ScopeReportDefinition.md b/docs/docs/models/ScopeReportDefinition.md deleted file mode 100644 index 19a5203..0000000 --- a/docs/docs/models/ScopeReportDefinition.md +++ /dev/null @@ -1,31 +0,0 @@ ---- -sidebar_position: 4 ---- - -# ScopeReportDefinition - -There can only be one `ScopeReportDefinition` at any time. If there are multiple when searching, the "closest" is used. - -Looking at `report.yaml` in the example directory. - -```yaml -apiVersion: scope.github.com/v1alpha -kind: ScopeReportDefinition -metadata: - name: template -spec: - additionalData: - username: id -u - ruby: which ruby - node: which node - nodeVersion: node -v - template: | - # There was an error! - - When running `{{ command }}` scope ran into an error -``` - -## Schema - -- `.spec.additionalData` defines additional data that needs to be pulled from the system when reporting a bug. `additionalData` is a map of `string:string`, the value is a command that should be run. When a report is built, the commands will be run and automatically included in the report. -- `.spec.template` is a Jinja2 style template, to be included. The text should be in Markdown format. Scope injects `command` as the command that was run. \ No newline at end of file diff --git a/docs/docs/models/ScopeReportDefinition.mdx b/docs/docs/models/ScopeReportDefinition.mdx new file mode 100644 index 0000000..b5fe28c --- /dev/null +++ b/docs/docs/models/ScopeReportDefinition.mdx @@ -0,0 +1,43 @@ +--- +sidebar_position: 3 +--- + +import CodeBlock from '@theme/CodeBlock'; +import Schema from "../../static/schema/v1alpha.com.github.scope.ScopeReportDefinition.json"; +import JSONSchemaViewer from "@theme/JSONSchemaViewer"; +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +# ScopeReportDefinition + +There can only be one `ScopeReportDefinition` at any time. If there are multiple when searching, the "closest" is used. + +Looking at `report.yaml` in the example directory. + +```yaml +apiVersion: scope.github.com/v1alpha +kind: ScopeReportDefinition +metadata: + name: template +spec: + additionalData: + username: id -u + ruby: which ruby + node: which node + nodeVersion: node -v + template: | + # There was an error! + + When running `{{ command }}` scope ran into an error +``` + +## Schema + + + + + + + {JSON.stringify(Schema, null, 2)} + + diff --git a/docs/docs/models/ScopeReportLocation.md b/docs/docs/models/ScopeReportLocation.mdx similarity index 59% rename from docs/docs/models/ScopeReportLocation.md rename to docs/docs/models/ScopeReportLocation.mdx index 25d40f8..aea1898 100644 --- a/docs/docs/models/ScopeReportLocation.md +++ b/docs/docs/models/ScopeReportLocation.mdx @@ -1,7 +1,13 @@ --- -sidebar_position: 5 +sidebar_position: 4 --- +import CodeBlock from '@theme/CodeBlock'; +import Schema from "../../static/schema/v1alpha.com.github.scope.ScopeReportLocation.json"; +import JSONSchemaViewer from "@theme/JSONSchemaViewer"; +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + # ScopeReportLocation Define where to upload the bug report to. Currently, only support `GitHubIssues` and `rustyPaste`. @@ -38,3 +44,14 @@ spec: rustyPaste: url: http://localhost:8000 ``` + +### Schema + + + + + + + {JSON.stringify(Schema, null, 2)} + + diff --git a/docs/docusaurus.config.ts b/docs/docusaurus.config.ts index 7e8a5cd..9e8f51d 100644 --- a/docs/docusaurus.config.ts +++ b/docs/docusaurus.config.ts @@ -22,6 +22,8 @@ const config: Config = { onBrokenMarkdownLinks: 'warn', trailingSlash: false, + staticDirectories: ['static'], + // Even if you don't use internationalization, you can use this field to set // useful metadata like html lang. For example, if your site is Chinese, you // may want to replace "en" with "zh-Hans". diff --git a/docs/static/schema b/docs/static/schema new file mode 120000 index 0000000..2a049ca --- /dev/null +++ b/docs/static/schema @@ -0,0 +1 @@ +../../scope/schema \ No newline at end of file diff --git a/scope/schema/merged.json b/scope/schema/merged.json index fd21237..215c982 100644 --- a/scope/schema/merged.json +++ b/scope/schema/merged.json @@ -17,9 +17,11 @@ ], "definitions": { "DoctorCheckSpec": { + "description": "What needs to be checked before the action will run. All `paths` will be checked first, then `commands`. If a `path` has changed, the `command` will not run.", "type": "object", "properties": { "commands": { + "description": "A list of commands to execute to check the environment.", "default": null, "type": [ "array", @@ -31,6 +33,7 @@ "nullable": true }, "paths": { + "description": "A list of globs to check for changes. When the glob matches a new file, or the contents of the file change, the check will require a fix.", "default": null, "type": [ "array", @@ -45,9 +48,11 @@ "additionalProperties": false }, "DoctorFixSpec": { + "description": "Definition for fixing the environment.", "type": "object", "properties": { "commands": { + "description": "List of commands to run to fix the env.", "default": [], "type": "array", "items": { @@ -55,6 +60,7 @@ } }, "helpText": { + "description": "Text to display when no command is provided / fails to fix the env.", "default": null, "type": [ "string", @@ -63,6 +69,7 @@ "nullable": true }, "helpUrl": { + "description": "Link to documentation to fix the issue.", "default": null, "type": [ "string", @@ -74,15 +81,18 @@ "additionalProperties": false }, "DoctorGroupActionSpec": { + "description": "An action is a single step used to check in a group. This is most commonly used to build a series of tasks for a system, like `ruby`, `python`, and databases.", "type": "object", "required": [ "check" ], "properties": { "check": { + "description": "The `check` run before `fix` (if provided). A check is used to determine if the fix needs to be executed, or fail the action if no fix is provided. If a fix is specified, the check will re-execute to ensure that the fix applied correctly.", "$ref": "#/definitions/DoctorCheckSpec" }, "description": { + "description": "A description of this specific action, used for information to the users.", "type": [ "string", "null" @@ -90,6 +100,7 @@ "nullable": true }, "fix": { + "description": "A fix defines how to fix the issue that a `check` is validating. When provided, will only run when the `check` \"fails\".", "anyOf": [ { "$ref": "#/definitions/DoctorFixSpec" @@ -101,6 +112,7 @@ "nullable": true }, "name": { + "description": "Name of the \"action\". When not provided, it will be the index of the action within the group. This is used when reporting status to the users.", "type": [ "string", "null" @@ -108,6 +120,7 @@ "nullable": true }, "required": { + "description": "If false, the action is allowed to fail and let other actions in the group execute. Defaults to `true`.", "default": true, "type": "boolean" } @@ -121,18 +134,21 @@ ] }, "DoctorGroupSpec": { + "description": "Often used to describe how to fix a \"system\", like `ruby`, `python`, or databases. Able to depend on other \"system\".", "type": "object", "required": [ "actions" ], "properties": { "actions": { + "description": "A series of steps to check and fix for the group.", "type": "array", "items": { "$ref": "#/definitions/DoctorGroupActionSpec" } }, "needs": { + "description": "A list of `ScopeDoctorGroup` that are required for this group to execute. If not all finish successfully, this group will not execute.", "default": [], "type": "array", "items": { @@ -149,6 +165,7 @@ ] }, "KnownErrorSpec": { + "description": "Definition of the known error", "type": "object", "required": [ "help", @@ -156,9 +173,11 @@ ], "properties": { "help": { + "description": "Text that the user can use to fix the issue", "type": "string" }, "pattern": { + "description": "A Regex used to determine if the line is an error.", "type": "string" } }, @@ -171,6 +190,7 @@ ], "properties": { "annotations": { + "description": "Annotations attach arbitrary non-identifying metadata to objects.", "default": { "scope.github.com/bin-path": null, "scope.github.com/file-dir": null, @@ -179,10 +199,12 @@ "$ref": "#/definitions/ModelMetadataAnnotations" }, "description": { + "description": "Description of this resource, used when listing resources and helpful to inform users why the resource exists.", "default": "Description not provided", "type": "string" }, "labels": { + "description": "Key/value pairs, allows resources to be easily filtered from the CLI.", "default": {}, "type": "object", "additionalProperties": { @@ -190,6 +212,7 @@ } }, "name": { + "description": "Name of the resource, needs to be unique across `kinds`. When two resources share a name, the one \"closest\" to the current working directory will take precedence.", "type": "string" } } @@ -198,20 +221,7 @@ "type": "object", "properties": { "scope.github.com/bin-path": { - "type": [ - "string", - "null" - ], - "nullable": true - }, - "scope.github.com/file-dir": { - "type": [ - "string", - "null" - ], - "nullable": true - }, - "scope.github.com/file-path": { + "description": "When running commands, additional paths that should be paced at the _beginning_ of the `PATH`.", "type": [ "string", "null" @@ -227,12 +237,14 @@ ] }, "ReportDefinitionSpec": { + "description": "Definition of the Report Definition", "type": "object", "required": [ "template" ], "properties": { "additionalData": { + "description": "defines additional data that needs to be pulled from the system when reporting a bug. `additionalData` is a map of `string:string`, the value is a command that should be run. When a report is built, the commands will be run and automatically included in the report.", "default": {}, "type": "object", "additionalProperties": { @@ -240,12 +252,14 @@ } }, "template": { + "description": "a Jinja2 style template, to be included. The text should be in Markdown format. Scope injects `command` as the command that was run.", "type": "string" } }, "additionalProperties": false }, "ReportDestinationGithubIssueSpec": { + "description": "How to load the report to GitHub Issue", "type": "object", "required": [ "owner", @@ -253,12 +267,15 @@ ], "properties": { "owner": { + "description": "`owner` of the repository for the issue", "type": "string" }, "repo": { + "description": "`repo` the name of the repo for the issue", "type": "string" }, "tags": { + "description": "A list of tags to be added to the issue", "default": [], "type": "array", "items": { @@ -268,6 +285,20 @@ }, "additionalProperties": false }, + "ReportDestinationRustyPasteSpec": { + "description": "How to upload a report to RustyPaste", + "type": "object", + "required": [ + "url" + ], + "properties": { + "url": { + "description": "URL of RustyPaste", + "type": "string" + } + }, + "additionalProperties": false + }, "ReportDestinationSpec": { "oneOf": [ { @@ -277,16 +308,7 @@ ], "properties": { "rustyPaste": { - "type": "object", - "required": [ - "url" - ], - "properties": { - "url": { - "type": "string" - } - }, - "additionalProperties": false + "$ref": "#/definitions/ReportDestinationRustyPasteSpec" } }, "additionalProperties": false @@ -312,24 +334,33 @@ ] }, "ReportLocationSpec": { + "description": "Define where to upload the report to", "type": "object", "required": [ "destination" ], "properties": { "destination": { + "description": "Destination the report should be uploaded to", "$ref": "#/definitions/ReportDestinationSpec" } }, "additionalProperties": false }, "V1AlphaApiVersion": { - "type": "string", - "enum": [ - "scope.github.com/v1alpha" + "description": "Version of the Scope API", + "oneOf": [ + { + "description": "Current latest version of the resources.", + "type": "string", + "enum": [ + "scope.github.com/v1alpha" + ] + } ] }, "V1AlphaDoctorGroup": { + "description": "Resource used to define a `ScopeDoctorGroup`.", "type": "object", "required": [ "apiVersion", @@ -339,21 +370,26 @@ ], "properties": { "apiVersion": { + "description": "API version of the resource", "$ref": "#/definitions/V1AlphaApiVersion" }, "kind": { + "description": "The type of resource.", "$ref": "#/definitions/DoctorGroupKind" }, "metadata": { + "description": "Standard set of options including name, description for the resource. Together `kind` and `metadata.name` are required to be unique. If there are duplicate, the resources \"closest\" to the execution dir will take precedence.", "$ref": "#/definitions/ModelMetadata" }, "spec": { + "description": "Options for the resource.", "$ref": "#/definitions/DoctorGroupSpec" } }, "additionalProperties": false }, "V1AlphaKnownError": { + "description": "Resource used to define a `ScopeKnownError`. A known error is a specific error that a user may run into.", "type": "object", "required": [ "apiVersion", @@ -363,21 +399,26 @@ ], "properties": { "apiVersion": { + "description": "API version of the resource", "$ref": "#/definitions/V1AlphaApiVersion" }, "kind": { + "description": "The type of resource.", "$ref": "#/definitions/KnownErrorKind" }, "metadata": { + "description": "Standard set of options including name, description for the resource. Together `kind` and `metadata.name` are required to be unique. If there are duplicate, the resources \"closest\" to the execution dir will take precedence.", "$ref": "#/definitions/ModelMetadata" }, "spec": { + "description": "Options for the resource.", "$ref": "#/definitions/KnownErrorSpec" } }, "additionalProperties": false }, "V1AlphaReportDefinition": { + "description": "A `ScopeReportDefinition` tells scope how to collect details about the system when there is an issue they need to report.", "type": "object", "required": [ "apiVersion", @@ -387,21 +428,26 @@ ], "properties": { "apiVersion": { + "description": "API version of the resource", "$ref": "#/definitions/V1AlphaApiVersion" }, "kind": { + "description": "The type of resource.", "$ref": "#/definitions/ReportDefinitionKind" }, "metadata": { + "description": "Standard set of options including name, description for the resource. Together `kind` and `metadata.name` are required to be unique. If there are duplicate, the resources \"closest\" to the execution dir will take precedence.", "$ref": "#/definitions/ModelMetadata" }, "spec": { + "description": "Options for the resource.", "$ref": "#/definitions/ReportDefinitionSpec" } }, "additionalProperties": false }, "V1AlphaReportLocation": { + "description": "A `ScopeReportLocation` tells where to upload a report to.", "type": "object", "required": [ "apiVersion", @@ -411,15 +457,19 @@ ], "properties": { "apiVersion": { + "description": "API version of the resource", "$ref": "#/definitions/V1AlphaApiVersion" }, "kind": { + "description": "The type of resource.", "$ref": "#/definitions/ReportLocationKind" }, "metadata": { + "description": "Standard set of options including name, description for the resource. Together `kind` and `metadata.name` are required to be unique. If there are duplicate, the resources \"closest\" to the execution dir will take precedence.", "$ref": "#/definitions/ModelMetadata" }, "spec": { + "description": "Options for the resource.", "$ref": "#/definitions/ReportLocationSpec" } }, diff --git a/scope/schema/v1alpha.com.github.scope.ScopeDoctorGroup.json b/scope/schema/v1alpha.com.github.scope.ScopeDoctorGroup.json index d594744..4f02f66 100644 --- a/scope/schema/v1alpha.com.github.scope.ScopeDoctorGroup.json +++ b/scope/schema/v1alpha.com.github.scope.ScopeDoctorGroup.json @@ -1,6 +1,7 @@ { "$schema": "https://json-schema.org/draft/2019-09/schema", "title": "V1AlphaDoctorGroup", + "description": "Resource used to define a `ScopeDoctorGroup`.", "type": "object", "required": [ "apiVersion", @@ -10,24 +11,30 @@ ], "properties": { "apiVersion": { + "description": "API version of the resource", "$ref": "#/definitions/V1AlphaApiVersion" }, "kind": { + "description": "The type of resource.", "$ref": "#/definitions/DoctorGroupKind" }, "metadata": { + "description": "Standard set of options including name, description for the resource. Together `kind` and `metadata.name` are required to be unique. If there are duplicate, the resources \"closest\" to the execution dir will take precedence.", "$ref": "#/definitions/ModelMetadata" }, "spec": { + "description": "Options for the resource.", "$ref": "#/definitions/DoctorGroupSpec" } }, "additionalProperties": false, "definitions": { "DoctorCheckSpec": { + "description": "What needs to be checked before the action will run. All `paths` will be checked first, then `commands`. If a `path` has changed, the `command` will not run.", "type": "object", "properties": { "commands": { + "description": "A list of commands to execute to check the environment.", "default": null, "type": [ "array", @@ -39,6 +46,7 @@ "nullable": true }, "paths": { + "description": "A list of globs to check for changes. When the glob matches a new file, or the contents of the file change, the check will require a fix.", "default": null, "type": [ "array", @@ -53,9 +61,11 @@ "additionalProperties": false }, "DoctorFixSpec": { + "description": "Definition for fixing the environment.", "type": "object", "properties": { "commands": { + "description": "List of commands to run to fix the env.", "default": [], "type": "array", "items": { @@ -63,6 +73,7 @@ } }, "helpText": { + "description": "Text to display when no command is provided / fails to fix the env.", "default": null, "type": [ "string", @@ -71,6 +82,7 @@ "nullable": true }, "helpUrl": { + "description": "Link to documentation to fix the issue.", "default": null, "type": [ "string", @@ -82,15 +94,18 @@ "additionalProperties": false }, "DoctorGroupActionSpec": { + "description": "An action is a single step used to check in a group. This is most commonly used to build a series of tasks for a system, like `ruby`, `python`, and databases.", "type": "object", "required": [ "check" ], "properties": { "check": { + "description": "The `check` run before `fix` (if provided). A check is used to determine if the fix needs to be executed, or fail the action if no fix is provided. If a fix is specified, the check will re-execute to ensure that the fix applied correctly.", "$ref": "#/definitions/DoctorCheckSpec" }, "description": { + "description": "A description of this specific action, used for information to the users.", "type": [ "string", "null" @@ -98,6 +113,7 @@ "nullable": true }, "fix": { + "description": "A fix defines how to fix the issue that a `check` is validating. When provided, will only run when the `check` \"fails\".", "anyOf": [ { "$ref": "#/definitions/DoctorFixSpec" @@ -109,6 +125,7 @@ "nullable": true }, "name": { + "description": "Name of the \"action\". When not provided, it will be the index of the action within the group. This is used when reporting status to the users.", "type": [ "string", "null" @@ -116,6 +133,7 @@ "nullable": true }, "required": { + "description": "If false, the action is allowed to fail and let other actions in the group execute. Defaults to `true`.", "default": true, "type": "boolean" } @@ -129,18 +147,21 @@ ] }, "DoctorGroupSpec": { + "description": "Often used to describe how to fix a \"system\", like `ruby`, `python`, or databases. Able to depend on other \"system\".", "type": "object", "required": [ "actions" ], "properties": { "actions": { + "description": "A series of steps to check and fix for the group.", "type": "array", "items": { "$ref": "#/definitions/DoctorGroupActionSpec" } }, "needs": { + "description": "A list of `ScopeDoctorGroup` that are required for this group to execute. If not all finish successfully, this group will not execute.", "default": [], "type": "array", "items": { @@ -157,6 +178,7 @@ ] }, "KnownErrorSpec": { + "description": "Definition of the known error", "type": "object", "required": [ "help", @@ -164,9 +186,11 @@ ], "properties": { "help": { + "description": "Text that the user can use to fix the issue", "type": "string" }, "pattern": { + "description": "A Regex used to determine if the line is an error.", "type": "string" } }, @@ -179,6 +203,7 @@ ], "properties": { "annotations": { + "description": "Annotations attach arbitrary non-identifying metadata to objects.", "default": { "scope.github.com/bin-path": null, "scope.github.com/file-dir": null, @@ -187,10 +212,12 @@ "$ref": "#/definitions/ModelMetadataAnnotations" }, "description": { + "description": "Description of this resource, used when listing resources and helpful to inform users why the resource exists.", "default": "Description not provided", "type": "string" }, "labels": { + "description": "Key/value pairs, allows resources to be easily filtered from the CLI.", "default": {}, "type": "object", "additionalProperties": { @@ -198,6 +225,7 @@ } }, "name": { + "description": "Name of the resource, needs to be unique across `kinds`. When two resources share a name, the one \"closest\" to the current working directory will take precedence.", "type": "string" } } @@ -206,20 +234,7 @@ "type": "object", "properties": { "scope.github.com/bin-path": { - "type": [ - "string", - "null" - ], - "nullable": true - }, - "scope.github.com/file-dir": { - "type": [ - "string", - "null" - ], - "nullable": true - }, - "scope.github.com/file-path": { + "description": "When running commands, additional paths that should be paced at the _beginning_ of the `PATH`.", "type": [ "string", "null" @@ -235,12 +250,14 @@ ] }, "ReportDefinitionSpec": { + "description": "Definition of the Report Definition", "type": "object", "required": [ "template" ], "properties": { "additionalData": { + "description": "defines additional data that needs to be pulled from the system when reporting a bug. `additionalData` is a map of `string:string`, the value is a command that should be run. When a report is built, the commands will be run and automatically included in the report.", "default": {}, "type": "object", "additionalProperties": { @@ -248,12 +265,14 @@ } }, "template": { + "description": "a Jinja2 style template, to be included. The text should be in Markdown format. Scope injects `command` as the command that was run.", "type": "string" } }, "additionalProperties": false }, "ReportDestinationGithubIssueSpec": { + "description": "How to load the report to GitHub Issue", "type": "object", "required": [ "owner", @@ -261,12 +280,15 @@ ], "properties": { "owner": { + "description": "`owner` of the repository for the issue", "type": "string" }, "repo": { + "description": "`repo` the name of the repo for the issue", "type": "string" }, "tags": { + "description": "A list of tags to be added to the issue", "default": [], "type": "array", "items": { @@ -276,6 +298,20 @@ }, "additionalProperties": false }, + "ReportDestinationRustyPasteSpec": { + "description": "How to upload a report to RustyPaste", + "type": "object", + "required": [ + "url" + ], + "properties": { + "url": { + "description": "URL of RustyPaste", + "type": "string" + } + }, + "additionalProperties": false + }, "ReportDestinationSpec": { "oneOf": [ { @@ -285,16 +321,7 @@ ], "properties": { "rustyPaste": { - "type": "object", - "required": [ - "url" - ], - "properties": { - "url": { - "type": "string" - } - }, - "additionalProperties": false + "$ref": "#/definitions/ReportDestinationRustyPasteSpec" } }, "additionalProperties": false @@ -320,24 +347,33 @@ ] }, "ReportLocationSpec": { + "description": "Define where to upload the report to", "type": "object", "required": [ "destination" ], "properties": { "destination": { + "description": "Destination the report should be uploaded to", "$ref": "#/definitions/ReportDestinationSpec" } }, "additionalProperties": false }, "V1AlphaApiVersion": { - "type": "string", - "enum": [ - "scope.github.com/v1alpha" + "description": "Version of the Scope API", + "oneOf": [ + { + "description": "Current latest version of the resources.", + "type": "string", + "enum": [ + "scope.github.com/v1alpha" + ] + } ] }, "V1AlphaDoctorGroup": { + "description": "Resource used to define a `ScopeDoctorGroup`.", "type": "object", "required": [ "apiVersion", @@ -347,21 +383,26 @@ ], "properties": { "apiVersion": { + "description": "API version of the resource", "$ref": "#/definitions/V1AlphaApiVersion" }, "kind": { + "description": "The type of resource.", "$ref": "#/definitions/DoctorGroupKind" }, "metadata": { + "description": "Standard set of options including name, description for the resource. Together `kind` and `metadata.name` are required to be unique. If there are duplicate, the resources \"closest\" to the execution dir will take precedence.", "$ref": "#/definitions/ModelMetadata" }, "spec": { + "description": "Options for the resource.", "$ref": "#/definitions/DoctorGroupSpec" } }, "additionalProperties": false }, "V1AlphaKnownError": { + "description": "Resource used to define a `ScopeKnownError`. A known error is a specific error that a user may run into.", "type": "object", "required": [ "apiVersion", @@ -371,21 +412,26 @@ ], "properties": { "apiVersion": { + "description": "API version of the resource", "$ref": "#/definitions/V1AlphaApiVersion" }, "kind": { + "description": "The type of resource.", "$ref": "#/definitions/KnownErrorKind" }, "metadata": { + "description": "Standard set of options including name, description for the resource. Together `kind` and `metadata.name` are required to be unique. If there are duplicate, the resources \"closest\" to the execution dir will take precedence.", "$ref": "#/definitions/ModelMetadata" }, "spec": { + "description": "Options for the resource.", "$ref": "#/definitions/KnownErrorSpec" } }, "additionalProperties": false }, "V1AlphaReportDefinition": { + "description": "A `ScopeReportDefinition` tells scope how to collect details about the system when there is an issue they need to report.", "type": "object", "required": [ "apiVersion", @@ -395,21 +441,26 @@ ], "properties": { "apiVersion": { + "description": "API version of the resource", "$ref": "#/definitions/V1AlphaApiVersion" }, "kind": { + "description": "The type of resource.", "$ref": "#/definitions/ReportDefinitionKind" }, "metadata": { + "description": "Standard set of options including name, description for the resource. Together `kind` and `metadata.name` are required to be unique. If there are duplicate, the resources \"closest\" to the execution dir will take precedence.", "$ref": "#/definitions/ModelMetadata" }, "spec": { + "description": "Options for the resource.", "$ref": "#/definitions/ReportDefinitionSpec" } }, "additionalProperties": false }, "V1AlphaReportLocation": { + "description": "A `ScopeReportLocation` tells where to upload a report to.", "type": "object", "required": [ "apiVersion", @@ -419,15 +470,19 @@ ], "properties": { "apiVersion": { + "description": "API version of the resource", "$ref": "#/definitions/V1AlphaApiVersion" }, "kind": { + "description": "The type of resource.", "$ref": "#/definitions/ReportLocationKind" }, "metadata": { + "description": "Standard set of options including name, description for the resource. Together `kind` and `metadata.name` are required to be unique. If there are duplicate, the resources \"closest\" to the execution dir will take precedence.", "$ref": "#/definitions/ModelMetadata" }, "spec": { + "description": "Options for the resource.", "$ref": "#/definitions/ReportLocationSpec" } }, diff --git a/scope/schema/v1alpha.com.github.scope.ScopeKnownError.json b/scope/schema/v1alpha.com.github.scope.ScopeKnownError.json index 26b4058..1762512 100644 --- a/scope/schema/v1alpha.com.github.scope.ScopeKnownError.json +++ b/scope/schema/v1alpha.com.github.scope.ScopeKnownError.json @@ -1,6 +1,7 @@ { "$schema": "https://json-schema.org/draft/2019-09/schema", "title": "V1AlphaKnownError", + "description": "Resource used to define a `ScopeKnownError`. A known error is a specific error that a user may run into.", "type": "object", "required": [ "apiVersion", @@ -10,24 +11,30 @@ ], "properties": { "apiVersion": { + "description": "API version of the resource", "$ref": "#/definitions/V1AlphaApiVersion" }, "kind": { + "description": "The type of resource.", "$ref": "#/definitions/KnownErrorKind" }, "metadata": { + "description": "Standard set of options including name, description for the resource. Together `kind` and `metadata.name` are required to be unique. If there are duplicate, the resources \"closest\" to the execution dir will take precedence.", "$ref": "#/definitions/ModelMetadata" }, "spec": { + "description": "Options for the resource.", "$ref": "#/definitions/KnownErrorSpec" } }, "additionalProperties": false, "definitions": { "DoctorCheckSpec": { + "description": "What needs to be checked before the action will run. All `paths` will be checked first, then `commands`. If a `path` has changed, the `command` will not run.", "type": "object", "properties": { "commands": { + "description": "A list of commands to execute to check the environment.", "default": null, "type": [ "array", @@ -39,6 +46,7 @@ "nullable": true }, "paths": { + "description": "A list of globs to check for changes. When the glob matches a new file, or the contents of the file change, the check will require a fix.", "default": null, "type": [ "array", @@ -53,9 +61,11 @@ "additionalProperties": false }, "DoctorFixSpec": { + "description": "Definition for fixing the environment.", "type": "object", "properties": { "commands": { + "description": "List of commands to run to fix the env.", "default": [], "type": "array", "items": { @@ -63,6 +73,7 @@ } }, "helpText": { + "description": "Text to display when no command is provided / fails to fix the env.", "default": null, "type": [ "string", @@ -71,6 +82,7 @@ "nullable": true }, "helpUrl": { + "description": "Link to documentation to fix the issue.", "default": null, "type": [ "string", @@ -82,15 +94,18 @@ "additionalProperties": false }, "DoctorGroupActionSpec": { + "description": "An action is a single step used to check in a group. This is most commonly used to build a series of tasks for a system, like `ruby`, `python`, and databases.", "type": "object", "required": [ "check" ], "properties": { "check": { + "description": "The `check` run before `fix` (if provided). A check is used to determine if the fix needs to be executed, or fail the action if no fix is provided. If a fix is specified, the check will re-execute to ensure that the fix applied correctly.", "$ref": "#/definitions/DoctorCheckSpec" }, "description": { + "description": "A description of this specific action, used for information to the users.", "type": [ "string", "null" @@ -98,6 +113,7 @@ "nullable": true }, "fix": { + "description": "A fix defines how to fix the issue that a `check` is validating. When provided, will only run when the `check` \"fails\".", "anyOf": [ { "$ref": "#/definitions/DoctorFixSpec" @@ -109,6 +125,7 @@ "nullable": true }, "name": { + "description": "Name of the \"action\". When not provided, it will be the index of the action within the group. This is used when reporting status to the users.", "type": [ "string", "null" @@ -116,6 +133,7 @@ "nullable": true }, "required": { + "description": "If false, the action is allowed to fail and let other actions in the group execute. Defaults to `true`.", "default": true, "type": "boolean" } @@ -129,18 +147,21 @@ ] }, "DoctorGroupSpec": { + "description": "Often used to describe how to fix a \"system\", like `ruby`, `python`, or databases. Able to depend on other \"system\".", "type": "object", "required": [ "actions" ], "properties": { "actions": { + "description": "A series of steps to check and fix for the group.", "type": "array", "items": { "$ref": "#/definitions/DoctorGroupActionSpec" } }, "needs": { + "description": "A list of `ScopeDoctorGroup` that are required for this group to execute. If not all finish successfully, this group will not execute.", "default": [], "type": "array", "items": { @@ -157,6 +178,7 @@ ] }, "KnownErrorSpec": { + "description": "Definition of the known error", "type": "object", "required": [ "help", @@ -164,9 +186,11 @@ ], "properties": { "help": { + "description": "Text that the user can use to fix the issue", "type": "string" }, "pattern": { + "description": "A Regex used to determine if the line is an error.", "type": "string" } }, @@ -179,6 +203,7 @@ ], "properties": { "annotations": { + "description": "Annotations attach arbitrary non-identifying metadata to objects.", "default": { "scope.github.com/bin-path": null, "scope.github.com/file-dir": null, @@ -187,10 +212,12 @@ "$ref": "#/definitions/ModelMetadataAnnotations" }, "description": { + "description": "Description of this resource, used when listing resources and helpful to inform users why the resource exists.", "default": "Description not provided", "type": "string" }, "labels": { + "description": "Key/value pairs, allows resources to be easily filtered from the CLI.", "default": {}, "type": "object", "additionalProperties": { @@ -198,6 +225,7 @@ } }, "name": { + "description": "Name of the resource, needs to be unique across `kinds`. When two resources share a name, the one \"closest\" to the current working directory will take precedence.", "type": "string" } } @@ -206,20 +234,7 @@ "type": "object", "properties": { "scope.github.com/bin-path": { - "type": [ - "string", - "null" - ], - "nullable": true - }, - "scope.github.com/file-dir": { - "type": [ - "string", - "null" - ], - "nullable": true - }, - "scope.github.com/file-path": { + "description": "When running commands, additional paths that should be paced at the _beginning_ of the `PATH`.", "type": [ "string", "null" @@ -235,12 +250,14 @@ ] }, "ReportDefinitionSpec": { + "description": "Definition of the Report Definition", "type": "object", "required": [ "template" ], "properties": { "additionalData": { + "description": "defines additional data that needs to be pulled from the system when reporting a bug. `additionalData` is a map of `string:string`, the value is a command that should be run. When a report is built, the commands will be run and automatically included in the report.", "default": {}, "type": "object", "additionalProperties": { @@ -248,12 +265,14 @@ } }, "template": { + "description": "a Jinja2 style template, to be included. The text should be in Markdown format. Scope injects `command` as the command that was run.", "type": "string" } }, "additionalProperties": false }, "ReportDestinationGithubIssueSpec": { + "description": "How to load the report to GitHub Issue", "type": "object", "required": [ "owner", @@ -261,12 +280,15 @@ ], "properties": { "owner": { + "description": "`owner` of the repository for the issue", "type": "string" }, "repo": { + "description": "`repo` the name of the repo for the issue", "type": "string" }, "tags": { + "description": "A list of tags to be added to the issue", "default": [], "type": "array", "items": { @@ -276,6 +298,20 @@ }, "additionalProperties": false }, + "ReportDestinationRustyPasteSpec": { + "description": "How to upload a report to RustyPaste", + "type": "object", + "required": [ + "url" + ], + "properties": { + "url": { + "description": "URL of RustyPaste", + "type": "string" + } + }, + "additionalProperties": false + }, "ReportDestinationSpec": { "oneOf": [ { @@ -285,16 +321,7 @@ ], "properties": { "rustyPaste": { - "type": "object", - "required": [ - "url" - ], - "properties": { - "url": { - "type": "string" - } - }, - "additionalProperties": false + "$ref": "#/definitions/ReportDestinationRustyPasteSpec" } }, "additionalProperties": false @@ -320,24 +347,33 @@ ] }, "ReportLocationSpec": { + "description": "Define where to upload the report to", "type": "object", "required": [ "destination" ], "properties": { "destination": { + "description": "Destination the report should be uploaded to", "$ref": "#/definitions/ReportDestinationSpec" } }, "additionalProperties": false }, "V1AlphaApiVersion": { - "type": "string", - "enum": [ - "scope.github.com/v1alpha" + "description": "Version of the Scope API", + "oneOf": [ + { + "description": "Current latest version of the resources.", + "type": "string", + "enum": [ + "scope.github.com/v1alpha" + ] + } ] }, "V1AlphaDoctorGroup": { + "description": "Resource used to define a `ScopeDoctorGroup`.", "type": "object", "required": [ "apiVersion", @@ -347,21 +383,26 @@ ], "properties": { "apiVersion": { + "description": "API version of the resource", "$ref": "#/definitions/V1AlphaApiVersion" }, "kind": { + "description": "The type of resource.", "$ref": "#/definitions/DoctorGroupKind" }, "metadata": { + "description": "Standard set of options including name, description for the resource. Together `kind` and `metadata.name` are required to be unique. If there are duplicate, the resources \"closest\" to the execution dir will take precedence.", "$ref": "#/definitions/ModelMetadata" }, "spec": { + "description": "Options for the resource.", "$ref": "#/definitions/DoctorGroupSpec" } }, "additionalProperties": false }, "V1AlphaKnownError": { + "description": "Resource used to define a `ScopeKnownError`. A known error is a specific error that a user may run into.", "type": "object", "required": [ "apiVersion", @@ -371,21 +412,26 @@ ], "properties": { "apiVersion": { + "description": "API version of the resource", "$ref": "#/definitions/V1AlphaApiVersion" }, "kind": { + "description": "The type of resource.", "$ref": "#/definitions/KnownErrorKind" }, "metadata": { + "description": "Standard set of options including name, description for the resource. Together `kind` and `metadata.name` are required to be unique. If there are duplicate, the resources \"closest\" to the execution dir will take precedence.", "$ref": "#/definitions/ModelMetadata" }, "spec": { + "description": "Options for the resource.", "$ref": "#/definitions/KnownErrorSpec" } }, "additionalProperties": false }, "V1AlphaReportDefinition": { + "description": "A `ScopeReportDefinition` tells scope how to collect details about the system when there is an issue they need to report.", "type": "object", "required": [ "apiVersion", @@ -395,21 +441,26 @@ ], "properties": { "apiVersion": { + "description": "API version of the resource", "$ref": "#/definitions/V1AlphaApiVersion" }, "kind": { + "description": "The type of resource.", "$ref": "#/definitions/ReportDefinitionKind" }, "metadata": { + "description": "Standard set of options including name, description for the resource. Together `kind` and `metadata.name` are required to be unique. If there are duplicate, the resources \"closest\" to the execution dir will take precedence.", "$ref": "#/definitions/ModelMetadata" }, "spec": { + "description": "Options for the resource.", "$ref": "#/definitions/ReportDefinitionSpec" } }, "additionalProperties": false }, "V1AlphaReportLocation": { + "description": "A `ScopeReportLocation` tells where to upload a report to.", "type": "object", "required": [ "apiVersion", @@ -419,15 +470,19 @@ ], "properties": { "apiVersion": { + "description": "API version of the resource", "$ref": "#/definitions/V1AlphaApiVersion" }, "kind": { + "description": "The type of resource.", "$ref": "#/definitions/ReportLocationKind" }, "metadata": { + "description": "Standard set of options including name, description for the resource. Together `kind` and `metadata.name` are required to be unique. If there are duplicate, the resources \"closest\" to the execution dir will take precedence.", "$ref": "#/definitions/ModelMetadata" }, "spec": { + "description": "Options for the resource.", "$ref": "#/definitions/ReportLocationSpec" } }, diff --git a/scope/schema/v1alpha.com.github.scope.ScopeReportDefinition.json b/scope/schema/v1alpha.com.github.scope.ScopeReportDefinition.json index 7375068..5e14259 100644 --- a/scope/schema/v1alpha.com.github.scope.ScopeReportDefinition.json +++ b/scope/schema/v1alpha.com.github.scope.ScopeReportDefinition.json @@ -1,6 +1,7 @@ { "$schema": "https://json-schema.org/draft/2019-09/schema", "title": "V1AlphaReportDefinition", + "description": "A `ScopeReportDefinition` tells scope how to collect details about the system when there is an issue they need to report.", "type": "object", "required": [ "apiVersion", @@ -10,24 +11,30 @@ ], "properties": { "apiVersion": { + "description": "API version of the resource", "$ref": "#/definitions/V1AlphaApiVersion" }, "kind": { + "description": "The type of resource.", "$ref": "#/definitions/ReportDefinitionKind" }, "metadata": { + "description": "Standard set of options including name, description for the resource. Together `kind` and `metadata.name` are required to be unique. If there are duplicate, the resources \"closest\" to the execution dir will take precedence.", "$ref": "#/definitions/ModelMetadata" }, "spec": { + "description": "Options for the resource.", "$ref": "#/definitions/ReportDefinitionSpec" } }, "additionalProperties": false, "definitions": { "DoctorCheckSpec": { + "description": "What needs to be checked before the action will run. All `paths` will be checked first, then `commands`. If a `path` has changed, the `command` will not run.", "type": "object", "properties": { "commands": { + "description": "A list of commands to execute to check the environment.", "default": null, "type": [ "array", @@ -39,6 +46,7 @@ "nullable": true }, "paths": { + "description": "A list of globs to check for changes. When the glob matches a new file, or the contents of the file change, the check will require a fix.", "default": null, "type": [ "array", @@ -53,9 +61,11 @@ "additionalProperties": false }, "DoctorFixSpec": { + "description": "Definition for fixing the environment.", "type": "object", "properties": { "commands": { + "description": "List of commands to run to fix the env.", "default": [], "type": "array", "items": { @@ -63,6 +73,7 @@ } }, "helpText": { + "description": "Text to display when no command is provided / fails to fix the env.", "default": null, "type": [ "string", @@ -71,6 +82,7 @@ "nullable": true }, "helpUrl": { + "description": "Link to documentation to fix the issue.", "default": null, "type": [ "string", @@ -82,15 +94,18 @@ "additionalProperties": false }, "DoctorGroupActionSpec": { + "description": "An action is a single step used to check in a group. This is most commonly used to build a series of tasks for a system, like `ruby`, `python`, and databases.", "type": "object", "required": [ "check" ], "properties": { "check": { + "description": "The `check` run before `fix` (if provided). A check is used to determine if the fix needs to be executed, or fail the action if no fix is provided. If a fix is specified, the check will re-execute to ensure that the fix applied correctly.", "$ref": "#/definitions/DoctorCheckSpec" }, "description": { + "description": "A description of this specific action, used for information to the users.", "type": [ "string", "null" @@ -98,6 +113,7 @@ "nullable": true }, "fix": { + "description": "A fix defines how to fix the issue that a `check` is validating. When provided, will only run when the `check` \"fails\".", "anyOf": [ { "$ref": "#/definitions/DoctorFixSpec" @@ -109,6 +125,7 @@ "nullable": true }, "name": { + "description": "Name of the \"action\". When not provided, it will be the index of the action within the group. This is used when reporting status to the users.", "type": [ "string", "null" @@ -116,6 +133,7 @@ "nullable": true }, "required": { + "description": "If false, the action is allowed to fail and let other actions in the group execute. Defaults to `true`.", "default": true, "type": "boolean" } @@ -129,18 +147,21 @@ ] }, "DoctorGroupSpec": { + "description": "Often used to describe how to fix a \"system\", like `ruby`, `python`, or databases. Able to depend on other \"system\".", "type": "object", "required": [ "actions" ], "properties": { "actions": { + "description": "A series of steps to check and fix for the group.", "type": "array", "items": { "$ref": "#/definitions/DoctorGroupActionSpec" } }, "needs": { + "description": "A list of `ScopeDoctorGroup` that are required for this group to execute. If not all finish successfully, this group will not execute.", "default": [], "type": "array", "items": { @@ -157,6 +178,7 @@ ] }, "KnownErrorSpec": { + "description": "Definition of the known error", "type": "object", "required": [ "help", @@ -164,9 +186,11 @@ ], "properties": { "help": { + "description": "Text that the user can use to fix the issue", "type": "string" }, "pattern": { + "description": "A Regex used to determine if the line is an error.", "type": "string" } }, @@ -179,6 +203,7 @@ ], "properties": { "annotations": { + "description": "Annotations attach arbitrary non-identifying metadata to objects.", "default": { "scope.github.com/bin-path": null, "scope.github.com/file-dir": null, @@ -187,10 +212,12 @@ "$ref": "#/definitions/ModelMetadataAnnotations" }, "description": { + "description": "Description of this resource, used when listing resources and helpful to inform users why the resource exists.", "default": "Description not provided", "type": "string" }, "labels": { + "description": "Key/value pairs, allows resources to be easily filtered from the CLI.", "default": {}, "type": "object", "additionalProperties": { @@ -198,6 +225,7 @@ } }, "name": { + "description": "Name of the resource, needs to be unique across `kinds`. When two resources share a name, the one \"closest\" to the current working directory will take precedence.", "type": "string" } } @@ -206,20 +234,7 @@ "type": "object", "properties": { "scope.github.com/bin-path": { - "type": [ - "string", - "null" - ], - "nullable": true - }, - "scope.github.com/file-dir": { - "type": [ - "string", - "null" - ], - "nullable": true - }, - "scope.github.com/file-path": { + "description": "When running commands, additional paths that should be paced at the _beginning_ of the `PATH`.", "type": [ "string", "null" @@ -235,12 +250,14 @@ ] }, "ReportDefinitionSpec": { + "description": "Definition of the Report Definition", "type": "object", "required": [ "template" ], "properties": { "additionalData": { + "description": "defines additional data that needs to be pulled from the system when reporting a bug. `additionalData` is a map of `string:string`, the value is a command that should be run. When a report is built, the commands will be run and automatically included in the report.", "default": {}, "type": "object", "additionalProperties": { @@ -248,12 +265,14 @@ } }, "template": { + "description": "a Jinja2 style template, to be included. The text should be in Markdown format. Scope injects `command` as the command that was run.", "type": "string" } }, "additionalProperties": false }, "ReportDestinationGithubIssueSpec": { + "description": "How to load the report to GitHub Issue", "type": "object", "required": [ "owner", @@ -261,12 +280,15 @@ ], "properties": { "owner": { + "description": "`owner` of the repository for the issue", "type": "string" }, "repo": { + "description": "`repo` the name of the repo for the issue", "type": "string" }, "tags": { + "description": "A list of tags to be added to the issue", "default": [], "type": "array", "items": { @@ -276,6 +298,20 @@ }, "additionalProperties": false }, + "ReportDestinationRustyPasteSpec": { + "description": "How to upload a report to RustyPaste", + "type": "object", + "required": [ + "url" + ], + "properties": { + "url": { + "description": "URL of RustyPaste", + "type": "string" + } + }, + "additionalProperties": false + }, "ReportDestinationSpec": { "oneOf": [ { @@ -285,16 +321,7 @@ ], "properties": { "rustyPaste": { - "type": "object", - "required": [ - "url" - ], - "properties": { - "url": { - "type": "string" - } - }, - "additionalProperties": false + "$ref": "#/definitions/ReportDestinationRustyPasteSpec" } }, "additionalProperties": false @@ -320,24 +347,33 @@ ] }, "ReportLocationSpec": { + "description": "Define where to upload the report to", "type": "object", "required": [ "destination" ], "properties": { "destination": { + "description": "Destination the report should be uploaded to", "$ref": "#/definitions/ReportDestinationSpec" } }, "additionalProperties": false }, "V1AlphaApiVersion": { - "type": "string", - "enum": [ - "scope.github.com/v1alpha" + "description": "Version of the Scope API", + "oneOf": [ + { + "description": "Current latest version of the resources.", + "type": "string", + "enum": [ + "scope.github.com/v1alpha" + ] + } ] }, "V1AlphaDoctorGroup": { + "description": "Resource used to define a `ScopeDoctorGroup`.", "type": "object", "required": [ "apiVersion", @@ -347,21 +383,26 @@ ], "properties": { "apiVersion": { + "description": "API version of the resource", "$ref": "#/definitions/V1AlphaApiVersion" }, "kind": { + "description": "The type of resource.", "$ref": "#/definitions/DoctorGroupKind" }, "metadata": { + "description": "Standard set of options including name, description for the resource. Together `kind` and `metadata.name` are required to be unique. If there are duplicate, the resources \"closest\" to the execution dir will take precedence.", "$ref": "#/definitions/ModelMetadata" }, "spec": { + "description": "Options for the resource.", "$ref": "#/definitions/DoctorGroupSpec" } }, "additionalProperties": false }, "V1AlphaKnownError": { + "description": "Resource used to define a `ScopeKnownError`. A known error is a specific error that a user may run into.", "type": "object", "required": [ "apiVersion", @@ -371,21 +412,26 @@ ], "properties": { "apiVersion": { + "description": "API version of the resource", "$ref": "#/definitions/V1AlphaApiVersion" }, "kind": { + "description": "The type of resource.", "$ref": "#/definitions/KnownErrorKind" }, "metadata": { + "description": "Standard set of options including name, description for the resource. Together `kind` and `metadata.name` are required to be unique. If there are duplicate, the resources \"closest\" to the execution dir will take precedence.", "$ref": "#/definitions/ModelMetadata" }, "spec": { + "description": "Options for the resource.", "$ref": "#/definitions/KnownErrorSpec" } }, "additionalProperties": false }, "V1AlphaReportDefinition": { + "description": "A `ScopeReportDefinition` tells scope how to collect details about the system when there is an issue they need to report.", "type": "object", "required": [ "apiVersion", @@ -395,21 +441,26 @@ ], "properties": { "apiVersion": { + "description": "API version of the resource", "$ref": "#/definitions/V1AlphaApiVersion" }, "kind": { + "description": "The type of resource.", "$ref": "#/definitions/ReportDefinitionKind" }, "metadata": { + "description": "Standard set of options including name, description for the resource. Together `kind` and `metadata.name` are required to be unique. If there are duplicate, the resources \"closest\" to the execution dir will take precedence.", "$ref": "#/definitions/ModelMetadata" }, "spec": { + "description": "Options for the resource.", "$ref": "#/definitions/ReportDefinitionSpec" } }, "additionalProperties": false }, "V1AlphaReportLocation": { + "description": "A `ScopeReportLocation` tells where to upload a report to.", "type": "object", "required": [ "apiVersion", @@ -419,15 +470,19 @@ ], "properties": { "apiVersion": { + "description": "API version of the resource", "$ref": "#/definitions/V1AlphaApiVersion" }, "kind": { + "description": "The type of resource.", "$ref": "#/definitions/ReportLocationKind" }, "metadata": { + "description": "Standard set of options including name, description for the resource. Together `kind` and `metadata.name` are required to be unique. If there are duplicate, the resources \"closest\" to the execution dir will take precedence.", "$ref": "#/definitions/ModelMetadata" }, "spec": { + "description": "Options for the resource.", "$ref": "#/definitions/ReportLocationSpec" } }, diff --git a/scope/schema/v1alpha.com.github.scope.ScopeReportLocation.json b/scope/schema/v1alpha.com.github.scope.ScopeReportLocation.json index e9087e9..d8ef530 100644 --- a/scope/schema/v1alpha.com.github.scope.ScopeReportLocation.json +++ b/scope/schema/v1alpha.com.github.scope.ScopeReportLocation.json @@ -1,6 +1,7 @@ { "$schema": "https://json-schema.org/draft/2019-09/schema", "title": "V1AlphaReportLocation", + "description": "A `ScopeReportLocation` tells where to upload a report to.", "type": "object", "required": [ "apiVersion", @@ -10,24 +11,30 @@ ], "properties": { "apiVersion": { + "description": "API version of the resource", "$ref": "#/definitions/V1AlphaApiVersion" }, "kind": { + "description": "The type of resource.", "$ref": "#/definitions/ReportLocationKind" }, "metadata": { + "description": "Standard set of options including name, description for the resource. Together `kind` and `metadata.name` are required to be unique. If there are duplicate, the resources \"closest\" to the execution dir will take precedence.", "$ref": "#/definitions/ModelMetadata" }, "spec": { + "description": "Options for the resource.", "$ref": "#/definitions/ReportLocationSpec" } }, "additionalProperties": false, "definitions": { "DoctorCheckSpec": { + "description": "What needs to be checked before the action will run. All `paths` will be checked first, then `commands`. If a `path` has changed, the `command` will not run.", "type": "object", "properties": { "commands": { + "description": "A list of commands to execute to check the environment.", "default": null, "type": [ "array", @@ -39,6 +46,7 @@ "nullable": true }, "paths": { + "description": "A list of globs to check for changes. When the glob matches a new file, or the contents of the file change, the check will require a fix.", "default": null, "type": [ "array", @@ -53,9 +61,11 @@ "additionalProperties": false }, "DoctorFixSpec": { + "description": "Definition for fixing the environment.", "type": "object", "properties": { "commands": { + "description": "List of commands to run to fix the env.", "default": [], "type": "array", "items": { @@ -63,6 +73,7 @@ } }, "helpText": { + "description": "Text to display when no command is provided / fails to fix the env.", "default": null, "type": [ "string", @@ -71,6 +82,7 @@ "nullable": true }, "helpUrl": { + "description": "Link to documentation to fix the issue.", "default": null, "type": [ "string", @@ -82,15 +94,18 @@ "additionalProperties": false }, "DoctorGroupActionSpec": { + "description": "An action is a single step used to check in a group. This is most commonly used to build a series of tasks for a system, like `ruby`, `python`, and databases.", "type": "object", "required": [ "check" ], "properties": { "check": { + "description": "The `check` run before `fix` (if provided). A check is used to determine if the fix needs to be executed, or fail the action if no fix is provided. If a fix is specified, the check will re-execute to ensure that the fix applied correctly.", "$ref": "#/definitions/DoctorCheckSpec" }, "description": { + "description": "A description of this specific action, used for information to the users.", "type": [ "string", "null" @@ -98,6 +113,7 @@ "nullable": true }, "fix": { + "description": "A fix defines how to fix the issue that a `check` is validating. When provided, will only run when the `check` \"fails\".", "anyOf": [ { "$ref": "#/definitions/DoctorFixSpec" @@ -109,6 +125,7 @@ "nullable": true }, "name": { + "description": "Name of the \"action\". When not provided, it will be the index of the action within the group. This is used when reporting status to the users.", "type": [ "string", "null" @@ -116,6 +133,7 @@ "nullable": true }, "required": { + "description": "If false, the action is allowed to fail and let other actions in the group execute. Defaults to `true`.", "default": true, "type": "boolean" } @@ -129,18 +147,21 @@ ] }, "DoctorGroupSpec": { + "description": "Often used to describe how to fix a \"system\", like `ruby`, `python`, or databases. Able to depend on other \"system\".", "type": "object", "required": [ "actions" ], "properties": { "actions": { + "description": "A series of steps to check and fix for the group.", "type": "array", "items": { "$ref": "#/definitions/DoctorGroupActionSpec" } }, "needs": { + "description": "A list of `ScopeDoctorGroup` that are required for this group to execute. If not all finish successfully, this group will not execute.", "default": [], "type": "array", "items": { @@ -157,6 +178,7 @@ ] }, "KnownErrorSpec": { + "description": "Definition of the known error", "type": "object", "required": [ "help", @@ -164,9 +186,11 @@ ], "properties": { "help": { + "description": "Text that the user can use to fix the issue", "type": "string" }, "pattern": { + "description": "A Regex used to determine if the line is an error.", "type": "string" } }, @@ -179,6 +203,7 @@ ], "properties": { "annotations": { + "description": "Annotations attach arbitrary non-identifying metadata to objects.", "default": { "scope.github.com/bin-path": null, "scope.github.com/file-dir": null, @@ -187,10 +212,12 @@ "$ref": "#/definitions/ModelMetadataAnnotations" }, "description": { + "description": "Description of this resource, used when listing resources and helpful to inform users why the resource exists.", "default": "Description not provided", "type": "string" }, "labels": { + "description": "Key/value pairs, allows resources to be easily filtered from the CLI.", "default": {}, "type": "object", "additionalProperties": { @@ -198,6 +225,7 @@ } }, "name": { + "description": "Name of the resource, needs to be unique across `kinds`. When two resources share a name, the one \"closest\" to the current working directory will take precedence.", "type": "string" } } @@ -206,20 +234,7 @@ "type": "object", "properties": { "scope.github.com/bin-path": { - "type": [ - "string", - "null" - ], - "nullable": true - }, - "scope.github.com/file-dir": { - "type": [ - "string", - "null" - ], - "nullable": true - }, - "scope.github.com/file-path": { + "description": "When running commands, additional paths that should be paced at the _beginning_ of the `PATH`.", "type": [ "string", "null" @@ -235,12 +250,14 @@ ] }, "ReportDefinitionSpec": { + "description": "Definition of the Report Definition", "type": "object", "required": [ "template" ], "properties": { "additionalData": { + "description": "defines additional data that needs to be pulled from the system when reporting a bug. `additionalData` is a map of `string:string`, the value is a command that should be run. When a report is built, the commands will be run and automatically included in the report.", "default": {}, "type": "object", "additionalProperties": { @@ -248,12 +265,14 @@ } }, "template": { + "description": "a Jinja2 style template, to be included. The text should be in Markdown format. Scope injects `command` as the command that was run.", "type": "string" } }, "additionalProperties": false }, "ReportDestinationGithubIssueSpec": { + "description": "How to load the report to GitHub Issue", "type": "object", "required": [ "owner", @@ -261,12 +280,15 @@ ], "properties": { "owner": { + "description": "`owner` of the repository for the issue", "type": "string" }, "repo": { + "description": "`repo` the name of the repo for the issue", "type": "string" }, "tags": { + "description": "A list of tags to be added to the issue", "default": [], "type": "array", "items": { @@ -276,6 +298,20 @@ }, "additionalProperties": false }, + "ReportDestinationRustyPasteSpec": { + "description": "How to upload a report to RustyPaste", + "type": "object", + "required": [ + "url" + ], + "properties": { + "url": { + "description": "URL of RustyPaste", + "type": "string" + } + }, + "additionalProperties": false + }, "ReportDestinationSpec": { "oneOf": [ { @@ -285,16 +321,7 @@ ], "properties": { "rustyPaste": { - "type": "object", - "required": [ - "url" - ], - "properties": { - "url": { - "type": "string" - } - }, - "additionalProperties": false + "$ref": "#/definitions/ReportDestinationRustyPasteSpec" } }, "additionalProperties": false @@ -320,24 +347,33 @@ ] }, "ReportLocationSpec": { + "description": "Define where to upload the report to", "type": "object", "required": [ "destination" ], "properties": { "destination": { + "description": "Destination the report should be uploaded to", "$ref": "#/definitions/ReportDestinationSpec" } }, "additionalProperties": false }, "V1AlphaApiVersion": { - "type": "string", - "enum": [ - "scope.github.com/v1alpha" + "description": "Version of the Scope API", + "oneOf": [ + { + "description": "Current latest version of the resources.", + "type": "string", + "enum": [ + "scope.github.com/v1alpha" + ] + } ] }, "V1AlphaDoctorGroup": { + "description": "Resource used to define a `ScopeDoctorGroup`.", "type": "object", "required": [ "apiVersion", @@ -347,21 +383,26 @@ ], "properties": { "apiVersion": { + "description": "API version of the resource", "$ref": "#/definitions/V1AlphaApiVersion" }, "kind": { + "description": "The type of resource.", "$ref": "#/definitions/DoctorGroupKind" }, "metadata": { + "description": "Standard set of options including name, description for the resource. Together `kind` and `metadata.name` are required to be unique. If there are duplicate, the resources \"closest\" to the execution dir will take precedence.", "$ref": "#/definitions/ModelMetadata" }, "spec": { + "description": "Options for the resource.", "$ref": "#/definitions/DoctorGroupSpec" } }, "additionalProperties": false }, "V1AlphaKnownError": { + "description": "Resource used to define a `ScopeKnownError`. A known error is a specific error that a user may run into.", "type": "object", "required": [ "apiVersion", @@ -371,21 +412,26 @@ ], "properties": { "apiVersion": { + "description": "API version of the resource", "$ref": "#/definitions/V1AlphaApiVersion" }, "kind": { + "description": "The type of resource.", "$ref": "#/definitions/KnownErrorKind" }, "metadata": { + "description": "Standard set of options including name, description for the resource. Together `kind` and `metadata.name` are required to be unique. If there are duplicate, the resources \"closest\" to the execution dir will take precedence.", "$ref": "#/definitions/ModelMetadata" }, "spec": { + "description": "Options for the resource.", "$ref": "#/definitions/KnownErrorSpec" } }, "additionalProperties": false }, "V1AlphaReportDefinition": { + "description": "A `ScopeReportDefinition` tells scope how to collect details about the system when there is an issue they need to report.", "type": "object", "required": [ "apiVersion", @@ -395,21 +441,26 @@ ], "properties": { "apiVersion": { + "description": "API version of the resource", "$ref": "#/definitions/V1AlphaApiVersion" }, "kind": { + "description": "The type of resource.", "$ref": "#/definitions/ReportDefinitionKind" }, "metadata": { + "description": "Standard set of options including name, description for the resource. Together `kind` and `metadata.name` are required to be unique. If there are duplicate, the resources \"closest\" to the execution dir will take precedence.", "$ref": "#/definitions/ModelMetadata" }, "spec": { + "description": "Options for the resource.", "$ref": "#/definitions/ReportDefinitionSpec" } }, "additionalProperties": false }, "V1AlphaReportLocation": { + "description": "A `ScopeReportLocation` tells where to upload a report to.", "type": "object", "required": [ "apiVersion", @@ -419,15 +470,19 @@ ], "properties": { "apiVersion": { + "description": "API version of the resource", "$ref": "#/definitions/V1AlphaApiVersion" }, "kind": { + "description": "The type of resource.", "$ref": "#/definitions/ReportLocationKind" }, "metadata": { + "description": "Standard set of options including name, description for the resource. Together `kind` and `metadata.name` are required to be unique. If there are duplicate, the resources \"closest\" to the execution dir will take precedence.", "$ref": "#/definitions/ModelMetadata" }, "spec": { + "description": "Options for the resource.", "$ref": "#/definitions/ReportLocationSpec" } }, diff --git a/scope/src/models/core.rs b/scope/src/models/core.rs index 0671daa..bc5a0e0 100644 --- a/scope/src/models/core.rs +++ b/scope/src/models/core.rs @@ -11,10 +11,15 @@ pub const FILE_EXEC_PATH_ANNOTATION: &str = "scope.github.com/bin-path"; #[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Default, Builder, JsonSchema)] pub struct ModelMetadataAnnotations { #[serde(rename = "scope.github.com/file-path")] + #[schemars(skip)] + /// File path for the resource, generated automatically. pub file_path: Option, #[serde(rename = "scope.github.com/file-dir")] + #[schemars(skip)] + /// Directory containing the resource, generated automatically. pub file_dir: Option, #[serde(rename = "scope.github.com/bin-path")] + /// When running commands, additional paths that should be paced at the _beginning_ of the `PATH`. pub bin_path: Option, #[serde(flatten)] pub extra: BTreeMap, @@ -67,12 +72,21 @@ impl ModelMetadata { #[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Default, Builder, JsonSchema)] #[builder(setter(into))] pub struct ModelMetadata { + /// Name of the resource, needs to be unique across `kinds`. When two resources share a name, + /// the one "closest" to the current working directory will take precedence. pub name: String, + #[serde(default = "default_description")] + /// Description of this resource, used when listing resources and helpful to inform users why + /// the resource exists. pub description: String, + #[serde(default)] + /// Annotations attach arbitrary non-identifying metadata to objects. pub annotations: ModelMetadataAnnotations, + #[serde(default)] + /// Key/value pairs, allows resources to be easily filtered from the CLI. pub labels: BTreeMap, } diff --git a/scope/src/models/v1alpha/doctor_group.rs b/scope/src/models/v1alpha/doctor_group.rs index a5a626a..59eb99b 100644 --- a/scope/src/models/v1alpha/doctor_group.rs +++ b/scope/src/models/v1alpha/doctor_group.rs @@ -6,37 +6,66 @@ use derive_builder::Builder; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; +/// What needs to be checked before the action will run. All `paths` will be checked first, then +/// `commands`. If a `path` has changed, the `command` will not run. #[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema)] #[serde(rename_all = "camelCase")] #[schemars(deny_unknown_fields)] pub struct DoctorCheckSpec { #[serde(default)] + /// A list of globs to check for changes. When the glob matches a new file, or the contents + /// of the file change, the check will require a fix. pub paths: Option>, + + #[serde(default)] + /// A list of commands to execute to check the environment. pub commands: Option>, } +/// Definition for fixing the environment. #[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema)] #[serde(rename_all = "camelCase")] #[schemars(deny_unknown_fields)] pub struct DoctorFixSpec { #[serde(default)] + /// List of commands to run to fix the env. pub commands: Vec, + #[serde(default)] + /// Text to display when no command is provided / fails to fix the env. pub help_text: Option, + #[serde(default)] + /// Link to documentation to fix the issue. pub help_url: Option, } +/// An action is a single step used to check in a group. This is most commonly used to build a +/// series of tasks for a system, like `ruby`, `python`, and databases. #[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema)] #[serde(rename_all = "camelCase")] #[schemars(deny_unknown_fields)] pub struct DoctorGroupActionSpec { + /// Name of the "action". When not provided, it will be the index of the action within the group. + /// This is used when reporting status to the users. pub name: Option, + + /// A description of this specific action, used for information to the users. pub description: Option, + + /// The `check` run before `fix` (if provided). A check is used to determine if the fix needs + /// to be executed, or fail the action if no fix is provided. If a fix is specified, the check + /// will re-execute to ensure that the fix applied correctly. pub check: DoctorCheckSpec, + + /// A fix defines how to fix the issue that a `check` is validating. When provided, will only + /// run when the `check` "fails". pub fix: Option, + #[serde(default = "doctor_group_action_required_default")] + /// If false, the action is allowed to fail and let other actions in the group execute. Defaults + /// to `true`. pub required: bool, } @@ -44,12 +73,18 @@ fn doctor_group_action_required_default() -> bool { true } +/// Often used to describe how to fix a "system", like `ruby`, `python`, or databases. Able to +/// depend on other "system". #[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema)] #[serde(rename_all = "camelCase")] #[schemars(deny_unknown_fields)] pub struct DoctorGroupSpec { #[serde(default)] + /// A list of `ScopeDoctorGroup` that are required for this group to execute. If not all finish + /// successfully, this group will not execute. pub needs: Vec, + + /// A series of steps to check and fix for the group. pub actions: Vec, } @@ -59,14 +94,21 @@ pub enum DoctorGroupKind { ScopeDoctorGroup, } +/// Resource used to define a `ScopeDoctorGroup`. #[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Builder, JsonSchema)] #[builder(setter(into))] #[serde(rename_all = "camelCase")] #[schemars(deny_unknown_fields)] pub struct V1AlphaDoctorGroup { + /// API version of the resource pub api_version: V1AlphaApiVersion, + /// The type of resource. pub kind: DoctorGroupKind, + /// Standard set of options including name, description for the resource. + /// Together `kind` and `metadata.name` are required to be unique. If there are duplicate, the + /// resources "closest" to the execution dir will take precedence. pub metadata: ModelMetadata, + /// Options for the resource. pub spec: DoctorGroupSpec, } diff --git a/scope/src/models/v1alpha/known_error.rs b/scope/src/models/v1alpha/known_error.rs index e3286bc..ae30601 100644 --- a/scope/src/models/v1alpha/known_error.rs +++ b/scope/src/models/v1alpha/known_error.rs @@ -5,11 +5,15 @@ use derive_builder::Builder; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; +/// Definition of the known error #[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema)] #[serde(rename_all = "camelCase")] #[schemars(deny_unknown_fields)] pub struct KnownErrorSpec { + /// Text that the user can use to fix the issue pub help: String, + + /// A Regex used to determine if the line is an error. pub pattern: String, } @@ -19,14 +23,22 @@ pub enum KnownErrorKind { ScopeKnownError, } +/// Resource used to define a `ScopeKnownError`. +/// A known error is a specific error that a user may run into. #[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Builder, JsonSchema)] #[builder(setter(into))] #[serde(rename_all = "camelCase")] #[schemars(deny_unknown_fields)] pub struct V1AlphaKnownError { + /// API version of the resource pub api_version: V1AlphaApiVersion, + /// The type of resource. pub kind: KnownErrorKind, + /// Standard set of options including name, description for the resource. + /// Together `kind` and `metadata.name` are required to be unique. If there are duplicate, the + /// resources "closest" to the execution dir will take precedence. pub metadata: ModelMetadata, + /// Options for the resource. pub spec: KnownErrorSpec, } diff --git a/scope/src/models/v1alpha/mod.rs b/scope/src/models/v1alpha/mod.rs index 0fbc735..be89fa0 100644 --- a/scope/src/models/v1alpha/mod.rs +++ b/scope/src/models/v1alpha/mod.rs @@ -10,9 +10,11 @@ mod report_location; #[derive( Serialize, Deserialize, Debug, strum::Display, Clone, PartialEq, EnumString, JsonSchema, )] +/// Version of the Scope API pub enum V1AlphaApiVersion { #[serde(rename = "scope.github.com/v1alpha")] #[strum(serialize = "scope.github.com/v1alpha")] + /// Current latest version of the resources. ScopeV1Alpha, } diff --git a/scope/src/models/v1alpha/report_definition.rs b/scope/src/models/v1alpha/report_definition.rs index 5ce58c2..a87fc05 100644 --- a/scope/src/models/v1alpha/report_definition.rs +++ b/scope/src/models/v1alpha/report_definition.rs @@ -8,12 +8,19 @@ use schemars::JsonSchema; use serde::{Deserialize, Serialize}; use std::collections::BTreeMap; +/// Definition of the Report Definition #[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Builder, JsonSchema)] #[serde(rename_all = "camelCase")] #[schemars(deny_unknown_fields)] pub struct ReportDefinitionSpec { #[serde(default)] + /// defines additional data that needs to be pulled from the system when reporting a bug. + /// `additionalData` is a map of `string:string`, the value is a command that should be run. + /// When a report is built, the commands will be run and automatically included in the report. pub additional_data: BTreeMap, + + /// a Jinja2 style template, to be included. The text should be in Markdown format. Scope + /// injects `command` as the command that was run. pub template: String, } @@ -23,14 +30,22 @@ pub enum ReportDefinitionKind { ScopeReportDefinition, } +/// A `ScopeReportDefinition` tells scope how to collect details about the system when there +/// is an issue they need to report. #[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Builder, JsonSchema)] #[builder(setter(into))] #[serde(rename_all = "camelCase")] #[schemars(deny_unknown_fields)] pub struct V1AlphaReportDefinition { + /// API version of the resource pub api_version: V1AlphaApiVersion, + /// The type of resource. pub kind: ReportDefinitionKind, + /// Standard set of options including name, description for the resource. + /// Together `kind` and `metadata.name` are required to be unique. If there are duplicate, the + /// resources "closest" to the execution dir will take precedence. pub metadata: ModelMetadata, + /// Options for the resource. pub spec: ReportDefinitionSpec, } diff --git a/scope/src/models/v1alpha/report_location.rs b/scope/src/models/v1alpha/report_location.rs index 25bdd68..431b2a5 100644 --- a/scope/src/models/v1alpha/report_location.rs +++ b/scope/src/models/v1alpha/report_location.rs @@ -5,30 +5,47 @@ use derive_builder::Builder; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; +/// How to load the report to GitHub Issue #[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema)] #[serde(rename_all = "camelCase")] #[schemars(deny_unknown_fields)] pub struct ReportDestinationGithubIssueSpec { + /// `owner` of the repository for the issue pub owner: String, + + /// `repo` the name of the repo for the issue pub repo: String, + #[serde(default)] + /// A list of tags to be added to the issue pub tags: Vec, } +/// How to upload a report to RustyPaste +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema)] +#[serde(rename_all = "camelCase")] +#[schemars(deny_unknown_fields)] +pub struct ReportDestinationRustyPasteSpec { + /// URL of RustyPaste + pub url: String, +} + #[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema)] #[serde(rename_all = "camelCase")] #[schemars(deny_unknown_fields)] pub enum ReportDestinationSpec { - RustyPaste { url: String }, + RustyPaste(ReportDestinationRustyPasteSpec), GithubIssue(ReportDestinationGithubIssueSpec), } +/// Define where to upload the report to #[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema)] #[serde(rename_all = "camelCase")] #[schemars(deny_unknown_fields)] pub struct ReportLocationSpec { #[serde(with = "serde_yaml::with::singleton_map")] #[schemars(with = "ReportDestinationSpec")] + /// Destination the report should be uploaded to pub destination: ReportDestinationSpec, } @@ -38,14 +55,21 @@ pub enum ReportLocationKind { ScopeReportLocation, } +/// A `ScopeReportLocation` tells where to upload a report to. #[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Builder, JsonSchema)] #[builder(setter(into))] #[serde(rename_all = "camelCase")] #[schemars(deny_unknown_fields)] pub struct V1AlphaReportLocation { + /// API version of the resource pub api_version: V1AlphaApiVersion, + /// The type of resource. pub kind: ReportLocationKind, + /// Standard set of options including name, description for the resource. + /// Together `kind` and `metadata.name` are required to be unique. If there are duplicate, the + /// resources "closest" to the execution dir will take precedence. pub metadata: ModelMetadata, + /// Options for the resource. pub spec: ReportLocationSpec, } diff --git a/scope/src/shared/models/internal/upload_location.rs b/scope/src/shared/models/internal/upload_location.rs index 4466bb5..0e0607d 100644 --- a/scope/src/shared/models/internal/upload_location.rs +++ b/scope/src/shared/models/internal/upload_location.rs @@ -34,9 +34,9 @@ impl TryFrom for ReportUploadLocation { fn try_from(value: V1AlphaReportLocation) -> Result { let destination = match value.spec.destination { - crate::models::prelude::ReportDestinationSpec::RustyPaste { ref url } => { + crate::models::prelude::ReportDestinationSpec::RustyPaste (ref def ) => { ReportUploadLocationDestination::RustyPaste { - url: url.to_string(), + url: def.url.to_string(), } } crate::models::prelude::ReportDestinationSpec::GithubIssue(ref github_issue) => { From e179db695c5557aa9c783ff1234068fdbd82dd6c Mon Sep 17 00:00:00 2001 From: Ethan Hall Date: Mon, 4 Mar 2024 20:06:22 -0800 Subject: [PATCH 10/14] bind mount better --- .github/bin/build-page.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/bin/build-page.sh b/.github/bin/build-page.sh index b7116aa..c528b7b 100755 --- a/.github/bin/build-page.sh +++ b/.github/bin/build-page.sh @@ -2,4 +2,4 @@ SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) -docker run -v "${SCRIPT_DIR}/../../docs:/app/docs" --entrypoint sh --workdir /app/docs node:20-buster build.sh +docker run -v "${SCRIPT_DIR}/../..:/app" --entrypoint sh --workdir /app/docs node:20-buster build.sh From 048f8eea8db561b4e8963f179c82e79a19bf6520 Mon Sep 17 00:00:00 2001 From: Ethan Hall Date: Mon, 4 Mar 2024 20:12:06 -0800 Subject: [PATCH 11/14] fix removing resource --- docs/docs/commands/doctor.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/docs/commands/doctor.md b/docs/docs/commands/doctor.md index 31b0d65..c05bfae 100644 --- a/docs/docs/commands/doctor.md +++ b/docs/docs/commands/doctor.md @@ -4,7 +4,7 @@ sidebar_position: 1 # Doctor -Doctor is used to fix a local environment. To fix a machine, you'll need to provide either [ScopeDoctorCheck](../models/ScopeDoctorCheck.md) or [ScopeDoctorSetup](../models/ScopeDoctorSetup.md) files. Multiple are supported and recommended. +Doctor is used to fix a local environment. To fix a machine, you'll need to a [ScopeDoctorGroup](../models/ScopeDoctorGroup.mdx). Multiple are supported and recommended. **Help Text** @@ -25,7 +25,7 @@ Commands: By default, any provided fix's will be run. If you don't want to run fixes add `--fix=false` to disable fixing issues. -When using a [ScopeDoctorSetup](../models/ScopeDoctorSetup.md), the checksum of files are stored on disk. If you need to disable caching, add `--no-cache`. +When using a [ScopeDoctorGroup](../models/ScopeDoctorGroup.mdx), the checksum of files are stored on disk. If you need to disable caching, add `--no-cache`. ```text Run checks against your machine, generating support output From e7a0ffdb5b85b1dc536236e403dc8b1432e9d7d5 Mon Sep 17 00:00:00 2001 From: Ethan Hall Date: Mon, 4 Mar 2024 20:12:30 -0800 Subject: [PATCH 12/14] fix fmt --- scope/src/models/v1alpha/doctor_group.rs | 1 - scope/src/shared/models/internal/upload_location.rs | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/scope/src/models/v1alpha/doctor_group.rs b/scope/src/models/v1alpha/doctor_group.rs index 59eb99b..c74cc5c 100644 --- a/scope/src/models/v1alpha/doctor_group.rs +++ b/scope/src/models/v1alpha/doctor_group.rs @@ -17,7 +17,6 @@ pub struct DoctorCheckSpec { /// of the file change, the check will require a fix. pub paths: Option>, - #[serde(default)] /// A list of commands to execute to check the environment. pub commands: Option>, diff --git a/scope/src/shared/models/internal/upload_location.rs b/scope/src/shared/models/internal/upload_location.rs index 0e0607d..ae16d74 100644 --- a/scope/src/shared/models/internal/upload_location.rs +++ b/scope/src/shared/models/internal/upload_location.rs @@ -34,7 +34,7 @@ impl TryFrom for ReportUploadLocation { fn try_from(value: V1AlphaReportLocation) -> Result { let destination = match value.spec.destination { - crate::models::prelude::ReportDestinationSpec::RustyPaste (ref def ) => { + crate::models::prelude::ReportDestinationSpec::RustyPaste(ref def) => { ReportUploadLocationDestination::RustyPaste { url: def.url.to_string(), } From a92f94ba1f2f9f04a8775b3bf89a5b543d0985a6 Mon Sep 17 00:00:00 2001 From: Ethan Hall Date: Mon, 4 Mar 2024 20:18:48 -0800 Subject: [PATCH 13/14] fail if files change --- .github/workflows/on-pull-request.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/on-pull-request.yml b/.github/workflows/on-pull-request.yml index 385a531..ad180a3 100644 --- a/.github/workflows/on-pull-request.yml +++ b/.github/workflows/on-pull-request.yml @@ -46,6 +46,8 @@ jobs: ## Cargo test - name: cargo test run: cargo test + - name: check for changes + run: git diff --quiet && git diff --cached --quiet ## Cargo fmt - run: rustup component add rustfmt - name: cargo fmt From de010f48f06f19f9ae63b40a750e49f6b94c61d6 Mon Sep 17 00:00:00 2001 From: Ethan Hall Date: Mon, 4 Mar 2024 20:21:50 -0800 Subject: [PATCH 14/14] update output format --- scope/src/models/mod.rs | 2 +- scope/tests/integration_tests.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/scope/src/models/mod.rs b/scope/src/models/mod.rs index 05d068e..b2d9abd 100644 --- a/scope/src/models/mod.rs +++ b/scope/src/models/mod.rs @@ -54,7 +54,7 @@ where { let value = serde_json::to_value(input)?; if let Err(e) = Self::validate_resource(&value) { - warn!(target: "user", "Resource {} didn't match the schema for {}. {}", input.name(), Self::int_kind(), e); + warn!(target: "user", "Resource '{}' didn't match the schema for {}. {}", input.full_name(), Self::int_kind(), e); } return Ok(Some(serde_json::from_value::(value)?)); } diff --git a/scope/tests/integration_tests.rs b/scope/tests/integration_tests.rs index 3ee600d..83c0327 100644 --- a/scope/tests/integration_tests.rs +++ b/scope/tests/integration_tests.rs @@ -34,7 +34,7 @@ fn test_list_reports_all_config() { )) .stdout(predicate::str::contains("setup")) .stdout(predicate::str::contains(".scope/known-error.yaml")) - .stdout(predicate::str::contains("Resource setup didn't match the schema for ScopeDoctorGroup. Additional properties are not allowed ('extra' was unexpected)")) + .stdout(predicate::str::contains("Resource 'ScopeDoctorGroup/setup' didn't match the schema for ScopeDoctorGroup. Additional properties are not allowed ('extra' was unexpected)")) .stdout( predicate::str::is_match(r"bar\s+External sub-command, run `scope bar` for help") .unwrap(),