Skip to main content

pop_chains/
omni_node.rs

1use 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};
17use std::path::PathBuf;
18use 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)]
23pub enum PolkadotOmniNodeCli {
24	#[strum(props(
25		Repository = "https://github.com/r0gue-io/polkadot",
26		Binary = "polkadot-omni-node",
27		TagPattern = "polkadot-{version}",
28		Fallback = "stable2512-1"
29	))]
30	/// Polkadot Omni Node binary. Used to bootstrap parachains without node.
31	PolkadotOmniNode,
32}
33
34impl 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.
61pub 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)]
77mod 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("stable2512-1"));
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, "stable2512-1");
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}