From 3f5ab34c44a893724dd96c9fc29d8f27fa406e37 Mon Sep 17 00:00:00 2001 From: mb Date: Sun, 30 Jun 2024 14:10:47 +0200 Subject: [PATCH] chore: Update build scripts to include release notes --- .github/workflows/build.yml | 3 ++ cliff-release-notes.toml | 71 +++++++++++++++++++++++++++++++++++++ cliff.toml | 22 ++++++------ xtask/src/wasm.rs | 68 ++++++++++++++++++++++++++++++----- 4 files changed, 145 insertions(+), 19 deletions(-) create mode 100644 cliff-release-notes.toml diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 178245d5..0eef5d24 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -36,6 +36,9 @@ jobs: with: version: latest + - name: Install git-cliff + run: cargo install git-cliff + - name: Verify versions run: rustc --version && rustup --version && cargo --version && wasm-pack --version && node --version && npm --version && node -p process.versions.v8 diff --git a/cliff-release-notes.toml b/cliff-release-notes.toml new file mode 100644 index 00000000..e41a3493 --- /dev/null +++ b/cliff-release-notes.toml @@ -0,0 +1,71 @@ +# git-cliff ~ configuration file +# https://git-cliff.org/docs/configuration + +[remote.github] +owner = "prose-im" +repo = "prose-core-client" +token = "" + +[changelog] +# template for the release notes +# https://keats.github.io/tera/docs/#introduction +body = """ +{% for commit in commits %} + {% if commit.github.pr_title -%} + {%- set commit_message = commit.github.pr_title -%} + {%- else -%} + {%- set commit_message = commit.message -%} + {%- endif -%} + * {{ commit_message | split(pat="\n") | first | trim }}\ + {% if commit.github.username %} by @{{ commit.github.username }}{%- endif -%} + {% if commit.github.pr_number %} in \ + [#{{ commit.github.pr_number }}]({{ self::remote_url() }}/pull/{{ commit.github.pr_number }}) \ + {%- endif %} +{%- endfor -%} +{%- macro remote_url() -%} + https://github.com/{{ remote.github.owner }}/{{ remote.github.repo }} +{%- endmacro -%} +""" +# remove the leading and trailing whitespace from the template +trim = true +# changelog footer +footer = "" +# postprocessors +postprocessors = [ + { pattern = '', replace = "https://github.com/prose-im/prose-core-client" }, # replace repository URL + { pattern = '', replace = "https://github.com/prose-im/prose-app-web" }, # replace repository URL +] + +[git] +# parse the commits based on https://www.conventionalcommits.org +conventional_commits = true +# filter out the commits that are not conventional +filter_unconventional = true +# process each line of a commit as an individual commit +split_commits = false +# regex for preprocessing the commit messages +commit_preprocessors = [ + # Replace issue numbers + { pattern = '\((\w+\s)?#([0-9]+)\)', replace = "([#${2}](/issues/${2}))" }, + { pattern = '\((\w+\s)?prose-im\/prose-app-web(\/)?#([0-9]+)\)', replace = "([prose-app-web#${3}](/issues/${3}))" }, +] +commit_parsers = [ + { message = "^style", skip = true }, + { message = "^test", skip = true }, + { message = "^chore: release", skip = true }, + { message = "^chore|^ci", skip = true }, +] +# protect breaking changes from being skipped due to matching a skipping commit_parser +protect_breaking_commits = false +# filter out the commits that are not matched by commit parsers +filter_commits = false +# regex for matching git tags +# tag_pattern = "v[0-9].*" +# regex for skipping tags +skip_tags = "beta|alpha" +# regex for ignoring tags +ignore_tags = "rc" +# sort the tags topologically +topo_order = false +# sort the commits inside sections by oldest/newest order +sort_commits = "newest" \ No newline at end of file diff --git a/cliff.toml b/cliff.toml index e7f5793f..17985a17 100644 --- a/cliff.toml +++ b/cliff.toml @@ -10,9 +10,11 @@ token = "" # template for the changelog body # https://keats.github.io/tera/docs/#introduction body = """ +{%- if version %} ## What's Changed - {%- if version %} in {{ version }}{%- endif -%} +{% raw %}\n{% endraw %} +{%- endif -%} {% for commit in commits %} {% if commit.github.pr_title -%} {%- set commit_message = commit.github.pr_title -%} @@ -55,8 +57,8 @@ trim = true footer = "" # postprocessors postprocessors = [ - { pattern = '', replace = "https://github.com/prose-im/prose-core-client" }, # replace repository URL - { pattern = '', replace = "https://github.com/prose-im/prose-app-web" }, # replace repository URL + { pattern = '', replace = "https://github.com/prose-im/prose-core-client" }, # replace repository URL + { pattern = '', replace = "https://github.com/prose-im/prose-app-web" }, # replace repository URL ] [git] @@ -68,15 +70,15 @@ filter_unconventional = true split_commits = false # regex for preprocessing the commit messages commit_preprocessors = [ - # Replace issue numbers - { pattern = '\((\w+\s)?#([0-9]+)\)', replace = "([#${2}](/issues/${2}))"}, - { pattern = '\((\w+\s)?prose-im\/prose-app-web(\/)?#([0-9]+)\)', replace = "([prose-app-web#${3}](/issues/${3}))"}, + # Replace issue numbers + { pattern = '\((\w+\s)?#([0-9]+)\)', replace = "([#${2}](/issues/${2}))" }, + { pattern = '\((\w+\s)?prose-im\/prose-app-web(\/)?#([0-9]+)\)', replace = "([prose-app-web#${3}](/issues/${3}))" }, ] commit_parsers = [ - { message = "^style", skip = true }, - { message = "^test", skip = true }, - { message = "^chore: release", skip = true }, - { message = "^chore|^ci", skip = true }, + { message = "^style", skip = true }, + { message = "^test", skip = true }, + { message = "^chore: release", skip = true }, + { message = "^chore|^ci", skip = true }, ] # protect breaking changes from being skipped due to matching a skipping commit_parser protect_breaking_commits = false diff --git a/xtask/src/wasm.rs b/xtask/src/wasm.rs index 658cc6eb..a53c20ae 100644 --- a/xtask/src/wasm.rs +++ b/xtask/src/wasm.rs @@ -9,7 +9,7 @@ use std::path::{Path, PathBuf}; use std::str::FromStr; use std::{env, fs}; -use anyhow::{anyhow, Result}; +use anyhow::{anyhow, bail, Result}; use octocrab::Octocrab; use serde::{Deserialize, Serialize}; use url::Url; @@ -138,6 +138,7 @@ fn run_wasm_pack(sh: &Shell, cmd: WasmPackCommand) -> Result<()> { } async fn run_release_github( + sh: &Shell, github_token: &str, version: &str, filename: &str, @@ -152,6 +153,18 @@ async fn run_release_github( let body = reqwest::Body::wrap_stream(stream); let client = reqwest::Client::builder().build()?; + let cwd = env::current_dir()?; + let config_file = cwd.join("cliff-release-notes.toml"); + let output = String::from_utf8( + cmd!( + sh, + "git cliff --workdir {cwd} --config {config_file} --latest" + ) + .output()? + .stdout, + )?; + let release_notes = output.trim(); + // Create GitHub release let github_release = Octocrab::builder() .personal_token(github_token.to_string()) @@ -163,6 +176,7 @@ async fn run_release_github( .name(&format!("Version {}", version)) .draft(false) .prerelease(true) + .body(release_notes) .send() .await?; @@ -231,9 +245,10 @@ fn run_release_npm(sh: &Shell, npm_token: &str, file_path: &PathBuf) -> Result<( } async fn publish(sh: &Shell) -> Result<()> { + ensure_git_cliff_installed(sh)?; + // Read tokens from environment - let github_token = - std::env::var("GITHUB_TOKEN").expect("GITHUB_TOKEN env variable is required"); + let github_token = env::var("GITHUB_TOKEN").expect("GITHUB_TOKEN env variable is required"); let npm_token = std::env::var("NPM_TOKEN").expect("NPM_TOKEN env variable is required"); // Build & pack archive contents @@ -268,7 +283,7 @@ async fn publish(sh: &Shell) -> Result<()> { .join(&filename); // Upload release archive to GitHub - run_release_github(&github_token, &version, &filename, &file_path).await?; + run_release_github(sh, &github_token, &version, &filename, &file_path).await?; // Upload release archive to NPM run_release_npm(sh, &npm_token, &file_path)?; @@ -277,7 +292,11 @@ async fn publish(sh: &Shell) -> Result<()> { } async fn bump_patch(sh: &Shell) -> Result<()> { - let manifest_path = env::current_dir()? + ensure_git_cliff_installed(sh)?; + + let cwd = env::current_dir()?; + + let manifest_path = cwd .join(paths::BINDINGS) .join(paths::bindings::WASM) .join("Cargo.toml"); @@ -295,15 +314,28 @@ async fn bump_patch(sh: &Shell) -> Result<()> { // Increment patch version version.patch += 1; + let version = version.to_string(); + + // Update changelog + let changelog_path = cwd.join("CHANGELOG.md"); + cmd!( + sh, + "git cliff --workdir {cwd} --output {changelog_path} --tag 2.0.0" + ) + .run()?; + + // Commit changelog + let commit_message = "chore: Update changelog"; + cmd!(sh, "git add {changelog_path}").run()?; + cmd!(sh, "git commit -m {commit_message}").run()?; + // Update the version in the manifest - manifest["package"]["version"] = toml_edit::value(version.to_string()); + manifest["package"]["version"] = toml_edit::value(&version); fs::write(&manifest_path, manifest.to_string())?; - let version = version.to_string(); + // Commit manifest let manifest_path = manifest_path.display().to_string(); let commit_message = format!("chore(sdk-js): Bump version to {version}"); - - // Commit changes cmd!(sh, "git add {manifest_path}").run()?; cmd!(sh, "git commit -m {commit_message}").run()?; @@ -312,3 +344,21 @@ async fn bump_patch(sh: &Shell) -> Result<()> { Ok(()) } + +fn ensure_git_cliff_installed(sh: &Shell) -> Result<()> { + let git_cliff_installed = cmd!(sh, "git cliff --version") + .output() + .map(|output| output.status.success()) + .unwrap_or(false); + + if !git_cliff_installed { + bail!( + r#"git-cliff is not installed. + + Install by running `cargo install git-cliff or see other options at https://git-cliff.org/docs/installation/crates-io. + "# + ) + } + + Ok(()) +}