Skip to content
Open
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 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ All notable changes to this project will be documented in this file.

# Unreleased

- Rename `resolved_schema_uri` to `resolved_registry_uri` in publication manifest and in `package` command. ([#1425](https://github.com/open-telemetry/weaver/pull/1425))
- Fix V2 resolver overwriting `SpanName.note` with the span type id during resolution. ([#1401](https://github.com/open-telemetry/weaver/pull/1401))
- New feature ([#1344](https://github.com/open-telemetry/weaver/issues/1344)) - Support authenticated HTTP downloads of remote registries, including GitHub private release assets. Auth is configured per-URL via `[[auth]]` entries in `.weaver.toml` (longest `url_prefix` wins), with tokens sourced from a literal `token`, a `token_env` variable, or a `token_command` helper (e.g. `["gh", "auth", "token"]`). ([#1356](https://github.com/open-telemetry/weaver/pull/1356) by @jerbly)
- New feature - `.weaver.toml` project configuration now covers all subcommands allowing for simplified configuration management. See the [README.md](https://github.com/open-telemetry/weaver/blob/main/crates/weaver_config/README.md) ([#1410](https://github.com/open-telemetry/weaver/pull/1410) by @jerbly)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
file_format: manifest/2.0
stability: stable
schema_url: https://opentelemetry.io/schemas/1.0.0
resolved_schema_uri: resolved_schema.yaml
resolved_registry_uri: resolved_schema.yaml
description: Test repository that has been resolved.
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
file_format: manifest/2.0
stability: stable
schema_url: https://opentelemetry.io/schemas/1.0.0
resolved_schema_uri: resolved_schema.yaml
resolved_registry_uri: resolved_schema.yaml
description: Test repository that has been resolved.
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
file_format: manifest/2.0
stability: stable
schema_url: https://example.com/schemas/1.2.3
resolved_schema_uri: resolved_schema.yaml
resolved_registry_uri: resolved_schema.yaml
description: Test repository that has been resolved.
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,4 @@ dependencies:
- schema_url: https://server.example.com/schemas/1.0.0
registry_path: data/registry-test-v2-dep/published
stability: development
resolved_schema_uri: resolved.yaml
resolved_registry_uri: resolved.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@ file_format: manifest/2.0
schema_url: https://server.example.com/schemas/1.0.0
description: Server semantic conventions.
stability: development
resolved_schema_uri: resolved.yaml
resolved_registry_uri: resolved.yaml
2 changes: 1 addition & 1 deletion crates/weaver_resolver/src/loader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -227,7 +227,7 @@ fn load_semconv_repository_recursive(

// Either load a fully resolved repository, or read in raw files.
if let Some(manifest) = registry_repo.manifest() {
if let Some(resolved_url) = registry_repo.resolved_schema_uri() {
if let Some(resolved_url) = registry_repo.resolved_registry_uri() {
let res = load_resolved_repository(&resolved_url, auth);
let _ = dependency_chain.pop();
res
Expand Down
161 changes: 132 additions & 29 deletions crates/weaver_semconv/src/manifest.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
//! Two manifest types are defined here:
//! - [`DefinitionRegistryManifest`]: the definition manifest for an unpublished registry
//! - [`PublicationRegistryManifest`]: the publication manifest produced by `weaver registry package`
//! (strict, always includes `resolved_schema_uri`).
//! (strict, always includes `resolved_registry_uri`).
//! - [`RegistryManifest`]: an enum discriminated by `file_format` that can be either

use std::vec;
Expand Down Expand Up @@ -159,6 +159,8 @@ struct RawManifestFields {
dependencies: Vec<Dependency>,
#[serde(default)]
stability: Stability,
resolved_registry_uri: Option<String>,
/// Deprecated alias for `resolved_registry_uri`.
resolved_schema_uri: Option<String>,
}

Expand All @@ -172,19 +174,32 @@ impl RawManifestFields {
path: path.to_path_buf(),
details: "missing required field 'schema_url'".into(),
})?;
let resolved_schema_uri =
self.resolved_schema_uri
.ok_or_else(|| Error::InvalidPublicationManifest {
let mut warnings = vec![];
let resolved_registry_uri = match (self.resolved_registry_uri, self.resolved_schema_uri)
{
(Some(v), _) => v,
(None, Some(v)) => {
warnings.push(
"The 'resolved_schema_uri' field is deprecated in favor of 'resolved_registry_uri'."
.to_owned(),
);
v
}
(None, None) => {
return Err(Error::InvalidPublicationManifest {
path: path.to_path_buf(),
details: "missing required field 'resolved_schema_uri'".into(),
})?;
details: "missing required field 'resolved_registry_uri'".into(),
});
}
};
Ok(RegistryManifest::Publication(PublicationRegistryManifest {
file_format: PUBLICATION_MANIFEST_FILE_FORMAT.to_owned(),
schema_url,
description: self.description,
dependencies: self.dependencies,
stability: self.stability,
resolved_schema_uri,
resolved_registry_uri,
deserialization_warnings: warnings,
}))
} else {
let mut warnings = vec![];
Expand Down Expand Up @@ -286,14 +301,18 @@ impl RegistryManifest {
});
}

if let RegistryManifest::Definition(ref def) = manifest {
nfes.extend(def.deserialization_warnings.iter().map(|w| {
DeprecatedSyntaxInRegistryManifest {
let deserialization_warnings = match &manifest {
RegistryManifest::Definition(def) => def.deserialization_warnings.as_slice(),
RegistryManifest::Publication(pubm) => pubm.deserialization_warnings.as_slice(),
};
nfes.extend(
deserialization_warnings
.iter()
.map(|w| DeprecatedSyntaxInRegistryManifest {
path: manifest_path_buf.clone(),
error: w.clone(),
}
}));
}
}),
);

Ok(manifest)
}
Expand Down Expand Up @@ -332,7 +351,8 @@ impl RegistryManifest {
/// Represents the publication manifest for a packaged semantic convention registry.
///
/// This is produced by `weaver registry package` and describes the contents of
/// a self-contained registry artifact, including its resolved schema location.
/// a self-contained registry artifact, including the URI of the resolved
/// registry artifact (`resolved.yaml`).
#[derive(Serialize, Deserialize, Debug, Clone, JsonSchema)]
pub struct PublicationRegistryManifest {
/// The file format version of this publication manifest.
Expand All @@ -356,25 +376,30 @@ pub struct PublicationRegistryManifest {
#[serde(default)]
pub stability: Stability,

/// URI pointing to the resolved telemetry schema included in this package.
pub resolved_schema_uri: String,
/// URI pointing to the resolved registry artifact included in this package.
#[serde(alias = "resolved_schema_uri")]
pub resolved_registry_uri: String,

#[serde(skip)]
deserialization_warnings: Vec<String>,
}

impl PublicationRegistryManifest {
/// Creates a `PublicationRegistryManifest` from a `DefinitionRegistryManifest` and a
/// `resolved_schema_uri` pointing to where the resolved schema will be published.
/// `resolved_registry_uri` pointing to where the resolved registry will be published.
#[must_use]
pub fn try_from_registry_manifest(
registry_manifest: &DefinitionRegistryManifest,
resolved_schema_uri: String,
resolved_registry_uri: String,
) -> Self {
Self {
file_format: PUBLICATION_MANIFEST_FILE_FORMAT.to_owned(),
schema_url: registry_manifest.schema_url.clone(),
description: registry_manifest.description.clone(),
dependencies: registry_manifest.dependencies.clone(),
stability: registry_manifest.stability.clone(),
resolved_schema_uri,
resolved_registry_uri,
deserialization_warnings: vec![],
}
}
}
Expand Down Expand Up @@ -598,11 +623,11 @@ registry_path: "./registry"
);
}

fn manifest_from_yaml(yaml: &str) -> Result<RegistryManifest, Error> {
fn manifest_from_yaml(yaml: &str, nfes: &mut Vec<Error>) -> Result<RegistryManifest, Error> {
use std::io::Write;
let mut tmp = tempfile::NamedTempFile::new().unwrap();
tmp.write_all(yaml.as_bytes()).unwrap();
RegistryManifest::try_from_file(tmp.path(), &mut vec![])
RegistryManifest::try_from_file(tmp.path(), nfes)
}

#[test]
Expand All @@ -612,6 +637,7 @@ registry_path: "./registry"
file_format: "garbage/1.0.0"
schema_url: "https://example.com/schemas/1.0.0"
"#,
&mut vec![],
);
assert!(result.is_err());
assert!(result
Expand All @@ -628,6 +654,7 @@ schema_url: "https://example.com/schemas/1.0.0"
description: "A test registry"
stability: stable
"#,
&mut vec![],
)
.expect("Failed to load RegistryManifest");

Expand All @@ -643,8 +670,9 @@ stability: stable
r#"
file_format: "manifest/2.0"
schema_url: "https://example.com/schemas/1.0.0"
resolved_schema_uri: "https://example.com/resolved/1.0.0/resolved.yaml"
resolved_registry_uri: "https://example.com/resolved/1.0.0/resolved.yaml"
"#,
&mut vec![],
)
.expect("Failed to load RegistryManifest");

Expand All @@ -660,11 +688,11 @@ mod publication_tests {
use super::*;
use crate::stability::Stability;

fn manifest_from_yaml(yaml: &str) -> Result<RegistryManifest, Error> {
fn manifest_from_yaml(yaml: &str, nfes: &mut Vec<Error>) -> Result<RegistryManifest, Error> {
use std::io::Write;
let mut tmp = tempfile::NamedTempFile::new().unwrap();
tmp.write_all(yaml.as_bytes()).unwrap();
RegistryManifest::try_from_file(tmp.path(), &mut vec![])
RegistryManifest::try_from_file(tmp.path(), nfes)
}

#[test]
Expand All @@ -675,17 +703,18 @@ schema_url: "https://example.com/schemas/1.0.0"
description: "A test registry"
stability: stable
"#,
&mut vec![],
)
.expect("Failed to load RegistryManifest");

let RegistryManifest::Definition(definition) = manifest else {
panic!("Expected a Definition manifest");
};

let resolved_schema_uri = "https://example.com/resolved/1.0.0/resolved.yaml".to_owned();
let resolved_registry_uri = "https://example.com/resolved/1.0.0/resolved.yaml".to_owned();
let publication = PublicationRegistryManifest::try_from_registry_manifest(
&definition,
resolved_schema_uri.clone(),
resolved_registry_uri.clone(),
);

assert_eq!(publication.file_format, PUBLICATION_MANIFEST_FILE_FORMAT);
Expand All @@ -696,19 +725,20 @@ stability: stable
assert_eq!(publication.description.as_deref(), Some("A test registry"));
assert_eq!(publication.stability, Stability::Stable);
assert!(publication.dependencies.is_empty());
assert_eq!(publication.resolved_schema_uri, resolved_schema_uri);
assert_eq!(publication.resolved_registry_uri, resolved_registry_uri);
}

#[test]
fn test_publication_manifest_parsed_as_publication_variant() {
// A manifest with file_format "manifest/2.0" and resolved_schema_uri
// A manifest with file_format "manifest/2.0" and resolved_registry_uri
// is parsed as the Publication variant.
let manifest = manifest_from_yaml(
r#"
schema_url: "https://example.com/schemas/1.0.0"
file_format: "manifest/2.0"
resolved_schema_uri: "https://example.com/resolved/1.0.0/resolved.yaml"
resolved_registry_uri: "https://example.com/resolved/1.0.0/resolved.yaml"
"#,
&mut vec![],
)
.expect("Failed to load RegistryManifest");

Expand All @@ -717,4 +747,77 @@ resolved_schema_uri: "https://example.com/resolved/1.0.0/resolved.yaml"
"expected Publication variant, got {manifest:?}"
);
}

/// A publication YAML using the deprecated `resolved_schema_uri` field name
/// must still deserialize correctly into the renamed `resolved_registry_uri`
/// field, and surface a deprecation warning via `nfes`.
#[test]
fn test_publication_manifest_accepts_deprecated_resolved_schema_uri() {
let mut nfes = vec![];
let manifest = manifest_from_yaml(
r#"
file_format: "manifest/2.0"
schema_url: "https://example.com/schemas/1.0.0"
resolved_schema_uri: "https://example.com/resolved/1.0.0/resolved.yaml"
"#,
&mut nfes,
)
.expect("Failed to load RegistryManifest");

let RegistryManifest::Publication(pubm) = manifest else {
panic!("expected Publication variant");
};
assert_eq!(
pubm.resolved_registry_uri,
"https://example.com/resolved/1.0.0/resolved.yaml"
);
assert!(
nfes.iter()
.any(|w| matches!(w, DeprecatedSyntaxInRegistryManifest { .. })),
"expected a DeprecatedSyntaxInRegistryManifest warning, got: {nfes:?}"
);
}

/// When both the deprecated `resolved_schema_uri` and the new
/// `resolved_registry_uri` are provided, the new name wins (no warning).
#[test]
fn test_publication_manifest_new_name_wins_over_deprecated() {
let mut nfes = vec![];
let manifest = manifest_from_yaml(
r#"
file_format: "manifest/2.0"
schema_url: "https://example.com/schemas/1.0.0"
resolved_registry_uri: "https://example.com/resolved/new.yaml"
resolved_schema_uri: "https://example.com/resolved/old.yaml"
"#,
&mut nfes,
)
.expect("Failed to load RegistryManifest");

let RegistryManifest::Publication(pubm) = manifest else {
panic!("expected Publication variant");
};
assert_eq!(
pubm.resolved_registry_uri,
"https://example.com/resolved/new.yaml"
);
}

/// A publication manifest that omits both the new and deprecated names
/// is rejected with `InvalidPublicationManifest`.
#[test]
fn test_publication_manifest_missing_resolved_registry_uri_is_error() {
let result = manifest_from_yaml(
r#"
file_format: "manifest/2.0"
schema_url: "https://example.com/schemas/1.0.0"
"#,
&mut vec![],
);
assert!(matches!(
result,
Err(Error::InvalidPublicationManifest { details, .. })
if details.contains("resolved_registry_uri")
));
}
}
Loading
Loading