Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ jobs:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
with:
targets: "wasm32-wasi"
targets: "wasm32-wasip1"
# We have to run these separately so we can deactivate a feature for one of the tests
- name: Run client tests
working-directory: ./crates/wasm-pkg-client
Expand Down
105 changes: 95 additions & 10 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 3 additions & 3 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,6 @@ tracing-subscriber = { version = "0.3.18", default-features = false, features =
wasm-pkg-common = { version = "0.9.0", path = "crates/wasm-pkg-common" }
wasm-pkg-client = { version = "0.9.0", path = "crates/wasm-pkg-client" }
wasm-pkg-core = { version = "0.9.0", path = "crates/wasm-pkg-core" }
wasm-metadata = "0.219"
wit-component = "0.219"
wit-parser = "0.219"
wasm-metadata = "0.224"
wit-component = "0.224"
wit-parser = "0.224"
58 changes: 26 additions & 32 deletions crates/wasm-pkg-client/src/oci/publisher.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ use std::collections::BTreeMap;

use oci_client::{Reference, RegistryOperation};
use tokio::io::AsyncReadExt;
use wasm_metadata::LinkType;

use crate::publisher::PackagePublisher;
use crate::{PackageRef, PublishingSource, Version};
Expand All @@ -22,44 +21,39 @@ impl PackagePublisher for OciBackend {
// to remove this and use the stream directly.
let mut buf = Vec::new();
data.read_to_end(&mut buf).await?;
let meta = wasm_metadata::RegistryMetadata::from_wasm(&buf).map_err(|e| {
crate::Error::InvalidComponent(anyhow::anyhow!("Unable to parse component: {e}"))
let payload = wasm_metadata::Payload::from_binary(&buf).map_err(|e| {
crate::Error::InvalidComponent(anyhow::anyhow!("Unable to parse WASM: {e}"))
})?;
let meta = payload.metadata();
let (config, layer) = oci_wasm::WasmConfig::from_raw_component(buf, None)
.map_err(crate::Error::InvalidComponent)?;
let mut annotations = BTreeMap::from_iter([(
"org.opencontainers.image.version".to_string(),
version.to_string(),
)]);
if let Some(meta) = meta {
if let Some(desc) = meta.get_description() {
annotations.insert(
"org.opencontainers.image.description".to_string(),
desc.to_owned(),
);
}
if let Some(licenses) = meta.get_license() {
annotations.insert(
"org.opencontainers.image.licenses".to_string(),
licenses.to_owned(),
);
}
if let Some(sources) = meta.get_links() {
for link in sources {
if link.ty == LinkType::Repository {
annotations.insert(
"org.opencontainers.image.source".to_string(),
link.value.to_owned(),
);
}
if link.ty == LinkType::Homepage {
annotations.insert(
"org.opencontainers.image.url".to_string(),
link.value.to_owned(),
);
}
}
}
if let Some(desc) = &meta.description {
annotations.insert(
"org.opencontainers.image.description".to_string(),
desc.to_string(),
);
}
if let Some(licenses) = &meta.licenses {
annotations.insert(
"org.opencontainers.image.licenses".to_string(),
licenses.to_string(),
);
}
if let Some(source) = &meta.source {
annotations.insert(
"org.opencontainers.image.source".to_string(),
source.to_string(),
);
}
if let Some(homepage) = &meta.homepage {
annotations.insert(
"org.opencontainers.image.url".to_string(),
homepage.to_string(),
);
}

let reference: Reference = self.make_reference(package, Some(version));
Expand Down
69 changes: 18 additions & 51 deletions crates/wasm-pkg-core/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,14 @@ use anyhow::{Context, Result};
use semver::VersionReq;
use serde::{Deserialize, Serialize};
use tokio::io::AsyncWriteExt;
use wasm_metadata::{Link, LinkType, RegistryMetadata};

/// The default name of the configuration file.
pub const CONFIG_FILE_NAME: &str = "wkg.toml";

/// The structure for a wkg.toml configuration file. This file is entirely optional and is used for
/// overriding and annotating wasm packages.
#[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq, Eq)]
#[serde(deny_unknown_fields)]
pub struct Config {
/// Overrides for various packages
#[serde(default, skip_serializing_if = "Option::is_none")]
Expand Down Expand Up @@ -60,6 +60,7 @@ impl Config {
}

#[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq, Eq)]
#[serde(deny_unknown_fields)]
pub struct Override {
/// A path to the package on disk. If this is set, the package will be loaded from the given
/// path. If this is not set, the package will be loaded from the registry.
Expand All @@ -72,59 +73,26 @@ pub struct Override {
}

#[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq, Eq)]
#[serde(deny_unknown_fields)]
pub struct Metadata {
/// The authors of the package.
/// The author(s) of the package.
#[serde(default, skip_serializing_if = "Option::is_none")]
pub authors: Option<Vec<String>>,
/// The categories of the package.
#[serde(default, skip_serializing_if = "Option::is_none")]
pub categories: Option<Vec<String>>,
pub author: Option<String>,
/// The package description.
#[serde(default, skip_serializing_if = "Option::is_none")]
pub description: Option<String>,
/// The package license.
#[serde(default, skip_serializing_if = "Option::is_none")]
pub license: Option<String>,
/// The package documentation URL.
#[serde(default, skip_serializing_if = "Option::is_none")]
pub documentation: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none", alias = "license")]
pub licenses: Option<String>,
/// The package source code URL.
#[serde(default, skip_serializing_if = "Option::is_none", alias = "repository")]
pub source: Option<String>,
/// The package homepage URL.
#[serde(default, skip_serializing_if = "Option::is_none")]
pub homepage: Option<String>,
/// The package repository URL.
/// The package source control revision.
#[serde(default, skip_serializing_if = "Option::is_none")]
pub repository: Option<String>,
}

impl From<Metadata> for wasm_metadata::RegistryMetadata {
fn from(value: Metadata) -> Self {
let mut meta = RegistryMetadata::default();
meta.set_authors(value.authors);
meta.set_categories(value.categories);
meta.set_description(value.description);
meta.set_license(value.license);
let mut links = Vec::new();
if let Some(documentation) = value.documentation {
links.push(Link {
ty: LinkType::Documentation,
value: documentation,
});
}
if let Some(homepage) = value.homepage {
links.push(Link {
ty: LinkType::Homepage,
value: homepage,
});
}
if let Some(repository) = value.repository {
links.push(Link {
ty: LinkType::Repository,
value: repository,
});
}
meta.set_links((!links.is_empty()).then_some(links));
meta
}
pub revision: Option<String>,
}

#[cfg(test)]
Expand All @@ -144,13 +112,12 @@ mod tests {
},
)])),
metadata: Some(Metadata {
authors: Some(vec!["foo".to_string(), "bar".to_string()]),
categories: Some(vec!["foo".to_string(), "bar".to_string()]),
description: Some("foo".to_string()),
license: Some("foo".to_string()),
documentation: Some("foo".to_string()),
homepage: Some("foo".to_string()),
repository: Some("foo".to_string()),
author: Some("Foo Bar".to_string()),
description: Some("Foobar baz".to_string()),
licenses: Some("FBB".to_string()),
source: Some("https://gitfoo/bar".to_string()),
homepage: Some("https://foo.bar".to_string()),
revision: Some("f00ba4".to_string()),
}),
};

Expand Down
Loading