|
| 1 | +use pop_common::{ |
| 2 | + Error, |
| 3 | + git::GitHub, |
| 4 | + polkadot_sdk::sort_by_latest_semantic_version, |
| 5 | + sourcing::{ |
| 6 | + ArchiveFileSpec, Binary, |
| 7 | + GitHub::*, |
| 8 | + Source, |
| 9 | + filters::prefix, |
| 10 | + traits::{ |
| 11 | + Source as SourceT, |
| 12 | + enums::{Source as _, *}, |
| 13 | + }, |
| 14 | + }, |
| 15 | + target, |
| 16 | +}; |
| 17 | +use std::path::PathBuf; |
| 18 | +use strum_macros::EnumProperty; |
| 19 | + |
| 20 | +/// CLI enum for managing Polkadot Omni Node binary sources and configuration. |
| 21 | +/// Provides repository information and binary specifications for fetching and managing the node. |
| 22 | +#[derive(Debug, EnumProperty, PartialEq)] |
| 23 | +pub enum PolkadotOmniNodeCli { |
| 24 | + #[strum(props( |
| 25 | + Repository = "https://github.com/r0gue-io/polkadot", |
| 26 | + Binary = "polkadot-omni-node", |
| 27 | + TagPattern = "polkadot-{version}", |
| 28 | + Fallback = "stable2506-2" |
| 29 | + ))] |
| 30 | + /// Polkadot Omni Node binary. Used to bootstrap parachains without node. |
| 31 | + PolkadotOmniNode, |
| 32 | +} |
| 33 | + |
| 34 | +impl SourceT for PolkadotOmniNodeCli { |
| 35 | + type Error = Error; |
| 36 | + /// Creates a Source configuration for fetching the Polkadot Omni Node binary from GitHub. |
| 37 | + fn source(&self) -> Result<Source, Error> { |
| 38 | + // Source from GitHub release asset |
| 39 | + let repo = GitHub::parse(self.repository())?; |
| 40 | + let binary = self.binary(); |
| 41 | + Ok(Source::GitHub(ReleaseArchive { |
| 42 | + owner: repo.org, |
| 43 | + repository: repo.name, |
| 44 | + tag: None, |
| 45 | + tag_pattern: self.tag_pattern().map(|t| t.into()), |
| 46 | + prerelease: false, |
| 47 | + version_comparator: sort_by_latest_semantic_version, |
| 48 | + fallback: self.fallback().into(), |
| 49 | + archive: format!("{binary}-{}.tar.gz", target()?), |
| 50 | + contents: vec![ArchiveFileSpec::new(binary.into(), Some(binary.into()), true)], |
| 51 | + latest: None, |
| 52 | + })) |
| 53 | + } |
| 54 | +} |
| 55 | + |
| 56 | +/// Generate the source of the `polkadot-omni-node` binary on the remote repository. |
| 57 | +/// |
| 58 | +/// # Arguments |
| 59 | +/// * `cache` - The path to the directory where the binary should be cached. |
| 60 | +/// * `version` - An optional version string. If `None`, the latest available version is used. |
| 61 | +pub async fn polkadot_omni_node_generator( |
| 62 | + cache: PathBuf, |
| 63 | + version: Option<&str>, |
| 64 | +) -> Result<Binary, Error> { |
| 65 | + let cli = PolkadotOmniNodeCli::PolkadotOmniNode; |
| 66 | + let name = cli.binary().to_string(); |
| 67 | + let source = cli |
| 68 | + .source()? |
| 69 | + .resolve(&name, version, cache.as_path(), |f| prefix(f, &name)) |
| 70 | + .await |
| 71 | + .into(); |
| 72 | + let binary = Binary::Source { name, source, cache: cache.to_path_buf() }; |
| 73 | + Ok(binary) |
| 74 | +} |
| 75 | + |
| 76 | +#[cfg(test)] |
| 77 | +mod tests { |
| 78 | + use super::*; |
| 79 | + use pop_common::sourcing::TagPattern; |
| 80 | + use strum::EnumProperty; |
| 81 | + |
| 82 | + #[test] |
| 83 | + fn polkadot_omni_node_cli_properties_work() { |
| 84 | + let cli = PolkadotOmniNodeCli::PolkadotOmniNode; |
| 85 | + |
| 86 | + // Test enum properties |
| 87 | + assert_eq!(cli.get_str("Repository"), Some("https://github.com/r0gue-io/polkadot")); |
| 88 | + assert_eq!(cli.get_str("Binary"), Some("polkadot-omni-node")); |
| 89 | + assert_eq!(cli.get_str("TagPattern"), Some("polkadot-{version}")); |
| 90 | + assert_eq!(cli.get_str("Fallback"), Some("stable2506-2")); |
| 91 | + } |
| 92 | + |
| 93 | + #[test] |
| 94 | + fn polkadot_omni_node_cli_source_works() -> anyhow::Result<()> { |
| 95 | + let cli = PolkadotOmniNodeCli::PolkadotOmniNode; |
| 96 | + let source = cli.source()?; |
| 97 | + |
| 98 | + // Verify source is GitHub variant |
| 99 | + match source { |
| 100 | + Source::GitHub(ReleaseArchive { |
| 101 | + owner, |
| 102 | + repository, |
| 103 | + tag, |
| 104 | + tag_pattern, |
| 105 | + prerelease, |
| 106 | + fallback, |
| 107 | + archive, |
| 108 | + contents, |
| 109 | + .. |
| 110 | + }) => { |
| 111 | + assert_eq!(owner, "r0gue-io"); |
| 112 | + assert_eq!(repository, "polkadot"); |
| 113 | + assert_eq!(tag, None); |
| 114 | + assert_eq!(tag_pattern, Some(TagPattern::new("polkadot-{version}"))); |
| 115 | + assert!(!prerelease); |
| 116 | + assert_eq!(fallback, "stable2506-2"); |
| 117 | + assert!(archive.starts_with("polkadot-omni-node-")); |
| 118 | + assert!(archive.ends_with(".tar.gz")); |
| 119 | + assert_eq!(contents.len(), 1); |
| 120 | + assert_eq!(contents[0].name, "polkadot-omni-node"); |
| 121 | + assert!(contents[0].required); |
| 122 | + }, |
| 123 | + _ => panic!("Expected GitHub ReleaseArchive source variant"), |
| 124 | + } |
| 125 | + |
| 126 | + Ok(()) |
| 127 | + } |
| 128 | + |
| 129 | + #[tokio::test] |
| 130 | + async fn polkadot_omni_node_generator_works() -> anyhow::Result<()> { |
| 131 | + let cache = tempfile::tempdir()?; |
| 132 | + let binary = polkadot_omni_node_generator(cache.path().to_path_buf(), None).await?; |
| 133 | + |
| 134 | + match binary { |
| 135 | + Binary::Source { name, source, cache: cache_path } => { |
| 136 | + assert_eq!(name, "polkadot-omni-node"); |
| 137 | + assert_eq!(cache_path, cache.path()); |
| 138 | + // Source should be a ResolvedRelease |
| 139 | + match *source { |
| 140 | + Source::GitHub(github) => |
| 141 | + if let ReleaseArchive { archive, .. } = github { |
| 142 | + assert!(archive.contains("polkadot-omni-node")); |
| 143 | + }, |
| 144 | + _ => panic!("Expected GitHub variant"), |
| 145 | + } |
| 146 | + }, |
| 147 | + _ => panic!("Expected Binary::Source variant"), |
| 148 | + } |
| 149 | + |
| 150 | + Ok(()) |
| 151 | + } |
| 152 | +} |
0 commit comments