diff --git a/Cargo.lock b/Cargo.lock index 085c7339e68cb32e2991f83b16a990021bd945f2..fb1b1b03ef6780a8a447945f607c539396d65766 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -133,6 +133,12 @@ version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "be4dc07131ffa69b8072d35f5007352af944213cde02545e2103680baed38fcd" +[[package]] +name = "ascii" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eab1c04a571841102f5345a8fc0f6bb3d31c315dec879b5c6e42e40ce7ffa34e" + [[package]] name = "asn1_der" version = "0.7.4" @@ -850,6 +856,19 @@ dependencies = [ "os_str_bytes", ] +[[package]] +name = "combine" +version = "3.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da3da6baa321ec19e1cc41d31bf599f00c783d0517095cdaf0332e3fe8d20680" +dependencies = [ + "ascii", + "byteorder", + "either", + "memchr", + "unreachable", +] + [[package]] name = "common-runtime" version = "0.8.0-dev" @@ -1627,6 +1646,15 @@ version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f" +[[package]] +name = "encoding_rs" +version = "0.8.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9852635589dc9f9ea1b6fe9f05b50ef208c85c834a562f0c6abb1c475736ec2b" +dependencies = [ + "cfg-if 1.0.0", +] + [[package]] name = "enum-as-inner" version = "0.3.3" @@ -1704,6 +1732,28 @@ dependencies = [ "futures 0.3.19", ] +[[package]] +name = "failure" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d32e9bd16cc02eae7db7ef620b392808b89f6a5e16bb3497d159c6b92a0f4f86" +dependencies = [ + "backtrace", + "failure_derive", +] + +[[package]] +name = "failure_derive" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa4da3c766cd7a0db8242e326e9e4e081edd567072893ed320008189715366a4" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "synstructure", +] + [[package]] name = "fake-simd" version = "0.1.2" @@ -1809,6 +1859,21 @@ version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" +[[package]] +name = "foreign-types" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" +dependencies = [ + "foreign-types-shared", +] + +[[package]] +name = "foreign-types-shared" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" + [[package]] name = "fork-tree" version = "3.0.0" @@ -2502,6 +2567,64 @@ dependencies = [ "web-sys", ] +[[package]] +name = "graphql-introspection-query" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f2a4732cf5140bd6c082434494f785a19cfb566ab07d1382c3671f5812fed6d" +dependencies = [ + "serde", +] + +[[package]] +name = "graphql-parser" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5613c31f18676f164112732202124f373bb2103ff017b3b85ca954ea6a66ada" +dependencies = [ + "combine", + "failure", +] + +[[package]] +name = "graphql_client" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9b58571cfc3cc42c3e8ff44fc6cfbb6c0dea17ed22d20f9d8f1efc4e8209a3f" +dependencies = [ + "graphql_query_derive", + "serde", + "serde_json", +] + +[[package]] +name = "graphql_client_codegen" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4bf9cd823359d74ad3d3ecf1afd4a975f4ff2f891cdf9a66744606daf52de8c" +dependencies = [ + "graphql-introspection-query", + "graphql-parser", + "heck 0.3.3", + "lazy_static", + "proc-macro2", + "quote", + "serde", + "serde_json", + "syn", +] + +[[package]] +name = "graphql_query_derive" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e56b093bfda71de1da99758b036f4cc811fd2511c8a76f75680e9ffbd2bb4251" +dependencies = [ + "graphql_client_codegen", + "proc-macro2", + "syn", +] + [[package]] name = "gtest-runtime" version = "3.0.0" @@ -2736,9 +2859,9 @@ dependencies = [ [[package]] name = "httparse" -version = "1.5.1" +version = "1.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "acd94fdbe1d4ff688b67b04eee2e17bd50995534a61539e45adfefb45e5e5503" +checksum = "496ce29bb5a52785b44e0f7ca2847ae0bb839c9bd28f69acac9b99d461c0c04c" [[package]] name = "httpdate" @@ -2754,9 +2877,9 @@ checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" [[package]] name = "hyper" -version = "0.14.16" +version = "0.14.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7ec3e62bdc98a2f0393a5048e4c30ef659440ea6e0e572965103e72bd836f55" +checksum = "42dc3c131584288d375f2d07f822b0cb012d8c6fb899a5b9fdb3cb7eb9b6004f" dependencies = [ "bytes 1.1.0", "futures-channel", @@ -2767,7 +2890,7 @@ dependencies = [ "http-body", "httparse", "httpdate", - "itoa 0.4.7", + "itoa 1.0.1", "pin-project-lite 0.2.7", "socket2 0.4.1", "tokio", @@ -2809,6 +2932,19 @@ dependencies = [ "webpki-roots 0.22.2", ] +[[package]] +name = "hyper-tls" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6183ddfa99b85da61a140bea0efc93fdf56ceaa041b37d553518030827f9905" +dependencies = [ + "bytes 1.1.0", + "hyper", + "native-tls", + "tokio", + "tokio-native-tls", +] + [[package]] name = "ident_case" version = "1.0.1" @@ -3019,7 +3155,7 @@ dependencies = [ "socket2 0.3.19", "widestring", "winapi 0.3.9", - "winreg", + "winreg 0.6.2", ] [[package]] @@ -4320,6 +4456,12 @@ dependencies = [ "zeroize", ] +[[package]] +name = "mime" +version = "0.3.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a60c7ce501c71e03a9c9c0d35b861413ae925bd979cc7a4e30d060069aaac8d" + [[package]] name = "minimal-lexical" version = "0.2.1" @@ -4538,6 +4680,24 @@ dependencies = [ "rand 0.8.4", ] +[[package]] +name = "native-tls" +version = "0.2.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd7e2f3618557f980e0b17e8856252eee3c97fa12c54dff0ca290fb6266ca4a9" +dependencies = [ + "lazy_static", + "libc", + "log", + "openssl", + "openssl-probe", + "openssl-sys", + "schannel", + "security-framework", + "security-framework-sys", + "tempfile", +] + [[package]] name = "net2" version = "0.2.37" @@ -4787,12 +4947,51 @@ dependencies = [ "syn", ] +[[package]] +name = "openssl" +version = "0.10.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb81a6430ac911acb25fe5ac8f1d2af1b4ea8a4fdfda0f1ee4292af2e2d8eb0e" +dependencies = [ + "bitflags", + "cfg-if 1.0.0", + "foreign-types", + "libc", + "once_cell", + "openssl-macros", + "openssl-sys", +] + +[[package]] +name = "openssl-macros" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b501e44f11665960c7e7fcf062c7d96a14ade4aa98116c004b2e37b5be7d736c" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "openssl-probe" version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "28988d872ab76095a6e6ac88d99b54fd267702734fd7ffe610ca27f533ddb95a" +[[package]] +name = "openssl-sys" +version = "0.9.74" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "835363342df5fba8354c5b453325b110ffd54044e588c539cf2f20a8014e4cb1" +dependencies = [ + "autocfg", + "cc", + "libc", + "pkg-config", + "vcpkg", +] + [[package]] name = "os_str_bytes" version = "6.0.0" @@ -6209,6 +6408,43 @@ dependencies = [ "winapi 0.3.9", ] +[[package]] +name = "reqwest" +version = "0.11.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b75aa69a3f06bbcc66ede33af2af253c6f7a86b1ca0033f60c580a27074fbf92" +dependencies = [ + "base64", + "bytes 1.1.0", + "encoding_rs", + "futures-core", + "futures-util", + "h2", + "http", + "http-body", + "hyper", + "hyper-tls", + "ipnet", + "js-sys", + "lazy_static", + "log", + "mime", + "native-tls", + "percent-encoding 2.1.0", + "pin-project-lite 0.2.7", + "serde", + "serde_json", + "serde_urlencoded", + "tokio", + "tokio-native-tls", + "tower-service", + "url 2.2.2", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", + "winreg 0.10.1", +] + [[package]] name = "resolv-conf" version = "0.7.0" @@ -7510,6 +7746,18 @@ dependencies = [ "serde", ] +[[package]] +name = "serde_urlencoded" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" +dependencies = [ + "form_urlencoded", + "itoa 1.0.1", + "ryu", + "serde", +] + [[package]] name = "sha-1" version = "0.8.2" @@ -8839,6 +9087,16 @@ dependencies = [ "syn", ] +[[package]] +name = "tokio-native-tls" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7d995660bd2b7f8c1568414c1126076c13fbb725c40112dc0120b78eb9b717b" +dependencies = [ + "native-tls", + "tokio", +] + [[package]] name = "tokio-rustls" version = "0.22.0" @@ -9188,6 +9446,15 @@ dependencies = [ "subtle", ] +[[package]] +name = "unreachable" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "382810877fe448991dfc7f0dd6e3ae5d58088fd0ea5e35189655f84e6814fa56" +dependencies = [ + "void", +] + [[package]] name = "unsigned-varint" version = "0.5.1" @@ -9783,6 +10050,15 @@ dependencies = [ "winapi 0.3.9", ] +[[package]] +name = "winreg" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "80d0f4e272c85def139476380b12f9ac60926689dd2e01d4923222f40580869d" +dependencies = [ + "winapi 0.3.9", +] + [[package]] name = "ws2_32-sys" version = "0.2.1" @@ -9817,14 +10093,17 @@ dependencies = [ "anyhow", "clap", "frame-metadata", + "graphql_client", "hex", "memmap2 0.5.0", "parity-scale-codec", "placeholder", + "reqwest", "run_script", "scale-info", "serde", "serde_json", + "tokio", "version-compare", "version_check", ] diff --git a/xtask/Cargo.toml b/xtask/Cargo.toml index cb1e389cb49bd5f35b77855623575f05bc708e31..9f85cb58a42b07a9b0c7a251cc40f351618d59a5 100644 --- a/xtask/Cargo.toml +++ b/xtask/Cargo.toml @@ -17,12 +17,15 @@ anyhow = "1.0.32" clap = { version = "3.0", features = ["derive"] } codec = { package = "parity-scale-codec", version = "2", default-features = false, features = ["derive", "full", "bit-vec"] } frame-metadata = "14.0.0" +graphql_client = "0.10.0" hex = "0.4" memmap2 = "0.5.0" placeholder = "1.1.3" +reqwest = { version = "0.11.11", features = ["json"] } run_script = "0.6.3" scale-info = { version = "1.0.0", features = ["bit-vec"] } -serde = "1" +serde = { version = "1.0.101", features = ["derive"] } serde_json = "1.0" +tokio = { version = "1.15.0", features = ["macros"] } version_check = "0.9.2" version-compare = "0.0.11" diff --git a/xtask/res/create_release.gql b/xtask/res/create_release.gql new file mode 100644 index 0000000000000000000000000000000000000000..de9c9d6170d40253c6a4f4bd3d7594f1ac8df830 --- /dev/null +++ b/xtask/res/create_release.gql @@ -0,0 +1,13 @@ +mutation CreateReleaseMutation($branch: String!, $description: String!, $milestone: String!) { + releaseCreate(input: { + clientMutationId: "duniter-v2s-xtask" + description: $description + milestones: [$milestone] + name: $milestone + projectPath: "nodes/rust/duniter-v2s" + ref: $branch + tagName: $milestone + }) { + errors + } +} diff --git a/xtask/res/get_changes.gql b/xtask/res/get_changes.gql new file mode 100644 index 0000000000000000000000000000000000000000..2cb9db20866ae7efdf1ba14f10f39455d312b9f6 --- /dev/null +++ b/xtask/res/get_changes.gql @@ -0,0 +1,10 @@ +query GetChangesQuery($milestone: String!) { + project(fullPath: "nodes/rust/duniter-v2s") { + mergeRequests(milestoneTitle: $milestone, state: merged) { + nodes { + iid + title + } + } + } +} diff --git a/xtask/res/runtime_release_notes.template b/xtask/res/runtime_release_notes.template index c33733edee15ce0f85ebb5001b2761cb5ca39e03..c1ee069f3189ef969bf86505d4c0dab5deddf3b3 100644 --- a/xtask/res/runtime_release_notes.template +++ b/xtask/res/runtime_release_notes.template @@ -5,12 +5,12 @@ The runtimes have been built using [{srtool_version}](https://github.com/parityt ## ÄžDev ``` -ðŸ‹ï¸ 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} +ðŸ‹ï¸ 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} ``` # Changes diff --git a/xtask/res/schema.gql b/xtask/res/schema.gql new file mode 100644 index 0000000000000000000000000000000000000000..27559c05236ac9e6fa36a32e93f0452b172bdea3 --- /dev/null +++ b/xtask/res/schema.gql @@ -0,0 +1,85 @@ +schema { + query: Query + mutation: Mutation +} + +type Query { + project(fullPath: ID!): Project + mergeRequest(id: MergeRequestID!): MergeRequest +} + +type Mutation { + releaseCreate(input: ReleaseCreateInput!): ReleaseCreatePayload +} + +type Project { + mergeRequests( + state: MergeRequestState + milestoneTitle: String + ): MergeRequestConnection +} + +scalar MergeRequestID + +type MergeRequest { + conflicts: Boolean! + diffHeadSha: String + draft: Boolean! + headPipeline: Pipeline + id: ID! + iid: String! + mergeable: Boolean! + title: String! +} + +type MergeRequestConnection { + count: Int! + nodes: [MergeRequest] +} + +enum MergeRequestState { + opened + closed + locked + all + merged +} + +type Pipeline { + active: Boolean! + cancelable: Boolean! + id: ID! + iid: String! +} + +input ReleaseCreateInput { + projectPath: ID! + tagName: String! + name: String + description: String + milestones: [String!] + assets: ReleaseAssetsInput + clientMutationId: String +} + +input ReleaseAssetsInput { + links: [ReleaseAssetLinkInput!] +} + +input ReleaseAssetLinkInput { + name: String! + url: String! + directAssetPath: String + linkType: ReleaseAssetLinkType = OTHER +} + +enum ReleaseAssetLinkType { + OTHER + RUNBOOK + PACKAGE + IMAGE +} + +type ReleaseCreatePayload { + errors: [String!]! +} diff --git a/xtask/src/main.rs b/xtask/src/main.rs index 934d2f49640722c30154c4b44ed3e4c5585e05e0..c14b004c6df2483512669e88691bd80644a71f5e 100644 --- a/xtask/src/main.rs +++ b/xtask/src/main.rs @@ -56,7 +56,8 @@ enum DuniterXTaskCommand { Test, } -fn main() -> Result<()> { +#[tokio::main(flavor = "current_thread")] +async fn main() -> Result<()> { let args = DuniterXTask::parse(); if !version_check::is_min_version(MIN_RUST_VERSION).unwrap_or(false) @@ -78,7 +79,7 @@ fn main() -> Result<()> { inject_runtime_code(&raw_spec, &runtime) } DuniterXTaskCommand::ReleaseRuntime { spec_version } => { - release_runtime::release_runtime(spec_version) + release_runtime::release_runtime(spec_version).await } DuniterXTaskCommand::Test => test(), } diff --git a/xtask/src/release_runtime.rs b/xtask/src/release_runtime.rs index 978ea69827a3ecf44e033ca39407ff2027e9f1b5..084af923f1eaacffe07e064595ff7f13ea86280d 100644 --- a/xtask/src/release_runtime.rs +++ b/xtask/src/release_runtime.rs @@ -14,30 +14,33 @@ // You should have received a copy of the GNU Affero General Public License // along with Substrate-Libre-Currency. If not, see <https://www.gnu.org/licenses/>. +mod create_release; +mod get_changes; + use anyhow::{anyhow, Context, Result}; use serde::Deserialize; use std::io::Read; use std::process::Command; -#[derive(Deserialize)] +#[derive(Default, Deserialize)] struct Srtool { gen: String, rustc: String, runtimes: SrtoolRuntimes, } -#[derive(Deserialize)] +#[derive(Default, Deserialize)] struct SrtoolRuntimes { compact: SrtoolRuntime, compressed: SrtoolRuntime, } -#[derive(Deserialize)] +#[derive(Default, Deserialize)] struct SrtoolRuntime { subwasm: SrtoolRuntimeSubWasm, } -#[derive(Deserialize)] +#[derive(Default, Deserialize)] struct SrtoolRuntimeSubWasm { core_version: String, metadata_version: u32, @@ -46,7 +49,7 @@ struct SrtoolRuntimeSubWasm { proposal_hash: String, } -pub(super) fn release_runtime(_spec_version: u32) -> Result<()> { +pub(super) async fn release_runtime(spec_version: u32) -> Result<()> { // Get current dir let pwd = std::env::current_dir()? .into_os_string() @@ -88,16 +91,20 @@ pub(super) fn release_runtime(_spec_version: u32) -> Result<()> { .with_context(|| "Fail to parse srtool json output")?; // Generate release notes - let release_notes = - gen_release_notes(srtool).with_context(|| "Fail to generate release notes")?; + let release_notes = gen_release_notes(spec_version, srtool) + .await + .with_context(|| "Fail to generate release notes")?; // TODO: Call gitlab API to publish the release notes (and upload the wasm) println!("{}", release_notes); + let gitlab_token = + std::env::var("GITLAB_TOKEN").with_context(|| "missing env var GITLAB_TOKEN")?; + create_release::create_release(gitlab_token, spec_version, release_notes).await?; Ok(()) } -fn gen_release_notes(srtool: Srtool) -> Result<String> { +async fn gen_release_notes(spec_version: u32, srtool: Srtool) -> Result<String> { // Read template file const RELEASE_NOTES_TEMPLATE_FILEPATH: &str = "xtask/res/runtime_release_notes.template"; let mut file = std::fs::File::open(RELEASE_NOTES_TEMPLATE_FILEPATH)?; @@ -109,8 +116,8 @@ fn gen_release_notes(srtool: Srtool) -> Result<String> { let wasm = srtool.runtimes.compressed.subwasm; let compression_percent = (1.0 - (wasm.size as f64 / uncompressed_size as f64)) * 100.0; - // TODO: get changes (list of MRs) from gitlab API - let changes = String::new(); + // Get changes (list of MRs) from gitlab API + let changes = get_changes::get_changes(spec_version).await?; // Fill template values let mut values = std::collections::HashMap::new(); diff --git a/xtask/src/release_runtime/create_release.rs b/xtask/src/release_runtime/create_release.rs new file mode 100644 index 0000000000000000000000000000000000000000..11d0b3afa52ab3e011ac70508d5efc71a9c20c64 --- /dev/null +++ b/xtask/src/release_runtime/create_release.rs @@ -0,0 +1,72 @@ +// Copyright 2021 Axiom-Team +// +// This file is part of Substrate-Libre-Currency. +// +// Substrate-Libre-Currency 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. +// +// Substrate-Libre-Currency 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 Substrate-Libre-Currency. If not, see <https://www.gnu.org/licenses/>. + +use anyhow::{anyhow, Result}; +use graphql_client::{GraphQLQuery, Response}; + +#[derive(GraphQLQuery)] +#[graphql( + schema_path = "res/schema.gql", + query_path = "res/create_release.gql", + response_derives = "Debug" +)] +pub struct CreateReleaseMutation; + +pub(super) async fn create_release( + gitlab_token: String, + spec_version: u32, + release_notes: String, +) -> Result<()> { + // this is the important line + let request_body = CreateReleaseMutation::build_query(create_release_mutation::Variables { + branch: format!("release/runtime-{}", spec_version - (spec_version % 100)), + description: release_notes, + milestone: format!("runtime-{}", spec_version), + }); + + let client = reqwest::Client::new(); + let res = client + .post("https://git.duniter.org/api/graphql") + .header("PRIVATE-TOKEN", gitlab_token) + .json(&request_body) + .send() + .await?; + let response_body: Response<create_release_mutation::ResponseData> = res.json().await?; + + if let Some(data) = response_body.data { + if let Some(release_create) = data.release_create { + if release_create.errors.is_empty() { + Ok(()) + } else { + println!("{} errors:", release_create.errors.len()); + for error in release_create.errors { + println!("{}", error); + } + Err(anyhow!("Logic errors")) + } + } else { + Err(anyhow!("Invalid response: no release_create")) + } + } else if let Some(errors) = response_body.errors { + println!("{} errors:", errors.len()); + for error in errors { + println!("{}", error); + } + Err(anyhow!("GraphQL errors")) + } else { + Err(anyhow!("Invalid response: no data nor errors")) + } +} diff --git a/xtask/src/release_runtime/get_changes.rs b/xtask/src/release_runtime/get_changes.rs new file mode 100644 index 0000000000000000000000000000000000000000..0caaa68d3578ae3cb72ca9e018dcafcc429beb22 --- /dev/null +++ b/xtask/src/release_runtime/get_changes.rs @@ -0,0 +1,75 @@ +// Copyright 2021 Axiom-Team +// +// This file is part of Substrate-Libre-Currency. +// +// Substrate-Libre-Currency 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. +// +// Substrate-Libre-Currency 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 Substrate-Libre-Currency. If not, see <https://www.gnu.org/licenses/>. + +use anyhow::{anyhow, Result}; +use graphql_client::{GraphQLQuery, Response}; + +#[derive(GraphQLQuery)] +#[graphql( + schema_path = "res/schema.gql", + query_path = "res/get_changes.gql", + response_derives = "Debug" +)] +pub struct GetChangesQuery; + +pub(super) async fn get_changes(spec_version: u32) -> Result<String> { + // this is the important line + let request_body = GetChangesQuery::build_query(get_changes_query::Variables { + milestone: format!("runtime-{}", spec_version), + }); + + let client = reqwest::Client::new(); + let res = client + .post("https://git.duniter.org/api/graphql") + .json(&request_body) + .send() + .await?; + let response_body: Response<get_changes_query::ResponseData> = res.json().await?; + + if let Some(data) = response_body.data { + if let Some(project) = data.project { + if let Some(merge_requests) = project.merge_requests { + if let Some(nodes) = merge_requests.nodes { + let mut changes = String::new(); + for merge_request in nodes { + if let Some(merge_request) = merge_request { + changes.push_str(&format!( + "* {mr_title} (!{mr_number})\n", + mr_title = merge_request.title, + mr_number = merge_request.iid + )); + } + } + Ok(changes) + } else { + Err(anyhow!("No changes found")) + } + } else { + Err(anyhow!("No changes found")) + } + } else { + Err(anyhow!("Project not found")) + } + } else if let Some(errors) = response_body.errors { + println!("{} errors:", errors.len()); + for error in errors { + println!("{}", error); + } + Err(anyhow!("GraphQL errors")) + } else { + Err(anyhow!("Invalid response: no data nor errors")) + } +}