Compare commits
3 Commits
a9fb779c35
...
826ef3b100
Author | SHA1 | Date |
---|---|---|
~erin | 826ef3b100 | |
~erin | f3dda40180 | |
~erin | 1e4c33c6d6 |
14
README.md
14
README.md
|
@ -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
|
||||
```
|
||||
|
|
|
@ -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) => {
|
||||
|
|
|
@ -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,
|
||||
|
|
Loading…
Reference in New Issue