<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <updated>2026-04-03T02:18:42Z</updated>
  <generator>https://yabu.me</generator>

  <title>Nostr notes by build.rs</title>
  <author>
    <name>build.rs</name>
  </author>
  <link rel="self" type="application/atom+xml" href="https://yabu.me/npub1gd63ca3y4q9cdr7537myg4jz9utdxhgnwrt8wc8p8nyhdx0vzams0pmcwp.rss" />
  <link href="https://yabu.me/npub1gd63ca3y4q9cdr7537myg4jz9utdxhgnwrt8wc8p8nyhdx0vzams0pmcwp" />
  <id>https://yabu.me/npub1gd63ca3y4q9cdr7537myg4jz9utdxhgnwrt8wc8p8nyhdx0vzams0pmcwp</id>
  <icon>https://avatars.githubusercontent.com/u/135379339?s=400&amp;u=11cb72cccbc2b13252867099546074c50caef1ae&amp;v=4</icon>
  <logo>https://avatars.githubusercontent.com/u/135379339?s=400&amp;u=11cb72cccbc2b13252867099546074c50caef1ae&amp;v=4</logo>




  <entry>
    <id>https://yabu.me/nevent1qqsytnn4clqv4ujq6gzqvdqhmveva8axkxm82d4tagmx5w9535g45vgzypph28rkyj5qhp506j8mv3zkggh3d56azdcdvamquy7vja5easthwfnhs5n</id>
    
      <title type="html">/// deterministic nostr event build example // deterministic ...</title>
    
    <link rel="alternate" href="https://yabu.me/nevent1qqsytnn4clqv4ujq6gzqvdqhmveva8axkxm82d4tagmx5w9535g45vgzypph28rkyj5qhp506j8mv3zkggh3d56azdcdvamquy7vja5easthwfnhs5n" />
    <content type="html">
      /// deterministic nostr event build example&lt;br/&gt;// deterministic nostr event build example&lt;br/&gt;use get_file_hash_core::get_file_hash;&lt;br/&gt;#[cfg(all(not(debug_assertions), feature = &amp;#34;nostr&amp;#34;))]&lt;br/&gt;use get_file_hash_core::{get_git_tracked_files, DEFAULT_GNOSTR_KEY, DEFAULT_PICTURE_URL, DEFAULT_BANNER_URL};&lt;br/&gt;#[cfg(all(not(debug_assertions), feature = &amp;#34;nostr&amp;#34;))]&lt;br/&gt;use nostr_sdk::{EventBuilder, Keys, EventId, Tag, SecretKey, JsonUtil, Kind, Event};&lt;br/&gt;&lt;br/&gt;#[cfg(all(not(debug_assertions), feature = &amp;#34;nostr&amp;#34;))]&lt;br/&gt;use std::fs;&lt;br/&gt;use std::path::PathBuf;&lt;br/&gt;use sha2::{Digest, Sha256};&lt;br/&gt;#[cfg(all(not(debug_assertions), feature = &amp;#34;nostr&amp;#34;))]&lt;br/&gt;use ::hex;&lt;br/&gt;#[cfg(all(not(debug_assertions), feature = &amp;#34;nostr&amp;#34;))]&lt;br/&gt;use std::io::Write;&lt;br/&gt;&lt;br/&gt;#[cfg(all(not(debug_assertions), feature = &amp;#34;nostr&amp;#34;))]&lt;br/&gt;fn should_remove_relay(error_msg: &amp;amp;str) -&amp;gt; bool {&lt;br/&gt;    error_msg.contains(&amp;#34;relay not connected&amp;#34;) ||&lt;br/&gt;    error_msg.contains(&amp;#34;not in web of trust&amp;#34;) ||&lt;br/&gt;    error_msg.contains(&amp;#34;blocked: not authorized&amp;#34;) ||&lt;br/&gt;    error_msg.contains(&amp;#34;timeout&amp;#34;) ||&lt;br/&gt;    error_msg.contains(&amp;#34;blocked: spam not permitted&amp;#34;) ||&lt;br/&gt;    error_msg.contains(&amp;#34;relay experienced an error trying to publish the latest event&amp;#34;) ||&lt;br/&gt;    error_msg.contains(&amp;#34;duplicate: event already broadcast&amp;#34;)&lt;br/&gt;}&lt;br/&gt;&lt;br/&gt;#[cfg(all(not(debug_assertions), feature = &amp;#34;nostr&amp;#34;))]&lt;br/&gt;fn write_event_json_to_file(&lt;br/&gt;    output_dir: &amp;amp;PathBuf,&lt;br/&gt;    filename: &amp;amp;str,&lt;br/&gt;    event: &amp;amp;Event,&lt;br/&gt;) -&amp;gt; Option&amp;lt;()&amp;gt; {&lt;br/&gt;    let file_path = output_dir.join(filename);&lt;br/&gt;    if let Some(parent) = file_path.parent() {&lt;br/&gt;        if let Err(e) = fs::create_dir_all(parent) {&lt;br/&gt;            println!(&amp;#34;cargo:warning=Failed to create parent directories for {}: {}&amp;#34;, file_path.display(), e);&lt;br/&gt;            return None;&lt;br/&gt;        }&lt;br/&gt;    }&lt;br/&gt;    if let Err(e) = fs::File::create(&amp;amp;file_path).and_then(|mut file| write!(file, &amp;#34;{}&amp;#34;, event.as_json())) {&lt;br/&gt;        println!(&amp;#34;cargo:warning=Failed to write event JSON to file {}: {}&amp;#34;, file_path.display(), e);&lt;br/&gt;        None&lt;br/&gt;    } else {&lt;br/&gt;        println!(&amp;#34;cargo:warning=Successfully wrote event JSON to {}&amp;#34;, file_path.display());&lt;br/&gt;        Some(())&lt;br/&gt;    }&lt;br/&gt;}&lt;br/&gt;&lt;br/&gt;#[cfg(all(not(debug_assertions), feature = &amp;#34;nostr&amp;#34;))]&lt;br/&gt;async fn publish_nostr_event_if_release(&lt;br/&gt;    hash: String,&lt;br/&gt;    keys: Keys,&lt;br/&gt;    event_builder: EventBuilder,&lt;br/&gt;    mut relay_urls: Vec&amp;lt;String&amp;gt;,&lt;br/&gt;    file_path_str: &amp;amp;str,&lt;br/&gt;    output_dir: &amp;amp;PathBuf,&lt;br/&gt;) -&amp;gt; Option&amp;lt;EventId&amp;gt; {&lt;br/&gt;    let client = nostr_sdk::Client::new(keys.clone());&lt;br/&gt;        let public_key = keys.public_key().to_string();&lt;br/&gt;&lt;br/&gt;    for i in (0..relay_urls.len()).rev() {&lt;br/&gt;        let relay_url = &amp;amp;relay_urls[i];&lt;br/&gt;        if let Err(e) = client.add_relay(relay_url).await {&lt;br/&gt;            println!(&amp;#34;cargo:warning=Failed to add relay {}: {}&amp;#34;, relay_url, e);&lt;br/&gt;        }&lt;br/&gt;    }&lt;br/&gt;    println!(&amp;#34;cargo:warning=Added {} relays&amp;#34;, relay_urls.len());&lt;br/&gt;&lt;br/&gt;    client.connect().await;&lt;br/&gt;    println!(&amp;#34;cargo:warning=Connected to {} relays&amp;#34;, relay_urls.len());&lt;br/&gt;&lt;br/&gt;    let event = client.sign_event_builder(event_builder).await.unwrap();&lt;br/&gt;&lt;br/&gt;    match client.send_event(&amp;amp;event).await {        Ok(event_output) =&amp;gt; {&lt;br/&gt;            println!(&amp;#34;cargo:warning=Published Nostr event for {}: {}&amp;#34;, file_path_str, event_output.val);&lt;br/&gt;&lt;br/&gt;            // Print successful relays&lt;br/&gt;            for relay_url in event_output.success.iter() {&lt;br/&gt;                println!(&amp;#34;cargo:warning=Successfully published to relay: {}&amp;#34;, relay_url);&lt;br/&gt;            }&lt;br/&gt;            // Print failed relays and remove &amp;#34;unfriendly&amp;#34; relays from the list&lt;br/&gt;            let mut relays_to_remove: Vec&amp;lt;String&amp;gt; = Vec::new();&lt;br/&gt;            for (relay_url, error_msg) in event_output.failed.iter() {&lt;br/&gt;                if should_remove_relay(error_msg) {&lt;br/&gt;                    relays_to_remove.push(relay_url.to_string());&lt;br/&gt;                }&lt;br/&gt;            }&lt;br/&gt;            // Remove failed relays from the list&lt;br/&gt;            relay_urls.retain(|url| !relays_to_remove.contains(url));&lt;br/&gt;            if !relays_to_remove.is_empty() {&lt;br/&gt;                println!(&amp;#34;cargo:warning=Removed {} unresponsive relays from the list.&amp;#34;, relays_to_remove.len());&lt;br/&gt;            }&lt;br/&gt;&lt;br/&gt;            let filename = format!(&amp;#34;{}/{}/{}/{}.json&amp;#34;, file_path_str, hash, public_key.clone(), event_output.val.to_string());&lt;br/&gt;            write_event_json_to_file(output_dir, &amp;amp;filename, &amp;amp;event);&lt;br/&gt;            Some(event_output.val)&lt;br/&gt;        },&lt;br/&gt;        Err(e) =&amp;gt; {&lt;br/&gt;            println!(&amp;#34;cargo:warning=Failed to publish Nostr event for {}: {}&amp;#34;, file_path_str, e);&lt;br/&gt;            None&lt;br/&gt;        },&lt;br/&gt;    }&lt;br/&gt;}&lt;br/&gt;&lt;br/&gt;#[cfg(all(not(debug_assertions), feature = &amp;#34;nostr&amp;#34;))]&lt;br/&gt;pub async fn get_repo_announcement_event(&lt;br/&gt;    keys: &amp;amp;Keys,&lt;br/&gt;    relay_urls: &amp;amp;Vec&amp;lt;String&amp;gt;,&lt;br/&gt;    repo_url: &amp;amp;str,&lt;br/&gt;    repo_name: &amp;amp;str,&lt;br/&gt;    repo_description: &amp;amp;str,&lt;br/&gt;    git_commit_hash: &amp;amp;str,&lt;br/&gt;    git_branch: &amp;amp;str,&lt;br/&gt;    output_dir: &amp;amp;PathBuf,&lt;br/&gt;    public_key_hex: &amp;amp;str,&lt;br/&gt;) -&amp;gt; Option&amp;lt;EventId&amp;gt; {&lt;br/&gt;    let client = nostr_sdk::Client::new(keys.clone());&lt;br/&gt;&lt;br/&gt;    for relay_url in relay_urls {&lt;br/&gt;        if let Err(e) = client.add_relay(relay_url).await {&lt;br/&gt;            println!(&amp;#34;cargo:warning=Failed to add relay {}: {}&amp;#34;, relay_url, e);&lt;br/&gt;        }&lt;br/&gt;    }&lt;br/&gt;    client.connect().await;&lt;br/&gt;&lt;br/&gt;    let tags = vec![&lt;br/&gt;        Tag::parse([&amp;#34;r&amp;#34;, repo_url].iter().map(ToString::to_string).collect::&amp;lt;Vec&amp;lt;String&amp;gt;&amp;gt;()).unwrap(),&lt;br/&gt;        Tag::parse([&amp;#34;name&amp;#34;, repo_name].iter().map(ToString::to_string).collect::&amp;lt;Vec&amp;lt;String&amp;gt;&amp;gt;()).unwrap(),&lt;br/&gt;        Tag::parse([&amp;#34;description&amp;#34;, repo_description].iter().map(ToString::to_string).collect::&amp;lt;Vec&amp;lt;String&amp;gt;&amp;gt;()).unwrap(),&lt;br/&gt;        Tag::parse([&amp;#34;commit&amp;#34;, git_commit_hash].iter().map(ToString::to_string).collect::&amp;lt;Vec&amp;lt;String&amp;gt;&amp;gt;()).unwrap(),&lt;br/&gt;        Tag::parse([&amp;#34;branch&amp;#34;, git_branch].iter().map(ToString::to_string).collect::&amp;lt;Vec&amp;lt;String&amp;gt;&amp;gt;()).unwrap(),&lt;br/&gt;    ];&lt;br/&gt;&lt;br/&gt;    let event_builder = EventBuilder::new(Kind::Custom(30617), repo_description).tags(tags);&lt;br/&gt;    let event = client.sign_event_builder(event_builder).await.unwrap();&lt;br/&gt;&lt;br/&gt;    match client.send_event(&amp;amp;event).await {&lt;br/&gt;        Ok(event_output) =&amp;gt; {&lt;br/&gt;            println!(&amp;#34;cargo:warning=Published Nostr Repository Announcement for {}: {}&amp;#34;, repo_name, event_output.val);&lt;br/&gt;            &lt;br/&gt;            let filename = format!(&amp;#34;30617/{}/{}/{}.json&amp;#34;, repo_name, public_key_hex, event_output.val.to_string());&lt;br/&gt;            write_event_json_to_file(output_dir, &amp;amp;filename, &amp;amp;event);&lt;br/&gt;            Some(event_output.val)&lt;br/&gt;        },&lt;br/&gt;        Err(e) =&amp;gt; {&lt;br/&gt;            println!(&amp;#34;cargo:warning=Failed to publish Nostr Repository Announcement for {}: {}&amp;#34;, repo_name, e);&lt;br/&gt;            None&lt;br/&gt;        },&lt;br/&gt;    }&lt;br/&gt;}&lt;br/&gt;&lt;br/&gt;#[tokio::main]&lt;br/&gt;async fn main() {&lt;br/&gt;    let manifest_dir = std::env::var(&amp;#34;CARGO_MANIFEST_DIR&amp;#34;).unwrap();&lt;br/&gt;    let is_git_repo = std::path::Path::new(&amp;amp;manifest_dir).join(&amp;#34;.git&amp;#34;).exists();&lt;br/&gt;&lt;br/&gt;&lt;br/&gt;    println!(&amp;#34;cargo:rustc-env=CARGO_PKG_NAME={}&amp;#34;, env!(&amp;#34;CARGO_PKG_NAME&amp;#34;));&lt;br/&gt;    println!(&amp;#34;cargo:rustc-env=CARGO_PKG_VERSION={}&amp;#34;, env!(&amp;#34;CARGO_PKG_VERSION&amp;#34;));&lt;br/&gt;&lt;br/&gt;    if is_git_repo {&lt;br/&gt;        let git_commit_hash_output = std::process::Command::new(&amp;#34;git&amp;#34;)&lt;br/&gt;            .args(&amp;amp;[&amp;#34;rev-parse&amp;#34;, &amp;#34;HEAD&amp;#34;])&lt;br/&gt;            .stdout(std::process::Stdio::piped())&lt;br/&gt;            .stderr(std::process::Stdio::piped())&lt;br/&gt;            .output()&lt;br/&gt;            .expect(&amp;#34;Failed to execute git command for commit hash&amp;#34;);&lt;br/&gt;&lt;br/&gt;        let git_commit_hash_str = if git_commit_hash_output.status.success() &amp;amp;&amp;amp; !git_commit_hash_output.stdout.is_empty() {&lt;br/&gt;            String::from_utf8(git_commit_hash_output.stdout).unwrap().trim().to_string()&lt;br/&gt;        } else {&lt;br/&gt;            println!(&amp;#34;cargo:warning=Git commit hash command failed or returned empty. Status: {:?}, Stderr: {}&amp;#34;, &lt;br/&gt;                     git_commit_hash_output.status, String::from_utf8_lossy(&amp;amp;git_commit_hash_output.stderr));&lt;br/&gt;            String::new()&lt;br/&gt;        };&lt;br/&gt;        println!(&amp;#34;cargo:rustc-env=GIT_COMMIT_HASH={}&amp;#34;, git_commit_hash_str);&lt;br/&gt;&lt;br/&gt;        let git_branch_output = std::process::Command::new(&amp;#34;git&amp;#34;)&lt;br/&gt;            .args(&amp;amp;[&amp;#34;rev-parse&amp;#34;, &amp;#34;--abbrev-ref&amp;#34;, &amp;#34;HEAD&amp;#34;])&lt;br/&gt;            .stdout(std::process::Stdio::piped())&lt;br/&gt;            .stderr(std::process::Stdio::piped())&lt;br/&gt;            .output()&lt;br/&gt;            .expect(&amp;#34;Failed to execute git command for branch name&amp;#34;);&lt;br/&gt;&lt;br/&gt;        let git_branch_str = if git_branch_output.status.success() &amp;amp;&amp;amp; !git_branch_output.stdout.is_empty() {&lt;br/&gt;            String::from_utf8(git_branch_output.stdout).unwrap().trim().to_string()&lt;br/&gt;        } else {&lt;br/&gt;            println!(&amp;#34;cargo:warning=Git branch command failed or returned empty. Status: {:?}, Stderr: {}&amp;#34;, &lt;br/&gt;                     git_branch_output.status, String::from_utf8_lossy(&amp;amp;git_branch_output.stderr));&lt;br/&gt;            String::new()&lt;br/&gt;        };&lt;br/&gt;        println!(&amp;#34;cargo:rustc-env=GIT_BRANCH={}&amp;#34;, git_branch_str);&lt;br/&gt;    } else {&lt;br/&gt;        println!(&amp;#34;cargo:rustc-env=GIT_COMMIT_HASH=&amp;#34;);&lt;br/&gt;        println!(&amp;#34;cargo:rustc-env=GIT_BRANCH=&amp;#34;);&lt;br/&gt;    }&lt;br/&gt;&lt;br/&gt;    println!(&amp;#34;cargo:rerun-if-changed=.git/HEAD&amp;#34;);&lt;br/&gt;&lt;br/&gt;    #[cfg(all(not(debug_assertions), feature = &amp;#34;nostr&amp;#34;))]&lt;br/&gt;    let relay_urls = get_file_hash_core::get_relay_urls();&lt;br/&gt;&lt;br/&gt;    let cargo_toml_hash = get_file_hash!(&amp;#34;Cargo.toml&amp;#34;);&lt;br/&gt;    println!(&amp;#34;cargo:rustc-env=CARGO_TOML_HASH={}&amp;#34;, cargo_toml_hash);&lt;br/&gt;&lt;br/&gt;    let lib_hash = get_file_hash!(&amp;#34;src/lib.rs&amp;#34;);&lt;br/&gt;    println!(&amp;#34;cargo:rustc-env=LIB_HASH={}&amp;#34;, lib_hash);&lt;br/&gt;&lt;br/&gt;    let build_hash = get_file_hash!(&amp;#34;build.rs&amp;#34;);&lt;br/&gt;    println!(&amp;#34;cargo:rustc-env=BUILD_HASH={}&amp;#34;, build_hash);&lt;br/&gt;&lt;br/&gt;    println!(&amp;#34;cargo:rerun-if-changed=Cargo.toml&amp;#34;);&lt;br/&gt;    println!(&amp;#34;cargo:rerun-if-changed=src/lib.rs&amp;#34;);&lt;br/&gt;    println!(&amp;#34;cargo:rerun-if-changed=build.rs&amp;#34;);&lt;br/&gt;    let online_relays_csv_path = PathBuf::from(&amp;amp;manifest_dir).join(&amp;#34;src/get_file_hash_core/src/online_relays_gps.csv&amp;#34;);&lt;br/&gt;    if online_relays_csv_path.exists() {&lt;br/&gt;        println!(&amp;#34;cargo:rerun-if-changed={}&amp;#34;, online_relays_csv_path.to_str().unwrap());&lt;br/&gt;    }&lt;br/&gt;&lt;br/&gt;#[cfg(all(not(debug_assertions), feature = &amp;#34;nostr&amp;#34;))]&lt;br/&gt;    if cfg!(not(debug_assertions)) {&lt;br/&gt;        println!(&amp;#34;cargo:warning=Nostr feature enabled: Build may take longer due to network operations (publishing events to relays).&amp;#34;);&lt;br/&gt;&lt;br/&gt;        // This code only runs in release builds&lt;br/&gt;        let package_version = std::env::var(&amp;#34;CARGO_PKG_VERSION&amp;#34;).unwrap();&lt;br/&gt;&lt;br/&gt;        let output_dir = PathBuf::from(format!(&amp;#34;.gnostr/build/{}&amp;#34;, package_version));&lt;br/&gt;        if let Err(e) = fs::create_dir_all(&amp;amp;output_dir) {&lt;br/&gt;            println!(&amp;#34;cargo:warning=Failed to create output directory {}: {}&amp;#34;, output_dir.display(), e);&lt;br/&gt;        }&lt;br/&gt;&lt;br/&gt;        let files_to_publish: Vec&amp;lt;String&amp;gt; = get_git_tracked_files(&amp;amp;PathBuf::from(&amp;amp;manifest_dir));&lt;br/&gt;        &lt;br/&gt;        let mut published_event_ids: Vec&amp;lt;Tag&amp;gt; = Vec::new();&lt;br/&gt;&lt;br/&gt;        for file_path_str in &amp;amp;files_to_publish {&lt;br/&gt;            println!(&amp;#34;cargo:warning=Processing file: {}&amp;#34;, file_path_str);&lt;br/&gt;            match fs::read(file_path_str) {&lt;br/&gt;                Ok(bytes) =&amp;gt; {&lt;br/&gt;                    let mut hasher = Sha256::new();&lt;br/&gt;                    hasher.update(&amp;amp;bytes);&lt;br/&gt;                    let result = hasher.finalize();&lt;br/&gt;                    let file_hash_hex = hex::encode(result);&lt;br/&gt;&lt;br/&gt;                    match SecretKey::from_hex(&amp;amp;file_hash_hex.clone()) {&lt;br/&gt;                        Ok(secret_key) =&amp;gt; {&lt;br/&gt;                            let keys = Keys::new(secret_key);&lt;br/&gt;                            let content = String::from_utf8_lossy(&amp;amp;bytes).into_owned();&lt;br/&gt;                            let tags = vec![&lt;br/&gt;                                Tag::parse([&amp;#34;file&amp;#34;, file_path_str].iter().map(ToString::to_string).collect::&amp;lt;Vec&amp;lt;String&amp;gt;&amp;gt;()).unwrap(),&lt;br/&gt;                                Tag::parse([&amp;#34;version&amp;#34;, &amp;amp;package_version].iter().map(ToString::to_string).collect::&amp;lt;Vec&amp;lt;String&amp;gt;&amp;gt;()).unwrap(),&lt;br/&gt;                            ];&lt;br/&gt;                            let event_builder = EventBuilder::text_note(content).tags(tags);&lt;br/&gt;&lt;br/&gt;                            if let Some(event_id) = publish_nostr_event_if_release(file_hash_hex, keys.clone(), event_builder, relay_urls.clone(), file_path_str, &amp;amp;output_dir).await {&lt;br/&gt;                                published_event_ids.push(Tag::event(event_id));&lt;br/&gt;                            }&lt;br/&gt;&lt;br/&gt;                            // Publish metadata event&lt;br/&gt;                            get_file_hash_core::publish_metadata_event(&lt;br/&gt;                                &amp;amp;keys,&lt;br/&gt;                                &amp;amp;relay_urls,&lt;br/&gt;                                DEFAULT_PICTURE_URL,&lt;br/&gt;                                DEFAULT_BANNER_URL,&lt;br/&gt;                                file_path_str,&lt;br/&gt;                            ).await;&lt;br/&gt;                        }&lt;br/&gt;                        Err(e) =&amp;gt; {&lt;br/&gt;                            println!(&amp;#34;cargo:warning=Failed to derive Nostr secret key for {}: {}&amp;#34;, file_path_str, e);&lt;br/&gt;                        }&lt;br/&gt;                    }&lt;br/&gt;                }&lt;br/&gt;                Err(e) =&amp;gt; {&lt;br/&gt;                    println!(&amp;#34;cargo:warning=Failed to read file {}: {}&amp;#34;, file_path_str, e);&lt;br/&gt;                }&lt;br/&gt;            }&lt;br/&gt;        }&lt;br/&gt;&lt;br/&gt;        // Create and publish the build_manifest&lt;br/&gt;        if !published_event_ids.is_empty() {&lt;br/&gt;&lt;br/&gt;            //TODO this will be either the default or detected from env vars PRIVATE_KEY&lt;br/&gt;            let keys = Keys::new(SecretKey::from_hex(DEFAULT_GNOSTR_KEY).expect(&amp;#34;Failed to create Nostr keys from DEFAULT_GNOSTR_KEY&amp;#34;));&lt;br/&gt;            let cloned_keys = keys.clone();&lt;br/&gt;            let content = format!(&amp;#34;Build manifest for get_file_hash v{}&amp;#34;, package_version);&lt;br/&gt;            let mut tags = vec![&lt;br/&gt;                Tag::parse([&amp;#34;build_manifest&amp;#34;, &amp;amp;package_version].iter().map(ToString::to_string).collect::&amp;lt;Vec&amp;lt;String&amp;gt;&amp;gt;()).unwrap(),&lt;br/&gt;                Tag::parse([&amp;#34;build_manifest&amp;#34;, &amp;amp;package_version].iter().map(ToString::to_string).collect::&amp;lt;Vec&amp;lt;String&amp;gt;&amp;gt;()).unwrap(),&lt;br/&gt;                Tag::parse([&amp;#34;build_manifest&amp;#34;, &amp;amp;package_version].iter().map(ToString::to_string).collect::&amp;lt;Vec&amp;lt;String&amp;gt;&amp;gt;()).unwrap(),&lt;br/&gt;                Tag::parse([&amp;#34;build_manifest&amp;#34;, &amp;amp;package_version].iter().map(ToString::to_string).collect::&amp;lt;Vec&amp;lt;String&amp;gt;&amp;gt;()).unwrap(),&lt;br/&gt;            ];&lt;br/&gt;            tags.extend(published_event_ids);&lt;br/&gt;&lt;br/&gt;            let event_builder = EventBuilder::text_note(content.clone()).tags(tags);&lt;br/&gt;&lt;br/&gt;            if let Some(event_id) = publish_nostr_event_if_release(&lt;br/&gt;                hex::encode(Sha256::digest(content.as_bytes())),&lt;br/&gt;                keys,&lt;br/&gt;                event_builder,&lt;br/&gt;                relay_urls.clone(),&lt;br/&gt;                &amp;#34;build_manifest.json&amp;#34;,&lt;br/&gt;                &amp;amp;output_dir,&lt;br/&gt;            ).await {&lt;br/&gt;&lt;br/&gt;                let build_manifest_event_id = Some(event_id);&lt;br/&gt;&lt;br/&gt;            // Publish metadata event for the build manifest&lt;br/&gt;            get_file_hash_core::publish_metadata_event(&lt;br/&gt;                &amp;amp;cloned_keys, // Use reference to cloned keys here&lt;br/&gt;                &amp;amp;relay_urls,&lt;br/&gt;                DEFAULT_PICTURE_URL,&lt;br/&gt;                DEFAULT_BANNER_URL,&lt;br/&gt;                &amp;amp;format!(&amp;#34;build_manifest:{}&amp;#34;, package_version),&lt;br/&gt;            ).await;&lt;br/&gt;            let git_commit_hash = std::env::var(&amp;#34;GIT_COMMIT_HASH&amp;#34;).unwrap_or_default();&lt;br/&gt;            let git_branch = std::env::var(&amp;#34;GIT_BRANCH&amp;#34;).unwrap_or_default();&lt;br/&gt;            let repo_url = std::env::var(&amp;#34;CARGO_PKG_REPOSITORY&amp;#34;).unwrap();&lt;br/&gt;            let repo_name = std::env::var(&amp;#34;CARGO_PKG_NAME&amp;#34;).unwrap();&lt;br/&gt;            let repo_description = std::env::var(&amp;#34;CARGO_PKG_DESCRIPTION&amp;#34;).unwrap();&lt;br/&gt;&lt;br/&gt;            let output_dir = PathBuf::from(format!(&amp;#34;.gnostr/build/{}&amp;#34;, package_version));&lt;br/&gt;            if let Err(e) = fs::create_dir_all(&amp;amp;output_dir) {&lt;br/&gt;                println!(&amp;#34;cargo:warning=Failed to create output directory {}: {}&amp;#34;, output_dir.display(), e);&lt;br/&gt;            }&lt;br/&gt;&lt;br/&gt;            let announcement_keys = Keys::new(SecretKey::from_hex(build_manifest_event_id.unwrap().to_hex().as_str()).expect(&amp;#34;Failed to create Nostr keys from build_manifest_event_id&amp;#34;));&lt;br/&gt;            let announcement_pubkey_hex = announcement_keys.public_key().to_string();&lt;br/&gt;&lt;br/&gt;            // Publish NIP-34 Repository Announcement&lt;br/&gt;            if let Some(_event_id) = get_repo_announcement_event(&lt;br/&gt;                &amp;amp;announcement_keys,&lt;br/&gt;                &amp;amp;relay_urls,&lt;br/&gt;                &amp;amp;repo_url,&lt;br/&gt;                &amp;amp;repo_name,&lt;br/&gt;                &amp;amp;repo_description,&lt;br/&gt;                &amp;amp;git_commit_hash,&lt;br/&gt;                &amp;amp;git_branch,&lt;br/&gt;                &amp;amp;output_dir,&lt;br/&gt;                &amp;amp;announcement_pubkey_hex&lt;br/&gt;            ).await {&lt;br/&gt;                // Successfully published announcement&lt;br/&gt;            }&lt;br/&gt;            }&lt;br/&gt;        }&lt;br/&gt;    }&lt;br/&gt;}&lt;br/&gt;// deterministic nostr event build example&lt;br/&gt;
    </content>
    <updated>2026-04-03T02:18:31Z</updated>
  </entry>

</feed>