Skip to content

Commit 9661c33

Browse files
committed
start integrating xtasks
1 parent 466e718 commit 9661c33

File tree

5 files changed

+222
-0
lines changed

5 files changed

+222
-0
lines changed

.cargo/config.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,5 @@
11
[env]
22
TARGET_DIR = { value = "target", relative = true }
3+
4+
[alias]
5+
xtask = "run --package xtask --"

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@ members = [
8181
"crates/languages/bevy_mod_scripting_rune",
8282
"crates/test_utils",
8383
"crates/bevy_mod_scripting_functions",
84+
"crates/xtask",
8485
]
8586
resolver = "2"
8687
exclude = ["crates/bevy_api_gen", "crates/macro_tests"]

crates/xtask/Cargo.toml

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
[package]
2+
name = "xtask"
3+
version = "0.1.0"
4+
edition = "2021"
5+
publish = false
6+
7+
8+
[[bin]]
9+
name = "xtask"
10+
path = "src/main.rs"
11+
12+
[dependencies]
13+
xtasks = "*"
14+
clap = { version = "4", features = ["derive", "string"] }
15+
strum = { version = "0.26", features = ["derive"] }
16+
anyhow = "1"
17+
pretty_env_logger = "0.5"
18+
log = "0.4"

crates/xtask/readme.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# X-Tasks
2+
3+
This crate provides a set of tasks to be used in CI/CD pipelines as well as for local development.

crates/xtask/src/main.rs

Lines changed: 197 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,197 @@
1+
use anyhow::*;
2+
use clap::Parser;
3+
use log::*;
4+
use std::{process::Command, str::FromStr};
5+
use strum::VariantNames;
6+
7+
#[derive(
8+
Clone,
9+
Copy,
10+
Debug,
11+
PartialEq,
12+
Eq,
13+
strum::EnumString,
14+
strum::EnumIter,
15+
strum::Display,
16+
strum::VariantNames,
17+
)]
18+
#[strum(serialize_all = "snake_case")]
19+
enum Feature {
20+
// Lua
21+
Lua,
22+
Lua51,
23+
Lua52,
24+
Lua53,
25+
Lua54,
26+
Luajit,
27+
Luajit52,
28+
Luau,
29+
BevyBindings,
30+
CoreFunctions,
31+
UnsafeLuaModules,
32+
MluaSerialize,
33+
MluaMacros,
34+
MluaAsync,
35+
36+
// Rhai
37+
Rhai,
38+
39+
// Rune
40+
Rune,
41+
}
42+
43+
#[derive(Debug, Clone)]
44+
struct Features(Vec<Feature>);
45+
46+
impl Features {
47+
fn to_cargo_args(&self) -> Vec<String> {
48+
if self.0.is_empty() {
49+
vec![]
50+
} else {
51+
vec!["--features".to_owned(), self.to_string()]
52+
}
53+
}
54+
55+
fn to_placeholder() -> clap::builder::Str {
56+
format!("[{}]", Feature::VARIANTS.join("|")).into()
57+
}
58+
}
59+
60+
impl std::fmt::Display for Features {
61+
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
62+
for (i, feature) in self.0.iter().enumerate() {
63+
if i > 0 {
64+
write!(f, ",")?;
65+
}
66+
write!(f, "{}", feature)?;
67+
}
68+
std::result::Result::Ok(())
69+
}
70+
}
71+
72+
impl From<String> for Features {
73+
fn from(s: String) -> Self {
74+
if s.is_empty() {
75+
return Self(vec![]);
76+
}
77+
78+
let features = s
79+
.trim()
80+
.split(',')
81+
.map(|f| {
82+
Feature::from_str(f).unwrap_or_else(|_| {
83+
eprintln!("Unknown feature: '{}'", f);
84+
std::process::exit(1);
85+
})
86+
})
87+
.collect();
88+
Self(features)
89+
}
90+
}
91+
92+
#[derive(Debug, Parser)]
93+
struct App {
94+
#[clap(long, short, global = true, value_parser=clap::value_parser!(Features), value_name=Features::to_placeholder(), default_value="lua54",required = false)]
95+
features: Features,
96+
97+
#[clap(subcommand)]
98+
subcmd: Xtasks,
99+
}
100+
101+
#[derive(Debug, clap::Subcommand)]
102+
#[clap(
103+
name = "xtask",
104+
bin_name = "cargo xtask",
105+
about = "A set of xtasks for managing the project. Run 'cargo xtask init' to get started."
106+
)]
107+
enum Xtasks {
108+
/// Performs first time local-development environment setup
109+
Init,
110+
/// Build the main workspace only
111+
Build,
112+
/// Build the main workspace, apply all prefferred lints
113+
Check,
114+
/// Build the main workspace, and then run all tests
115+
Test,
116+
/// Perform a full check as it would be done in CI
117+
CiCheck,
118+
}
119+
120+
impl Xtasks {
121+
fn run(self, features: Features) -> Result<(), Error> {
122+
match self {
123+
Xtasks::Build => Self::build(features),
124+
Xtasks::Check => self.check(),
125+
Xtasks::Test => self.test(),
126+
Xtasks::CiCheck => self.cicd(),
127+
Xtasks::Init => self.init(),
128+
}
129+
}
130+
131+
fn run_workspace_command(
132+
command: &str,
133+
context: &str,
134+
features: Features,
135+
) -> Result<(), anyhow::Error> {
136+
info!("Running workspace command: {}", command);
137+
138+
let mut args = vec![];
139+
args.push(command.to_owned());
140+
args.push("--workspace".to_owned());
141+
args.extend(features.to_cargo_args());
142+
143+
let mut cmd = Command::new("cargo");
144+
cmd.args(args)
145+
.stdout(std::process::Stdio::inherit())
146+
.stderr(std::process::Stdio::inherit());
147+
148+
info!("Using command: {:?}", cmd);
149+
150+
let output = cmd.output().with_context(|| context.to_owned())?;
151+
match output.status.code() {
152+
Some(0) => Ok(()),
153+
_ => bail!(
154+
"{} failed with exit code: {}",
155+
context,
156+
output.status.code().unwrap_or(-1)
157+
),
158+
}
159+
}
160+
161+
fn build(features: Features) -> Result<(), anyhow::Error> {
162+
// build workspace using the given features
163+
Self::run_workspace_command("build", "Failed to build workspace", features)?;
164+
Ok(())
165+
}
166+
167+
fn check(self) -> Result<(), anyhow::Error> {
168+
todo!()
169+
}
170+
171+
fn test(self) -> Result<(), anyhow::Error> {
172+
todo!()
173+
}
174+
175+
fn cicd(self) -> Result<(), anyhow::Error> {
176+
todo!()
177+
}
178+
179+
fn init(self) -> Result<(), anyhow::Error> {
180+
todo!()
181+
}
182+
}
183+
184+
fn try_main() -> Result<(), anyhow::Error> {
185+
pretty_env_logger::formatted_builder()
186+
.filter_level(LevelFilter::Info)
187+
.init();
188+
let args = App::try_parse()?;
189+
args.subcmd.run(args.features)
190+
}
191+
192+
fn main() {
193+
if let Err(e) = try_main() {
194+
eprintln!("{}", e);
195+
std::process::exit(1);
196+
}
197+
}

0 commit comments

Comments
 (0)