Skip to content
Snippets Groups Projects
Select Git revision
  • master default protected
  • network/gdev-800 protected
  • cgeek/issue-297-cpu
  • gdev-800-tests
  • update-docker-compose-rpc-squid-names
  • fix-252
  • 1000i100-test
  • hugo/tmp-0.9.1
  • network/gdev-803 protected
  • hugo/endpoint-gossip
  • network/gdev-802 protected
  • hugo/distance-precompute
  • network/gdev-900 protected
  • tuxmain/anonymous-tx
  • debug/podman
  • hugo/195-doc
  • hugo/195-graphql-schema
  • hugo-tmp-dockerfile-cache
  • release/client-800.2 protected
  • release/runtime-800 protected
  • gdev-900-0.10.1 protected
  • gdev-900-0.10.0 protected
  • gdev-900-0.9.2 protected
  • gdev-800-0.8.0 protected
  • gdev-900-0.9.1 protected
  • gdev-900-0.9.0 protected
  • gdev-803 protected
  • gdev-802 protected
  • runtime-801 protected
  • gdev-800 protected
  • runtime-800-bis protected
  • runtime-800 protected
  • runtime-800-backup protected
  • runtime-701 protected
  • runtime-700 protected
  • runtime-600 protected
  • runtime-500 protected
  • v0.4.1 protected
  • runtime-401 protected
  • v0.4.0 protected
40 results

release_runtime.rs

Blame
  • release_runtime.rs 6.65 KiB
    // Copyright 2021 Axiom-Team
    //
    // This file is part of Duniter-v2S.
    //
    // Duniter-v2S is free software: you can redistribute it and/or modify
    // it under the terms of the GNU Affero General Public License as published by
    // the Free Software Foundation, version 3 of the License.
    //
    // Duniter-v2S is distributed in the hope that it will be useful,
    // but WITHOUT ANY WARRANTY; without even the implied warranty of
    // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    // GNU Affero General Public License for more details.
    //
    // You should have received a copy of the GNU Affero General Public License
    // along with Duniter-v2S. If not, see <https://www.gnu.org/licenses/>.
    
    mod create_asset_link;
    mod create_release;
    mod get_changes;
    mod get_issues;
    mod get_release;
    
    use anyhow::{anyhow, Context, Result};
    use serde::Deserialize;
    use std::fs;
    
    #[derive(Default, Deserialize)]
    struct Srtool {
        gen: String,
        rustc: String,
        runtimes: SrtoolRuntimes,
    }
    
    #[derive(Default, Deserialize)]
    struct SrtoolRuntimes {
        compact: SrtoolRuntime,
        compressed: SrtoolRuntime,
    }
    
    #[derive(Default, Deserialize)]
    struct SrtoolRuntime {
        subwasm: SrtoolRuntimeSubWasm,
    }
    
    #[derive(Default, Deserialize)]
    struct SrtoolRuntimeSubWasm {
        core_version: CoreVersion,
        metadata_version: u32,
        size: u32,
        blake2_256: String,
        proposal_hash: String,
    }
    
    #[derive(Default, Deserialize)]
    #[serde(rename_all = "camelCase")]
    struct CoreVersion {
        //impl_name: String,
        //impl_version: u32,
        spec_name: String,
        spec_version: u32,
        //transaction_version: u32,
    }
    
    pub(super) async fn release_runtime(milestone: String, branch: String) -> Result<()> {
        // TODO: check spec_version in the code and bump if necessary (with a commit)
        // TODO: create and push a git tag runtime-{spec_version}
    
        let mut release_notes = String::from(
            "
    # Runtimes
    
    ",
        );
    
        // Generate release notes
        let runtimes = vec![
            ("ĞDev", "SRTOOL_OUTPUT_GDEV"),
            ("ĞTest", "SRTOOL_OUTPUT_GTEST"),
            ("Ğ1", "SRTOOL_OUTPUT_G1"),
        ];
        for (currency, env_var) in runtimes {
            if let Ok(sr_tool_output_file) = std::env::var(env_var) {
                let read = fs::read_to_string(sr_tool_output_file);
                match read {
                    Ok(sr_tool_output) => {
                        release_notes.push_str(
                            gen_release_notes(currency.to_string(), sr_tool_output)
                                .with_context(|| {
                                    format!("Fail to generate release notes for {}", currency)
                                })?
                                .as_str(),
                        );
                    }
                    Err(e) => {
                        eprintln!("srtool JSON output could not be read ({}). Skipped.", e)
                    }
                }
            }
        }
    
        // Get changes (list of MRs) from gitlab API
        let changes = get_changes::get_changes(milestone.clone()).await?;
    
        release_notes.push_str(
            format!(
                "
    # Changes
    
    {changes}
    "
            )
            .as_str(),
        );
    
        // Get changes (list of MRs) from gitlab API
        let issues = get_issues::get_issues(milestone.clone()).await?;
    
        release_notes.push_str(
            format!(
                "
    # Issues
    
    {issues}
    "
            )
            .as_str(),
        );
        println!("{}", release_notes);
        let gitlab_token =
            std::env::var("GITLAB_TOKEN").with_context(|| "missing env var GITLAB_TOKEN")?;
        create_release::create_release(gitlab_token, branch, milestone, release_notes.to_string())
            .await?;
    
        Ok(())
    }
    
    pub(super) async fn update_raw_specs(milestone: String) -> Result<()> {
        let specs = vec!["gdev-raw.json", "gtest-raw.json", "g1-raw.json"];
        println!("Fetching release info…");
        let assets = get_release::get_release(milestone).await?;
        for spec in specs {
            if let Some(gdev_raw_specs) = assets.iter().find(|asset| asset.ends_with(spec)) {
                println!("Downloading {}…", spec);
                let client = reqwest::Client::new();
                let res = client.get(gdev_raw_specs).send().await?;
                let write_to = format!("./node/specs/{}", spec);
                fs::write(write_to, res.bytes().await?)?;
            }
        }
        println!("Done.");
        Ok(())
    }
    
    fn gen_release_notes(currency: String, srtool_output: String) -> Result<String> {
        println!("Read srtool output… ");
    
        // Read the srtool json output
        let srtool: Srtool = serde_json::from_str(
            srtool_output
                .lines()
                .last()
                .ok_or_else(|| anyhow!("empty srtool output"))?,
        )
        .with_context(|| "Fail to parse srtool json output")?;
    
        // Read template file
        let template = String::from(
            "
    ## {currency}
    
    ```
    🔨 Srtool version: {srtool_version}
    🦀 Rustc version: {rustc_version}
    🏋️ Runtime Size: {runtime_human_size} ({runtime_size} bytes)
    🔥 Core Version: {core_version}
    🗜 Compressed: Yes: {compression_percent} %
    🎁 Metadata version: {metadata_version}
    🗳️ system.setCode hash: {proposal_hash}
    #️⃣ Blake2-256 hash:  {blake2_256}
    ```
    ",
        );
    
        // Prepare srtool values
        let uncompressed_size = srtool.runtimes.compact.subwasm.size;
        let wasm = srtool.runtimes.compressed.subwasm;
        let compression_percent = (1.0 - (wasm.size as f64 / uncompressed_size as f64)) * 100.0;
    
        // Fill template values
        let mut values = std::collections::HashMap::new();
        values.insert("currency".to_owned(), currency);
        values.insert("srtool_version".to_owned(), srtool.gen);
        values.insert("rustc_version".to_owned(), srtool.rustc);
        values.insert(
            "runtime_human_size".to_owned(),
            format!("{} KB", wasm.size / 1_024),
        );
        values.insert("runtime_size".to_owned(), wasm.size.to_string());
        values.insert(
            "core_version".to_owned(),
            format!(
                "{}-{}",
                wasm.core_version.spec_name, wasm.core_version.spec_version
            ),
        );
        values.insert(
            "compression_percent".to_owned(),
            format!("{:.2}", compression_percent),
        );
        values.insert(
            "metadata_version".to_owned(),
            wasm.metadata_version.to_string(),
        );
        values.insert("proposal_hash".to_owned(), wasm.proposal_hash);
        values.insert("blake2_256".to_owned(), wasm.blake2_256);
    
        // Render template
        placeholder::render(&template, &values).map_err(|e| anyhow!("Fail to render template: {}", e))
    }
    
    pub(crate) async fn create_asset_link(
        tag: String,
        asset_name: String,
        asset_url: String,
    ) -> Result<()> {
        let gitlab_token =
            std::env::var("GITLAB_TOKEN").with_context(|| "missing env var GITLAB_TOKEN")?;
        create_asset_link::create_asset_link(gitlab_token, tag, asset_name, asset_url).await?;
    
        Ok(())
    }