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
1,039 changes: 559 additions & 480 deletions Cargo.lock

Large diffs are not rendered by default.

6 changes: 5 additions & 1 deletion crates/wasm-pkg-client/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,9 @@ pub struct PublishOpts {
pub package: Option<(PackageRef, Version)>,
/// Override the registry to publish to.
pub registry: Option<Registry>,
/// If true, resolve the package, version, and registry but do not call the
/// backend to publish.
pub dry_run: bool,
}

/// A read-only registry client.
Expand Down Expand Up @@ -181,8 +184,9 @@ impl Client {
let source = self
.resolve_source(&package, additional_options.registry)
.await?;

source
.publish(&package, &version, data)
.publish(&package, &version, data, additional_options.dry_run)
.await
.map(|_| (package, version))
}
Expand Down
4 changes: 4 additions & 0 deletions crates/wasm-pkg-client/src/local.rs
Original file line number Diff line number Diff line change
Expand Up @@ -112,11 +112,15 @@ impl PackagePublisher for LocalBackend {
package: &PackageRef,
version: &Version,
mut data: PublishingSource,
dry_run: bool,
) -> Result<(), Error> {
let package_dir = self.package_dir(package);
// Ensure the package directory exists.
tokio::fs::create_dir_all(package_dir).await?;
let path = self.version_path(package, version);
if dry_run {
return Ok(());
}
let mut out = tokio::fs::File::create(path).await?;
tokio::io::copy(&mut data, &mut out)
.await
Expand Down
7 changes: 7 additions & 0 deletions crates/wasm-pkg-client/src/oci/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,13 @@ impl OciBackend {
Ok(auth)
})
.await
.map_err(|e| {
if let Error::RegistryError(anyhow_err) = e {
Error::RegistryError(anyhow_err.context(reference.repository().to_owned()))
} else {
e
}
})
.cloned()
}

Expand Down
11 changes: 7 additions & 4 deletions crates/wasm-pkg-client/src/oci/publisher.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ impl PackagePublisher for OciBackend {
package: &PackageRef,
version: &Version,
mut data: PublishingSource,
dry_run: bool,
) -> Result<(), crate::Error> {
// NOTE(thomastaylor312): oci-client doesn't support publishing from a stream or reader, so
// we have to read all the data in for now. Once we can address that upstream, we'll be able
Expand Down Expand Up @@ -64,10 +65,12 @@ impl PackagePublisher for OciBackend {

let reference: Reference = self.make_reference(package, Some(version));
let auth = self.auth(&reference, RegistryOperation::Push).await?;
self.client
.push(&reference, &auth, layer, config, Some(annotations))
.await
.map_err(crate::Error::RegistryError)?;
if !dry_run {
self.client
.push(&reference, &auth, layer, config, Some(annotations))
.await
.map_err(crate::Error::RegistryError)?;
}
Ok(())
}
}
1 change: 1 addition & 0 deletions crates/wasm-pkg-client/src/publisher.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,6 @@ pub trait PackagePublisher: Send + Sync {
package: &PackageRef,
version: &Version,
data: PublishingSource,
dry_run: bool,
) -> Result<(), crate::Error>;
}
5 changes: 5 additions & 0 deletions crates/wasm-pkg-client/src/warg/publisher.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ impl PackagePublisher for WargBackend {
package: &PackageRef,
version: &Version,
data: PublishingSource,
dry_run: bool,
) -> Result<(), crate::Error> {
// store the Wasm in Warg cache, so that it is available to Warg client for uploading
let content = self
Expand All @@ -37,6 +38,10 @@ impl PackagePublisher for WargBackend {
// convert package name to Warg package name
let name = super::package_ref_to_name(package)?;

if dry_run {
return Ok(());

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Totally fine if you don't want to make this change but for dry runs I've found it can be nice to model them as an error variant, e.g.

Suggested change
return Ok(());
return Err(Error::DryRun);

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm following cargo publish --dry-run logic as much as possible and they seem to throw an exit code of zero.

I also use cargo publish dry runs as CI steps that would abort on exit code so this would cause issues if one wanted to check that a current commit/PR would be able to publish.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah you would catch the varient down-stack and exit 0. Anyway definitely not a blocker.

}

// start Warg publish, using the keyring to sign
let version = version.clone();
let info = PublishInfo {
Expand Down
1 change: 1 addition & 0 deletions crates/wasm-pkg-common/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ sha2 = { workspace = true }
tokio = { workspace = true, optional = true, features = ["fs"] }
toml = { workspace = true, optional = true }
thiserror = { workspace = true }
tracing.workspace = true

[dev-dependencies]
tokio = { workspace = true, features = ["macros", "rt"] }
2 changes: 2 additions & 0 deletions crates/wasm-pkg-common/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,8 @@ impl Config {
Some(path) => path,
None => return Ok(None),
};

tracing::debug!(path = %path.display(), "using global config");
let contents = match tokio::fs::read_to_string(&path).await {
Ok(contents) => contents,
Err(err) if err.kind() == ErrorKind::NotFound => return Ok(None),
Expand Down
1 change: 1 addition & 0 deletions crates/wasm-pkg-core/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ pub struct Config {
impl Config {
/// Loads a configuration file from the given path.
pub async fn load_from_path(path: impl AsRef<Path>) -> Result<Config> {
tracing::info!(path = %path.as_ref().display(), "loading wkg config file");

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is unfortunate that the tracing deps has to be added for this line but it was particularly valuable to have visibility in what file actually gets resolved here.

let contents = tokio::fs::read_to_string(path)
.await
.context("unable to load config from file")?;
Expand Down
3 changes: 2 additions & 1 deletion crates/wasm-pkg-core/src/resolver.rs
Original file line number Diff line number Diff line change
Expand Up @@ -530,7 +530,8 @@ impl<'a> DependencyResolver<'a> {
} else {
let versions =
load_package(&mut self.packages, &self.client, dependency.package.clone())
.await?
.await
.with_context(|| format!("package: {}", dependency.package.clone()))?

@lann lann Jun 2, 2026

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like a dupe with the next line?

Suggested change
.with_context(|| format!("package: {}", dependency.package.clone()))?

@mkatychev mkatychev Jun 2, 2026

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I thought so too, but if you look, the next line is actually an option because load_package returns Result<Option<T>> so the added with_context is if the loading logic failed rather than if the package exists (this issue I specifically ran into).

async fn load_package<'b>(
packages: &'b mut HashMap<PackageRef, Vec<VersionInfo>>,
client: &CachingClient<FileCache>,
package: PackageRef,
) -> Result<Option<&'b Vec<VersionInfo>>> {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah confusing!

.with_context(|| {
format!(
"package `{name}` was not found in component registry",
Expand Down
8 changes: 5 additions & 3 deletions crates/wasm-pkg-core/src/wit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ pub async fn build_package(
) -> Result<(PackageRef, Option<Version>, Vec<u8>)> {
let dependencies = resolve_dependencies(config, &wit_dir, Some(lock_file), client)
.await
.with_context(|| format!("wit_dir: {}", wit_dir.as_ref().display()))
.context("Unable to resolve dependencies")?;

lock_file.update_dependencies(&dependencies);
Expand Down Expand Up @@ -179,16 +180,17 @@ pub async fn resolve_dependencies(
let mut resolver = DependencyResolver::new_with_client(client, lock_file)?;
// add deps from config first in case they're local deps and then add deps from the directory
if let Some(overrides) = config.overrides.as_ref() {
tracing::debug!("detected config overrides");
for (pkg, ovr) in overrides.iter() {
let pkg: PackageRef = pkg.parse().context("Unable to parse as a package ref")?;
let dep = match (ovr.path.as_ref(), ovr.version.as_ref()) {
(Some(path), v) => {
if v.is_some() {
tracing::warn!("Ignoring version override for local package");
}
let path = tokio::fs::canonicalize(path)
.await
.with_context(|| format!("resolving local dependency {}", path.display()))?;
let path = tokio::fs::canonicalize(path).await.with_context(|| {
format!("resolving local dependency {}", path.display())
})?;
Dependency::Local(path)
}
(None, Some(version)) => Dependency::Package(RegistryPackage {
Expand Down
12 changes: 11 additions & 1 deletion crates/wkg/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ impl Common {
/// Helper to load the config from the given path
pub async fn load_config(&self) -> anyhow::Result<Config> {
if let Some(config_file) = self.config.as_ref() {
tracing::info!(config = %config_file.display());
Config::from_file(config_file)
.await
.context(format!("error loading config file {config_file:?}"))
Expand Down Expand Up @@ -237,6 +238,10 @@ struct PublishArgs {
#[arg(long, env = "WKG_PACKAGE")]
package: Option<PackageSpec>,

/// Attempt package, version, and registry resolution without publishing.
#[arg(long)]
dry_run: bool,

#[command(flatten)]
common: Common,
}
Expand All @@ -262,10 +267,15 @@ impl PublishArgs {
PublishOpts {
package,
registry: self.registry_args.registry,
dry_run: self.dry_run,
},
)
.await?;
println!("Published {}@{}", package, version);
if self.dry_run {
println!("Aborting publish due to dry run: {}@{}", package, version);
} else {
println!("Published {}@{}", package, version);
}
Ok(())
}
}
Expand Down
Loading