Compare commits

...

3 Commits

Author SHA1 Message Date
~erin 826ef3b100
Actually run build commands (only cargo rn though) 2023-04-03 01:05:08 -04:00
~erin f3dda40180
Specify basename, build directory 2023-04-03 00:07:17 -04:00
~erin 1e4c33c6d6
Slightly better formatting 2023-04-02 23:34:36 -04:00
3 changed files with 78 additions and 15 deletions

View File

@ -6,10 +6,18 @@ On first run, `forge-server` will create a configuration file for you in the def
Use this to configure options, such as the IP & port to bind on, and whether to use authentication (along with a password).
Authentication will use *Argon2id* to hash and verify passwords.
Right now it only supports building `cargo` projects.
Actually building stuff is a **WIP**.
### Build
```bash
cargo run -p forge-server
$EDITOR ~/.config/forge/config.toml
cargo run -p forge-server
```
## Client
Fully **WIP**.
Sends data to the server specified via commandline options.
```bash
cargo run -p forge
```

View File

@ -59,6 +59,10 @@ enum Commands {
/// Optional cargo flag
#[arg(long, require_equals = true, num_args = 0..=1, default_value_t = Tag::Debug, default_missing_value = "debug")]
tag: Tag,
/// Basename of the repository
#[arg(long, value_name = "NAME")]
basename: String,
},
}
@ -140,6 +144,7 @@ async fn main() -> Result<(), Box<dyn Error>> {
subcommand,
features,
tag,
basename,
} => {
// Connect to a peer
let remote = format!("{}:{}", args.host, args.port);
@ -165,9 +170,11 @@ async fn main() -> Result<(), Box<dyn Error>> {
profile,
command: test_command,
repository: Url::parse(&repo).unwrap(),
basename: "serde_json".to_string(),
basename,
};
info!("Message UUID: <magenta>{}<//>", &test_message.uuid);
let j = match serde_json::to_string(&test_message) {
Ok(s) => s,
Err(e) => {

View File

@ -5,6 +5,7 @@ use argon2::{
use paris::{error, info, success, warn};
use serde::{Deserialize, Serialize};
use serde_json::Result;
use std::process::Command as pCommand;
use std::{fmt, fs, io, net::SocketAddr, path::PathBuf, process::exit};
use tokio::io::{AsyncBufReadExt, AsyncReadExt, AsyncWriteExt, BufReader};
use tokio::net::{TcpListener, TcpStream};
@ -16,6 +17,7 @@ use uuid_simd::UuidExt;
struct HostConfig {
ip: String,
port: u16,
build_directory: Option<String>,
}
#[derive(Serialize, Deserialize, Clone)]
@ -100,7 +102,7 @@ struct Message {
basename: String,
}
async fn build(msg: Message, address: SocketAddr) {
async fn build(msg: Message, address: SocketAddr, dir: PathBuf) {
let mut features = String::new();
match msg.command.features {
Some(f) => {
@ -114,17 +116,53 @@ async fn build(msg: Message, address: SocketAddr) {
None => features = "".to_string(),
}
let mut build_dir = dir;
build_dir.push(&msg.basename);
let mut manifest = build_dir.clone();
manifest.push("Cargo.toml");
success!(
"Received message from <green>{:?}<//>: <magenta>{}<//>\n<bright-white>git clone {}\n{} {} {} {}<//>",
"Received message from <green>{:?}<//>: <magenta>{}<//>",
address,
msg.uuid.format_hyphenated(),
msg.repository,
msg.command.build_system,
msg.command.subcommand,
msg.command.tag,
features
msg.uuid,
);
let git_output = pCommand::new("git")
.arg("clone")
.arg(msg.repository.to_string())
.arg(&build_dir)
.output()
.unwrap();
if !git_output.status.success() {
error!("{:?}", git_output);
} else {
info!("{:?}", git_output);
}
let build_output = match msg.command.tag {
Tag::Release => {
pCommand::new(msg.command.build_system.to_string())
.arg(msg.command.subcommand.to_string())
.arg(msg.command.tag.to_string())
.arg(format!("--manifest-path={}", &manifest.display()))
// .arg(features.to_string())
.output()
.unwrap()
}
Tag::Debug => pCommand::new(msg.command.build_system.to_string())
.arg(msg.command.subcommand.to_string())
.arg(format!("--manifest-path={}", &manifest.display()))
.output()
.unwrap(),
};
if !build_output.status.success() {
error!("{:?}", build_output);
} else {
info!("{:?}", build_output);
}
match msg.pre_exec {
Some(e) => info!("Running pre-exec: {}", e),
None => {}
@ -162,6 +200,7 @@ async fn process_socket(
mut socket: TcpStream,
address: SocketAddr,
auth: AuthConfig,
dir: PathBuf,
salt: SaltString,
argon2: Argon2<'_>,
) {
@ -187,12 +226,13 @@ async fn process_socket(
if auth.authenticate {
match &auth.password {
Some(pass) => {
let directory = dir.clone();
if json
.authenticate(pass.clone(), salt.clone(), argon2.clone())
.await
{
tokio::spawn(async move {
build(json, address).await;
build(json, address, directory).await;
});
}
}
@ -201,7 +241,10 @@ async fn process_socket(
}
}
} else {
build(json, address).await;
let directory = dir.clone();
tokio::spawn(async move {
build(json, address, directory).await;
});
}
}
}
@ -220,10 +263,11 @@ async fn main() -> io::Result<()> {
match listener.accept().await {
Ok((socket, addr)) => {
let auth = config.auth.clone();
let dir = PathBuf::from(config.host.build_directory.clone().unwrap());
let m_salt = salt.clone();
let m_argon2 = argon2.clone();
tokio::spawn(async move {
process_socket(socket, addr, auth, m_salt, m_argon2).await;
process_socket(socket, addr, auth, dir, m_salt, m_argon2).await;
});
}
Err(e) => error!("couldn't get client: {:?}", e),
@ -236,6 +280,9 @@ async fn configure() -> Config {
default_config.push("forge");
default_config.push("config.toml");
let mut default_build_dir = dirs::home_dir().unwrap();
default_build_dir.push("src");
let config_contents = match fs::read_to_string(&default_config) {
Ok(f) => f,
Err(e) => {
@ -244,6 +291,7 @@ async fn configure() -> Config {
host: HostConfig {
ip: "127.0.0.1".to_string(),
port: 9134,
build_directory: Some(default_build_dir.to_str().unwrap().to_string()),
},
auth: AuthConfig {
authenticate: false,