Rename the project to Synchronik

This commit is contained in:
R Tyler Croy 2023-03-12 16:26:15 -07:00
parent 3b95ff87ad
commit 8e600ba3b6
12 changed files with 48 additions and 45 deletions

View File

@ -1,14 +1,14 @@
[package]
name = "janky"
name = "synchronik"
version = "0.1.0"
edition = "2021"
[[bin]]
name = "janky-server"
name = "synchronik-server"
path = "src/server/main.rs"
[[bin]]
name = "janky-agent"
name = "synchronik-agent"
path = "src/agent/main.rs"
[dependencies]
@ -30,6 +30,7 @@ serde = { version = "1.0", features = ["derive"] }
serde_json = "1"
serde_yaml = "0.9"
sqlx = { version = "~0.6", features = ["chrono", "json", "migrate", "offline", "sqlite", "uuid", "runtime-async-std-rustls"] }
subprocess = "0.2"
tide = "0"
uuid = { version = "1", features = ["v4", "serde"]}
url = "2"

View File

@ -1,14 +1,15 @@
= Janky CI
= Synchronik
Janky is a simple CI system built in Rust. This is performative coding and not
intended to be a production system you can actually use.
Synchronik is a simple task execution system built in Rust. This is
performative coding and not intended to be a production system you can actually
use.
* Two binaries:
* `janky-server`
* `synchronik-server`
* Listens HTTP
* Does web shit
* Does web things
* Interacts with agents
* `janky-agent`:
* `synchronik-agent`:
* Run workloads
* Listen HTTP
* executes commands

View File

@ -2,11 +2,11 @@
openapi: "3.0.0"
info:
description: |
Janky API v1 defintion
Synchronik API v1 defintion
version: "1.0.0"
title: Janky APIs
title: Synchronik APIs
contact:
email: "rtyler+janky@brokenco.de"
email: "rtyler+synchronik@brokenco.de"
license:
name: "AGPL v3.0"
url: "https://www.gnu.org/licenses/agpl-3.0.en.html"
@ -33,7 +33,7 @@ paths:
- in: path
name: name
required: true
example: 'janky'
example: 'synchronik'
schema:
type: string
responses:

View File

@ -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"}}}}}}

View File

@ -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
needs:

View File

@ -5,22 +5,22 @@ agents:
'Duplicate Local':
url: 'http://localhost:9000'
projects:
'janky':
'synchronik':
description: |
Self-hosted Janky project
filename: 'ci.janky.yml'
Self-hosted project
filename: 'ci.synchronik.yml'
scm:
github:
owner: 'rtyler'
repo: 'janky'
repo: 'synchronik'
ref: 'main'
'janky with spaces':
'with spaces':
description: A test configuration with spaces in the name
filename: 'ci.janky.yml'
filename: 'ci.synchronik.yml'
scm:
github:
owner: 'rtyler'
repo: 'janky'
repo: 'synchronik'
ref: 'main'
# The filetype Git is not yet supported
#- type: 'git'

View File

@ -5,8 +5,8 @@ use std::path::PathBuf;
use async_std::channel::{bounded, Receiver, Sender};
use dotenv::dotenv;
use janky::CommandRequest;
use log::*;
use synchronik::CommandRequest;
use uuid::Uuid;
const AGENT_LOGS_DIR: &str = "agent-logs";
@ -20,13 +20,13 @@ mod routes {
* GET /
*/
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 {
use crate::caps::*;
use crate::*;
use janky::{CommandRequest, CommandResponse};
use synchronik::{CommandRequest, CommandResponse};
use tide::{Body, Request, Response, StatusCode};
use uuid::Uuid;

View File

@ -6,10 +6,10 @@ use url::Url;
use crate::AppState;
/*
* Representation of the Janky YAML format
* Representation of the Synchronik YAML format
*/
#[derive(Clone, Debug, Deserialize)]
pub struct JankyYml {
pub struct Yml {
pub needs: Vec<String>,
pub commands: Vec<String>,
}
@ -44,11 +44,11 @@ pub struct Project {
pub struct Agent {
pub name: String,
pub url: Url,
pub capabilities: Vec<janky::Capability>,
pub capabilities: Vec<synchronik::Capability>,
}
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 {
name,
url,

View File

@ -1,5 +1,5 @@
/*
* This is the main Janky entrypoint for the server"
* This is the main Synchronik entrypoint for the server
*/
#[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 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:" {
sqlx::migrate!().run(&pool).await?;
}
@ -118,10 +118,11 @@ async fn main() -> Result<(), tide::Error> {
for (name, agent) in config.agents.iter() {
debug!("Requesting capabilities from agent: {:?}", agent);
let response: janky::CapsResponse = reqwest::get(agent.url.join("/api/v1/capabilities")?)
.await?
.json()
.await?;
let response: synchronik::CapsResponse =
reqwest::get(agent.url.join("/api/v1/capabilities")?)
.await?
.json()
.await?;
state.agents.push(Agent::new(
name.to_string(),
agent.url.clone(),
@ -177,7 +178,7 @@ async fn main() -> Result<(), tide::Error> {
#[cfg(test)]
mod tests {
use super::*;
use janky::*;
use synchronik::*;
#[test]
fn agent_can_meet_false() {

View File

@ -46,7 +46,7 @@ pub async fn project(req: Request<AppState<'_>>) -> Result<Body, tide::Error> {
}
pub mod api {
use crate::config::{JankyYml, Scm};
use crate::config::{Scm, Yml};
use crate::AppState;
use log::*;
use serde::Deserialize;
@ -88,18 +88,18 @@ pub mod api {
&project.filename,
)
.await?;
let jankyfile: JankyYml = serde_yaml::from_str(&res.text().await?)?;
debug!("text: {:?}", jankyfile);
let config_file: Yml = serde_yaml::from_str(&res.text().await?)?;
debug!("text: {:?}", config_file);
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);
let commands: Vec<janky::Command> = jankyfile
let commands: Vec<synchronik::Command> = config_file
.commands
.iter()
.map(|c| janky::Command::with_script(c))
.map(|c| synchronik::Command::with_script(c))
.collect();
let commands = janky::CommandRequest { commands };
let commands = synchronik::CommandRequest { commands };
let client = reqwest::Client::new();
let _res = client
.put(

View File

@ -1,6 +1,6 @@
<nav class="navbar navbar-expand-lg bg-dark" data-bs-theme="dark">
<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">
<span class="navbar-toggler-icon"></span>
</button>

View File

@ -1,7 +1,7 @@
<!doctype html>
<html lang="en">
<head>
<title>Janky</title>
<title>Synchronik</title>
<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>