Skip to content

Commit 2a3e6b2

Browse files
rami3lr7kamura
andcommitted
feat(cli/rustup-mode): add rustup ci subcommand
Co-authored-by: r7kamura <r7kamura@gmail.com>
1 parent 9b191c4 commit 2a3e6b2

7 files changed

Lines changed: 186 additions & 1 deletion

File tree

src/cli.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
/// The CLI specific code lives in the cli module and sub-modules.
22
#[macro_use]
33
pub mod log;
4+
mod ci;
45
pub mod common;
56
mod docs;
67
pub mod errors;

src/cli/ci.rs

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
use std::{fmt, io::Write};
2+
3+
use anyhow::Result;
4+
use clap::{ValueEnum, builder::PossibleValue};
5+
6+
use crate::{config::Cfg, utils::ExitCode};
7+
8+
pub(crate) fn env(cfg: &Cfg<'_>) -> Result<ExitCode> {
9+
print_str(include_str!("ci/base.env"), cfg)
10+
}
11+
12+
pub(crate) fn problem_matcher(flavor: Flavor, cfg: &Cfg<'_>) -> Result<ExitCode> {
13+
print_str(flavor.problem_matcher(), cfg)
14+
}
15+
16+
fn print_str(s: &str, cfg: &Cfg<'_>) -> Result<ExitCode> {
17+
let stdout = cfg.process.stdout();
18+
write!(stdout.lock(), "{s}")?;
19+
Ok(ExitCode::SUCCESS)
20+
}
21+
22+
#[derive(Copy, Clone, Debug, PartialEq)]
23+
pub(crate) enum Flavor {
24+
Github,
25+
}
26+
27+
impl Flavor {
28+
fn problem_matcher(&self) -> &'static str {
29+
match self {
30+
Self::Github => include_str!("ci/matcher/github.json"),
31+
}
32+
}
33+
}
34+
35+
impl ValueEnum for Flavor {
36+
fn value_variants<'a>() -> &'a [Self] {
37+
&[Self::Github]
38+
}
39+
40+
fn to_possible_value<'a>(&self) -> Option<PossibleValue> {
41+
Some(match self {
42+
Self::Github => PossibleValue::new("github"),
43+
})
44+
}
45+
}
46+
47+
impl fmt::Display for Flavor {
48+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
49+
match self.to_possible_value() {
50+
Some(v) => write!(f, "{}", v.get_name()),
51+
None => unreachable!(),
52+
}
53+
}
54+
}

src/cli/ci/base.env

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
RUSTUP_PERMIT_COPY_RENAME=1
2+
RUST_BACKTRACE=short

src/cli/ci/matcher/github.json

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
{
2+
"problemMatcher": [
3+
{
4+
"owner": "rust-compiler",
5+
"pattern": [
6+
{
7+
"regexp": "^(?:\\x1B\\[[0-9;]*[a-zA-Z])*(warning|warn|error)(\\[(\\S*)\\])?(?:\\x1B\\[[0-9;]*[a-zA-Z])*: (.*?)(?:\\x1B\\[[0-9;]*[a-zA-Z])*$",
8+
"severity": 1,
9+
"message": 4,
10+
"code": 3
11+
},
12+
{
13+
"regexp": "^(?:\\x1B\\[[0-9;]*[a-zA-Z])*\\s+(?:\\x1B\\[[0-9;]*[a-zA-Z])*-->\\s(?:\\x1B\\[[0-9;]*[a-zA-Z])*(\\S+):(\\d+):(\\d+)(?:\\x1B\\[[0-9;]*[a-zA-Z])*$",
14+
"file": 1,
15+
"line": 2,
16+
"column": 3
17+
}
18+
]
19+
},
20+
{
21+
"owner": "rust-formatter",
22+
"pattern": [
23+
{
24+
"regexp": "^(Diff in (\\S+)) at line (\\d+):",
25+
"message": 1,
26+
"file": 2,
27+
"line": 3
28+
}
29+
]
30+
},
31+
{
32+
"owner": "rust-panic",
33+
"pattern": [
34+
{
35+
"regexp": "^.*panicked\\s+at\\s+'(.*)',\\s+(.*):(\\d+):(\\d+)$",
36+
"message": 1,
37+
"file": 2,
38+
"line": 3,
39+
"column": 4
40+
}
41+
]
42+
}
43+
]
44+
}

src/cli/rustup_mode.rs

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ use tracing_subscriber::{EnvFilter, Registry, reload::Handle};
3232

3333
use crate::{
3434
cli::{
35+
ci,
3536
common::{self, PackageUpdate, update_console_filter},
3637
docs,
3738
errors::CliError,
@@ -300,6 +301,13 @@ enum RustupSubcmd {
300301
#[arg(default_value = "rustup")]
301302
command: CompletionCommand,
302303
},
304+
305+
/// Generate CI-specific configurations
306+
#[command(hide = true)]
307+
Ci {
308+
#[command(subcommand)]
309+
subcmd: CiSubcmd,
310+
},
303311
}
304312

305313
fn update_toolchain_value_parser(s: &str) -> Result<PartialToolchainDesc> {
@@ -322,6 +330,7 @@ impl RustupSubcmd {
322330
// These subcommands don't require the active toolchain, so auto-installing it should be
323331
// disabled to avoid surprises.
324332
Self::Check { .. }
333+
| Self::Ci { .. }
325334
| Self::Completions { .. }
326335
| Self::Component { .. }
327336
| Self::Default { .. }
@@ -343,7 +352,10 @@ impl RustupSubcmd {
343352
fn should_warn_empty_setup(&self) -> bool {
344353
match self {
345354
// These subcommands are not about toolchains, so the hint would be noise.
346-
Self::Completions { .. } | Self::DumpTestament | Self::Self_ { .. } => false,
355+
Self::Ci { .. }
356+
| Self::Completions { .. }
357+
| Self::DumpTestament
358+
| Self::Self_ { .. } => false,
347359

348360
// For all other subcommands, the hint may be useful if rustup is still unusable after
349361
// the command has completed.
@@ -670,6 +682,20 @@ enum SetSubcmd {
670682
},
671683
}
672684

685+
#[derive(Debug, Subcommand)]
686+
#[command(arg_required_else_help = true, subcommand_required = true)]
687+
enum CiSubcmd {
688+
/// Show the recommended environment variables in `.env` format
689+
Env,
690+
691+
/// Show the example problem matcher for the given CI flavor
692+
#[command(alias = "matcher")]
693+
ProblemMatcher {
694+
#[arg(value_enum)]
695+
flavor: ci::Flavor,
696+
},
697+
}
698+
673699
#[tracing::instrument(level = "trace", fields(args = format!("{:?}", process.args_os().collect::<Vec<_>>())), skip(process, console_filter))]
674700
pub async fn main(
675701
current_dir: PathBuf,
@@ -863,6 +889,10 @@ pub async fn main(
863889
RustupSubcmd::Completions { shell, command } => {
864890
output_completion_script(shell, command, process)
865891
}
892+
RustupSubcmd::Ci { subcmd } => match subcmd {
893+
CiSubcmd::Env => ci::env(cfg),
894+
CiSubcmd::ProblemMatcher { flavor } => ci::problem_matcher(flavor, cfg),
895+
},
866896
}?;
867897

868898
if should_warn && cfg.list_toolchains()?.is_empty() && cfg.get_default()?.is_none() {

tests/suite/cli_rustup_ui.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -535,6 +535,11 @@ fn rustup_upgrade_cmd_help_flag() {
535535
test_help("rustup_upgrade_cmd_help_flag", &["upgrade", "--help"]);
536536
}
537537

538+
#[test]
539+
fn rustup_ci_cmd_help_flag() {
540+
test_help("rustup_ci_cmd_help_flag", &["ci", "--help"]);
541+
}
542+
538543
#[test]
539544
fn rustup_which_cmd_help_flag() {
540545
test_help("rustup_which_cmd_help_flag", &["which", "--help"]);
Lines changed: 49 additions & 0 deletions
Loading

0 commit comments

Comments
 (0)