diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index d11465d..b6da14d 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -12,28 +12,56 @@ env: RUSTFLAGS: "-Dwarnings" jobs: - check-linux: - name: check-linux - runs-on: ubuntu-latest + lint-and-test: + name: Run linters and tests + strategy: + matrix: + platform: + - os_name: Linux-x86_64 + os: ubuntu-latest + target: x86_64-unknown-linux-musl + bin: coman + name: coman-Linux-x86_64-musl.tar.gz + cargo_command: cargo + + - os_name: Windows-aarch64 + os: windows-latest + target: aarch64-pc-windows-msvc + bin: coman.exe + name: coman-Windows-aarch64.zip + cargo_command: cargo + + # enable this if there's ever a case where something works on linux but not on macos + # - os_name: macOS-x86_64 + # os: macOS-latest + # target: x86_64-apple-darwin + # bin: coman + # name: coman-Darwin-x86_64.tar.gz + # cargo_command: cargo + runs-on: ${{ matrix.platform.os }} steps: - name: Checkout uses: actions/checkout@v5 - - name: setup rust - run: | - rustup update stable - rustup default stable - rustup component add --toolchain nightly-x86_64-unknown-linux-gnu rustfmt + - name: Install toolchain + # nightly needed for cargo fmt + uses: dtolnay/rust-toolchain@nightly + with: + targets: ${{ matrix.platform.target }} + components: clippy rustfmt - name: Rust cache uses: Swatinem/rust-cache@v2 with: prefix-key: "v0-rust" + cache-workspace-crates: "true" - name: install tooling run: cargo install oas3-gen@0.21.1 - name: Build run: cargo build --verbose - name: Check formatting + if: contains(matrix.platform.os, 'ubuntu') run: cargo +nightly fmt --check - name: Lint + if: contains(matrix.platform.os, 'ubuntu') run: cargo clippy --all-targets --all-features -p coman - name: Test run: cargo test --verbose diff --git a/Cargo.lock b/Cargo.lock index 0366a15..7a55fb0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1039,6 +1039,7 @@ dependencies = [ "pretty_assertions", "ratatui", "reqwest", + "rstest", "serde", "serde_json", "signal-hook", @@ -2090,6 +2091,12 @@ version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" +[[package]] +name = "futures-timer" +version = "3.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f288b0a4f20f9a56b5d1da57e2227c661b7b16168e2f72365f57b63326e29b24" + [[package]] name = "futures-util" version = "0.3.31" @@ -2974,6 +2981,12 @@ dependencies = [ "gix-validate 0.9.4", ] +[[package]] +name = "glob" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0cc23270f6e1808e30a928bdc84dea0b9b4136a8bc82338574f23baf47bbd280" + [[package]] name = "globset" version = "0.4.18" @@ -5140,6 +5153,12 @@ version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "caf4aa5b0f434c91fe5c7f1ecb6a5ece2130b02ad2a590589dda5146df959001" +[[package]] +name = "relative-path" +version = "1.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba39f3699c378cd8970968dcbff9c43159ea4cfbd88d43c00b22f2ef10a435d2" + [[package]] name = "reqwest" version = "0.12.24" @@ -5255,6 +5274,35 @@ dependencies = [ "zeroize", ] +[[package]] +name = "rstest" +version = "0.26.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f5a3193c063baaa2a95a33f03035c8a72b83d97a54916055ba22d35ed3839d49" +dependencies = [ + "futures-timer", + "futures-util", + "rstest_macros", +] + +[[package]] +name = "rstest_macros" +version = "0.26.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c845311f0ff7951c5506121a9ad75aec44d083c31583b2ea5a30bcb0b0abba0" +dependencies = [ + "cfg-if", + "glob", + "proc-macro-crate", + "proc-macro2", + "quote", + "regex", + "relative-path", + "rustc_version", + "syn 2.0.108", + "unicode-ident", +] + [[package]] name = "rust-ini" version = "0.20.0" diff --git a/coman/Cargo.toml b/coman/Cargo.toml index 1df5954..62f5258 100644 --- a/coman/Cargo.toml +++ b/coman/Cargo.toml @@ -76,3 +76,6 @@ aws-sdk-s3 = "1.115.0" [build-dependencies] anyhow = "1.0.90" vergen-gix = { version = "1.0.2", features = ["build", "cargo"] } + +[dev-dependencies] +rstest = "0.26.1" diff --git a/coman/src/util/types.rs b/coman/src/util/types.rs index d228ea6..17b011b 100644 --- a/coman/src/util/types.rs +++ b/coman/src/util/types.rs @@ -9,7 +9,7 @@ use nom::{ bytes::tag, character::complete::{alphanumeric1, digit1}, combinator::{complete, opt, recognize}, - multi::separated_list1, + multi::{many_m_n, many1, separated_list0, separated_list1}, sequence::{preceded, terminated}, }; use oci_distribution::{ @@ -127,18 +127,31 @@ impl FromStr for DockerImageUrl { type Err = Report; fn from_str(s: &str) -> Result { - let mut parser = complete(( - opt(terminated( + // see https://ktomk.github.io/pipelines/doc/DOCKER-NAME-TAG.html#syntax + let host = opt(terminated( + alt(( + recognize((separated_list1(tag("."), alphanumeric1), tag(":"), digit1)), + recognize(separated_list1(tag("."), alphanumeric1)), + )), + tag("/"), + )); + let image = recognize(separated_list0( + tag("/"), + separated_list0( alt(( - recognize((separated_list1(tag("."), alphanumeric1), tag(":"), digit1)), - recognize(separated_list1(tag("."), alphanumeric1)), + tag("."), + recognize(many_m_n(1, 2, tag("_"))), + recognize(many1(tag("-"))), )), - tag("/"), - )), - alt((recognize((alphanumeric1, tag("/"), alphanumeric1)), alphanumeric1)), - opt(preceded(tag(":"), alphanumeric1)), - opt(preceded(tag("@sha256:"), alphanumeric1)), + alphanumeric1, + ), + )); + let docker_tag = opt(preceded( + tag(":"), + recognize(separated_list0(alt((tag("."), tag("-"))), alphanumeric1)), )); + let digest = opt(preceded(tag("@sha256:"), alphanumeric1)); + let mut parser = complete((host, image, docker_tag, digest)); let parsed: DockerParseType = parser.parse(s); match parsed { Ok(result) => Ok(DockerImageUrl { @@ -178,3 +191,26 @@ impl Display for DockerImageUrl { Ok(()) } } + +#[cfg(test)] +mod tests { + use rstest::rstest; + + use super::*; + + #[rstest] + #[case("ubuntu",(None,"ubuntu",None,None))] + #[case("docker.io/library/hello-world:latest@sha256:deadbeef",(Some("docker.io"),"library/hello-world",Some("latest"),Some("deadbeef")))] + #[case("ghcr.io/swissdatasciencecenter/renku-frontend-buildpacks/run-image:0.2.1",(Some("ghcr.io"),"swissdatasciencecenter/renku-frontend-buildpacks/run-image",Some("0.2.1"),None))] + #[case("test.ghcr.io/a/b/c/d/e:a-1.f-2", (Some("test.ghcr.io"), "a/b/c/d/e", Some("a-1.f-2"), None))] + fn test_docker_parsing( + #[case] docker_url: &str, + #[case] expected: (Option<&str>, &str, Option<&str>, Option<&str>), + ) { + let image = DockerImageUrl::from_str(docker_url).expect("couldn't parse image"); + assert_eq!(image.registry, expected.0.map(|s| s.to_owned())); + assert_eq!(image.image.as_str(), expected.1); + assert_eq!(image.tag, expected.2.map(|s| s.to_owned())); + assert_eq!(image.digest, expected.3.map(|s| s.to_owned())); + } +} diff --git a/firecrest_client/src/types.rs b/firecrest_client/src/types.rs index 3421724..5c6e9e1 100644 --- a/firecrest_client/src/types.rs +++ b/firecrest_client/src/types.rs @@ -9,7 +9,7 @@ //! AUTO-GENERATED CODE - DO NOT EDIT! //! //! FirecREST -//! Source: /tmp/.tmprFbIr1.json +//! Source: /tmp/.tmppwtkBD.json //! Version: 2.4.1 //! Generated by `oas3-gen v0.21.1` //!