atagen

matrix-rust-sdk

public
Star0
Watch0
ssh://brewery@pls.lobotomise.me:33/atagen/matrix-rust-sdk.git

Blame: xtask/src/release.rs

7ff8adafe9e4atagen2026-10-22 12:30 UTC1
use clap::{Args, Subcommand, ValueEnum};
7ff8adafe9e4atagen2026-10-22 12:30 UTC2
use xshell::{Cmd, cmd};
7ff8adafe9e4atagen2026-10-22 12:30 UTC3
7ff8adafe9e4atagen2026-10-22 12:30 UTC4
use crate::{Result, sh};
7ff8adafe9e4atagen2026-10-22 12:30 UTC5
7ff8adafe9e4atagen2026-10-22 12:30 UTC6
#[derive(Args)]
7ff8adafe9e4atagen2026-10-22 12:30 UTC7
pub struct ReleaseArgs {
7ff8adafe9e4atagen2026-10-22 12:30 UTC8
    #[clap(subcommand)]
7ff8adafe9e4atagen2026-10-22 12:30 UTC9
    cmd: ReleaseCommand,
7ff8adafe9e4atagen2026-10-22 12:30 UTC10
}
7ff8adafe9e4atagen2026-10-22 12:30 UTC11
7ff8adafe9e4atagen2026-10-22 12:30 UTC12
#[derive(PartialEq, Subcommand)]
7ff8adafe9e4atagen2026-10-22 12:30 UTC13
enum ReleaseCommand {
7ff8adafe9e4atagen2026-10-22 12:30 UTC14
    /// Prepare the release of the matrix-sdk workspace.
7ff8adafe9e4atagen2026-10-22 12:30 UTC15
    ///
7ff8adafe9e4atagen2026-10-22 12:30 UTC16
    /// This command will update the `README.md`, update the `CHANGELOG.md` file
7ff8adafe9e4atagen2026-10-22 12:30 UTC17
    /// using, and bump the versions in the `Cargo.toml` files.
7ff8adafe9e4atagen2026-10-22 12:30 UTC18
    Prepare {
7ff8adafe9e4atagen2026-10-22 12:30 UTC19
        /// What type of version bump we should perform.
7ff8adafe9e4atagen2026-10-22 12:30 UTC20
        version: ReleaseVersion,
7ff8adafe9e4atagen2026-10-22 12:30 UTC21
        /// Actually prepare a release. Dry-run mode is the default.
7ff8adafe9e4atagen2026-10-22 12:30 UTC22
        #[clap(long)]
7ff8adafe9e4atagen2026-10-22 12:30 UTC23
        execute: bool,
7ff8adafe9e4atagen2026-10-22 12:30 UTC24
        /// The crate or package that should be released. Use this if you'd like
7ff8adafe9e4atagen2026-10-22 12:30 UTC25
        /// to release only one specific crate. The default is to
7ff8adafe9e4atagen2026-10-22 12:30 UTC26
        /// release all crates.
7ff8adafe9e4atagen2026-10-22 12:30 UTC27
        #[clap(long)]
7ff8adafe9e4atagen2026-10-22 12:30 UTC28
        package: Option<String>,
7ff8adafe9e4atagen2026-10-22 12:30 UTC29
    },
7ff8adafe9e4atagen2026-10-22 12:30 UTC30
    /// Publish the release.
7ff8adafe9e4atagen2026-10-22 12:30 UTC31
    ///
7ff8adafe9e4atagen2026-10-22 12:30 UTC32
    /// This command will create signed tags, publish the release on crates.io,
7ff8adafe9e4atagen2026-10-22 12:30 UTC33
    /// and finally push the tags to the repo.
7ff8adafe9e4atagen2026-10-22 12:30 UTC34
    Publish {
7ff8adafe9e4atagen2026-10-22 12:30 UTC35
        /// Actually publish a release. Dry-run mode is the default
7ff8adafe9e4atagen2026-10-22 12:30 UTC36
        #[clap(long)]
7ff8adafe9e4atagen2026-10-22 12:30 UTC37
        execute: bool,
7ff8adafe9e4atagen2026-10-22 12:30 UTC38
        /// The crate or package that should be released. Use this if you'd like
7ff8adafe9e4atagen2026-10-22 12:30 UTC39
        /// to release only one specific crate. The default is to
7ff8adafe9e4atagen2026-10-22 12:30 UTC40
        /// release all crates.
7ff8adafe9e4atagen2026-10-22 12:30 UTC41
        #[clap(long)]
7ff8adafe9e4atagen2026-10-22 12:30 UTC42
        package: Option<String>,
7ff8adafe9e4atagen2026-10-22 12:30 UTC43
    },
7ff8adafe9e4atagen2026-10-22 12:30 UTC44
    /// Get a list of interesting changes that happened in the last week.
7ff8adafe9e4atagen2026-10-22 12:30 UTC45
    WeeklyReport,
7ff8adafe9e4atagen2026-10-22 12:30 UTC46
}
7ff8adafe9e4atagen2026-10-22 12:30 UTC47
7ff8adafe9e4atagen2026-10-22 12:30 UTC48
#[derive(Clone, Copy, Debug, Default, PartialEq, ValueEnum)]
7ff8adafe9e4atagen2026-10-22 12:30 UTC49
enum ReleaseVersion {
7ff8adafe9e4atagen2026-10-22 12:30 UTC50
    // TODO: Add a Major variant here once we're stable.
7ff8adafe9e4atagen2026-10-22 12:30 UTC51
    /// Create a new minor release.
7ff8adafe9e4atagen2026-10-22 12:30 UTC52
    #[default]
7ff8adafe9e4atagen2026-10-22 12:30 UTC53
    Minor,
7ff8adafe9e4atagen2026-10-22 12:30 UTC54
    /// Create a new patch release.
7ff8adafe9e4atagen2026-10-22 12:30 UTC55
    Patch,
7ff8adafe9e4atagen2026-10-22 12:30 UTC56
    /// Create a new release candidate.
7ff8adafe9e4atagen2026-10-22 12:30 UTC57
    Rc,
7ff8adafe9e4atagen2026-10-22 12:30 UTC58
}
7ff8adafe9e4atagen2026-10-22 12:30 UTC59
7ff8adafe9e4atagen2026-10-22 12:30 UTC60
impl ReleaseVersion {
7ff8adafe9e4atagen2026-10-22 12:30 UTC61
    fn as_str(&self) -> &str {
7ff8adafe9e4atagen2026-10-22 12:30 UTC62
        match self {
7ff8adafe9e4atagen2026-10-22 12:30 UTC63
            ReleaseVersion::Minor => "minor",
7ff8adafe9e4atagen2026-10-22 12:30 UTC64
            ReleaseVersion::Patch => "patch",
7ff8adafe9e4atagen2026-10-22 12:30 UTC65
            ReleaseVersion::Rc => "rc",
7ff8adafe9e4atagen2026-10-22 12:30 UTC66
        }
7ff8adafe9e4atagen2026-10-22 12:30 UTC67
    }
7ff8adafe9e4atagen2026-10-22 12:30 UTC68
}
7ff8adafe9e4atagen2026-10-22 12:30 UTC69
7ff8adafe9e4atagen2026-10-22 12:30 UTC70
impl ReleaseArgs {
7ff8adafe9e4atagen2026-10-22 12:30 UTC71
    pub fn run(self) -> Result<()> {
7ff8adafe9e4atagen2026-10-22 12:30 UTC72
        check_prerequisites();
7ff8adafe9e4atagen2026-10-22 12:30 UTC73
7ff8adafe9e4atagen2026-10-22 12:30 UTC74
        match self.cmd {
7ff8adafe9e4atagen2026-10-22 12:30 UTC75
            ReleaseCommand::Prepare { version, execute, package } => {
7ff8adafe9e4atagen2026-10-22 12:30 UTC76
                prepare(version, execute, package)
7ff8adafe9e4atagen2026-10-22 12:30 UTC77
            }
7ff8adafe9e4atagen2026-10-22 12:30 UTC78
            ReleaseCommand::Publish { execute, package } => publish(execute, package),
7ff8adafe9e4atagen2026-10-22 12:30 UTC79
            ReleaseCommand::WeeklyReport => weekly_report(),
7ff8adafe9e4atagen2026-10-22 12:30 UTC80
        }
7ff8adafe9e4atagen2026-10-22 12:30 UTC81
    }
7ff8adafe9e4atagen2026-10-22 12:30 UTC82
}
7ff8adafe9e4atagen2026-10-22 12:30 UTC83
7ff8adafe9e4atagen2026-10-22 12:30 UTC84
fn check_prerequisites() {
7ff8adafe9e4atagen2026-10-22 12:30 UTC85
    let sh = sh();
7ff8adafe9e4atagen2026-10-22 12:30 UTC86
7ff8adafe9e4atagen2026-10-22 12:30 UTC87
    if cmd!(sh, "cargo release --version").quiet().ignore_stdout().run().is_err() {
7ff8adafe9e4atagen2026-10-22 12:30 UTC88
        eprintln!("This command requires cargo-release, please install it.");
7ff8adafe9e4atagen2026-10-22 12:30 UTC89
        eprintln!(
7ff8adafe9e4atagen2026-10-22 12:30 UTC90
            "More info can be found at: \
7ff8adafe9e4atagen2026-10-22 12:30 UTC91
             https://github.com/crate-ci/cargo-release?tab=readme-ov-file#install"
7ff8adafe9e4atagen2026-10-22 12:30 UTC92
        );
7ff8adafe9e4atagen2026-10-22 12:30 UTC93
7ff8adafe9e4atagen2026-10-22 12:30 UTC94
        std::process::exit(1);
7ff8adafe9e4atagen2026-10-22 12:30 UTC95
    }
7ff8adafe9e4atagen2026-10-22 12:30 UTC96
7ff8adafe9e4atagen2026-10-22 12:30 UTC97
    if cmd!(sh, "gh version").quiet().ignore_stdout().run().is_err() {
7ff8adafe9e4atagen2026-10-22 12:30 UTC98
        eprintln!("This command requires GitHub CLI, please install it.");
7ff8adafe9e4atagen2026-10-22 12:30 UTC99
        eprintln!("More info can be found at: https://cli.github.com/");
7ff8adafe9e4atagen2026-10-22 12:30 UTC100
7ff8adafe9e4atagen2026-10-22 12:30 UTC101
        std::process::exit(1);
7ff8adafe9e4atagen2026-10-22 12:30 UTC102
    }
7ff8adafe9e4atagen2026-10-22 12:30 UTC103
}
7ff8adafe9e4atagen2026-10-22 12:30 UTC104
7ff8adafe9e4atagen2026-10-22 12:30 UTC105
fn append_options<'a>(command: Cmd<'a>, execute: &bool, package: &Option<String>) -> Cmd<'a> {
7ff8adafe9e4atagen2026-10-22 12:30 UTC106
    let command = if *execute { command.arg("--execute") } else { command };
7ff8adafe9e4atagen2026-10-22 12:30 UTC107
    if let Some(package) = package.as_deref() {
7ff8adafe9e4atagen2026-10-22 12:30 UTC108
        command.args(["--package", package])
7ff8adafe9e4atagen2026-10-22 12:30 UTC109
    } else {
7ff8adafe9e4atagen2026-10-22 12:30 UTC110
        command.arg("--workspace")
7ff8adafe9e4atagen2026-10-22 12:30 UTC111
    }
7ff8adafe9e4atagen2026-10-22 12:30 UTC112
}
7ff8adafe9e4atagen2026-10-22 12:30 UTC113
7ff8adafe9e4atagen2026-10-22 12:30 UTC114
fn prepare(version: ReleaseVersion, execute: bool, package: Option<String>) -> Result<()> {
7ff8adafe9e4atagen2026-10-22 12:30 UTC115
    let sh = sh();
7ff8adafe9e4atagen2026-10-22 12:30 UTC116
7ff8adafe9e4atagen2026-10-22 12:30 UTC117
    let cmd = cmd!(sh, "cargo release --no-publish --no-tag --no-push");
7ff8adafe9e4atagen2026-10-22 12:30 UTC118
    let cmd = append_options(cmd, &execute, &package);
7ff8adafe9e4atagen2026-10-22 12:30 UTC119
7ff8adafe9e4atagen2026-10-22 12:30 UTC120
    let cmd = cmd.arg(version.as_str());
7ff8adafe9e4atagen2026-10-22 12:30 UTC121
7ff8adafe9e4atagen2026-10-22 12:30 UTC122
    cmd.run()?;
7ff8adafe9e4atagen2026-10-22 12:30 UTC123
7ff8adafe9e4atagen2026-10-22 12:30 UTC124
    if execute {
7ff8adafe9e4atagen2026-10-22 12:30 UTC125
        eprintln!(
7ff8adafe9e4atagen2026-10-22 12:30 UTC126
            "Please double check the changelogs and edit them if necessary, \
7ff8adafe9e4atagen2026-10-22 12:30 UTC127
             publish the PR, and once it's merged, switch to `main` and pull the PR \
7ff8adafe9e4atagen2026-10-22 12:30 UTC128
             and run `cargo xtask release publish`"
7ff8adafe9e4atagen2026-10-22 12:30 UTC129
        );
7ff8adafe9e4atagen2026-10-22 12:30 UTC130
    }
7ff8adafe9e4atagen2026-10-22 12:30 UTC131
7ff8adafe9e4atagen2026-10-22 12:30 UTC132
    Ok(())
7ff8adafe9e4atagen2026-10-22 12:30 UTC133
}
7ff8adafe9e4atagen2026-10-22 12:30 UTC134
7ff8adafe9e4atagen2026-10-22 12:30 UTC135
fn publish(execute: bool, package: Option<String>) -> Result<()> {
7ff8adafe9e4atagen2026-10-22 12:30 UTC136
    let sh = sh();
7ff8adafe9e4atagen2026-10-22 12:30 UTC137
7ff8adafe9e4atagen2026-10-22 12:30 UTC138
    let cmd = cmd!(sh, "cargo release tag");
7ff8adafe9e4atagen2026-10-22 12:30 UTC139
    let cmd = append_options(cmd, &execute, &package);
7ff8adafe9e4atagen2026-10-22 12:30 UTC140
    cmd.run()?;
7ff8adafe9e4atagen2026-10-22 12:30 UTC141
7ff8adafe9e4atagen2026-10-22 12:30 UTC142
    let cmd = cmd!(sh, "cargo release publish");
7ff8adafe9e4atagen2026-10-22 12:30 UTC143
    let cmd = append_options(cmd, &execute, &package);
7ff8adafe9e4atagen2026-10-22 12:30 UTC144
    cmd.run()?;
7ff8adafe9e4atagen2026-10-22 12:30 UTC145
7ff8adafe9e4atagen2026-10-22 12:30 UTC146
    let cmd = cmd!(sh, "cargo release push");
7ff8adafe9e4atagen2026-10-22 12:30 UTC147
    let cmd = append_options(cmd, &execute, &package);
7ff8adafe9e4atagen2026-10-22 12:30 UTC148
    cmd.run()?;
7ff8adafe9e4atagen2026-10-22 12:30 UTC149
7ff8adafe9e4atagen2026-10-22 12:30 UTC150
    Ok(())
7ff8adafe9e4atagen2026-10-22 12:30 UTC151
}
7ff8adafe9e4atagen2026-10-22 12:30 UTC152
7ff8adafe9e4atagen2026-10-22 12:30 UTC153
fn weekly_report() -> Result<()> {
7ff8adafe9e4atagen2026-10-22 12:30 UTC154
    const JSON_FIELDS: &str = "title,number,url,author";
7ff8adafe9e4atagen2026-10-22 12:30 UTC155
7ff8adafe9e4atagen2026-10-22 12:30 UTC156
    let sh = sh();
7ff8adafe9e4atagen2026-10-22 12:30 UTC157
7ff8adafe9e4atagen2026-10-22 12:30 UTC158
    let one_week_ago = cmd!(sh, "date -d '1 week ago' +%Y-%m-%d").read()?;
7ff8adafe9e4atagen2026-10-22 12:30 UTC159
    let today = cmd!(sh, "date +%Y-%m-%d").read()?;
7ff8adafe9e4atagen2026-10-22 12:30 UTC160
7ff8adafe9e4atagen2026-10-22 12:30 UTC161
    let _env_pager = sh.push_env("GH_PAGER", "");
7ff8adafe9e4atagen2026-10-22 12:30 UTC162
7ff8adafe9e4atagen2026-10-22 12:30 UTC163
    let header = format!("# This Week in the Matrix Rust SDK ({today})\n\n");
7ff8adafe9e4atagen2026-10-22 12:30 UTC164
    let template = "{{range .}}- {{.title}} ([#{{.number}}](https://github.com/matrix-org/matrix-rust-sdk/pull/{{.number}})){{\"\\n\\n\"}}{{end}}";
7ff8adafe9e4atagen2026-10-22 12:30 UTC165
    let template = format!("{header}{template}");
7ff8adafe9e4atagen2026-10-22 12:30 UTC166
7ff8adafe9e4atagen2026-10-22 12:30 UTC167
    cmd!(
7ff8adafe9e4atagen2026-10-22 12:30 UTC168
        sh,
7ff8adafe9e4atagen2026-10-22 12:30 UTC169
        "gh pr list --search merged:>{one_week_ago} --limit 100 --json {JSON_FIELDS} --template {template}"
7ff8adafe9e4atagen2026-10-22 12:30 UTC170
    )
7ff8adafe9e4atagen2026-10-22 12:30 UTC171
    .quiet()
7ff8adafe9e4atagen2026-10-22 12:30 UTC172
    .run()?;
7ff8adafe9e4atagen2026-10-22 12:30 UTC173
7ff8adafe9e4atagen2026-10-22 12:30 UTC174
    Ok(())
7ff8adafe9e4atagen2026-10-22 12:30 UTC175
}