diff --git a/.gitignore b/.gitignore index 4a5b0953..1a98f873 100644 --- a/.gitignore +++ b/.gitignore @@ -1,8 +1,8 @@ +*.pb.go *.tar.* .env .vagrant dist packer_*_*_*.box -rootfs target vorpal-*-* diff --git a/Cargo.lock b/Cargo.lock index 116bbbff..dbcf04e4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -659,9 +659,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.8.0" +version = "2.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f68f53c83ab957f72c32642f3868eec03eb974d1fb82e453128456482613d36" +checksum = "5c8214115b7bf84099f1309324e63141d4c5d7cc26862f97a0a857dbefe165bd" [[package]] name = "block-buffer" @@ -732,21 +732,20 @@ dependencies = [ [[package]] name = "bzip2" -version = "0.5.1" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75b89e7c29231c673a61a46e722602bcd138298f6b9e81e71119693534585f5c" +checksum = "49ecfb22d906f800d4fe833b6282cf4dc1c298f5057ca0b5445e5c209735ca47" dependencies = [ "bzip2-sys", ] [[package]] name = "bzip2-sys" -version = "0.1.12+1.0.8" +version = "0.1.13+1.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72ebc2f1a417f01e1da30ef264ee86ae31d2dcd2d603ea283d3c244a883ca2a9" +checksum = "225bff33b2141874fe80d71e07d6eec4f85c5c216453dd96388240f96e1acc14" dependencies = [ "cc", - "libc", "pkg-config", ] @@ -761,9 +760,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.2.15" +version = "1.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c736e259eea577f443d5c86c304f9f4ae0295c43f3ba05c21f1d66b5f06001af" +checksum = "be714c154be609ec7f5dad223a33bf1482fff90472de28f7362806e6d4832b8c" dependencies = [ "jobserver", "libc", @@ -1008,7 +1007,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "33d852cb9b869c2a9b3df2f71a3074817f01e1844f839a144f5fcef059a4eb5d" dependencies = [ "libc", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -1037,9 +1036,9 @@ checksum = "1d674e81391d1e1ab681a28d99df07927c6d4aa5b027d7da16ba32d1d21ecd99" [[package]] name = "flate2" -version = "1.0.35" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c936bfdafb507ebbf50b8074c54fa31c5be9a1e7e5f467dd659697041407d07c" +checksum = "11faaf5a5236997af9848be0bef4db95824b1d534ebc64d0f0c6cf3e67bd38dc" dependencies = [ "crc32fast", "miniz_oxide", @@ -1383,7 +1382,7 @@ dependencies = [ "rustls 0.23.23", "rustls-pki-types", "tokio", - "tokio-rustls 0.26.1", + "tokio-rustls 0.26.2", "tower-service", "webpki-roots", ] @@ -1694,7 +1693,7 @@ version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d" dependencies = [ - "bitflags 2.8.0", + "bitflags 2.9.0", "libc", "redox_syscall 0.5.9", ] @@ -1707,9 +1706,9 @@ checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab" [[package]] name = "litemap" -version = "0.7.4" +version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ee93343901ab17bd981295f2cf0026d4ad018c7c31ba84549a4ddbb47a45104" +checksum = "23fb14cb19457329c82206317a5663005a4d404783dc74f4252769b0d5f42856" [[package]] name = "log" @@ -2137,7 +2136,7 @@ dependencies = [ "once_cell", "socket2", "tracing", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -2194,7 +2193,7 @@ version = "0.5.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "82b568323e98e49e2a0899dcee453dd679fae22d69adf9b11dd508d1549b7e2f" dependencies = [ - "bitflags 2.8.0", + "bitflags 2.9.0", ] [[package]] @@ -2264,7 +2263,7 @@ dependencies = [ "serde_urlencoded", "sync_wrapper", "tokio", - "tokio-rustls 0.26.1", + "tokio-rustls 0.26.2", "tower 0.5.2", "tower-service", "url", @@ -2337,11 +2336,11 @@ version = "0.38.44" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154" dependencies = [ - "bitflags 2.8.0", + "bitflags 2.9.0", "errno", "libc", "linux-raw-sys", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -2505,7 +2504,7 @@ version = "2.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" dependencies = [ - "bitflags 2.8.0", + "bitflags 2.9.0", "core-foundation", "core-foundation-sys", "libc", @@ -2750,7 +2749,7 @@ dependencies = [ "getrandom 0.3.1", "once_cell", "rustix", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -2898,9 +2897,9 @@ dependencies = [ [[package]] name = "tokio-rustls" -version = "0.26.1" +version = "0.26.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f6d0975eaace0cf0fcadee4e4aaa5da15b5c079146f2cffb67c113be122bf37" +checksum = "8e727b36a1a0e8b74c376ac2211e40c2c8af09fb4013c60d910495810f008e9b" dependencies = [ "rustls 0.23.23", "tokio", @@ -3236,6 +3235,7 @@ version = "0.1.0" dependencies = [ "anyhow", "tokio", + "vorpal-schema", "vorpal-sdk", ] @@ -3502,7 +3502,7 @@ version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" dependencies = [ - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -3638,7 +3638,7 @@ version = "0.33.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3268f3d866458b787f390cf61f4bbb563b922d091359f9608842999eaee3943c" dependencies = [ - "bitflags 2.8.0", + "bitflags 2.9.0", ] [[package]] @@ -3706,18 +3706,18 @@ dependencies = [ [[package]] name = "zerofrom" -version = "0.1.5" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cff3ee08c995dee1859d998dea82f7374f2826091dd9cd47def953cae446cd2e" +checksum = "50cc42e0333e05660c3587f3bf9d0478688e15d870fab3346451ce7f8c9fbea5" dependencies = [ "zerofrom-derive", ] [[package]] name = "zerofrom-derive" -version = "0.1.5" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "595eed982f7d355beb85837f651fa22e90b3c044842dc7f2c2842c086f295808" +checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502" dependencies = [ "proc-macro2", "quote", diff --git a/Cargo.toml b/Cargo.toml index 08198bcb..79235a79 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,3 +1,12 @@ [workspace] -members = ["cli", "config", "notary", "registry", "schema", "sdk", "store", "worker"] +members = [ + "cli", + "config", + "notary", + "registry", + "schema", + "sdk/rust", + "store", + "worker" +] resolver = "2" diff --git a/README.md b/README.md index 40e71115..65ddd3c9 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,9 @@ Build and ship software with one powerful tool. -![vorpal-purpose](./vorpal-purpose.jpg) +

+ +

## Overview @@ -14,20 +16,17 @@ Below are examples of a Rust application in Vorpal configured in different langu ```rust use anyhow::Result; -use vorpal_schema::vorpal::config::v0::Config; use vorpal_sdk::config::{artifact::language::rust::rust_artifact, get_context}; #[tokio::main] async fn main() -> Result<()> { let context = &mut get_context().await?; - let artifact = rust_artifact(context, "example-app").await?; + let example = rust_artifact(context, "example-app").await?; - context - .run(Config { - artifacts: vec![artifact], - }) - .await + let artifacts = vec![artifact]; + + context.run(artifacts).await } ``` @@ -40,7 +39,6 @@ import ( "context" "log" - "github.com/vorpal-sdk/vorpal" "github.com/vorpal-sdk/vorpal/config" "github.com/vorpal-sdk/vorpal/config/artifact/language/rust" ) @@ -51,20 +49,39 @@ func main() { log.Fatal(err) } - artifact, err := rust.Artifact(context, "example-app") + example, err := rust.Artifact(context, "example-app") if err != nil { log.Fatal(err) } - err = context.Run(config.Config{ - Artifacts: []config.Artifact{artifact}, - }) + artifacts := []config.Artifact{example} + + err = context.Run(artifacts) if err != nil { log.Fatal(err) } } ``` +### Python + +```python +from vorpal_sdk.config import get_context +from vorpal_sdk.config.artifact.language.rust import rust_artifact + +def main(): + context = get_context() + + example = rust_artifact(context, "example-app") + + artifacts = [example] + + context.run(artifacts) + +if __name__ == "__main__": + main() +``` + ### TypeScript ```typescript @@ -74,17 +91,17 @@ import { rustArtifact } from '@vorpal/sdk/config/artifact/language/rust'; async function main() { const context = await getContext(); - const artifact = await rustArtifact(context, 'example-app'); + const example = await rustArtifact(context, 'example-app'); + + const artifacts = [example]; - await context.run({ - artifacts: [artifact], - })); + await context.run(artifacts); } main().catch(console.error); ``` -## Infrastructure +## Components Below is the existing working diagram that illustrates the platform's design: diff --git a/cli/Cargo.toml b/cli/Cargo.toml index 65dd275a..dbdcd301 100644 --- a/cli/Cargo.toml +++ b/cli/Cargo.toml @@ -23,6 +23,6 @@ tracing-subscriber = { default-features = false, features = ["ansi", "fmt", "reg vorpal-notary = { default-features = false, path = "../notary" } vorpal-registry = { default-features = false, path = "../registry" } vorpal-schema = { default-features = false, path = "../schema" } -vorpal-sdk = { default-features = false, path = "../sdk" } +vorpal-sdk = { default-features = false, path = "../sdk/rust" } vorpal-store = { default-features = false, path = "../store" } vorpal-worker = { default-features = false, path = "../worker" } diff --git a/cli/src/main.rs b/cli/src/main.rs index 5f41127e..6cf1abd1 100644 --- a/cli/src/main.rs +++ b/cli/src/main.rs @@ -30,9 +30,9 @@ use vorpal_schema::{ registry::v0::registry_service_server::RegistryServiceServer, }, }; -use vorpal_sdk::config::{ - artifact::{language::rust, toolchain::protoc}, - ConfigContext, +use vorpal_sdk::{ + artifact::{language::rust, protoc}, + context::ConfigContext, }; use vorpal_store::paths::{get_artifact_path, get_public_key_path}; use vorpal_worker::artifact::ArtifactServer; @@ -238,7 +238,7 @@ async fn get_config_file_path( bail!("config toolchain not found: {}", toolchain_path.display()); } - let toolchain_target = rust::get_toolchain_target(artifact_system)?; + let toolchain_target = rust::get_rust_toolchain_target(artifact_system)?; let toolchain_version = get_rust_toolchain_version(); let toolchain_bin_path = Path::new(&format!( diff --git a/config/Cargo.toml b/config/Cargo.toml index 24abfa1d..bc73d0ba 100644 --- a/config/Cargo.toml +++ b/config/Cargo.toml @@ -10,4 +10,5 @@ path = "src/main.rs" [dependencies] anyhow = { default-features = false, version = "1" } tokio = { default-features = false, features = ["rt-multi-thread"], version = "1" } -vorpal-sdk = { default-features = false, path = "../sdk" } +vorpal-schema = { default-features = false, path = "../schema" } +vorpal-sdk = { default-features = false, path = "../sdk/rust" } diff --git a/config/src/main.rs b/config/src/main.rs index d2a385bf..80124579 100644 --- a/config/src/main.rs +++ b/config/src/main.rs @@ -1,20 +1,19 @@ use anyhow::Result; -use vorpal_sdk::config::{ - artifact::language::rust::{rust_package, rust_shell}, - get_context, -}; +use vorpal_sdk::context::get_context; + +mod vorpal; #[tokio::main] async fn main() -> Result<()> { - // Get the context + // 1. Get the context let context = &mut get_context().await?; - // Create artifacts + // 2. Create artifacts let artifacts = vec![ - rust_package(context, "vorpal").await?, - rust_shell(context, "vorpal").await?, + vorpal::package(context).await?, + vorpal::shell(context).await?, ]; - // Run the context + // 3. Run the context context.run(artifacts).await } diff --git a/config/src/vorpal.rs b/config/src/vorpal.rs new file mode 100644 index 00000000..67d29254 --- /dev/null +++ b/config/src/vorpal.rs @@ -0,0 +1,82 @@ +use anyhow::Result; +use vorpal_schema::vorpal::artifact::v0::ArtifactId; +use vorpal_sdk::{ + artifact::{ + get_artifact_envkey, go, goimports, gopls, + language::rust::{ + get_rust_toolchain_target, get_rust_toolchain_version, rust_package, toolchain_artifact, + }, + protoc, protoc_gen_go, protoc_gen_go_grpc, + shell::shell_artifact, + }, + context::ConfigContext, +}; + +pub async fn package(context: &mut ConfigContext) -> Result { + let excludes = vec![ + ".env", + ".envrc", + ".github", + ".gitignore", + ".packer", + ".vagrant", + "Dockerfile", + "Vagrantfile", + "dist", + "makefile", + "script", + "sdk/go", + "shell.nix", + "vorpal-domains.svg", + "vorpal-purpose.jpg", + ]; + + rust_package(context, "vorpal", excludes).await +} + +pub async fn shell(context: &mut ConfigContext) -> Result { + let name = "vorpal"; + + let go = go::artifact(context).await?; + let goimports = goimports::artifact(context).await?; + let gopls = gopls::artifact(context).await?; + let protoc = protoc::artifact(context).await?; + let protoc_gen_go = protoc_gen_go::artifact(context).await?; + let protoc_gen_go_grpc = protoc_gen_go_grpc::artifact(context).await?; + let rust_toolchain = toolchain_artifact(context, name).await?; + let rust_toolchain_target = get_rust_toolchain_target(context.get_target())?; + + let artifacts = vec![ + go.clone(), + goimports.clone(), + gopls.clone(), + protoc.clone(), + protoc_gen_go.clone(), + protoc_gen_go_grpc.clone(), + rust_toolchain.clone(), + ]; + + let envs = vec![ + format!( + "PATH={}/bin:{}/bin:{}/bin:{}/bin:{}/bin:{}/bin:{}/toolchains/{}-{}/bin:$PATH", + get_artifact_envkey(&go), + get_artifact_envkey(&goimports), + get_artifact_envkey(&gopls), + get_artifact_envkey(&protoc), + get_artifact_envkey(&protoc_gen_go), + get_artifact_envkey(&protoc_gen_go_grpc), + get_artifact_envkey(&rust_toolchain), + get_rust_toolchain_version(), + rust_toolchain_target + ), + format!("RUSTUP_HOME={}", get_artifact_envkey(&rust_toolchain)), + format!( + "RUSTUP_TOOLCHAIN={}-{}", + get_rust_toolchain_version(), + rust_toolchain_target + ), + ]; + + // Create shell artifact + shell_artifact(context, artifacts, envs, name).await +} diff --git a/makefile b/makefile index 13bcfbda..792f6bfb 100644 --- a/makefile +++ b/makefile @@ -46,6 +46,13 @@ dist: build tar -czvf $(DIST_DIR)/vorpal-$(ARCH)-$(OS).tar.gz \ -C $(WORK_DIR)/target/$(TARGET) vorpal +# Vorpal +generate: + mkdir -p sdk/go/api + protoc --go_opt=paths=source_relative --go_out=sdk/go/api --go-grpc_opt=paths=source_relative --go-grpc_out=sdk/go/api --proto_path=schema/api v0/artifact/artifact.proto + protoc --go_opt=paths=source_relative --go_out=sdk/go/api --go-grpc_opt=paths=source_relative --go-grpc_out=sdk/go/api --proto_path=schema/api v0/registry/registry.proto + protoc --go_opt=paths=source_relative --go_out=sdk/go/api --go-grpc_opt=paths=source_relative --go-grpc_out=sdk/go/api --proto_path=schema/api v0/config/config.proto + # Development (with Vorpal) vorpal-config: diff --git a/schema/api/v0/artifact/artifact.proto b/schema/api/v0/artifact/artifact.proto index 7f3c8fb9..aa616d45 100644 --- a/schema/api/v0/artifact/artifact.proto +++ b/schema/api/v0/artifact/artifact.proto @@ -2,6 +2,8 @@ syntax = "proto3"; package vorpal.artifact.v0; +option go_package = "github.com/ALT-F4-LLC/vorpal/sdk/go/api/v0/artifact"; + service ArtifactService { rpc Build (ArtifactBuildRequest) returns (stream ArtifactBuildResponse); } diff --git a/schema/api/v0/config/config.proto b/schema/api/v0/config/config.proto index 0582f291..53e742f7 100644 --- a/schema/api/v0/config/config.proto +++ b/schema/api/v0/config/config.proto @@ -2,6 +2,8 @@ syntax = "proto3"; package vorpal.config.v0; +option go_package = "github.com/ALT-F4-LLC/vorpal/sdk/go/api/v0/config"; + import "v0/artifact/artifact.proto"; service ConfigService { diff --git a/schema/api/v0/registry/registry.proto b/schema/api/v0/registry/registry.proto index d4e13e3c..0c109b7d 100644 --- a/schema/api/v0/registry/registry.proto +++ b/schema/api/v0/registry/registry.proto @@ -2,7 +2,7 @@ syntax = "proto3"; package vorpal.registry.v0; -import "v0/artifact/artifact.proto"; +option go_package = "github.com/ALT-F4-LLC/vorpal/sdk/go/api/v0/registry"; service RegistryService { rpc Exists(RegistryRequest) returns (RegistryResponse); diff --git a/sdk/go/go.mod b/sdk/go/go.mod new file mode 100644 index 00000000..d9eb0417 --- /dev/null +++ b/sdk/go/go.mod @@ -0,0 +1,35 @@ +module github.com/ALT-F4-LLC/vorpal/sdk/go + +go 1.23.5 + +require ( + github.com/google/uuid v1.6.0 + github.com/h2non/filetype v1.1.3 + github.com/mholt/archives v0.1.0 + google.golang.org/grpc v1.70.0 + google.golang.org/protobuf v1.36.3 +) + +require ( + github.com/STARRY-S/zip v0.2.1 // indirect + github.com/andybalholm/brotli v1.1.1 // indirect + github.com/bodgit/plumbing v1.3.0 // indirect + github.com/bodgit/sevenzip v1.6.0 // indirect + github.com/bodgit/windows v1.0.1 // indirect + github.com/dsnet/compress v0.0.2-0.20230904184137-39efe44ab707 // indirect + github.com/hashicorp/errwrap v1.1.0 // indirect + github.com/hashicorp/go-multierror v1.1.1 // indirect + github.com/hashicorp/golang-lru/v2 v2.0.7 // indirect + github.com/klauspost/compress v1.17.11 // indirect + github.com/klauspost/pgzip v1.2.6 // indirect + github.com/nwaples/rardecode/v2 v2.0.0-beta.4.0.20241112120701-034e449c6e78 // indirect + github.com/pierrec/lz4/v4 v4.1.21 // indirect + github.com/sorairolake/lzip-go v0.3.5 // indirect + github.com/therootcompany/xz v1.0.1 // indirect + github.com/ulikunitz/xz v0.5.12 // indirect + go4.org v0.0.0-20230225012048-214862532bf5 // indirect + golang.org/x/net v0.32.0 // indirect + golang.org/x/sys v0.28.0 // indirect + golang.org/x/text v0.21.0 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20241202173237-19429a94021a // indirect +) diff --git a/sdk/go/go.sum b/sdk/go/go.sum new file mode 100644 index 00000000..c4a9c4c2 --- /dev/null +++ b/sdk/go/go.sum @@ -0,0 +1,328 @@ +cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= +cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= +cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= +cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= +cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= +cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To= +cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M= +cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= +cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= +cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= +cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= +cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= +cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= +cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos= +dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= +github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= +github.com/STARRY-S/zip v0.2.1 h1:pWBd4tuSGm3wtpoqRZZ2EAwOmcHK6XFf7bU9qcJXyFg= +github.com/STARRY-S/zip v0.2.1/go.mod h1:xNvshLODWtC4EJ702g7cTYn13G53o1+X9BWnPFpcWV4= +github.com/andybalholm/brotli v1.1.1 h1:PR2pgnyFznKEugtsUo0xLdDop5SKXd5Qf5ysW+7XdTA= +github.com/andybalholm/brotli v1.1.1/go.mod h1:05ib4cKhjx3OQYUY22hTVd34Bc8upXjOLL2rKwwZBoA= +github.com/bodgit/plumbing v1.3.0 h1:pf9Itz1JOQgn7vEOE7v7nlEfBykYqvUYioC61TwWCFU= +github.com/bodgit/plumbing v1.3.0/go.mod h1:JOTb4XiRu5xfnmdnDJo6GmSbSbtSyufrsyZFByMtKEs= +github.com/bodgit/sevenzip v1.6.0 h1:a4R0Wu6/P1o1pP/3VV++aEOcyeBxeO/xE2Y9NSTrr6A= +github.com/bodgit/sevenzip v1.6.0/go.mod h1:zOBh9nJUof7tcrlqJFv1koWRrhz3LbDbUNngkuZxLMc= +github.com/bodgit/windows v1.0.1 h1:tF7K6KOluPYygXa3Z2594zxlkbKPAOvqr97etrGNIz4= +github.com/bodgit/windows v1.0.1/go.mod h1:a6JLwrB4KrTR5hBpp8FI9/9W9jJfeQ2h4XDXU74ZCdM= +github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= +github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= +github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= +github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/dsnet/compress v0.0.2-0.20230904184137-39efe44ab707 h1:2tV76y6Q9BB+NEBasnqvs7e49aEBFI8ejC89PSnWH+4= +github.com/dsnet/compress v0.0.2-0.20230904184137-39efe44ab707/go.mod h1:qssHWj60/X5sZFNxpG4HBPDHVqxNm4DfnCKgrbZOT+s= +github.com/dsnet/golib v0.0.0-20171103203638-1ea166775780/go.mod h1:Lj+Z9rebOhdfkVLjJ8T6VcRQv3SXugXy999NBtR9aFY= +github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= +github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= +github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= +github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= +github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= +github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= +github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= +github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= +github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= +github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= +github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= +github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= +github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= +github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= +github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= +github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= +github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= +github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= +github.com/h2non/filetype v1.1.3 h1:FKkx9QbD7HR/zjK1Ia5XiBsq9zdLi5Kf3zGyFTAFkGg= +github.com/h2non/filetype v1.1.3/go.mod h1:319b3zT68BvV+WRj7cwy856M2ehB3HqNOt6sy1HndBY= +github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= +github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I= +github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= +github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo= +github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= +github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hashicorp/golang-lru/v2 v2.0.7 h1:a+bsQ5rvGLjzHuww6tVxozPZFVghXaHOwFs4luLUK2k= +github.com/hashicorp/golang-lru/v2 v2.0.7/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM= +github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= +github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= +github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= +github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/klauspost/compress v1.4.1/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= +github.com/klauspost/compress v1.17.11 h1:In6xLpyWOi1+C7tXUUWv2ot1QvBjxevKAaI6IXrJmUc= +github.com/klauspost/compress v1.17.11/go.mod h1:pMDklpSncoRMuLFrf1W9Ss9KT+0rH90U12bZKk7uwG0= +github.com/klauspost/cpuid v1.2.0/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= +github.com/klauspost/pgzip v1.2.6 h1:8RXeL5crjEUFnR2/Sn6GJNWtSQ3Dk8pq4CL3jvdDyjU= +github.com/klauspost/pgzip v1.2.6/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/mholt/archives v0.1.0 h1:FacgJyrjiuyomTuNA92X5GyRBRZjE43Y/lrzKIlF35Q= +github.com/mholt/archives v0.1.0/go.mod h1:j/Ire/jm42GN7h90F5kzj6hf6ZFzEH66de+hmjEKu+I= +github.com/nwaples/rardecode/v2 v2.0.0-beta.4.0.20241112120701-034e449c6e78 h1:MYzLheyVx1tJVDqfu3YnN4jtnyALNzLvwl+f58TcvQY= +github.com/nwaples/rardecode/v2 v2.0.0-beta.4.0.20241112120701-034e449c6e78/go.mod h1:yntwv/HfMc/Hbvtq9I19D1n58te3h6KsqCf3GxyfBGY= +github.com/pierrec/lz4/v4 v4.1.21 h1:yOVMLb6qSIDP67pl/5F7RepeKYu/VmTyEXvuMI5d9mQ= +github.com/pierrec/lz4/v4 v4.1.21/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= +github.com/rwcarlsen/goexif v0.0.0-20190401172101-9e8deecbddbd/go.mod h1:hPqNNc0+uJM6H+SuU8sEs5K5IQeKccPqeSjfgcKGgPk= +github.com/sorairolake/lzip-go v0.3.5 h1:ms5Xri9o1JBIWvOFAorYtUNik6HI3HgBTkISiqu0Cwg= +github.com/sorairolake/lzip-go v0.3.5/go.mod h1:N0KYq5iWrMXI0ZEXKXaS9hCyOjZUQdBDEIbXfoUwbdk= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/therootcompany/xz v1.0.1 h1:CmOtsn1CbtmyYiusbfmhmkpAAETj0wBIH6kCYaX+xzw= +github.com/therootcompany/xz v1.0.1/go.mod h1:3K3UH1yCKgBneZYhuQUvJ9HPD19UEXEI0BWbMn8qNMY= +github.com/ulikunitz/xz v0.5.8/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= +github.com/ulikunitz/xz v0.5.12 h1:37Nm15o69RwBkXM0J6A5OlE67RZTfzUxTj8fB3dfcsc= +github.com/ulikunitz/xz v0.5.12/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= +github.com/xyproto/randomstring v1.0.5 h1:YtlWPoRdgMu3NZtP45drfy1GKoojuR7hmRcnhZqKjWU= +github.com/xyproto/randomstring v1.0.5/go.mod h1:rgmS5DeNXLivK7YprL0pY+lTuhNQW3iGxZ18UQApw/E= +github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= +go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= +go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= +go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.opentelemetry.io/otel v1.32.0 h1:WnBN+Xjcteh0zdk01SVqV55d/m62NJLJdIyb4y/WO5U= +go.opentelemetry.io/otel v1.32.0/go.mod h1:00DCVSB0RQcnzlwyTfqtxSm+DRr9hpYrHjNGiBHVQIg= +go.opentelemetry.io/otel/metric v1.32.0 h1:xV2umtmNcThh2/a/aCP+h64Xx5wsj8qqnkYZktzNa0M= +go.opentelemetry.io/otel/metric v1.32.0/go.mod h1:jH7CIbbK6SH2V2wE16W05BHCtIDzauciCRLoc/SyMv8= +go.opentelemetry.io/otel/sdk v1.32.0 h1:RNxepc9vK59A8XsgZQouW8ue8Gkb4jpWtJm9ge5lEG4= +go.opentelemetry.io/otel/sdk v1.32.0/go.mod h1:LqgegDBjKMmb2GC6/PrTnteJG39I8/vJCAP9LlJXEjU= +go.opentelemetry.io/otel/sdk/metric v1.32.0 h1:rZvFnvmvawYb0alrYkjraqJq0Z4ZUJAiyYCU9snn1CU= +go.opentelemetry.io/otel/sdk/metric v1.32.0/go.mod h1:PWeZlq0zt9YkYAp3gjKZ0eicRYvOh1Gd+X99x6GHpCQ= +go.opentelemetry.io/otel/trace v1.32.0 h1:WIC9mYrXf8TmY/EXuULKc8hR17vE+Hjv2cssQDe03fM= +go.opentelemetry.io/otel/trace v1.32.0/go.mod h1:+i4rkvCraA+tG6AzwloGaCtkx53Fa+L+V8e9a7YvhT8= +go4.org v0.0.0-20230225012048-214862532bf5 h1:nifaUDeh+rPaBCMPMQHZmvJf+QdpLFnuQPwx+LxVmtc= +go4.org v0.0.0-20230225012048-214862532bf5/go.mod h1:F57wTi5Lrj6WLyswp5EYV1ncrEbFGHD4hhz6S1ZYeaU= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= +golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek= +golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= +golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= +golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= +golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= +golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= +golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= +golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= +golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= +golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= +golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= +golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= +golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= +golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= +golang.org/x/net v0.32.0 h1:ZqPmj8Kzc+Y6e0+skZsuACbx+wzMgo5MQsJh9Qd6aYI= +golang.org/x/net v0.32.0/go.mod h1:CwU0IoeOlnQQWJ6ioyFrfRuomB8GKF6KbYXZVyeXNfs= +golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= +golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.10.0 h1:3NQrjDixjgGwUOCaF8w2+VYHv0Ve/vGYSbdkTa98gmQ= +golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA= +golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= +golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo= +golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ= +golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= +golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= +google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= +google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= +google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= +google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= +google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= +google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= +google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto/googleapis/rpc v0.0.0-20241202173237-19429a94021a h1:hgh8P4EuoxpsuKMXX/To36nOFD7vixReXgn8lPGnt+o= +google.golang.org/genproto/googleapis/rpc v0.0.0-20241202173237-19429a94021a/go.mod h1:5uTbfoYQed2U9p3KIj2/Zzm02PYhndfdmML0qC3q3FU= +google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= +google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= +google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= +google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.70.0 h1:pWFv03aZoHzlRKHWicjsZytKAiYCtNS0dHbXnIdq7jQ= +google.golang.org/grpc v1.70.0/go.mod h1:ofIJqVKDXx/JiXrwr2IG4/zwdH9txy3IlF40RmcJSQw= +google.golang.org/protobuf v1.36.3 h1:82DV7MYdb8anAVi3qge1wSnMDrnKK7ebr+I0hHRN1BU= +google.golang.org/protobuf v1.36.3/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= +rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= +rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= +rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= diff --git a/sdk/go/internal/artifact/source.go b/sdk/go/internal/artifact/source.go new file mode 100644 index 00000000..563441b7 --- /dev/null +++ b/sdk/go/internal/artifact/source.go @@ -0,0 +1,17 @@ +package artifact + +type ArtifactSource struct { + Excludes []string + Hash *string + Includes []string + Path string +} + +type ArtifactSourceKind string + +const ( + ArtifactSourceKind_GIT ArtifactSourceKind = "GIT" + ArtifactSourceKind_HTTP ArtifactSourceKind = "HTTP" + ArtifactSourceKind_LOCAL ArtifactSourceKind = "LOCAL" + ArtifactSourceKind_UNKNOWN ArtifactSourceKind = "UNKNOWN" +) diff --git a/sdk/go/internal/artifact/system.go b/sdk/go/internal/artifact/system.go new file mode 100644 index 00000000..162bcc77 --- /dev/null +++ b/sdk/go/internal/artifact/system.go @@ -0,0 +1,20 @@ +package artifact + +import ( + "github.com/ALT-F4-LLC/vorpal/sdk/go/api/v0/artifact" +) + +func GetArtifactSystem(system string) artifact.ArtifactSystem { + switch system { + case "aarch64-linux": + return artifact.ArtifactSystem_AARCH64_LINUX + case "aarch64-macos": + return artifact.ArtifactSystem_AARCH64_MACOS + case "x86_64-linux": + return artifact.ArtifactSystem_X86_64_LINUX + case "x86_64-macos": + return artifact.ArtifactSystem_X86_64_MACOS + default: + return artifact.ArtifactSystem_UNKNOWN_SYSTEM + } +} diff --git a/sdk/go/internal/cli/command.go b/sdk/go/internal/cli/command.go new file mode 100644 index 00000000..91c64527 --- /dev/null +++ b/sdk/go/internal/cli/command.go @@ -0,0 +1,74 @@ +package cli + +import ( + "flag" + "fmt" + "os" + "runtime" + + _artifact "github.com/ALT-F4-LLC/vorpal/sdk/go/api/v0/artifact" + "github.com/ALT-F4-LLC/vorpal/sdk/go/internal/artifact" +) + +type startCommand struct { + Level string + Port int + Registry string + Target _artifact.ArtifactSystem +} + +func getDefaultSystem() string { + arch := runtime.GOARCH + os := runtime.GOOS + + if arch == "arm64" { + arch = "aarch64" + } + + if os == "darwin" { + os = "macos" + } + + return fmt.Sprintf("%s-%s", arch, os) +} + +func NewStartCommand() (*startCommand, error) { + startCmd := flag.NewFlagSet("start", flag.ExitOnError) + + startLevel := startCmd.String("level", "INFO", "logging level") + startPort := startCmd.Int("port", 0, "port to listen on") + startRegistry := startCmd.String("registry", "http://localhost:23151", "registry to use") + startTarget := startCmd.String("target", getDefaultSystem(), "target system") + + switch os.Args[1] { + case "start": + startCmd.Parse(os.Args[2:]) + + if *startPort == 0 { + return nil, fmt.Errorf("port is required") + } + + if *startRegistry == "" { + return nil, fmt.Errorf("registry is required") + } + + if *startTarget == "" { + return nil, fmt.Errorf("target is required") + } + + system := artifact.GetArtifactSystem(*startTarget) + + if system == _artifact.ArtifactSystem_UNKNOWN_SYSTEM { + return nil, fmt.Errorf("unknown target system") + } + + return &startCommand{ + Level: *startLevel, + Port: *startPort, + Registry: *startRegistry, + Target: system, + }, nil + default: + return nil, fmt.Errorf("unknown command") + } +} diff --git a/sdk/go/internal/context/config.go b/sdk/go/internal/context/config.go new file mode 100644 index 00000000..f4c04eec --- /dev/null +++ b/sdk/go/internal/context/config.go @@ -0,0 +1,524 @@ +package context + +import ( + "context" + "crypto/sha256" + "encoding/json" + "fmt" + "io" + "log" + "net" + "net/http" + "net/url" + "os" + "path/filepath" + "strings" + + artifactApi "github.com/ALT-F4-LLC/vorpal/sdk/go/api/v0/artifact" + configApi "github.com/ALT-F4-LLC/vorpal/sdk/go/api/v0/config" + registryApi "github.com/ALT-F4-LLC/vorpal/sdk/go/api/v0/registry" + "github.com/ALT-F4-LLC/vorpal/sdk/go/internal/artifact" + "github.com/ALT-F4-LLC/vorpal/sdk/go/internal/cli" + "github.com/ALT-F4-LLC/vorpal/sdk/go/internal/store" + "github.com/h2non/filetype" + "github.com/mholt/archives" + "google.golang.org/grpc" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" +) + +type ConfigContext struct { + ArtifactId map[*artifactApi.ArtifactId]*artifactApi.Artifact + artifactSourceId map[string]*artifactApi.ArtifactSourceId + port int + registry string + system artifactApi.ArtifactSystem +} + +type ConfigServer struct { + configApi.UnimplementedConfigServiceServer + Config *configApi.Config + Context *ConfigContext +} + +func GetContext() *ConfigContext { + startCmd, err := cli.NewStartCommand() + if err != nil { + log.Fatal(err) + } + + return &ConfigContext{ + system: startCmd.Target, + } +} + +func NewConfigServer(context *ConfigContext, config *configApi.Config) *ConfigServer { + return &ConfigServer{ + Config: config, + Context: context, + } +} + +func handleFile(outputPath string) archives.FileHandler { + return func(ctx context.Context, info archives.FileInfo) error { + outputFilePath := filepath.Join(outputPath, filepath.Clean(info.NameInArchive)) + + if err := os.MkdirAll(filepath.Dir(outputFilePath), 0o755); err != nil { + return err + } + + outputFile, err := os.Create(outputFilePath) + if err != nil { + return err + } + + defer outputFile.Close() + + r, err := info.Open() + if err != nil { + return err + } + + defer r.Close() + + if _, err := io.Copy(outputFile, r); err != nil { + return err + } + + return nil + } +} + +func (c *ConfigContext) AddArtifactSource(sourceName string, source artifact.ArtifactSource) (*artifactApi.ArtifactSourceId, error) { + // 1. If source is cached using '-', return the source id + + // TODO: if any paths are relative, they should be expanded to the _artifact's source directory + + // 1a. Determine source kind + + sourcePathKind := artifact.ArtifactSourceKind_UNKNOWN + + if _, err := os.Stat(source.Path); err == nil { + sourcePathKind = artifact.ArtifactSourceKind_LOCAL + } + + if strings.HasPrefix(source.Path, "git://") { + sourcePathKind = artifact.ArtifactSourceKind_GIT + } + + if strings.HasPrefix(source.Path, "http://") || strings.HasPrefix(source.Path, "https://") { + sourcePathKind = artifact.ArtifactSourceKind_HTTP + } + + if sourcePathKind == artifact.ArtifactSourceKind_UNKNOWN { + return nil, fmt.Errorf("`source.%s.path` unknown kind: %v", sourceName, source.Path) + } + + // 1b. process source path + + if sourcePathKind == artifact.ArtifactSourceKind_GIT { + return nil, fmt.Errorf("`source.%s.path` git not supported", sourceName) + } + + if sourcePathKind == artifact.ArtifactSourceKind_LOCAL { + path, err := filepath.Abs(source.Path) + if err != nil { + return nil, err + } + + source.Path = path + + // TODO: add logging library like in rust code + } + + // 1c. process source id + + sourceJsonBytes, err := json.Marshal(source) + if err != nil { + return nil, err + } + + sourceKey := fmt.Sprintf("%s-%x", sourceName, sha256.Sum256(sourceJsonBytes)) + + if _, ok := c.artifactSourceId[sourceKey]; ok { + return c.artifactSourceId[sourceKey], nil + } + + // 2. Check if source exists in registry or local cache + + // TODO: check if source is also an empty value + + if source.Hash != nil { + // 2a. Check if source exists in the registry + + // TODO: put client at higher level with connection pooling + + registryConnOpts := []grpc.DialOption{} + + registryConn, err := grpc.NewClient(c.registry, registryConnOpts...) + if err != nil { + return nil, err + } + + defer registryConn.Close() + + registryClient := registryApi.NewRegistryServiceClient(registryConn) + + registryRequest := ®istryApi.RegistryRequest{ + Hash: *source.Hash, + Kind: registryApi.RegistryKind_ARTIFACT_SOURCE, + Name: sourceName, + } + + registryResponse, err := registryClient.Exists(context.Background(), registryRequest) + if err != nil && status.Code(err) != codes.NotFound { + return nil, err + } + + if registryResponse.Success { + return &artifactApi.ArtifactSourceId{ + Hash: *source.Hash, + Name: sourceName, + }, nil + } + + // 2b. Check if source exists in local cache + + sourceCacheArchivePath := store.GetCacheArchivePath(*source.Hash, sourceName) + + if _, err := os.Stat(sourceCacheArchivePath); err == nil { + return &artifactApi.ArtifactSourceId{ + Hash: *source.Hash, + Name: sourceName, + }, nil + } + } + + // 3. Prepare source if not cached + + sourceSandboxPath, err := store.NewSandboxDir() + if err != nil { + return nil, err + } + + if sourcePathKind == artifact.ArtifactSourceKind_HTTP { + if source.Hash == nil { + return nil, fmt.Errorf("`source.%s.hash` required for remote source", sourceName) + } + + if source.Hash != nil && *source.Hash == "" { + return nil, fmt.Errorf("`source.%s.hash` cannot be empty for remote source", sourceName) + } + + // 3a. Download source + + sourceRemotePath, err := url.Parse(source.Path) + if err != nil { + return nil, err + } + + if sourceRemotePath.Scheme != "http" && sourceRemotePath.Scheme != "https" { + return nil, fmt.Errorf("`source.%s.path` must be http or https", sourceName) + } + + sourceResponse, err := http.Get(sourceRemotePath.String()) + if err != nil { + return nil, err + } + + defer sourceResponse.Body.Close() + + if sourceResponse.StatusCode != http.StatusOK { + return nil, fmt.Errorf("HTTP request failed: %s", sourceResponse.Status) + } + + sourceContentType, err := filetype.MatchReader(sourceResponse.Body) + if err != nil { + return nil, err + } + + if sourceContentType == filetype.Unknown { + sourceFileName := filepath.Base(sourceRemotePath.Path) + + sourceFilePath := filepath.Join(*sourceSandboxPath, sourceFileName) + + sourceFile, err := os.Create(sourceFilePath) + if err != nil { + return nil, err + } + + defer sourceFile.Close() + + _, err = io.Copy(sourceFile, sourceResponse.Body) + if err != nil { + return nil, err + } + } + + // 3b. Extract source + + ctx := context.Background() + + switch sourceContentType.MIME.Value { + case "application/gzip": + decoder := archives.Gz{} + + decoderReader, err := decoder.OpenReader(sourceResponse.Body) + if err != nil { + return nil, err + } + + defer decoderReader.Close() + + archive := archives.Tar{} + + err = archive.Extract(ctx, decoderReader, handleFile(*sourceSandboxPath)) + + case "application/x-bzip2": + decoder := archives.Bz2{} + + decoderReader, err := decoder.OpenReader(sourceResponse.Body) + if err != nil { + return nil, err + } + + defer decoderReader.Close() + + archive := archives.Tar{} + + err = archive.Extract(ctx, decoderReader, handleFile(*sourceSandboxPath)) + + case "application/x-xz": + decoder := archives.Xz{} + + decoderReader, err := decoder.OpenReader(sourceResponse.Body) + if err != nil { + return nil, err + } + + defer decoderReader.Close() + + archive := archives.Tar{} + + err = archive.Extract(ctx, decoderReader, handleFile(*sourceSandboxPath)) + + case "application/zip": + archive := archives.Zip{} + + err = archive.Extract(ctx, sourceResponse.Body, handleFile(*sourceSandboxPath)) + + default: + return nil, fmt.Errorf("unsupported content type: %s", sourceContentType.MIME.Value) + } + + if err != nil { + return nil, err + } + } + + if sourcePathKind == artifact.ArtifactSourceKind_LOCAL { + sourcePaths, err := store.GetFilePaths(source.Path, source.Excludes, source.Includes) + if err != nil { + return nil, err + } + + _, err = store.CopyFiles(source.Path, sourcePaths, *sourceSandboxPath) + if err != nil { + return nil, err + } + } + + // 4. Calculate source hash + + sourceSandboxFiles, err := store.GetFilePaths(*sourceSandboxPath, source.Excludes, source.Includes) + if err != nil { + return nil, err + } + + if len(sourceSandboxFiles) == 0 { + return nil, fmt.Errorf("Artifact `source.%s.path` no files found: %s", sourceName, source.Path) + } + + // 4a. Set timestamps + + for _, file := range sourceSandboxFiles { + err := store.SetTimestamps(file) + if err != nil { + return nil, err + } + } + + // 4b. Hash source files + + sourceHash, err := store.HashFiles(sourceSandboxFiles) + if err != nil { + return nil, err + } + + if source.Hash != nil && *source.Hash != sourceHash { + return nil, fmt.Errorf("`source.%s.hash` mismatch: %s != %s", sourceName, sourceHash, *source.Hash) + } + + // 4c. Cache source + + ctx := context.Background() + + sourceCacheArchiveFiles := make(map[string]string) + + for _, file := range sourceSandboxFiles { + relPath, err := filepath.Rel(*sourceSandboxPath, file) + if err != nil { + return nil, err + } + + sourceCacheArchiveFiles[file] = relPath + } + + files, err := archives.FilesFromDisk(ctx, nil, sourceCacheArchiveFiles) + if err != nil { + return nil, err + } + + sourceCacheArchivePath := store.GetCacheArchivePath(sourceHash, sourceName) + + out, err := os.Create(sourceCacheArchivePath) + if err != nil { + return nil, err + } + + defer out.Close() + + format := archives.CompressedArchive{ + Archival: archives.Tar{}, + Compression: archives.Zstd{}, + } + + err = format.Archive(ctx, out, files) + if err != nil { + return nil, err + } + + err = os.RemoveAll(*sourceSandboxPath) + if err != nil { + return nil, err + } + + sourceId := &artifactApi.ArtifactSourceId{ + Hash: sourceHash, + Name: sourceName, + } + + c.artifactSourceId[sourceKey] = sourceId + + return sourceId, nil +} + +func (c *ConfigContext) AddArtifact(name string, artifacts []*artifactApi.ArtifactId, sources []*artifactApi.ArtifactSourceId, steps []*artifactApi.ArtifactStep, systems []string) (*artifactApi.ArtifactId, error) { + // 1. Setup systems + + systemsInt := make([]artifactApi.ArtifactSystem, len(systems)) + + for i, system := range systems { + systemType := artifact.GetArtifactSystem(system) + if systemType == artifactApi.ArtifactSystem_UNKNOWN_SYSTEM { + return nil, fmt.Errorf("Unsupported system: %s", system) + } + + systemsInt[i] = systemType + } + + // 2. Setup artifact id + + artifact := &artifactApi.Artifact{ + Artifacts: artifacts, + Name: name, + Sources: sources, + Steps: steps, + Systems: systemsInt, + } + + artifactManifest := &artifactApi.ArtifactBuildRequest{ + Artifact: artifact, + System: c.system, + } + + artifactManifestBytes, err := json.Marshal(artifactManifest) + if err != nil { + return nil, err + } + + artifactManifestHash := fmt.Sprintf("%x", sha256.Sum256(artifactManifestBytes)) + + artifactId := &artifactApi.ArtifactId{ + Hash: artifactManifestHash, + Name: name, + } + + if _, ok := c.ArtifactId[artifactId]; !ok { + c.ArtifactId[artifactId] = artifact + } + + return artifactId, nil +} + +func (c *ConfigContext) GetArtifact(hash string, name string) (*artifactApi.Artifact, error) { + artifactId := &artifactApi.ArtifactId{ + Hash: hash, + Name: name, + } + + // NOTE: this may be a bug as it requires a pointer to the artifactId + // instead, it may require a loop to find the artifactId + + artifact, ok := c.ArtifactId[artifactId] + if !ok { + return nil, fmt.Errorf("Artifact not found: %s", name) + } + + return artifact, nil +} + +func (c *ConfigContext) GetTarget() artifactApi.ArtifactSystem { + return c.system +} + +func (c *ConfigContext) Run(artifacts []*artifactApi.ArtifactId) error { + listener, err := net.Listen("tcp", fmt.Sprintf("[::]:%d", c.port)) + if err != nil { + log.Fatalf("failed to listen: %v", err) + } + + config := &configApi.Config{ + Artifacts: artifacts, + } + + var opts []grpc.ServerOption + + grpcServer := grpc.NewServer(opts...) + + configApi.RegisterConfigServiceServer(grpcServer, NewConfigServer(c, config)) + + err = grpcServer.Serve(listener) + if err != nil { + return err + } + + return nil +} + +func (s *ConfigServer) GetConfig(ctx context.Context, request *configApi.ConfigRequest) (*configApi.Config, error) { + return s.Config, nil +} + +func (s *ConfigServer) GetArtifact(ctx context.Context, request *artifactApi.ArtifactId) (*artifactApi.Artifact, error) { + artifact, err := s.Context.GetArtifact(request.Hash, request.Name) + if err != nil { + return nil, err + } + + if artifact == nil { + return nil, fmt.Errorf("Artifact not found: %s", request.Name) + } + + return artifact, nil +} diff --git a/sdk/go/internal/store/hash.go b/sdk/go/internal/store/hash.go new file mode 100644 index 00000000..ed14de39 --- /dev/null +++ b/sdk/go/internal/store/hash.go @@ -0,0 +1,124 @@ +package store + +import ( + "crypto/sha256" + "encoding/hex" + "fmt" + "io" + "os" +) + +// GetFileHash calculates the SHA-256 hash of a file +func GetFileHash(path string) (string, error) { + // Check if path is a file + fileInfo, err := os.Stat(path) + if err != nil { + return "", err + } + + if fileInfo.IsDir() { + return "", fmt.Errorf("path is not a file") + } + + // Open the file + file, err := os.Open(path) + if err != nil { + return "", err + } + defer file.Close() + + // Create a new SHA-256 hash + hash := sha256.New() + + // Copy file content to hash + if _, err := io.Copy(hash, file); err != nil { + return "", fmt.Errorf("failed to get file hash: %w", err) + } + + // Get the hash sum and convert to hex string + hashSum := hash.Sum(nil) + hashString := hex.EncodeToString(hashSum) + + return hashString, nil +} + +// GetFileHashes calculates SHA-256 hashes for multiple files +func GetFileHashes(files []string) ([]string, error) { + var hashes []string + + for _, file := range files { + // Check if path is a file + fileInfo, err := os.Stat(file) + if err != nil { + continue + } + + if fileInfo.IsDir() { + continue + } + + hash, err := GetFileHash(file) + if err != nil { + return nil, err + } + + hashes = append(hashes, hash) + } + + return hashes, nil +} + +// GetHashesDigest combines multiple hashes and creates a digest +func GetHashesDigest(hashes []string) (string, error) { + combined := "" + + for _, hash := range hashes { + combined += hash + } + + // Create a new SHA-256 hash + hash := sha256.New() + + // Write the combined string to the hash + hash.Write([]byte(combined)) + + // Get the hash sum and convert to hex string + hashSum := hash.Sum(nil) + hashString := hex.EncodeToString(hashSum) + + return hashString, nil +} + +// HashFiles calculates a combined hash for multiple files +func HashFiles(paths []string) (string, error) { + if len(paths) == 0 { + return "", fmt.Errorf("no source files found") + } + + pathsHashes, err := GetFileHashes(paths) + if err != nil { + return "", err + } + + pathsHashesJoined, err := GetHashesDigest(pathsHashes) + if err != nil { + return "", err + } + + return pathsHashesJoined, nil +} + +// GetHashDigest calculates the SHA-256 hash of a string +func GetHashDigest(hash string) string { + // Create a new SHA-256 hash + hasher := sha256.New() + + // Write the string to the hash + hasher.Write([]byte(hash)) + + // Get the hash sum and convert to hex string + hashSum := hasher.Sum(nil) + hashString := hex.EncodeToString(hashSum) + + return hashString +} diff --git a/sdk/go/internal/store/path.go b/sdk/go/internal/store/path.go new file mode 100644 index 00000000..89727475 --- /dev/null +++ b/sdk/go/internal/store/path.go @@ -0,0 +1,237 @@ +package store + +import ( + "fmt" + "io" + "os" + "path/filepath" + "strings" + "syscall" + "time" + + "github.com/google/uuid" +) + +func GetStoreDirName(hash string, name string) string { + return fmt.Sprintf("%s-%s", name, hash) +} + +func GetRootDirPath() string { + return "/var/lib/vorpal" +} + +func GetCacheDirPath() string { + return fmt.Sprintf("%s/cache", GetRootDirPath()) +} + +func GetSandboxDirPath() string { + return fmt.Sprintf("%s/sandbox", GetRootDirPath()) +} + +func GetCacheArchivePath(hash string, name string) string { + return fmt.Sprintf("%s/%s.tar.zst", GetCacheDirPath(), GetStoreDirName(hash, name)) +} + +func GetSandboxPath() (*string, error) { + id, err := uuid.NewV7() + if err != nil { + return nil, err + } + + path := fmt.Sprintf("%s/%s", GetSandboxDirPath(), id.String()) + + return &path, nil +} + +func shouldExclude(path string, excludes []string) bool { + for _, ex := range excludes { + // NOTE: Here, you might use filepath.Match for glob-style patterns. + if strings.Contains(path, ex) { + return true + } + } + + return false +} + +func shouldInclude(path string, includes []string) bool { + // If no includes are provided, consider every file valid. + if len(includes) == 0 { + return true + } + + for _, inc := range includes { + // NOTE: Again, you might use a more sophisticated matching mechanism. + if strings.Contains(path, inc) { + return true + } + } + + return false +} + +func GetFilePaths(inputPath string, excludes []string, includes []string) ([]string, error) { + paths := []string{} + + err := filepath.WalkDir(inputPath, func(path string, d os.DirEntry, err error) error { + if err != nil { + return err + } + + if shouldExclude(path, excludes) { + // If it's a directory, skip the entire directory tree. + if d.IsDir() { + return filepath.SkipDir + } + + // Otherwise, just skip this file. + return nil + } + + if d.IsDir() { + return nil + } + + if !shouldInclude(path, includes) { + return nil + } + + paths = append(paths, path) + + return nil + }) + if err != nil { + return nil, err + } + + return paths, nil +} + +func CopyFiles(sourcePath string, sourcePathFiles []string, targetPath string) ([]string, error) { + if len(sourcePathFiles) == 0 { + return nil, fmt.Errorf("no source files found") + } + + for _, src := range sourcePathFiles { + if strings.HasSuffix(src, ".tar.zst") { + return nil, fmt.Errorf("source file is a tar.zst archive") + } + + if _, err := os.Stat(src); os.IsNotExist(err) { + return nil, fmt.Errorf("source file not found: %s", src) + } + + fileInfo, err := os.Lstat(src) + if err != nil { + return nil, fmt.Errorf("failed to read metadata: %w", err) + } + + // Calculate destination path by removing source prefix + relPath, err := filepath.Rel(sourcePath, src) + if err != nil { + return nil, fmt.Errorf("failed to get relative path: %w", err) + } + + dest := filepath.Join(targetPath, relPath) + + if fileInfo.IsDir() { + if err := os.MkdirAll(dest, 0o755); err != nil { + return nil, fmt.Errorf("create directory fail: %w", err) + } + } else if fileInfo.Mode()&os.ModeSymlink != 0 { + // Handle symlink + linkTarget, err := os.Readlink(src) + if err != nil { + return nil, fmt.Errorf("failed to read symlink: %w", err) + } + + // Ensure parent directory exists + parent := filepath.Dir(dest) + if err := os.MkdirAll(parent, 0o755); err != nil { + return nil, fmt.Errorf("create parent directory fail: %w", err) + } + + // Remove existing symlink if it exists + if _, err := os.Lstat(dest); err == nil { + os.Remove(dest) + } + + if err := os.Symlink(linkTarget, dest); err != nil { + return nil, fmt.Errorf("symlink file fail: %w", err) + } + } else if fileInfo.Mode().IsRegular() { + // Handle regular file + parent := filepath.Dir(dest) + if err := os.MkdirAll(parent, 0o755); err != nil { + return nil, fmt.Errorf("create parent directory fail: %w", err) + } + + srcFile, err := os.Open(src) + if err != nil { + return nil, fmt.Errorf("open source file fail: %w", err) + } + + defer srcFile.Close() + + destFile, err := os.Create(dest) + if err != nil { + return nil, fmt.Errorf("create destination file fail: %w", err) + } + + defer destFile.Close() + + if _, err := io.Copy(destFile, srcFile); err != nil { + return nil, fmt.Errorf("copy file fail: %w", err) + } + + // Set the same permissions + if err := os.Chmod(dest, fileInfo.Mode()); err != nil { + return nil, fmt.Errorf("set file permissions fail: %w", err) + } + } else { + return nil, fmt.Errorf("source file is not a file or directory: %s", src) + } + } + + // Get all files in the target directory + targetPathFiles, err := GetFilePaths(targetPath, []string{}, []string{}) + if err != nil { + return nil, err + } + + return targetPathFiles, nil +} + +// SetSymlinkTimestamps sets the access and modification times of a symlink +func SetSymlinkTimestamps(path string) error { + // Create epoch time (January 1, 1970 UTC) + epoch := time.Unix(0, 0) + + // Convert to syscall timespec + ts := []syscall.Timespec{ + {Sec: epoch.Unix(), Nsec: 0}, // Access time + {Sec: epoch.Unix(), Nsec: 0}, // Modification time + } + + // Use Utimesnano syscall to set symlink timestamps without following the link + return syscall.UtimesNano(path, ts) +} + +// SetTimestamps sets the access and modification times of a file or symlink to epoch (0) +func SetTimestamps(path string) error { + // Check if the path is a symlink + fileInfo, err := os.Lstat(path) + if err != nil { + return err + } + + // Set timestamps based on whether it's a symlink or regular file + if fileInfo.Mode()&os.ModeSymlink != 0 { + return SetSymlinkTimestamps(path) + } else { + // Create epoch time (January 1, 1970 UTC) + epoch := time.Unix(0, 0) + // Set access and modification times for regular files + return os.Chtimes(path, epoch, epoch) + } +} diff --git a/sdk/go/internal/store/sandbox.go b/sdk/go/internal/store/sandbox.go new file mode 100644 index 00000000..1a9ee0a5 --- /dev/null +++ b/sdk/go/internal/store/sandbox.go @@ -0,0 +1,35 @@ +package store + +import ( + "fmt" + "os" +) + +func NewSandboxDir() (*string, error) { + path, err := GetSandboxPath() + if err != nil { + return nil, err + } + + if err := os.MkdirAll(*path, 0o755); err != nil { + return nil, err + } + + return path, nil +} + +func NewSandboxFile(extension string) (*os.File, error) { + path, err := GetSandboxPath() + if err != nil { + return nil, err + } + + filename := fmt.Sprintf("%s%s", *path, extension) + + file, err := os.Create(filename) + if err != nil { + return nil, err + } + + return file, nil +} diff --git a/sdk/go/main.go b/sdk/go/main.go new file mode 100644 index 00000000..050bdc59 --- /dev/null +++ b/sdk/go/main.go @@ -0,0 +1,13 @@ +package main + +import ( + "log" + + "github.com/ALT-F4-LLC/vorpal/sdk/go/internal/context" +) + +func main() { + ctx := context.GetContext() + + log.Printf("Context: %v", ctx) +} diff --git a/sdk/Cargo.toml b/sdk/rust/Cargo.toml similarity index 89% rename from sdk/Cargo.toml rename to sdk/rust/Cargo.toml index c63b8826..436caffb 100644 --- a/sdk/Cargo.toml +++ b/sdk/rust/Cargo.toml @@ -20,5 +20,5 @@ toml = { default-features = false, features = ["parse"], version = "0" } tonic = { default-features = false, version = "0" } tracing = { default-features = false, version = "0" } url = { default-features = false, version = "2" } -vorpal-schema = { default-features = false, path = "../schema" } -vorpal-store = { default-features = false, path = "../store" } +vorpal-schema = { default-features = false, path = "../../schema" } +vorpal-store = { default-features = false, path = "../../store" } diff --git a/sdk/src/config/artifact/toolchain/cargo.rs b/sdk/rust/src/artifact/cargo.rs similarity index 70% rename from sdk/src/config/artifact/toolchain/cargo.rs rename to sdk/rust/src/artifact/cargo.rs index d117d150..11dbe091 100644 --- a/sdk/src/config/artifact/toolchain/cargo.rs +++ b/sdk/rust/src/artifact/cargo.rs @@ -1,15 +1,19 @@ -use crate::config::{ - artifact::{add_artifact, language::rust::get_toolchain_target, ConfigContext}, - ArtifactSource, +use crate::{ + artifact::{add_artifact, language::rust::get_rust_toolchain_target, ArtifactSource}, + context::ConfigContext, }; use anyhow::{bail, Result}; use std::collections::BTreeMap; use vorpal_schema::vorpal::artifact::v0::{ - ArtifactId, + ArtifactId, ArtifactSourceId, ArtifactSystem::{Aarch64Linux, Aarch64Macos, UnknownSystem, X8664Linux, X8664Macos}, }; -pub async fn artifact(context: &mut ConfigContext, version: &str) -> Result { +pub async fn source( + context: &mut ConfigContext, + target: &str, + version: &str, +) -> Result { let hash = match context.get_target() { Aarch64Linux => "42781c7ae909a5cd01c955cb4343754ce33d75783b2599a3f1a3b3752a0947af", Aarch64Macos => "e88e4babfc20e0546fe28bc2ba3f71a467f83e9fb1be76c9a078d327379ee4d0", @@ -18,9 +22,25 @@ pub async fn artifact(context: &mut ConfigContext, version: &str) -> Result bail!("Invalid protoc system: {:?}", context.get_target()), }; + context + .add_artifact_source( + "cargo", + ArtifactSource { + excludes: vec![], + hash: Some(hash.to_string()), + includes: vec![], + path: format!("https://static.rust-lang.org/dist/cargo-{version}-{target}.tar.gz"), + }, + ) + .await +} + +pub async fn artifact(context: &mut ConfigContext, version: &str) -> Result { let name = "cargo"; - let target = get_toolchain_target(context.get_target())?; + let target = get_rust_toolchain_target(context.get_target())?; + + let source = source(context, &target, version).await?; add_artifact( context, @@ -30,15 +50,7 @@ pub async fn artifact(context: &mut ConfigContext, version: &str) -> Result Result { +pub async fn source( + context: &mut ConfigContext, + target: &str, + version: &str, +) -> Result { let hash = match context.get_target() { Aarch64Linux => "5e0b5cb7e8655501369a6f42cb10b1c5d4711a0edfcbe44483c5234da485819d", Aarch64Macos => "fe82bf19b064f6fca648b9be6a53ae210a9934023df364d669fc7c4ee5ccd485", @@ -18,9 +22,25 @@ pub async fn artifact(context: &mut ConfigContext, version: &str) -> Result bail!("Invalid protoc system: {:?}", context.get_target()), }; + context + .add_artifact_source( + "clippy", + ArtifactSource { + excludes: vec![], + hash: Some(hash.to_string()), + includes: vec![], + path: format!("https://static.rust-lang.org/dist/clippy-{version}-{target}.tar.gz"), + }, + ) + .await +} + +pub async fn artifact(context: &mut ConfigContext, version: &str) -> Result { let name = "clippy"; - let target = get_toolchain_target(context.get_target())?; + let target = get_rust_toolchain_target(context.get_target())?; + + let source = source(context, &target, version).await?; add_artifact( context, @@ -28,15 +48,7 @@ pub async fn artifact(context: &mut ConfigContext, version: &str) -> Result Result { + let target = context.get_target(); + + let hash = match target { + Aarch64Linux => "42cec86acdeb62f23b8a65afaa67c2d8c8818f28d7d3ca55430e10e8027a6234", + Aarch64Macos => "86c352c4ced8830cd92a9c85c2944eaa95ebb1e8908b3f01258962bcc94b9c14", + X8664Linux => "9037b22b154e44366e6a03963bd5584f76381070baa9cf6a548bd2bfcd28b72e", + X8664Macos => "123456789", + UnknownSystem => bail!("Invalid go system: {:?}", context.get_target()), + }; + + let target = match target { + Aarch64Linux => "linux-arm64", + Aarch64Macos => "darwin-arm64", + X8664Linux => "linux-386", + X8664Macos => "darwin-amd64", + UnknownSystem => bail!("Invalid go system: {:?}", target), + }; + + let version = "1.23.5"; + + context + .add_artifact_source( + "go", + ArtifactSource { + excludes: vec![], + hash: Some(hash.to_string()), + includes: vec![], + path: format!("https://go.dev/dl/go{}.{}.tar.gz", version, target), + }, + ) + .await +} + +pub async fn artifact(context: &mut ConfigContext) -> Result { + let name = "go"; + + let source = source(context).await?; + + add_artifact( + context, + vec![], + BTreeMap::new(), + name, + format!("cp -prv \"./source/{name}/go/.\" \"$VORPAL_OUTPUT\""), + vec![source], + vec![ + "aarch64-linux", + "aarch64-macos", + "x86_64-linux", + "x86_64-macos", + ], + ) + .await +} diff --git a/sdk/rust/src/artifact/goimports.rs b/sdk/rust/src/artifact/goimports.rs new file mode 100644 index 00000000..81e9bcb6 --- /dev/null +++ b/sdk/rust/src/artifact/goimports.rs @@ -0,0 +1,45 @@ +use crate::{ + artifact::{add_artifact, get_artifact_envkey, go}, + context::ConfigContext, + source::go_tools, +}; +use anyhow::Result; +use indoc::formatdoc; +use std::collections::BTreeMap; +use vorpal_schema::vorpal::artifact::v0::ArtifactId; + +pub async fn artifact(context: &mut ConfigContext) -> Result { + let go = go::artifact(context).await?; + + let name = "goimports"; + + let source = go_tools(context).await?; + + add_artifact( + context, + vec![go.clone()], + BTreeMap::from([ + ("GOCACHE", "$VORPAL_WORKSPACE/go/cache".to_string()), + ("GOPATH", "$VORPAL_WORKSPACE/go".to_string()), + ("PATH", format!("{}/bin", get_artifact_envkey(&go))), + ]), + name, + formatdoc! {" + pushd ./source/go-tools + + mkdir -p $VORPAL_OUTPUT/bin + + go build -o $VORPAL_OUTPUT/bin/goimports ./cmd/goimports + + go clean -modcache + "}, + vec![source], + vec![ + "aarch64-linux", + "aarch64-macos", + "x86_64-linux", + "x86_64-macos", + ], + ) + .await +} diff --git a/sdk/rust/src/artifact/gopls.rs b/sdk/rust/src/artifact/gopls.rs new file mode 100644 index 00000000..13953e80 --- /dev/null +++ b/sdk/rust/src/artifact/gopls.rs @@ -0,0 +1,45 @@ +use crate::{ + artifact::{add_artifact, get_artifact_envkey, go}, + context::ConfigContext, + source::go_tools, +}; +use anyhow::Result; +use indoc::formatdoc; +use std::collections::BTreeMap; +use vorpal_schema::vorpal::artifact::v0::ArtifactId; + +pub async fn artifact(context: &mut ConfigContext) -> Result { + let go = go::artifact(context).await?; + + let name = "gopls"; + + let source = go_tools(context).await?; + + add_artifact( + context, + vec![go.clone()], + BTreeMap::from([ + ("GOCACHE", "$VORPAL_WORKSPACE/go/cache".to_string()), + ("GOPATH", "$VORPAL_WORKSPACE/go".to_string()), + ("PATH", format!("{}/bin", get_artifact_envkey(&go))), + ]), + name, + formatdoc! {" + pushd ./source/go-tools/gopls + + mkdir -p $VORPAL_OUTPUT/bin + + go build -o $VORPAL_OUTPUT/bin/gopls . + + go clean -modcache + "}, + vec![source], + vec![ + "aarch64-linux", + "aarch64-macos", + "x86_64-linux", + "x86_64-macos", + ], + ) + .await +} diff --git a/sdk/src/config/artifact/language/mod.rs b/sdk/rust/src/artifact/language/mod.rs similarity index 100% rename from sdk/src/config/artifact/language/mod.rs rename to sdk/rust/src/artifact/language/mod.rs diff --git a/sdk/src/config/artifact/language/rust.rs b/sdk/rust/src/artifact/language/rust.rs similarity index 87% rename from sdk/src/config/artifact/language/rust.rs rename to sdk/rust/src/artifact/language/rust.rs index 0e99b706..adc2c57e 100644 --- a/sdk/src/config/artifact/language/rust.rs +++ b/sdk/rust/src/artifact/language/rust.rs @@ -1,11 +1,9 @@ -use crate::config::{ +use crate::{ artifact::{ - add_artifact, get_artifact_envkey, - shell::shell_artifact, - toolchain::{cargo, clippy, protoc, rust_analyzer, rust_src, rust_std, rustc, rustfmt}, - ArtifactSource, + add_artifact, cargo, clippy, get_artifact_envkey, protoc, rust_analyzer, rust_src, + rust_std, rustc, rustfmt, shell::shell_artifact, ArtifactSource, }, - ConfigContext, + context::ConfigContext, }; use anyhow::{bail, Result}; use indoc::formatdoc; @@ -36,7 +34,7 @@ struct RustArtifactCargoTomlWorkspace { members: Option>, } -pub fn get_toolchain_target(target: ArtifactSystem) -> Result { +pub fn get_rust_toolchain_target(target: ArtifactSystem) -> Result { let target = match target { Aarch64Linux => "aarch64-unknown-linux-gnu", Aarch64Macos => "aarch64-apple-darwin", @@ -61,7 +59,7 @@ fn read_cargo_toml(path: &str) -> Result { #[allow(clippy::too_many_arguments)] pub async fn toolchain_artifact(context: &mut ConfigContext, name: &str) -> Result { let version = get_rust_toolchain_version(); - let target = get_toolchain_target(context.get_target())?; + let target = get_rust_toolchain_target(context.get_target())?; let cargo = cargo::artifact(context, &version).await?; let clippy = clippy::artifact(context, &version).await?; @@ -126,7 +124,7 @@ pub async fn toolchain_artifact(context: &mut ConfigContext, name: &str) -> Resu EOF", component_paths = component_paths.join(" "), }, - BTreeMap::new(), + vec![], vec![ "aarch64-linux", "aarch64-macos", @@ -144,7 +142,7 @@ pub async fn rust_shell(context: &mut ConfigContext, name: &str) -> Result Result(context: &mut ConfigContext, name: &'a str) -> Result { +pub async fn rust_package<'a>( + context: &mut ConfigContext, + name: &'a str, + excludes: Vec<&'a str>, +) -> Result { let toolchain = toolchain_artifact(context, name).await?; // 1. READ CARGO.TOML FILES @@ -245,7 +247,7 @@ pub async fn rust_package<'a>(context: &mut ConfigContext, name: &'a str) -> Res // Get protoc artifact let protoc = protoc::artifact(context).await?; - let toolchain_target = get_toolchain_target(context.get_target())?; + let toolchain_target = get_rust_toolchain_target(context.get_target())?; let toolchain_version = get_rust_toolchain_version(); // Set environment variables @@ -267,6 +269,18 @@ pub async fn rust_package<'a>(context: &mut ConfigContext, name: &'a str) -> Res vendor_cargo_tomls.push(format!("{}/Cargo.toml", workspace)); } + let vendor_source = context + .add_artifact_source( + format!("{}-vendor", name).as_str(), + ArtifactSource { + excludes: vec![], + hash: None, + includes: vendor_cargo_tomls.clone(), + path: source_path.display().to_string(), + }, + ) + .await?; + let vendor = add_artifact( context, vec![toolchain.clone()], @@ -280,7 +294,7 @@ pub async fn rust_package<'a>(context: &mut ConfigContext, name: &'a str) -> Res formatdoc! {" mkdir -pv $HOME - pushd ./source/{name} + pushd ./source/{name}-vendor target_paths=({target_paths}) @@ -296,15 +310,7 @@ pub async fn rust_package<'a>(context: &mut ConfigContext, name: &'a str) -> Res echo \"$cargo_vendor\" > \"$VORPAL_OUTPUT/config.toml\"", target_paths = workspaces_targets.join(" "), }, - BTreeMap::from([( - name, - ArtifactSource { - excludes: vec![], - hash: None, - includes: vendor_cargo_tomls.clone(), - path: source_path.display().to_string(), - }, - )]), + vec![vendor_source], systems.clone(), ) .await?; @@ -317,6 +323,24 @@ pub async fn rust_package<'a>(context: &mut ConfigContext, name: &'a str) -> Res env_paths.push(format!("{}/bin", get_artifact_envkey(&protoc))); + let mut excludes_defaults = vec!["target".to_string()]; + + for exclude in excludes { + excludes_defaults.push(exclude.to_string()); + } + + let artifact_source = context + .add_artifact_source( + name, + ArtifactSource { + excludes: excludes_defaults, + hash: None, + includes: vec![], + path: source_path.display().to_string(), + }, + ) + .await?; + add_artifact( context, artifacts, @@ -353,31 +377,7 @@ pub async fn rust_package<'a>(context: &mut ConfigContext, name: &'a str) -> Res bin_names = workspaces_bin_names.join(" "), vendor = get_artifact_envkey(&vendor), }, - BTreeMap::from([( - name, - ArtifactSource { - excludes: vec![ - ".env".to_string(), - ".envrc".to_string(), - ".github".to_string(), - ".gitignore".to_string(), - ".packer".to_string(), - ".vagrant".to_string(), - "Dockerfile".to_string(), - "Vagrantfile".to_string(), - "dist".to_string(), - "makefile".to_string(), - "script".to_string(), - "shell.nix".to_string(), - "target".to_string(), - "vorpal-domains.svg".to_string(), - "vorpal-purpose.jpg".to_string(), - ], - hash: None, - includes: vec![], - path: source_path.display().to_string(), - }, - )]), + vec![artifact_source], systems, ) .await diff --git a/sdk/src/config/artifact/toolchain/linux/debian.rs b/sdk/rust/src/artifact/linux_debian.rs similarity index 98% rename from sdk/src/config/artifact/toolchain/linux/debian.rs rename to sdk/rust/src/artifact/linux_debian.rs index 6a3413c0..e32fb7c4 100644 --- a/sdk/src/config/artifact/toolchain/linux/debian.rs +++ b/sdk/rust/src/artifact/linux_debian.rs @@ -1,9 +1,9 @@ -use crate::config::{ +use crate::{ artifact::{ get_artifact_envkey, - steps::{bash, docker}, + step::{bash, docker}, }, - ConfigContext, + context::ConfigContext, }; use anyhow::Result; use indoc::formatdoc; @@ -167,7 +167,7 @@ pub async fn artifact(context: &mut ConfigContext) -> Result { .add_artifact( "linux-debian-docker", vec![], - BTreeMap::new(), + vec![], vec![bash( BTreeMap::new(), formatdoc! {" @@ -190,7 +190,7 @@ pub async fn artifact(context: &mut ConfigContext) -> Result { .add_artifact( "linux-debian", vec![dockerfile.clone()], - BTreeMap::new(), + vec![], vec![ docker(vec![ "buildx".to_string(), diff --git a/sdk/src/config/artifact/toolchain/linux/vorpal/mod.rs b/sdk/rust/src/artifact/linux_vorpal.rs similarity index 85% rename from sdk/src/config/artifact/toolchain/linux/vorpal/mod.rs rename to sdk/rust/src/artifact/linux_vorpal.rs index 2b9f0002..e03c9444 100644 --- a/sdk/src/config/artifact/toolchain/linux/vorpal/mod.rs +++ b/sdk/rust/src/artifact/linux_vorpal.rs @@ -1,10 +1,201 @@ -use crate::config::artifact::{steps, ConfigContext}; +use crate::{ + artifact::{step::bwrap, ArtifactSource}, + context::ConfigContext, +}; use anyhow::Result; use indoc::formatdoc; use std::collections::BTreeMap; use vorpal_schema::vorpal::artifact::v0::ArtifactId; -mod source; +pub fn curl(version: &str, hash: &str) -> ArtifactSource { + ArtifactSource { + excludes: vec![], + hash: Some(hash.to_string()), + includes: vec![], + path: format!("https://curl.se/download/curl-{version}.tar.xz"), + } +} + +pub fn curl_cacert(hash: &str) -> ArtifactSource { + ArtifactSource { + excludes: vec![], + hash: Some(hash.to_string()), + includes: vec![], + path: "https://curl.se/ca/cacert.pem".to_string(), + } +} + +pub fn file(version: &str, hash: &str) -> ArtifactSource { + ArtifactSource { + excludes: vec![], + hash: Some(hash.to_string()), + includes: vec![], + path: format!("https://astron.com/pub/file/file-{version}.tar.gz"), + } +} + +pub fn gnu(name: &str, version: &str, hash: &str) -> ArtifactSource { + ArtifactSource { + excludes: vec![], + hash: Some(hash.to_string()), + includes: vec![], + path: format!("https://ftpmirror.gnu.org/gnu/{name}/{name}-{version}.tar.gz"), + } +} + +pub fn gnu_xz(name: &str, version: &str, hash: &str) -> ArtifactSource { + ArtifactSource { + excludes: vec![], + hash: Some(hash.to_string()), + includes: vec![], + path: format!("https://ftpmirror.gnu.org/gnu/{name}/{name}-{version}.tar.xz"), + } +} + +pub fn gnu_gcc(version: &str, hash: &str) -> ArtifactSource { + ArtifactSource { + excludes: vec![], + hash: Some(hash.to_string()), + includes: vec![], + path: format!("https://ftpmirror.gnu.org/gnu/gcc/gcc-{version}/gcc-{version}.tar.xz"), + } +} + +pub fn gnu_glibc_patch(version: &str, hash: &str) -> ArtifactSource { + ArtifactSource { + excludes: vec![], + hash: Some(hash.to_string()), + includes: vec![], + path: format!( + "https://www.linuxfromscratch.org/patches/lfs/12.2/glibc-{version}-fhs-1.patch", + ), + } +} + +pub fn libidn2(version: &str, hash: &str) -> ArtifactSource { + ArtifactSource { + excludes: vec![], + hash: Some(hash.to_string()), + includes: vec![], + path: format!("https://ftpmirror.gnu.org/gnu/libidn/libidn2-{version}.tar.gz"), + } +} + +pub fn libpsl(version: &str, hash: &str) -> ArtifactSource { + ArtifactSource { + excludes: vec![], + hash: Some(hash.to_string()), + includes: vec![], + path: format!( + "https://github.com/rockdaboot/libpsl/releases/download/{version}/libpsl-{version}.tar.gz", + ), + } +} + +pub fn linux(version: &str, hash: &str) -> ArtifactSource { + ArtifactSource { + excludes: vec![], + hash: Some(hash.to_string()), + includes: vec![], + path: format!("https://cdn.kernel.org/pub/linux/kernel/v6.x/linux-{version}.tar.xz"), + } +} + +pub fn ncurses(version: &str, hash: &str) -> ArtifactSource { + ArtifactSource { + excludes: vec![], + hash: Some(hash.to_string()), + includes: vec![], + path: format!("https://invisible-mirror.net/archives/ncurses/ncurses-{version}.tar.gz"), + } +} + +pub fn openssl(version: &str, hash: &str) -> ArtifactSource { + ArtifactSource { + excludes: vec![], + hash: Some(hash.to_string()), + includes: vec![], + path: format!("https://www.openssl.org/source/openssl-{version}.tar.gz"), + } +} + +pub fn perl(version: &str, hash: &str) -> ArtifactSource { + ArtifactSource { + excludes: vec![], + hash: Some(hash.to_string()), + includes: vec![], + path: format!("https://www.cpan.org/src/5.0/perl-{version}.tar.xz"), + } +} + +pub fn python(version: &str, hash: &str) -> ArtifactSource { + ArtifactSource { + excludes: vec![], + hash: Some(hash.to_string()), + includes: vec![], + path: format!("https://www.python.org/ftp/python/{version}/Python-{version}.tar.xz"), + } +} + +pub fn unzip_patch_fixes(version: &str, hash: &str) -> ArtifactSource { + ArtifactSource { + excludes: vec![], + hash: Some(hash.to_string()), + includes: vec![], + path: format!("https://www.linuxfromscratch.org/patches/blfs/12.2/unzip-{version}-consolidated_fixes-1.patch"), + } +} + +pub fn unzip_patch_gcc14(version: &str, hash: &str) -> ArtifactSource { + ArtifactSource { + excludes: vec![], + hash: Some(hash.to_string()), + includes: vec![], + path: format!( + "https://www.linuxfromscratch.org/patches/blfs/12.2/unzip-{version}-gcc14-1.patch" + ), + } +} + +pub fn unzip(version: &str, hash: &str) -> ArtifactSource { + let version = version.replace(".", ""); + + ArtifactSource { + excludes: vec![], + hash: Some(hash.to_string()), + includes: vec![], + path: format!("https://cfhcable.dl.sourceforge.net/project/infozip/UnZip%206.x%20%28latest%29/UnZip%206.0/unzip{version}.tar.gz?viasf=1",), + } +} + +pub fn util_linux(version: &str, hash: &str) -> ArtifactSource { + ArtifactSource { + excludes: vec![], + hash: Some(hash.to_string()), + includes: vec![], + path: format!( + "https://www.kernel.org/pub/linux/utils/util-linux/v2.40/util-linux-{version}.tar.xz" + ), + } +} + +pub fn xz(version: &str, hash: &str) -> ArtifactSource { + ArtifactSource { + excludes: vec![], + hash: Some(hash.to_string()), + includes: vec![], + path: format!("https://github.com/tukaani-project/xz/releases/download/v{version}/xz-{version}.tar.xz"), + } +} + +pub fn zlib(version: &str, hash: &str) -> ArtifactSource { + ArtifactSource { + excludes: vec![], + hash: Some(hash.to_string()), + includes: vec![], + path: format!("https://zlib.net/fossils/zlib-{version}.tar.gz"), + } +} pub async fn artifact( context: &mut ConfigContext, @@ -17,229 +208,229 @@ pub async fn artifact( // Setup sources let bash_version = "5.2.32"; - let bash = source::gnu( + let bash = gnu( "bash", bash_version, "19a8087c947a587b491508a6675a5349e23992d5dfca40a0bd0735bbd81e0438", ); let binutils_version = "2.43.1"; - let binutils = source::gnu( + let binutils = gnu( "binutils", binutils_version, "c0d3e5ee772ee201eefe17544b2b2cc3a0a3d6833a21b9ea56371efaad0c5528", ); let bison_version = "3.8.2"; - let bison = source::gnu( + let bison = gnu( "bison", bison_version, "cb18c2c8562fc01bf3ae17ffe9cf8274e3dd49d39f89397c1a8bac7ee14ce85f", ); let coreutils_version = "9.5"; - let coreutils = source::gnu( + let coreutils = gnu( "coreutils", coreutils_version, "af6d643afd6241ec35c7781b7f999b97a66c84bea4710ad2bb15e75a5caf11b4", ); let curl_version = "8.11.0"; - let curl = source::curl( + let curl = curl( curl_version, "97dde4e45e89291bf5405b0363b16049333366f286a1989537441c261e9299fe", ); let curl_cacert = - source::curl_cacert("19c0bec2c9dc55ad5e63b008d55ef6021565cfa4ff25bb8b93cf96381b050386"); + curl_cacert("19c0bec2c9dc55ad5e63b008d55ef6021565cfa4ff25bb8b93cf96381b050386"); let diffutils_version = "3.10"; - let diffutils = source::gnu_xz( + let diffutils = gnu_xz( "diffutils", diffutils_version, "5045e29e7fa0ffe017f63da7741c800cbc0f89e04aebd78efcd661d6e5673326", ); let file_version = "5.45"; - let file = source::file( + let file = file( file_version, "c118ab56efa05798022a5a488827594a82d844f65159e95b918d5501adf1e58f", ); let findutils_version = "4.10.0"; - let findutils = source::gnu_xz( + let findutils = gnu_xz( "findutils", findutils_version, "242f804d87a5036bb0fab99966227dc61e853e5a67e1b10c3cc45681c792657e", ); let gawk_version = "5.3.0"; - let gawk = source::gnu( + let gawk = gnu( "gawk", gawk_version, "a21e5899707ddc030a0fcc0a35c95a9602dca1a681fa52a1790a974509b40133", ); let gcc_version = "14.2.0"; - let gcc = source::gnu_gcc( + let gcc = gnu_gcc( gcc_version, "cc20ef929f4a1c07594d606ca4f2ed091e69fac5c6779887927da82b0a62f583", ); let gettext_version = "0.22.5"; - let gettext = source::gnu( + let gettext = gnu( "gettext", gettext_version, "6e3ef842d1006a6af7778a8549a8e8048fc3b923e5cf48eaa5b82b5d142220ae", ); let glibc_version = "2.40"; - let glibc = source::gnu( + let glibc = gnu( "glibc", glibc_version, "da2594c64d61dacf80d85e568136bf31fba36c4ff1ececff59c6fb786a2a126b", ); - let glibc_patch = source::gnu_glibc_patch( + let glibc_patch = gnu_glibc_patch( glibc_version, "69cf0653ad0a6a178366d291f30629d4e1cb633178aa4b8efbea0c851fb944ca", ); let grep_version = "3.11"; - let grep = source::gnu( + let grep = gnu( "grep", grep_version, "1625eae01f6e4dbc41b58545aa2326c74791b2010434f8241d41903a4ea5ff70", ); let gzip_version = "1.13"; - let gzip = source::gnu( + let gzip = gnu( "gzip", gzip_version, "25e51d46402bab819045d452ded6c4558ef980f5249c470d9499e9eae34b59b1", ); let libidn2_version = "2.3.7"; - let libidn2 = source::libidn2( + let libidn2 = libidn2( libidn2_version, "cb09b889bc9e51a2f5ec9d04dbbf03582926a129340828271955d15a57da6a3c", ); let libpsl_version = "0.21.5"; - let libpsl = source::libpsl( + let libpsl = libpsl( libpsl_version, "65ecfe61646c50119a018a2003149833c11387efd92462f974f1ff9f907c1d78", ); let libunistring_version = "1.2"; - let libunistring = source::gnu( + let libunistring = gnu( "libunistring", libunistring_version, "c621c94a94108095cfe08cc61f484d4b4cb97824c64a4e2bb1830d8984b542f3", ); let linux_version = "6.10.5"; - let linux = source::linux( + let linux = linux( linux_version, "b1548c4f5bf63c5f44c1a8c3044842a49ef445deb1b3da55b8116200a25793be", ); let m4_version = "1.4.19"; - let m4 = source::gnu( + let m4 = gnu( "m4", m4_version, "fd793cdfc421fac76f4af23c7d960cbe4a29cbb18f5badf37b85e16a894b3b6d", ); let make_version = "4.4.1"; - let make = source::gnu( + let make = gnu( "make", make_version, "8dfe7b0e51b3e190cd75e046880855ac1be76cf36961e5cfcc82bfa91b2c3ba8", ); let ncurses_version = "6.5"; - let ncurses = source::ncurses( + let ncurses = ncurses( ncurses_version, "aab234a3b7a22e2632151fbe550cb36e371d3ee5318a633ee43af057f9f112fb", ); let openssl_version = "3.3.1"; - let openssl = source::openssl( + let openssl = openssl( openssl_version, "a53e2254e36124452582477935a680f07f9884fe1d6e9ec03c28ac71b750d84a", ); let patch_version = "2.7.6"; - let patch = source::gnu( + let patch = gnu( "patch", "2.7.6", "af8c281a05a6802075799c0c179e5fb3a218be6a21b726d8b672cd0f4c37eae9", ); let perl_version = "5.40.0"; - let perl = source::perl( + let perl = perl( perl_version, "59b6437a3da1d9de0126135b31f1f16aee9c3b7a0f61f6364b2da3e8bb5f771f", ); let python_version = "3.12.5"; - let python = source::python( + let python = python( python_version, "8359773924d33702ecd6f9fab01973e53d929d46d7cdc4b0df31eb1282c68b67", ); let sed_version = "4.9"; - let sed = source::gnu( + let sed = gnu( "sed", sed_version, "434ff552af89340088e0d8cb206c251761297909bbee401176bc8f655e8e7cf2", ); let tar_version = "1.35"; - let tar = source::gnu( + let tar = gnu( "tar", tar_version, "f9bb5f39ed45b1c6a324470515d2ef73e74422c5f345503106d861576d3f02f3", ); let texinfo_version = "7.1.1"; - let texinfo = source::gnu( + let texinfo = gnu( "texinfo", texinfo_version, "6e34604552af91db0b4ccf0bcceba63dd3073da2a492ebcf33c6e188a64d2b63", ); let unzip_version = "6.0"; - let unzip = source::unzip( + let unzip = unzip( unzip_version, "4585067be297ae977da3f81587fcf0a141a8d6ceb6137d199255683ed189c3ed", ); - let unzip_patch_fixes = source::unzip_patch_fixes( + let unzip_patch_fixes = unzip_patch_fixes( "6.0", "11350935be5bbb743f1a97ec069b78fc2904f92b24abbc7fb3d7f0ff8bb889ea", ); - let unzip_patch_gcc14 = source::unzip_patch_gcc14( + let unzip_patch_gcc14 = unzip_patch_gcc14( "6.0", "d6ac941672086ea4c8d5047d550b40047825a685cc7c48626d2f0939e1a0c797", ); let util_linux_version = "2.40.2"; - let util_linux = source::util_linux( + let util_linux = util_linux( util_linux_version, "7db19a1819ac5c743b52887a4571e42325b2bfded63d93b6a1797ae2b1f8019a", ); let xz_version = "5.6.2"; - let xz = source::xz( + let xz = xz( xz_version, "7a02b1278ed9a59b332657d613c5549b39afe34e315197f4da95c5322524ec26", ); let zlib_version = "1.3.1"; - let zlib = source::zlib( + let zlib = zlib( zlib_version, "3f7995d5f103719283f509c23624287ce95c349439e881ed935a3c2c807bb683", ); @@ -283,12 +474,18 @@ pub async fn artifact( ("zlib", zlib), ]); + let mut source_ids = vec![]; + + for (source_name, source) in sources { + source_ids.push(context.add_artifact_source(source_name, source).await?); + } + context.add_artifact( "linux-vorpal", artifacts.clone(), - sources, + source_ids, vec![ - steps::bwrap( + bwrap( vec![], artifacts, BTreeMap::from([("PATH", "/usr/bin:/usr/sbin".to_string())]), @@ -933,7 +1130,7 @@ pub async fn artifact( rm -rfv $VORPAL_OUTPUT/var", } ), - steps::bwrap( + bwrap( vec![ // mount bin "--bind".to_string(), diff --git a/sdk/src/config/artifact/mod.rs b/sdk/rust/src/artifact/mod.rs similarity index 75% rename from sdk/src/config/artifact/mod.rs rename to sdk/rust/src/artifact/mod.rs index da56d157..52b55f82 100644 --- a/sdk/src/config/artifact/mod.rs +++ b/sdk/rust/src/artifact/mod.rs @@ -1,21 +1,46 @@ -use crate::config::{ - artifact::{ - steps::{bash, bwrap}, - toolchain::linux::{debian, vorpal}, - }, - ArtifactSource, ConfigContext, -}; +use crate::context::ConfigContext; use anyhow::{bail, Result}; +use serde::{Deserialize, Serialize}; use std::collections::BTreeMap; use vorpal_schema::vorpal::artifact::v0::{ - ArtifactId, ArtifactStepEnvironment, ArtifactSystem, + ArtifactId, ArtifactSourceId, ArtifactStepEnvironment, ArtifactSystem, ArtifactSystem::{Aarch64Linux, Aarch64Macos, X8664Linux, X8664Macos}, }; +pub mod cargo; +pub mod clippy; +pub mod go; +pub mod goimports; +pub mod gopls; pub mod language; +pub mod linux_debian; +pub mod linux_vorpal; +pub mod protoc; +pub mod protoc_gen_go; +pub mod protoc_gen_go_grpc; +pub mod rust_analyzer; +pub mod rust_src; +pub mod rust_std; +pub mod rustc; +pub mod rustfmt; pub mod shell; -pub mod steps; -pub mod toolchain; +pub mod step; + +#[derive(Clone, Debug, Deserialize, Serialize)] +pub struct ArtifactSource { + pub excludes: Vec, + pub hash: Option, + pub includes: Vec, + pub path: String, +} + +#[derive(Debug, PartialEq)] +pub enum ArtifactSourceKind { + UnknownSourceKind, + Git, + Http, + Local, +} pub fn get_artifact_envkey(artifact: &ArtifactId) -> String { format!( @@ -49,7 +74,7 @@ pub async fn add_artifact( environment: BTreeMap<&str, String>, name: &str, script: String, - source: BTreeMap<&str, ArtifactSource>, + sources: Vec, systems: Vec<&str>, ) -> Result { // Setup target @@ -61,8 +86,8 @@ pub async fn add_artifact( let mut artifacts = artifacts.clone(); if target == Aarch64Linux || target == X8664Linux { - let linux_debian = debian::artifact(context).await?; - let linux_vorpal = vorpal::artifact(context, &linux_debian).await?; + let linux_debian = linux_debian::artifact(context).await?; + let linux_vorpal = linux_vorpal::artifact(context, &linux_debian).await?; artifacts.push(linux_vorpal.clone()); } @@ -125,7 +150,7 @@ pub async fn add_artifact( .find(|a| a.name == "linux-vorpal") .expect("linux-vorpal artifact not found"); - steps.push(bwrap( + steps.push(step::bwrap( vec![], artifacts.clone(), env.clone(), @@ -135,12 +160,12 @@ pub async fn add_artifact( } if target == Aarch64Macos || target == X8664Macos { - steps.push(bash(env.clone(), script.to_string())); + steps.push(step::bash(env.clone(), script.to_string())); } // Add artifact to context context - .add_artifact(name, artifacts, source, steps, systems) + .add_artifact(name, artifacts, sources, steps, systems) .await } diff --git a/sdk/src/config/artifact/toolchain/protoc.rs b/sdk/rust/src/artifact/protoc.rs similarity index 78% rename from sdk/src/config/artifact/toolchain/protoc.rs rename to sdk/rust/src/artifact/protoc.rs index fea3e678..3793ae26 100644 --- a/sdk/src/config/artifact/toolchain/protoc.rs +++ b/sdk/rust/src/artifact/protoc.rs @@ -1,13 +1,16 @@ -use crate::config::{artifact::add_artifact, ArtifactSource, ConfigContext}; +use crate::{ + artifact::{add_artifact, ArtifactSource}, + context::ConfigContext, +}; use anyhow::{bail, Result}; use indoc::formatdoc; use std::collections::BTreeMap; use vorpal_schema::vorpal::artifact::v0::{ - ArtifactId, + ArtifactId, ArtifactSourceId, ArtifactSystem::{Aarch64Linux, Aarch64Macos, UnknownSystem, X8664Linux, X8664Macos}, }; -pub async fn artifact(context: &mut ConfigContext) -> Result { +pub async fn source(context: &mut ConfigContext) -> Result { let hash = match context.get_target() { Aarch64Linux => "8a592a0dd590e92b1c0d77631e683fc743d1ed8158e0b093b6cfabf0685089af", Aarch64Macos => "d105abb1c1d2c024f29df884f0592f1307984d63aeb10f0e61ccb94aee2c2feb", @@ -16,8 +19,6 @@ pub async fn artifact(context: &mut ConfigContext) -> Result { UnknownSystem => bail!("Invalid protoc system: {:?}", context.get_target()), }; - let name = "protoc"; - let target = match context.get_target() { Aarch64Linux => "linux-aarch_64", Aarch64Macos => "osx-aarch_64", @@ -28,6 +29,24 @@ pub async fn artifact(context: &mut ConfigContext) -> Result { let version = "25.4"; + context + .add_artifact_source( + "protoc", + ArtifactSource { + excludes: vec![], + hash: Some(hash.to_string()), + includes: vec![], + path: format!("https://github.com/protocolbuffers/protobuf/releases/download/v{version}/protoc-{version}-{target}.zip"), + }, + ) + .await +} + +pub async fn artifact(context: &mut ConfigContext) -> Result { + let name = "protoc"; + + let source = source(context).await?; + add_artifact( context, vec![], @@ -40,20 +59,13 @@ pub async fn artifact(context: &mut ConfigContext) -> Result { chmod +x \"$VORPAL_OUTPUT/bin/protoc\"", }, - BTreeMap::from([( - name, - ArtifactSource { - excludes: vec![], - hash: Some(hash.to_string()), - includes: vec![], - path: format!("https://github.com/protocolbuffers/protobuf/releases/download/v{version}/{name}-{version}-{target}.zip"), - } - )]), + vec![source], vec![ "aarch64-linux", "aarch64-macos", "x86_64-linux", "x86_64-macos", - ] - ).await + ], + ) + .await } diff --git a/sdk/rust/src/artifact/protoc_gen_go.rs b/sdk/rust/src/artifact/protoc_gen_go.rs new file mode 100644 index 00000000..e95d2070 --- /dev/null +++ b/sdk/rust/src/artifact/protoc_gen_go.rs @@ -0,0 +1,71 @@ +use crate::{ + artifact::{add_artifact, ArtifactSource}, + context::ConfigContext, +}; +use anyhow::{bail, Result}; +use indoc::formatdoc; +use std::collections::BTreeMap; +use vorpal_schema::vorpal::artifact::v0::{ + ArtifactId, ArtifactSourceId, + ArtifactSystem::{Aarch64Linux, Aarch64Macos, UnknownSystem, X8664Linux, X8664Macos}, +}; + +pub async fn source(context: &mut ConfigContext) -> Result { + let hash = match context.get_target() { + Aarch64Linux => "597aae8080d7e3e575198a5417ac2278ae49078d7fa3be56405ffb43bbb9f501", + Aarch64Macos => "55c2a0cc7137f3625bd1bf3be85ed940c643e56fa1ceaf51f94c6434980f65a5", + X8664Linux => "07f2ee9051854e2d240c56e47cfa9ac9b7d6a2dc2a9b2b6dbd79726f78c27bb1", + X8664Macos => "1234567890", + UnknownSystem => bail!("Invalid protoc-gen-go system: {:?}", context.get_target()), + }; + + let target = match context.get_target() { + Aarch64Linux => "linux.arm64", + Aarch64Macos => "darwin.arm64", + X8664Linux => "linux.amd64", + X8664Macos => "darwin.amd64", + UnknownSystem => bail!("Invalid protoc-gen-go system: {:?}", context.get_target()), + }; + + let version = "1.36.3"; + + context + .add_artifact_source( + "protoc-gen-go", + ArtifactSource { + excludes: vec![], + hash: Some(hash.to_string()), + includes: vec![], + path: format!("https://github.com/protocolbuffers/protobuf-go/releases/download/v{version}/protoc-gen-go.v{version}.{target}.tar.gz"), + }, + ) + .await +} + +pub async fn artifact(context: &mut ConfigContext) -> Result { + let name = "protoc-gen-go"; + + let source = source(context).await?; + + add_artifact( + context, + vec![], + BTreeMap::new(), + name, + formatdoc! {" + mkdir -pv \"$VORPAL_OUTPUT/bin\" + + cp -prv \"source/protoc-gen-go/protoc-gen-go\" \"$VORPAL_OUTPUT/bin/protoc-gen-go\" + + chmod +x \"$VORPAL_OUTPUT/bin/protoc-gen-go\"", + }, + vec![source], + vec![ + "aarch64-linux", + "aarch64-macos", + "x86_64-linux", + "x86_64-macos", + ], + ) + .await +} diff --git a/sdk/rust/src/artifact/protoc_gen_go_grpc.rs b/sdk/rust/src/artifact/protoc_gen_go_grpc.rs new file mode 100644 index 00000000..b33adfaf --- /dev/null +++ b/sdk/rust/src/artifact/protoc_gen_go_grpc.rs @@ -0,0 +1,67 @@ +use crate::{ + artifact::{add_artifact, get_artifact_envkey, go, ArtifactSource}, + context::ConfigContext, +}; +use anyhow::Result; +use indoc::formatdoc; +use std::collections::BTreeMap; +use vorpal_schema::vorpal::artifact::v0::{ArtifactId, ArtifactSourceId}; + +pub async fn source(context: &mut ConfigContext, version: &str) -> Result { + let hash = "eba0f83ab252cffe2c6209f894c4c8238b2473a403bbdbcb985af25140aac95d"; + + context + .add_artifact_source( + "protoc-gen-go-grpc", + ArtifactSource { + excludes: vec![], + hash: Some(hash.to_string()), + includes: vec![], + path: format!( + "https://github.com/grpc/grpc-go/archive/refs/tags/v{}.tar.gz", + version + ), + }, + ) + .await +} + +pub async fn artifact(context: &mut ConfigContext) -> Result { + let go = go::artifact(context).await?; + + let name = "protoc-gen-go-grpc"; + + let version = "1.70.0"; + + let source = source(context, version).await?; + + add_artifact( + context, + vec![go.clone()], + BTreeMap::from([ + ("GOCACHE", "$VORPAL_WORKSPACE/go/cache".to_string()), + ("GOPATH", "$VORPAL_WORKSPACE/go".to_string()), + ("PATH", format!("{}/bin", get_artifact_envkey(&go))), + ]), + name, + formatdoc! {" + pushd ./source/protoc-gen-go-grpc/grpc-go-{version} + + mkdir -p $VORPAL_OUTPUT/bin + + pushd ./cmd/protoc-gen-go-grpc + + go build -o $VORPAL_OUTPUT/bin/protoc-gen-go-grpc . + + go clean -modcache + "}, + vec![source], + vec![ + "aarch64-linux", + "aarch64-macos", + "x86_64-linux", + "x86_64-macos", + ], + ) + .await +} diff --git a/sdk/src/config/artifact/toolchain/rust_analyzer.rs b/sdk/rust/src/artifact/rust_analyzer.rs similarity index 64% rename from sdk/src/config/artifact/toolchain/rust_analyzer.rs rename to sdk/rust/src/artifact/rust_analyzer.rs index c6b0afef..a5bf790e 100644 --- a/sdk/src/config/artifact/toolchain/rust_analyzer.rs +++ b/sdk/rust/src/artifact/rust_analyzer.rs @@ -1,15 +1,19 @@ -use crate::config::{ - artifact::{add_artifact, language::rust::get_toolchain_target, ConfigContext}, - ArtifactSource, +use crate::{ + artifact::{add_artifact, language::rust::get_rust_toolchain_target, ArtifactSource}, + context::ConfigContext, }; use anyhow::{bail, Result}; use std::collections::BTreeMap; use vorpal_schema::vorpal::artifact::v0::{ - ArtifactId, + ArtifactId, ArtifactSourceId, ArtifactSystem::{Aarch64Linux, Aarch64Macos, UnknownSystem, X8664Linux, X8664Macos}, }; -pub async fn artifact(context: &mut ConfigContext, version: &str) -> Result { +pub async fn source( + context: &mut ConfigContext, + target: &str, + version: &str, +) -> Result { let hash = match context.get_target() { Aarch64Linux => "79fbf7077b846a4b28935fa6a22259d589baed2197c08bfc5c362f1e3f54db44", Aarch64Macos => "ba92aa08cdada8fad8d772623b0522cb3d6e659a8edb9e037453fab998772a19", @@ -18,9 +22,27 @@ pub async fn artifact(context: &mut ConfigContext, version: &str) -> Result bail!("Invalid protoc system: {:?}", context.get_target()), }; + context + .add_artifact_source( + "rust-analyzer", + ArtifactSource { + excludes: vec![], + hash: Some(hash.to_string()), + includes: vec![], + path: format!( + "https://static.rust-lang.org/dist/rust-analyzer-{version}-{target}.tar.gz" + ), + }, + ) + .await +} + +pub async fn artifact(context: &mut ConfigContext, version: &str) -> Result { let name = "rust-analyzer"; - let target = get_toolchain_target(context.get_target())?; + let target = get_rust_toolchain_target(context.get_target())?; + + let source = source(context, &target, version).await?; add_artifact( context, @@ -28,15 +50,7 @@ pub async fn artifact(context: &mut ConfigContext, version: &str) -> Result Result { +pub async fn source(context: &mut ConfigContext, version: &str) -> Result { let hash = "5f0adbae49a5442bf3389f7798cbacba92a94b7fefe7810ce00d1356a861d305"; + context + .add_artifact_source( + "rust-src", + ArtifactSource { + excludes: vec![], + hash: Some(hash.to_string()), + includes: vec![], + path: format!("https://static.rust-lang.org/dist/rust-src-{version}.tar.gz"), + }, + ) + .await +} + +pub async fn artifact(context: &mut ConfigContext, version: &str) -> Result { let name = "rust-src"; + let source = source(context, version).await?; + add_artifact( context, vec![], BTreeMap::new(), name, format!("cp -prv \"./source/{name}/{name}-{version}/{name}/.\" \"$VORPAL_OUTPUT\""), - BTreeMap::from([( - name, - ArtifactSource { - excludes: vec![], - hash: Some(hash.to_string()), - includes: vec![], - path: format!("https://static.rust-lang.org/dist/{name}-{version}.tar.gz"), - }, - )]), + vec![source], vec![ "aarch64-linux", "aarch64-macos", diff --git a/sdk/src/config/artifact/toolchain/rust_std.rs b/sdk/rust/src/artifact/rust_std.rs similarity index 65% rename from sdk/src/config/artifact/toolchain/rust_std.rs rename to sdk/rust/src/artifact/rust_std.rs index 36ded36a..c85c9ac3 100644 --- a/sdk/src/config/artifact/toolchain/rust_std.rs +++ b/sdk/rust/src/artifact/rust_std.rs @@ -1,15 +1,19 @@ -use crate::config::{ - artifact::{add_artifact, language::rust::get_toolchain_target, ConfigContext}, - ArtifactSource, +use crate::{ + artifact::{add_artifact, language::rust::get_rust_toolchain_target, ArtifactSource}, + context::ConfigContext, }; use anyhow::{bail, Result}; use std::collections::BTreeMap; use vorpal_schema::vorpal::artifact::v0::{ - ArtifactId, + ArtifactId, ArtifactSourceId, ArtifactSystem::{Aarch64Linux, Aarch64Macos, UnknownSystem, X8664Linux, X8664Macos}, }; -pub async fn artifact(context: &mut ConfigContext, version: &str) -> Result { +pub async fn source( + context: &mut ConfigContext, + target: &str, + version: &str, +) -> Result { let hash = match context.get_target() { Aarch64Linux => "d560efe018be876f2d5a9106f4b37222f0d315f52aeb12ffb0bfbfc8071fc5b1", Aarch64Macos => "6d636e93ec5f9a2e8a7c5bae381dc9a89808087b2eec1f987f8ed5a797fef556", @@ -18,9 +22,27 @@ pub async fn artifact(context: &mut ConfigContext, version: &str) -> Result bail!("Invalid protoc system: {:?}", context.get_target()), }; + context + .add_artifact_source( + "rust-std", + ArtifactSource { + excludes: vec![], + hash: Some(hash.to_string()), + includes: vec![], + path: format!( + "https://static.rust-lang.org/dist/rust-std-{version}-{target}.tar.gz" + ), + }, + ) + .await +} + +pub async fn artifact(context: &mut ConfigContext, version: &str) -> Result { let name = "rust-std"; - let target = get_toolchain_target(context.get_target())?; + let target = get_rust_toolchain_target(context.get_target())?; + + let source = source(context, &target, version).await?; add_artifact( context, @@ -28,15 +50,7 @@ pub async fn artifact(context: &mut ConfigContext, version: &str) -> Result Result { +pub async fn source( + context: &mut ConfigContext, + target: &str, + version: &str, +) -> Result { let hash = match context.get_target() { Aarch64Linux => "f5e5eac428b2a62ffc14324e3a6e171fb3032921f24973b27959834e456388b1", Aarch64Macos => "d022dd6d61a7039c12834f90a0a5410c884bfb9ef1e38b085ad4d3f59a5bf04a", @@ -18,9 +22,25 @@ pub async fn artifact(context: &mut ConfigContext, version: &str) -> Result bail!("Invalid protoc system: {:?}", context.get_target()), }; + context + .add_artifact_source( + "rustc", + ArtifactSource { + excludes: vec![], + hash: Some(hash.to_string()), + includes: vec![], + path: format!("https://static.rust-lang.org/dist/rustc-{version}-{target}.tar.gz"), + }, + ) + .await +} + +pub async fn artifact(context: &mut ConfigContext, version: &str) -> Result { let name = "rustc"; - let target = get_toolchain_target(context.get_target())?; + let target = get_rust_toolchain_target(context.get_target())?; + + let source = source(context, &target, version).await?; add_artifact( context, @@ -30,15 +50,7 @@ pub async fn artifact(context: &mut ConfigContext, version: &str) -> Result Result { +pub async fn source( + context: &mut ConfigContext, + target: &str, + version: &str, +) -> Result { let hash = match context.get_target() { Aarch64Linux => "8a51bcfb496489a5fd6f2042617e84a35301d69325ce558e23589371729c75b2", Aarch64Macos => "4feacdd0fe93196c893a48458f4c3b78bf50a515b2a37a8dd03ce8ba0ef3e065", @@ -18,9 +22,27 @@ pub async fn artifact(context: &mut ConfigContext, version: &str) -> Result bail!("Invalid protoc system: {:?}", context.get_target()), }; + context + .add_artifact_source( + "rustfmt", + ArtifactSource { + excludes: vec![], + hash: Some(hash.to_string()), + includes: vec![], + path: format!( + "https://static.rust-lang.org/dist/rustfmt-{version}-{target}.tar.gz" + ), + }, + ) + .await +} + +pub async fn artifact(context: &mut ConfigContext, version: &str) -> Result { let name = "rustfmt"; - let target = get_toolchain_target(context.get_target())?; + let target = get_rust_toolchain_target(context.get_target())?; + + let source = source(context, &target, version).await?; add_artifact( context, @@ -28,15 +50,7 @@ pub async fn artifact(context: &mut ConfigContext, version: &str) -> Result( restores = restores.join("\n"), unsets = unsets.join("\n"), }, - BTreeMap::new(), + vec![], vec![ "aarch64-linux", "aarch64-macos", diff --git a/sdk/src/config/artifact/steps.rs b/sdk/rust/src/artifact/step.rs similarity index 98% rename from sdk/src/config/artifact/steps.rs rename to sdk/rust/src/artifact/step.rs index eb10fd06..a2844af7 100644 --- a/sdk/src/config/artifact/steps.rs +++ b/sdk/rust/src/artifact/step.rs @@ -1,4 +1,4 @@ -use crate::config::artifact::get_artifact_envkey; +use crate::artifact::get_artifact_envkey; use indoc::formatdoc; use std::collections::BTreeMap; use vorpal_schema::vorpal::artifact::v0::{ArtifactId, ArtifactStep, ArtifactStepEnvironment}; diff --git a/sdk/rust/src/cli.rs b/sdk/rust/src/cli.rs new file mode 100644 index 00000000..1aa1a7e8 --- /dev/null +++ b/sdk/rust/src/cli.rs @@ -0,0 +1,32 @@ +use clap::{Parser, Subcommand}; +use std::env::consts::{ARCH, OS}; +use tracing::Level; + +#[derive(Parser)] +#[command(author, version, about, long_about = None)] +#[command(propagate_version = true)] +pub struct Cli { + #[command(subcommand)] + pub command: Command, +} + +fn get_default_system() -> String { + format!("{}-{}", ARCH, OS) +} + +#[derive(Subcommand)] +pub enum Command { + Start { + #[clap(default_value_t = Level::INFO, global = true, long)] + level: Level, + + #[clap(long, short)] + port: u16, + + #[clap(default_value = "http://localhost:23151", long, short)] + registry: String, + + #[arg(default_value_t = get_default_system(), long, short)] + target: String, + }, +} diff --git a/sdk/src/config/mod.rs b/sdk/rust/src/context.rs similarity index 78% rename from sdk/src/config/mod.rs rename to sdk/rust/src/context.rs index f1bd38bf..04cd25a9 100644 --- a/sdk/src/config/mod.rs +++ b/sdk/rust/src/context.rs @@ -1,17 +1,17 @@ -use crate::config::service::ConfigServer; +use crate::{ + artifact::{ArtifactSource, ArtifactSourceKind}, + cli::{Cli, Command}, +}; use anyhow::{bail, Result}; use async_compression::tokio::bufread::{BzDecoder, GzipDecoder, XzDecoder}; -use clap::{Parser, Subcommand}; -use console::style; +use clap::Parser; use serde::{Deserialize, Serialize}; use sha256::digest; -use std::collections::{BTreeMap, HashMap}; -use std::env::consts::{ARCH, OS}; -use std::path::Path; +use std::{collections::HashMap, path::Path}; use tokio::fs::{remove_dir_all, remove_file, write}; use tokio_tar::Archive; use tonic::{transport::Server, Code::NotFound}; -use tracing::{info, Level}; +use tracing::info; use url::Url; use vorpal_schema::{ get_artifact_system, @@ -20,7 +20,10 @@ use vorpal_schema::{ Artifact, ArtifactBuildRequest, ArtifactId, ArtifactSourceId, ArtifactStep, ArtifactSystem, }, - config::v0::{config_service_server::ConfigServiceServer, Config}, + config::v0::{ + config_service_server::{ConfigService, ConfigServiceServer}, + Config, ConfigRequest, + }, registry::v0::{ registry_service_client::RegistryServiceClient, RegistryKind, RegistryRequest, }, @@ -33,42 +36,6 @@ use vorpal_store::{ temps::{create_sandbox_dir, create_sandbox_file}, }; -pub mod artifact; -pub mod service; - -#[derive(Parser)] -#[command(author, version, about, long_about = None)] -#[command(propagate_version = true)] -pub struct Cli { - #[command(subcommand)] - command: Command, -} - -fn get_default_system() -> String { - format!("{}-{}", ARCH, OS) -} - -fn get_prefix(name: &str) -> String { - style(format!("{} |>", name)).bold().to_string() -} - -#[derive(Subcommand)] -enum Command { - Start { - #[clap(default_value_t = Level::INFO, global = true, long)] - level: Level, - - #[clap(long, short)] - port: u16, - - #[clap(default_value = "http://localhost:23151", long, short)] - registry: String, - - #[arg(default_value_t = get_default_system(), long, short)] - target: String, - }, -} - #[derive(Clone, Debug, Default)] pub struct ConfigContext { pub artifact_id: HashMap, // TOOD: make this private @@ -78,25 +45,48 @@ pub struct ConfigContext { system: ArtifactSystem, } +#[derive(Debug, Default)] +pub struct ConfigServer { + pub config: Config, + pub context: ConfigContext, +} + #[derive(Debug, Serialize, Deserialize)] pub struct ArtifactMetadata { pub system: ArtifactSystem, } -#[derive(Clone, Debug, Deserialize, Serialize)] -pub struct ArtifactSource { - pub excludes: Vec, - pub hash: Option, - pub includes: Vec, - pub path: String, +impl ConfigServer { + pub fn new(context: ConfigContext, config: Config) -> Self { + Self { context, config } + } } -#[derive(Debug, PartialEq)] -pub enum ArtifactSourceKind { - UnknownSourceKind, - Git, - Http, - Local, +#[tonic::async_trait] +impl ConfigService for ConfigServer { + async fn get_config( + &self, + _request: tonic::Request, + ) -> Result, tonic::Status> { + Ok(tonic::Response::new(self.config.clone())) + } + + async fn get_artifact( + &self, + request: tonic::Request, + ) -> Result, tonic::Status> { + let request = request.into_inner(); + + let artifact = self + .context + .get_artifact(request.hash.as_str(), request.name.as_str()); + + if artifact.is_none() { + return Err(tonic::Status::not_found("Artifact input not found")); + } + + Ok(tonic::Response::new(artifact.unwrap().clone())) + } } pub async fn get_context() -> Result { @@ -131,16 +121,71 @@ impl ConfigContext { } } - async fn add_artifact_source( + pub async fn add_artifact_source( &mut self, - artifact_name: &str, source_name: &str, source: ArtifactSource, ) -> Result { - // 1. If source is cached using '--', return the source id + // 1. If source is cached using '-', return the source id + + // TODO: if any paths are relative, they should be expanded to the artifact's source directory + + // 1a. determine the kind of source path + + let source_path_kind = match &source.path { + s if Path::new(s).exists() => ArtifactSourceKind::Local, + s if s.starts_with("git") => ArtifactSourceKind::Git, + s if s.starts_with("http") => ArtifactSourceKind::Http, + _ => ArtifactSourceKind::UnknownSourceKind, + }; + + if source_path_kind == ArtifactSourceKind::UnknownSourceKind { + bail!( + "`source.{}.path` unknown kind: {:?}", + source_name, + source.path + ); + } + + // 1b. process source path + + let mut source = ArtifactSource { + excludes: source.excludes.clone(), + hash: source.hash.clone(), + includes: source.includes.clone(), + path: source.path.clone(), + }; + + if source_path_kind == ArtifactSourceKind::Git { + bail!("`source.{}.path` git not supported", source_name); + } + + if source_path_kind == ArtifactSourceKind::Local { + let local_path = Path::new(&source.path).to_path_buf(); + + if !local_path.exists() { + bail!("`source.{}.path` not found: {:?}", source_name, source.path); + } + + source.path = local_path + .canonicalize() + .map_err(|e| anyhow::anyhow!(e))? + .to_str() + .unwrap() + .to_string(); + + info!( + "{} canonicalized source: {}", + source_name, + local_path.display() + ); + } + + // 1c. process source id let source_json = serde_json::to_string(&source).map_err(|e| anyhow::anyhow!(e))?; - let source_key = format!("{}-{}-{}", artifact_name, source_name, digest(source_json)); + + let source_key = format!("{}-{}", source_name, digest(source_json)); if let Some(source_id) = self.artifact_source_id.get(&source_key) { return Ok(source_id.clone()); @@ -148,14 +193,18 @@ impl ConfigContext { // 2. Check if source exists in registry or local cache + // TODO: check if source is also an empty value + if let Some(hash) = source.hash.clone() { - let artifact_source_id = ArtifactSourceId { + let source_id = ArtifactSourceId { hash: hash.clone(), name: source_name.to_string(), }; // 2a. Check if source exists in the registry + // TODO: put client at higher level with connection pooling + let registry_host = self.registry.clone(); let mut registry = RegistryServiceClient::connect(registry_host.to_owned()) @@ -176,60 +225,31 @@ impl ConfigContext { } Ok(_) => { - info!( - "{} pushed source: {}-{}", - get_prefix(artifact_name), - source_name, - hash - ); + info!("{} pushed source: {}", source_name, hash); self.artifact_source_id - .insert(source_key, artifact_source_id.clone()); + .insert(source_key, source_id.clone()); - return Ok(artifact_source_id); + return Ok(source_id); } } // 2b. Check if source exists in local cache - let cache_archive_path = get_cache_archive_path(&hash, source_name); + let source_cache_archive_path = get_cache_archive_path(&hash, source_name); - if cache_archive_path.exists() { - info!( - "{} cached source: {}-{}", - get_prefix(artifact_name), - source_name, - hash - ); + if source_cache_archive_path.exists() { + info!("{} cached source: {}", source_name, hash); self.artifact_source_id - .insert(source_key, artifact_source_id.clone()); + .insert(source_key, source_id.clone()); - return Ok(artifact_source_id); + return Ok(source_id); } } // 3. Prepare source if not cached - let source_path_kind = match &source.path { - s if Path::new(s).exists() => ArtifactSourceKind::Local, - s if s.starts_with("git") => ArtifactSourceKind::Git, - s if s.starts_with("http") => ArtifactSourceKind::Http, - _ => ArtifactSourceKind::UnknownSourceKind, - }; - - if source_path_kind == ArtifactSourceKind::UnknownSourceKind { - bail!( - "`source.{}.path` unknown kind: {:?}", - source_name, - source.path - ); - } - - if source_path_kind == ArtifactSourceKind::Git { - bail!("`source.{}.path` git not supported", source_name); - } - let source_sandbox_path = create_sandbox_dir().await?; if source_path_kind == ArtifactSourceKind::Http { @@ -249,6 +269,8 @@ impl ConfigContext { ); } + // 3a. Download source + let remote_path = Url::parse(&source.path).map_err(|e| anyhow::anyhow!(e))?; if remote_path.scheme() != "http" && remote_path.scheme() != "https" { @@ -258,11 +280,7 @@ impl ConfigContext { ); } - info!( - "{} downloading source: {}", - get_prefix(artifact_name), - source.path - ); + info!("{} downloading source: {}", source_name, source.path); let remote_response = reqwest::get(remote_path.as_str()) .await @@ -295,13 +313,9 @@ impl ConfigContext { .map_err(|e| anyhow::anyhow!(e))?; } - // Unpack source data + // 3b. Extract source - info!( - "{} unpacking source: {}", - get_prefix(artifact_name), - source.path - ); + info!("{} unpacking source: {}", source_name, source.path); if let Some(kind) = kind { match kind.mime_type() { @@ -377,7 +391,7 @@ impl ConfigContext { info!( "{} copying source: {}", - get_prefix(artifact_name), + source_name, local_path.canonicalize().unwrap().display() ); @@ -411,11 +425,7 @@ impl ConfigContext { set_timestamps(&file_path).await?; } - info!( - "{} hashing source: {}", - get_prefix(artifact_name), - source.path - ); + info!("{} hashing source: {}", source_name, source.path); // 4b. Hash source files @@ -432,11 +442,9 @@ impl ConfigContext { } } - info!( - "{} caching source: {}", - get_prefix(artifact_name), - source.path - ); + // 4c. Cache source + + info!("{} caching source: {}", source_name, source.path); let cache_archive_path = get_cache_archive_path(&source_hash, source_name); @@ -465,21 +473,11 @@ impl ConfigContext { &mut self, name: &str, artifacts: Vec, - source: BTreeMap<&str, ArtifactSource>, + sources: Vec, steps: Vec, systems: Vec<&str>, ) -> Result { - // 1. Setup sources - - let mut sources = vec![]; - - for (source_name, source) in source.into_iter() { - let source = self.add_artifact_source(name, source_name, source).await?; - - sources.push(source); - } - - // 2. Setup systems + // 1. Setup systems let mut systems_int = vec![]; @@ -493,7 +491,7 @@ impl ConfigContext { systems_int.push(system.into()); } - // 3. Setup artifact id + // 2. Setup artifact id let artifact = Artifact { artifacts, diff --git a/sdk/rust/src/lib.rs b/sdk/rust/src/lib.rs new file mode 100644 index 00000000..b318fbd1 --- /dev/null +++ b/sdk/rust/src/lib.rs @@ -0,0 +1,4 @@ +pub mod artifact; +pub mod cli; +pub mod context; +pub mod source; diff --git a/sdk/rust/src/source/mod.rs b/sdk/rust/src/source/mod.rs new file mode 100644 index 00000000..8fd43e50 --- /dev/null +++ b/sdk/rust/src/source/mod.rs @@ -0,0 +1,24 @@ +use crate::{artifact::ArtifactSource, context::ConfigContext}; +use anyhow::Result; +use vorpal_schema::vorpal::artifact::v0::ArtifactSourceId; + +pub async fn go_tools(context: &mut ConfigContext) -> Result { + let hash = "b4faf133f053f372cfe8ea3189bf035d19ca1661cb3ac1e7cd34a465de5641c2"; + + let version = "0.29.0"; + + context + .add_artifact_source( + "go-tools", + ArtifactSource { + excludes: vec![], + hash: Some(hash.to_string()), + includes: vec![], + path: format!( + "https://go.googlesource.com/tools/+archive/refs/tags/v{}.tar.gz", + version + ), + }, + ) + .await +} diff --git a/sdk/src/config/artifact/toolchain/linux/mod.rs b/sdk/src/config/artifact/toolchain/linux/mod.rs deleted file mode 100644 index 95cdfaf8..00000000 --- a/sdk/src/config/artifact/toolchain/linux/mod.rs +++ /dev/null @@ -1,2 +0,0 @@ -pub mod debian; -pub mod vorpal; diff --git a/sdk/src/config/artifact/toolchain/linux/vorpal/source.rs b/sdk/src/config/artifact/toolchain/linux/vorpal/source.rs deleted file mode 100644 index 9e112f62..00000000 --- a/sdk/src/config/artifact/toolchain/linux/vorpal/source.rs +++ /dev/null @@ -1,191 +0,0 @@ -use crate::config::ArtifactSource; - -pub fn curl(version: &str, hash: &str) -> ArtifactSource { - ArtifactSource { - excludes: vec![], - hash: Some(hash.to_string()), - includes: vec![], - path: format!("https://curl.se/download/curl-{version}.tar.xz"), - } -} - -pub fn curl_cacert(hash: &str) -> ArtifactSource { - ArtifactSource { - excludes: vec![], - hash: Some(hash.to_string()), - includes: vec![], - path: "https://curl.se/ca/cacert.pem".to_string(), - } -} - -pub fn file(version: &str, hash: &str) -> ArtifactSource { - ArtifactSource { - excludes: vec![], - hash: Some(hash.to_string()), - includes: vec![], - path: format!("https://astron.com/pub/file/file-{version}.tar.gz"), - } -} - -pub fn gnu(name: &str, version: &str, hash: &str) -> ArtifactSource { - ArtifactSource { - excludes: vec![], - hash: Some(hash.to_string()), - includes: vec![], - path: format!("https://ftpmirror.gnu.org/gnu/{name}/{name}-{version}.tar.gz"), - } -} - -pub fn gnu_xz(name: &str, version: &str, hash: &str) -> ArtifactSource { - ArtifactSource { - excludes: vec![], - hash: Some(hash.to_string()), - includes: vec![], - path: format!("https://ftpmirror.gnu.org/gnu/{name}/{name}-{version}.tar.xz"), - } -} - -pub fn gnu_gcc(version: &str, hash: &str) -> ArtifactSource { - ArtifactSource { - excludes: vec![], - hash: Some(hash.to_string()), - includes: vec![], - path: format!("https://ftpmirror.gnu.org/gnu/gcc/gcc-{version}/gcc-{version}.tar.xz"), - } -} - -pub fn gnu_glibc_patch(version: &str, hash: &str) -> ArtifactSource { - ArtifactSource { - excludes: vec![], - hash: Some(hash.to_string()), - includes: vec![], - path: format!( - "https://www.linuxfromscratch.org/patches/lfs/12.2/glibc-{version}-fhs-1.patch", - ), - } -} - -pub fn libidn2(version: &str, hash: &str) -> ArtifactSource { - ArtifactSource { - excludes: vec![], - hash: Some(hash.to_string()), - includes: vec![], - path: format!("https://ftpmirror.gnu.org/gnu/libidn/libidn2-{version}.tar.gz"), - } -} - -pub fn libpsl(version: &str, hash: &str) -> ArtifactSource { - ArtifactSource { - excludes: vec![], - hash: Some(hash.to_string()), - includes: vec![], - path: format!( - "https://github.com/rockdaboot/libpsl/releases/download/{version}/libpsl-{version}.tar.gz", - ), - } -} - -pub fn linux(version: &str, hash: &str) -> ArtifactSource { - ArtifactSource { - excludes: vec![], - hash: Some(hash.to_string()), - includes: vec![], - path: format!("https://cdn.kernel.org/pub/linux/kernel/v6.x/linux-{version}.tar.xz"), - } -} - -pub fn ncurses(version: &str, hash: &str) -> ArtifactSource { - ArtifactSource { - excludes: vec![], - hash: Some(hash.to_string()), - includes: vec![], - path: format!("https://invisible-mirror.net/archives/ncurses/ncurses-{version}.tar.gz"), - } -} - -pub fn openssl(version: &str, hash: &str) -> ArtifactSource { - ArtifactSource { - excludes: vec![], - hash: Some(hash.to_string()), - includes: vec![], - path: format!("https://www.openssl.org/source/openssl-{version}.tar.gz"), - } -} - -pub fn perl(version: &str, hash: &str) -> ArtifactSource { - ArtifactSource { - excludes: vec![], - hash: Some(hash.to_string()), - includes: vec![], - path: format!("https://www.cpan.org/src/5.0/perl-{version}.tar.xz"), - } -} - -pub fn python(version: &str, hash: &str) -> ArtifactSource { - ArtifactSource { - excludes: vec![], - hash: Some(hash.to_string()), - includes: vec![], - path: format!("https://www.python.org/ftp/python/{version}/Python-{version}.tar.xz"), - } -} - -pub fn unzip_patch_fixes(version: &str, hash: &str) -> ArtifactSource { - ArtifactSource { - excludes: vec![], - hash: Some(hash.to_string()), - includes: vec![], - path: format!("https://www.linuxfromscratch.org/patches/blfs/12.2/unzip-{version}-consolidated_fixes-1.patch"), - } -} - -pub fn unzip_patch_gcc14(version: &str, hash: &str) -> ArtifactSource { - ArtifactSource { - excludes: vec![], - hash: Some(hash.to_string()), - includes: vec![], - path: format!( - "https://www.linuxfromscratch.org/patches/blfs/12.2/unzip-{version}-gcc14-1.patch" - ), - } -} - -pub fn unzip(version: &str, hash: &str) -> ArtifactSource { - let version = version.replace(".", ""); - - ArtifactSource { - excludes: vec![], - hash: Some(hash.to_string()), - includes: vec![], - path: format!("https://cfhcable.dl.sourceforge.net/project/infozip/UnZip%206.x%20%28latest%29/UnZip%206.0/unzip{version}.tar.gz?viasf=1",), - } -} - -pub fn util_linux(version: &str, hash: &str) -> ArtifactSource { - ArtifactSource { - excludes: vec![], - hash: Some(hash.to_string()), - includes: vec![], - path: format!( - "https://www.kernel.org/pub/linux/utils/util-linux/v2.40/util-linux-{version}.tar.xz" - ), - } -} - -pub fn xz(version: &str, hash: &str) -> ArtifactSource { - ArtifactSource { - excludes: vec![], - hash: Some(hash.to_string()), - includes: vec![], - path: format!("https://github.com/tukaani-project/xz/releases/download/v{version}/xz-{version}.tar.xz"), - } -} - -pub fn zlib(version: &str, hash: &str) -> ArtifactSource { - ArtifactSource { - excludes: vec![], - hash: Some(hash.to_string()), - includes: vec![], - path: format!("https://zlib.net/fossils/zlib-{version}.tar.gz"), - } -} diff --git a/sdk/src/config/artifact/toolchain/mod.rs b/sdk/src/config/artifact/toolchain/mod.rs deleted file mode 100644 index 54ad22dc..00000000 --- a/sdk/src/config/artifact/toolchain/mod.rs +++ /dev/null @@ -1,9 +0,0 @@ -pub mod cargo; -pub mod clippy; -pub mod linux; -pub mod protoc; -pub mod rust_analyzer; -pub mod rust_src; -pub mod rust_std; -pub mod rustc; -pub mod rustfmt; diff --git a/sdk/src/config/service.rs b/sdk/src/config/service.rs deleted file mode 100644 index a147e744..00000000 --- a/sdk/src/config/service.rs +++ /dev/null @@ -1,45 +0,0 @@ -use crate::config::ConfigContext; -use anyhow::Result; -use vorpal_schema::vorpal::{ - artifact::v0::{Artifact, ArtifactId}, - config::v0::{config_service_server::ConfigService, Config, ConfigRequest}, -}; - -#[derive(Debug, Default)] -pub struct ConfigServer { - pub context: ConfigContext, - pub config: Config, -} - -impl ConfigServer { - pub fn new(context: ConfigContext, config: Config) -> Self { - Self { context, config } - } -} - -#[tonic::async_trait] -impl ConfigService for ConfigServer { - async fn get_config( - &self, - _request: tonic::Request, - ) -> Result, tonic::Status> { - Ok(tonic::Response::new(self.config.clone())) - } - - async fn get_artifact( - &self, - request: tonic::Request, - ) -> Result, tonic::Status> { - let request = request.into_inner(); - - let artifact = self - .context - .get_artifact(request.hash.as_str(), request.name.as_str()); - - if artifact.is_none() { - return Err(tonic::Status::not_found("Artifact input not found")); - } - - Ok(tonic::Response::new(artifact.unwrap().clone())) - } -} diff --git a/sdk/src/lib.rs b/sdk/src/lib.rs deleted file mode 100644 index ef68c369..00000000 --- a/sdk/src/lib.rs +++ /dev/null @@ -1 +0,0 @@ -pub mod config; diff --git a/vorpal-purpose.jpg b/vorpal-purpose.jpg index 5c41d7cd..369435bd 100644 Binary files a/vorpal-purpose.jpg and b/vorpal-purpose.jpg differ