Rename the project to Synchronik
This commit is contained in:
parent
3b95ff87ad
commit
8e600ba3b6
|
@ -1,14 +1,14 @@
|
||||||
[package]
|
[package]
|
||||||
name = "janky"
|
name = "synchronik"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
[[bin]]
|
[[bin]]
|
||||||
name = "janky-server"
|
name = "synchronik-server"
|
||||||
path = "src/server/main.rs"
|
path = "src/server/main.rs"
|
||||||
|
|
||||||
[[bin]]
|
[[bin]]
|
||||||
name = "janky-agent"
|
name = "synchronik-agent"
|
||||||
path = "src/agent/main.rs"
|
path = "src/agent/main.rs"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
@ -30,6 +30,7 @@ serde = { version = "1.0", features = ["derive"] }
|
||||||
serde_json = "1"
|
serde_json = "1"
|
||||||
serde_yaml = "0.9"
|
serde_yaml = "0.9"
|
||||||
sqlx = { version = "~0.6", features = ["chrono", "json", "migrate", "offline", "sqlite", "uuid", "runtime-async-std-rustls"] }
|
sqlx = { version = "~0.6", features = ["chrono", "json", "migrate", "offline", "sqlite", "uuid", "runtime-async-std-rustls"] }
|
||||||
|
subprocess = "0.2"
|
||||||
tide = "0"
|
tide = "0"
|
||||||
uuid = { version = "1", features = ["v4", "serde"]}
|
uuid = { version = "1", features = ["v4", "serde"]}
|
||||||
url = "2"
|
url = "2"
|
||||||
|
|
13
README.adoc
13
README.adoc
|
@ -1,14 +1,15 @@
|
||||||
= Janky CI
|
= Synchronik
|
||||||
|
|
||||||
Janky is a simple CI system built in Rust. This is performative coding and not
|
Synchronik is a simple task execution system built in Rust. This is
|
||||||
intended to be a production system you can actually use.
|
performative coding and not intended to be a production system you can actually
|
||||||
|
use.
|
||||||
|
|
||||||
* Two binaries:
|
* Two binaries:
|
||||||
* `janky-server`
|
* `synchronik-server`
|
||||||
* Listens HTTP
|
* Listens HTTP
|
||||||
* Does web shit
|
* Does web things
|
||||||
* Interacts with agents
|
* Interacts with agents
|
||||||
* `janky-agent`:
|
* `synchronik-agent`:
|
||||||
* Run workloads
|
* Run workloads
|
||||||
* Listen HTTP
|
* Listen HTTP
|
||||||
* executes commands
|
* executes commands
|
||||||
|
|
|
@ -2,11 +2,11 @@
|
||||||
openapi: "3.0.0"
|
openapi: "3.0.0"
|
||||||
info:
|
info:
|
||||||
description: |
|
description: |
|
||||||
Janky API v1 defintion
|
Synchronik API v1 defintion
|
||||||
version: "1.0.0"
|
version: "1.0.0"
|
||||||
title: Janky APIs
|
title: Synchronik APIs
|
||||||
contact:
|
contact:
|
||||||
email: "rtyler+janky@brokenco.de"
|
email: "rtyler+synchronik@brokenco.de"
|
||||||
license:
|
license:
|
||||||
name: "AGPL v3.0"
|
name: "AGPL v3.0"
|
||||||
url: "https://www.gnu.org/licenses/agpl-3.0.en.html"
|
url: "https://www.gnu.org/licenses/agpl-3.0.en.html"
|
||||||
|
@ -33,7 +33,7 @@ paths:
|
||||||
- in: path
|
- in: path
|
||||||
name: name
|
name: name
|
||||||
required: true
|
required: true
|
||||||
example: 'janky'
|
example: 'synchronik'
|
||||||
schema:
|
schema:
|
||||||
type: string
|
type: string
|
||||||
responses:
|
responses:
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
{"openapi":"3.0.0","info":{"description":"Janky API v1 defintion\n","version":"1.0.0","title":"Janky APIs","contact":{"email":"rtyler+janky@brokenco.de"},"license":{"name":"AGPL v3.0","url":"https://www.gnu.org/licenses/agpl-3.0.en.html"}},"servers":[{"url":"http://localhost:8000","description":"Local dev server"},{"url":"http://localhost:9000","description":"Local dev agent"}],"tags":[{"name":"agent","description":"Agent APIs"},{"name":"server","description":"Server APIs"}],"paths":{"/api/v1/projects/{name}":{"post":{"tags":["server"],"summary":"Trigger execution for this project","description":null,"parameters":[{"in":"path","name":"name","required":true,"example":"janky","schema":{"type":"string"}}],"responses":{"404":{"summary":"No project configured by that name"},"200":{"summary":"Execution has been triggered"}}}},"/api/v1/capabilities":{"get":{"tags":["agent"],"summary":"Retrieve a list of capabilities of this agent","description":null,"responses":{"200":{"description":"Getting capabilities","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CapsResponse"}}}}}}},"/api/v1/execute":{"put":{"tags":["agent"],"summary":"Execute a series of commands on this agent","description":null,"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CommandRequest"},"example":{"commands":[{"script":"echo \"Hi\""}]}}}},"responses":{"201":{"description":"Successfully accepted the commands for execution","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CommandResponse"}}}},"409":{"description":"Returned when the agent is busy with another series of commands"}}}}},"components":{"schemas":{"CapsResponse":{"type":"object","properties":{"caps":{"type":"array","items":{"$ref":"#/components/schemas/Capability"}}}},"Capability":{"type":"object","properties":{"name":{"type":"string"},"path":{"type":"string"},"data":{"type":"object"}}},"Command":{"type":"object","properties":{"script":{"type":"string","description":"A script that can be exec()'d on the agent"}}},"CommandRequest":{"type":"object","properties":{"commands":{"type":"array","items":{"$ref":"#/components/schemas/Command"}}}},"CommandResponse":{"type":"object","properties":{"uuid":{"type":"string","format":"uuid"},"stream":{"description":"URL to streaming WebSockets logs","type":"string","format":"url"},"task":{"description":"URL to the task metadata","type":"string","format":"url"},"log":{"description":"URL to the raw log of the task run","type":"string","format":"url"}}}}}}
|
{"openapi":"3.0.0","info":{"description":"Synchronik API v1 defintion\n","version":"1.0.0","title":"Synchronik APIs","contact":{"email":"rtyler+synchronik@brokenco.de"},"license":{"name":"AGPL v3.0","url":"https://www.gnu.org/licenses/agpl-3.0.en.html"}},"servers":[{"url":"http://localhost:8000","description":"Local dev server"},{"url":"http://localhost:9000","description":"Local dev agent"}],"tags":[{"name":"agent","description":"Agent APIs"},{"name":"server","description":"Server APIs"}],"paths":{"/api/v1/projects/{name}":{"post":{"tags":["server"],"summary":"Trigger execution for this project","description":null,"parameters":[{"in":"path","name":"name","required":true,"example":"synchronik","schema":{"type":"string"}}],"responses":{"404":{"summary":"No project configured by that name"},"200":{"summary":"Execution has been triggered"}}}},"/api/v1/capabilities":{"get":{"tags":["agent"],"summary":"Retrieve a list of capabilities of this agent","description":null,"responses":{"200":{"description":"Getting capabilities","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CapsResponse"}}}}}}},"/api/v1/execute":{"put":{"tags":["agent"],"summary":"Execute a series of commands on this agent","description":null,"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CommandRequest"},"example":{"commands":[{"script":"echo \"Hi\""}]}}}},"responses":{"201":{"description":"Successfully accepted the commands for execution","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CommandResponse"}}}},"409":{"description":"Returned when the agent is busy with another series of commands"}}}}},"components":{"schemas":{"CapsResponse":{"type":"object","properties":{"caps":{"type":"array","items":{"$ref":"#/components/schemas/Capability"}}}},"Capability":{"type":"object","properties":{"name":{"type":"string"},"path":{"type":"string"},"data":{"type":"object"}}},"Command":{"type":"object","properties":{"script":{"type":"string","description":"A script that can be exec()'d on the agent"}}},"CommandRequest":{"type":"object","properties":{"commands":{"type":"array","items":{"$ref":"#/components/schemas/Command"}}}},"CommandResponse":{"type":"object","properties":{"uuid":{"type":"string","format":"uuid"},"stream":{"description":"URL to streaming WebSockets logs","type":"string","format":"url"},"task":{"description":"URL to the task metadata","type":"string","format":"url"},"log":{"description":"URL to the raw log of the task run","type":"string","format":"url"}}}}}}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
---
|
---
|
||||||
# This is a Janky formatted YAML file. Using YAML for now to make hacking on
|
# This is a Synchronik formatted YAML file. Using YAML for now to make hacking on
|
||||||
# this quicker and easier
|
# this quicker and easier
|
||||||
|
|
||||||
needs:
|
needs:
|
|
@ -5,22 +5,22 @@ agents:
|
||||||
'Duplicate Local':
|
'Duplicate Local':
|
||||||
url: 'http://localhost:9000'
|
url: 'http://localhost:9000'
|
||||||
projects:
|
projects:
|
||||||
'janky':
|
'synchronik':
|
||||||
description: |
|
description: |
|
||||||
Self-hosted Janky project
|
Self-hosted project
|
||||||
filename: 'ci.janky.yml'
|
filename: 'ci.synchronik.yml'
|
||||||
scm:
|
scm:
|
||||||
github:
|
github:
|
||||||
owner: 'rtyler'
|
owner: 'rtyler'
|
||||||
repo: 'janky'
|
repo: 'synchronik'
|
||||||
ref: 'main'
|
ref: 'main'
|
||||||
'janky with spaces':
|
'with spaces':
|
||||||
description: A test configuration with spaces in the name
|
description: A test configuration with spaces in the name
|
||||||
filename: 'ci.janky.yml'
|
filename: 'ci.synchronik.yml'
|
||||||
scm:
|
scm:
|
||||||
github:
|
github:
|
||||||
owner: 'rtyler'
|
owner: 'rtyler'
|
||||||
repo: 'janky'
|
repo: 'synchronik'
|
||||||
ref: 'main'
|
ref: 'main'
|
||||||
# The filetype Git is not yet supported
|
# The filetype Git is not yet supported
|
||||||
#- type: 'git'
|
#- type: 'git'
|
||||||
|
|
|
@ -5,8 +5,8 @@ use std::path::PathBuf;
|
||||||
|
|
||||||
use async_std::channel::{bounded, Receiver, Sender};
|
use async_std::channel::{bounded, Receiver, Sender};
|
||||||
use dotenv::dotenv;
|
use dotenv::dotenv;
|
||||||
use janky::CommandRequest;
|
|
||||||
use log::*;
|
use log::*;
|
||||||
|
use synchronik::CommandRequest;
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
|
||||||
const AGENT_LOGS_DIR: &str = "agent-logs";
|
const AGENT_LOGS_DIR: &str = "agent-logs";
|
||||||
|
@ -20,13 +20,13 @@ mod routes {
|
||||||
* GET /
|
* GET /
|
||||||
*/
|
*/
|
||||||
pub async fn index(_req: Request<crate::State>) -> Result<Body, tide::Error> {
|
pub async fn index(_req: Request<crate::State>) -> Result<Body, tide::Error> {
|
||||||
Ok("Hello World from the Janky Agent".into())
|
Ok("Hello World from the Synchronik Agent".into())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub mod api {
|
pub mod api {
|
||||||
use crate::caps::*;
|
use crate::caps::*;
|
||||||
use crate::*;
|
use crate::*;
|
||||||
use janky::{CommandRequest, CommandResponse};
|
use synchronik::{CommandRequest, CommandResponse};
|
||||||
use tide::{Body, Request, Response, StatusCode};
|
use tide::{Body, Request, Response, StatusCode};
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
|
||||||
|
|
|
@ -6,10 +6,10 @@ use url::Url;
|
||||||
use crate::AppState;
|
use crate::AppState;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Representation of the Janky YAML format
|
* Representation of the Synchronik YAML format
|
||||||
*/
|
*/
|
||||||
#[derive(Clone, Debug, Deserialize)]
|
#[derive(Clone, Debug, Deserialize)]
|
||||||
pub struct JankyYml {
|
pub struct Yml {
|
||||||
pub needs: Vec<String>,
|
pub needs: Vec<String>,
|
||||||
pub commands: Vec<String>,
|
pub commands: Vec<String>,
|
||||||
}
|
}
|
||||||
|
@ -44,11 +44,11 @@ pub struct Project {
|
||||||
pub struct Agent {
|
pub struct Agent {
|
||||||
pub name: String,
|
pub name: String,
|
||||||
pub url: Url,
|
pub url: Url,
|
||||||
pub capabilities: Vec<janky::Capability>,
|
pub capabilities: Vec<synchronik::Capability>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Agent {
|
impl Agent {
|
||||||
pub fn new(name: String, url: Url, capabilities: Vec<janky::Capability>) -> Self {
|
pub fn new(name: String, url: Url, capabilities: Vec<synchronik::Capability>) -> Self {
|
||||||
Self {
|
Self {
|
||||||
name,
|
name,
|
||||||
url,
|
url,
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* This is the main Janky entrypoint for the server"
|
* This is the main Synchronik entrypoint for the server
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
|
@ -93,7 +93,7 @@ async fn main() -> Result<(), tide::Error> {
|
||||||
let database_url = std::env::var("DATABASE_URL").unwrap_or(":memory:".to_string());
|
let database_url = std::env::var("DATABASE_URL").unwrap_or(":memory:".to_string());
|
||||||
let pool = SqlitePool::connect(&database_url).await?;
|
let pool = SqlitePool::connect(&database_url).await?;
|
||||||
|
|
||||||
/* If janky-server is running in memory, make sure the database is set up properly */
|
/* If synchronik-server is running in memory, make sure the database is set up properly */
|
||||||
if database_url == ":memory:" {
|
if database_url == ":memory:" {
|
||||||
sqlx::migrate!().run(&pool).await?;
|
sqlx::migrate!().run(&pool).await?;
|
||||||
}
|
}
|
||||||
|
@ -118,10 +118,11 @@ async fn main() -> Result<(), tide::Error> {
|
||||||
|
|
||||||
for (name, agent) in config.agents.iter() {
|
for (name, agent) in config.agents.iter() {
|
||||||
debug!("Requesting capabilities from agent: {:?}", agent);
|
debug!("Requesting capabilities from agent: {:?}", agent);
|
||||||
let response: janky::CapsResponse = reqwest::get(agent.url.join("/api/v1/capabilities")?)
|
let response: synchronik::CapsResponse =
|
||||||
.await?
|
reqwest::get(agent.url.join("/api/v1/capabilities")?)
|
||||||
.json()
|
.await?
|
||||||
.await?;
|
.json()
|
||||||
|
.await?;
|
||||||
state.agents.push(Agent::new(
|
state.agents.push(Agent::new(
|
||||||
name.to_string(),
|
name.to_string(),
|
||||||
agent.url.clone(),
|
agent.url.clone(),
|
||||||
|
@ -177,7 +178,7 @@ async fn main() -> Result<(), tide::Error> {
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
use janky::*;
|
use synchronik::*;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn agent_can_meet_false() {
|
fn agent_can_meet_false() {
|
||||||
|
|
|
@ -46,7 +46,7 @@ pub async fn project(req: Request<AppState<'_>>) -> Result<Body, tide::Error> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub mod api {
|
pub mod api {
|
||||||
use crate::config::{JankyYml, Scm};
|
use crate::config::{Scm, Yml};
|
||||||
use crate::AppState;
|
use crate::AppState;
|
||||||
use log::*;
|
use log::*;
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
|
@ -88,18 +88,18 @@ pub mod api {
|
||||||
&project.filename,
|
&project.filename,
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
let jankyfile: JankyYml = serde_yaml::from_str(&res.text().await?)?;
|
let config_file: Yml = serde_yaml::from_str(&res.text().await?)?;
|
||||||
debug!("text: {:?}", jankyfile);
|
debug!("text: {:?}", config_file);
|
||||||
|
|
||||||
for agent in &state.agents {
|
for agent in &state.agents {
|
||||||
if agent.can_meet(&jankyfile.needs) {
|
if agent.can_meet(&config_file.needs) {
|
||||||
debug!("agent: {:?} can meet our needs", agent);
|
debug!("agent: {:?} can meet our needs", agent);
|
||||||
let commands: Vec<janky::Command> = jankyfile
|
let commands: Vec<synchronik::Command> = config_file
|
||||||
.commands
|
.commands
|
||||||
.iter()
|
.iter()
|
||||||
.map(|c| janky::Command::with_script(c))
|
.map(|c| synchronik::Command::with_script(c))
|
||||||
.collect();
|
.collect();
|
||||||
let commands = janky::CommandRequest { commands };
|
let commands = synchronik::CommandRequest { commands };
|
||||||
let client = reqwest::Client::new();
|
let client = reqwest::Client::new();
|
||||||
let _res = client
|
let _res = client
|
||||||
.put(
|
.put(
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
<nav class="navbar navbar-expand-lg bg-dark" data-bs-theme="dark">
|
<nav class="navbar navbar-expand-lg bg-dark" data-bs-theme="dark">
|
||||||
<div class="container-fluid">
|
<div class="container-fluid">
|
||||||
<a class="navbar-brand" href="/">Janky</a>
|
<a class="navbar-brand" href="/">Synchronik</a>
|
||||||
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
|
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
|
||||||
<span class="navbar-toggler-icon"></span>
|
<span class="navbar-toggler-icon"></span>
|
||||||
</button>
|
</button>
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<!doctype html>
|
<!doctype html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
<title>Janky</title>
|
<title>Synchronik</title>
|
||||||
<link type="text/css" rel="stylesheet" href="/static/bootstrap.min.css"/>
|
<link type="text/css" rel="stylesheet" href="/static/bootstrap.min.css"/>
|
||||||
<script src="/static/bootstrap.bundle.min.js" integrity="sha384-w76AqPfDkMBDXo30jS1Sgez6pr3x5MlQ1ZAGC+nuZB+EYdgRZgiwxhTBTkF7CXvN" crossorigin="anonymous"></script>
|
<script src="/static/bootstrap.bundle.min.js" integrity="sha384-w76AqPfDkMBDXo30jS1Sgez6pr3x5MlQ1ZAGC+nuZB+EYdgRZgiwxhTBTkF7CXvN" crossorigin="anonymous"></script>
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue