mirror of
https://github.com/kjuulh/bitebuds.git
synced 2024-12-22 03:03:34 +01:00
feat: add ci
This commit is contained in:
parent
f56f8c6818
commit
2053220d01
855
Cargo.lock
generated
855
Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
@ -1,5 +1,5 @@
|
||||
[workspace]
|
||||
members = [".", "crates/services", "crates/domain", "crates/biteme"]
|
||||
members = [".", "crates/services", "crates/domain", "crates/biteme", "ci"]
|
||||
|
||||
[workspace.dependencies]
|
||||
domain = { path = "crates/domain" }
|
||||
@ -35,6 +35,8 @@ tower = { version = "0.4.13", optional = true }
|
||||
tower-http = { version = "0.3.4", features = ["fs"], optional = true }
|
||||
tokio = { version = "1", features = ["time"], optional = true }
|
||||
wasm-bindgen = "0.2"
|
||||
tracing-subscriber = { version = "0.3.16", optional = true }
|
||||
tracing = { version = "0.1.37", features = ["log"], optional = true }
|
||||
|
||||
serde = { workspace = true }
|
||||
chrono = { workspace = true }
|
||||
@ -55,6 +57,8 @@ ssr = [
|
||||
"leptos_router/ssr",
|
||||
"dep:leptos_axum",
|
||||
"dep:services",
|
||||
"dep:tracing-subscriber",
|
||||
"dep:tracing",
|
||||
]
|
||||
|
||||
[package.metadata.leptos]
|
||||
|
@ -30,3 +30,8 @@ command = "cargo"
|
||||
args = ["install", "--path", "crates/biteme"]
|
||||
workspace = false
|
||||
install_crate = "cargo-all-features"
|
||||
|
||||
[tasks.ci]
|
||||
command = "cargo"
|
||||
args = ["run", "-p", "ci"]
|
||||
workspace = false
|
||||
|
@ -7,7 +7,7 @@ description: |
|
||||
God gammeldags oksesteg med en intens og fyldig brun sauce. Gammeldags oksesteg
|
||||
er rigtig simremad som gør de fleste glade. Så server en gammeldags oksesteg for
|
||||
din gæster... både de unge og de gamle.
|
||||
time: 2023-03-06
|
||||
time: 2025-03-06
|
||||
---
|
||||
|
||||
Some article
|
||||
|
13
ci/Cargo.toml
Normal file
13
ci/Cargo.toml
Normal file
@ -0,0 +1,13 @@
|
||||
[package]
|
||||
name = "ci"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
dagger-sdk = "0.2.15"
|
||||
eyre = "0.6.8"
|
||||
color-eyre = "0.6.2"
|
||||
tokio = { version = "1.26.0", features = ["full"] }
|
||||
chrono.workspace = true
|
147
ci/src/main.rs
Normal file
147
ci/src/main.rs
Normal file
@ -0,0 +1,147 @@
|
||||
#[tokio::main]
|
||||
async fn main() -> eyre::Result<()> {
|
||||
let rust_image = "rustlang/rust:nightly";
|
||||
|
||||
let client = dagger_sdk::connect().await?;
|
||||
|
||||
let workdir = client.host().directory_opts(
|
||||
".",
|
||||
dagger_sdk::HostDirectoryOpts {
|
||||
exclude: Some(vec!["target/", ".git/"]),
|
||||
include: None,
|
||||
},
|
||||
);
|
||||
|
||||
let minio_url = "https://github.com/mozilla/sccache/releases/download/v0.3.3/sccache-v0.3.3-x86_64-unknown-linux-musl.tar.gz";
|
||||
|
||||
// Main container
|
||||
let rust_base = client
|
||||
.container()
|
||||
.from(rust_image)
|
||||
.with_exec(vec!["apt-get", "update"])
|
||||
.with_exec(vec!["apt-get", "install", "--yes", "libpq-dev", "wget"])
|
||||
.with_exec(vec!["wget", minio_url])
|
||||
.with_exec(vec![
|
||||
"tar",
|
||||
"xzf",
|
||||
"sccache-v0.3.3-x86_64-unknown-linux-musl.tar.gz",
|
||||
])
|
||||
.with_exec(vec![
|
||||
"mv",
|
||||
"sccache-v0.3.3-x86_64-unknown-linux-musl/sccache",
|
||||
"/usr/local/bin/sccache",
|
||||
])
|
||||
.with_exec(vec!["chmod", "+x", "/usr/local/bin/sccache"])
|
||||
.with_env_variable("RUSTC_WRAPPER", "/usr/local/bin/sccache")
|
||||
.with_env_variable(
|
||||
"AWS_ACCESS_KEY_ID",
|
||||
std::env::var("AWS_ACCESS_KEY_ID").unwrap_or("".into()),
|
||||
)
|
||||
.with_env_variable(
|
||||
"AWS_SECRET_ACCESS_KEY",
|
||||
std::env::var("AWS_SECRET_ACCESS_KEY").unwrap_or("".into()),
|
||||
)
|
||||
.with_env_variable("SCCACHE_BUCKET", "sccache")
|
||||
.with_env_variable("SCCACHE_REGION", "auto")
|
||||
.with_env_variable("SCCACHE_ENDPOINT", "https://api-minio.front.kjuulh.io")
|
||||
.with_exec(vec!["cargo", "install", "cargo-chef"])
|
||||
.with_exec(vec!["cargo", "install", "cargo-leptos"])
|
||||
.with_workdir("/app");
|
||||
|
||||
let exit_code = rust_base.exit_code().await?;
|
||||
if exit_code != 0 {
|
||||
eyre::bail!("could not build base");
|
||||
}
|
||||
|
||||
let rust_prepare = rust_base
|
||||
.with_mounted_directory(".", workdir.id().await?)
|
||||
.with_exec(vec![
|
||||
"cargo",
|
||||
"chef",
|
||||
"prepare",
|
||||
"--recipe-path",
|
||||
"recipe.json",
|
||||
]);
|
||||
|
||||
let exit_code = rust_prepare.exit_code().await?;
|
||||
if exit_code != 0 {
|
||||
eyre::bail!("could not build prepare");
|
||||
}
|
||||
|
||||
let rust_cacher = rust_base
|
||||
.with_exec(vec!["apt", "update"])
|
||||
.with_exec(vec![
|
||||
"apt",
|
||||
"install",
|
||||
"pkg-config",
|
||||
"openssl",
|
||||
"libssl-dev",
|
||||
"-y",
|
||||
])
|
||||
.with_exec(vec!["rustup", "target", "add", "wasm32-unknown-unknown"])
|
||||
.with_file(
|
||||
"/recipe.json",
|
||||
rust_prepare.file("./recipe.json").id().await?,
|
||||
)
|
||||
.with_mounted_directory(".", workdir.id().await?)
|
||||
.with_exec(vec![
|
||||
"cargo",
|
||||
"chef",
|
||||
"cook",
|
||||
"--release",
|
||||
"--recipe-path",
|
||||
"/recipe.json",
|
||||
]);
|
||||
|
||||
let exit_code = rust_cacher.exit_code().await?;
|
||||
if exit_code != 0 {
|
||||
eyre::bail!("could not build cacher");
|
||||
}
|
||||
|
||||
let rust_builder = rust_base
|
||||
.with_exec(vec![
|
||||
"curl",
|
||||
"-sL",
|
||||
"https://deb.nodesource.com/setup_12.x",
|
||||
"-o",
|
||||
"/node_12.txt",
|
||||
])
|
||||
.with_exec(vec!["chmod", "+x", "/node_12.txt"])
|
||||
.with_exec(vec!["bash", "-c", "/node_12.txt"])
|
||||
.with_exec(vec!["apt-get", "update"])
|
||||
.with_exec(vec!["apt-get", "install", "nodejs"])
|
||||
.with_mounted_directory(".", workdir.id().await?)
|
||||
.with_directory(
|
||||
"/app/target",
|
||||
rust_cacher.directory("/app/target").id().await?,
|
||||
)
|
||||
.with_directory(
|
||||
"/usr/local/cargo",
|
||||
rust_cacher.directory("/usr/local/cargo").id().await?,
|
||||
)
|
||||
.with_exec(vec!["rustup", "target", "add", "wasm32-unknown-unknown"])
|
||||
.with_exec(vec!["npm", "install", "-g", "sass"])
|
||||
.with_env_variable("LEPTOS_BROWSERQUERY", "defaults")
|
||||
.with_exec(vec!["cargo", "leptos", "build", "--release"]);
|
||||
|
||||
let exit_code = rust_builder.exit_code().await?;
|
||||
if exit_code != 0 {
|
||||
eyre::bail!("could not build builder");
|
||||
}
|
||||
|
||||
let tag = chrono::Utc::now().timestamp();
|
||||
|
||||
let prod_image = "gcr.io/distroless/cc-debian11";
|
||||
let prod = client
|
||||
.container()
|
||||
.from(prod_image)
|
||||
.with_workdir("/app")
|
||||
.with_directory("/app", rust_builder.directory("/app/target").id().await?)
|
||||
.with_env_variable("LEPTOS_SITE_ADDRESS", "0.0.0.0:3000")
|
||||
.with_entrypoint(vec!["./server/release/ssr_mode_axum"]);
|
||||
|
||||
prod.publish(format!("docker.io/kasperhermansen/bitebuds:{tag}"))
|
||||
.await?;
|
||||
|
||||
Ok(())
|
||||
}
|
@ -9,6 +9,7 @@ edition = "2021"
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
gitevents_sdk = { git = "https://github.com/kjuulh/gitevents.git", branch = "main" }
|
||||
cached = "0.42.0"
|
||||
chrono = { version = "0.4.23", features = ["serde"] }
|
||||
domain = { path = "../domain" }
|
||||
@ -18,3 +19,4 @@ serde_json = "1.0.94"
|
||||
serde_yaml = "0.9.19"
|
||||
tokio = { version = "1.26.0", features = ["full"] }
|
||||
uuid = { version = "1.3.0", features = ["v4", "serde"] }
|
||||
tracing = { version = "0.1.37", features = ["log"] }
|
||||
|
@ -1,15 +1,10 @@
|
||||
use cached::proc_macro::once;
|
||||
use domain::{Event, Image, Metadata};
|
||||
use gitevents_sdk::events::EventResponse;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::path::PathBuf;
|
||||
use std::sync::Arc;
|
||||
|
||||
use cached::proc_macro::{cached, once};
|
||||
use domain::{Event, Image, Metadata};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
pub struct EventStore {
|
||||
pub path: PathBuf,
|
||||
events: Arc<tokio::sync::RwLock<Vec<Event>>>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||
pub struct RawImage {
|
||||
pub url: String,
|
||||
@ -81,28 +76,89 @@ impl From<RawImage> for Image {
|
||||
}
|
||||
}
|
||||
|
||||
struct InnerEventStore {
|
||||
url: Option<String>,
|
||||
pub path: PathBuf,
|
||||
events: Arc<tokio::sync::RwLock<Vec<Event>>>,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct EventStore {
|
||||
inner: Arc<InnerEventStore>,
|
||||
}
|
||||
|
||||
impl EventStore {
|
||||
pub fn new(path: PathBuf) -> Self {
|
||||
let article_repo_url = std::env::var("BITE_ARTICLE_REPO_URL")
|
||||
.map(|a| (a != "").then(|| a))
|
||||
.unwrap_or(None);
|
||||
Self {
|
||||
path,
|
||||
events: Default::default(),
|
||||
inner: Arc::new(InnerEventStore {
|
||||
url: article_repo_url,
|
||||
path,
|
||||
events: Default::default(),
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn bootstrap(&self) -> eyre::Result<()> {
|
||||
tracing::info!("boostrapping event_store");
|
||||
//let mut event_path = self.inner.path.clone();
|
||||
//event_path.push("events");
|
||||
|
||||
//let events = fetch_events(event_path.clone()).await?;
|
||||
|
||||
//let mut e = self.inner.events.write().await;
|
||||
//*e = events;
|
||||
|
||||
if let Some(repo_url) = self.inner.url.clone() {
|
||||
tracing::info!(repo_url = repo_url, "subscribing to repo");
|
||||
let inner = self.inner.clone();
|
||||
|
||||
tokio::task::spawn(async move {
|
||||
gitevents_sdk::builder::Builder::new()
|
||||
.set_generic_git_url(repo_url)
|
||||
.set_scheduler_opts(&gitevents_sdk::cron::SchedulerOpts {
|
||||
duration: std::time::Duration::from_secs(30),
|
||||
})
|
||||
.action(move |req| {
|
||||
let inner = inner.clone();
|
||||
|
||||
async move {
|
||||
tracing::info!("updating articles");
|
||||
let mut event_path = req.git.path.clone();
|
||||
event_path.push("articles/events");
|
||||
|
||||
tracing::debug!(
|
||||
path = event_path.display().to_string(),
|
||||
"reading from"
|
||||
);
|
||||
|
||||
let events = fetch_events(event_path).await.unwrap();
|
||||
|
||||
let mut e = inner.events.write().await;
|
||||
*e = events.clone();
|
||||
|
||||
Ok(EventResponse {})
|
||||
}
|
||||
})
|
||||
.execute()
|
||||
.await
|
||||
.unwrap();
|
||||
});
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub async fn get_upcoming_events(&self) -> eyre::Result<Vec<Event>> {
|
||||
let mut event_path = self.path.clone();
|
||||
event_path.push("events");
|
||||
|
||||
let events = fetch_events(event_path).await?;
|
||||
|
||||
let mut e = self.events.write().await;
|
||||
*e = events.clone();
|
||||
let events = self.inner.events.read().await.clone();
|
||||
|
||||
Ok(events)
|
||||
}
|
||||
|
||||
pub async fn get_event(&self, event_id: uuid::Uuid) -> eyre::Result<Option<Event>> {
|
||||
let events = self.events.read().await;
|
||||
let events = self.inner.events.read().await;
|
||||
|
||||
let event = events.iter().find(|e| e.id == event_id);
|
||||
|
||||
@ -110,7 +166,6 @@ impl EventStore {
|
||||
}
|
||||
}
|
||||
|
||||
#[once(time = 60, result = true, sync_writes = true)]
|
||||
pub async fn fetch_events(event_path: PathBuf) -> eyre::Result<Vec<Event>> {
|
||||
let mut dir = tokio::fs::read_dir(event_path).await?;
|
||||
|
||||
@ -140,8 +195,11 @@ pub async fn fetch_events(event_path: PathBuf) -> eyre::Result<Vec<Event>> {
|
||||
impl Default for EventStore {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
path: PathBuf::from("articles"),
|
||||
events: Default::default(),
|
||||
inner: Arc::new(InnerEventStore {
|
||||
url: Default::default(),
|
||||
path: PathBuf::from("articles"),
|
||||
events: Default::default(),
|
||||
}),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,3 +1,5 @@
|
||||
use std::path::PathBuf;
|
||||
|
||||
use cfg_if::cfg_if;
|
||||
use leptos::*;
|
||||
use serde::{Deserialize, Serialize};
|
||||
@ -10,11 +12,9 @@ cfg_if! {
|
||||
use lazy_static::lazy_static;
|
||||
|
||||
lazy_static! {
|
||||
static ref EVENTSTORE: EventStore = EventStore::default();
|
||||
static ref EVENTSTORE: EventStore = EventStore::new(PathBuf::from("articles"));
|
||||
}
|
||||
async fn get_upcoming_events_fn() -> Result<UpcomingEventsOverview, ServerFnError> {
|
||||
let current_time = chrono::Utc::now();
|
||||
|
||||
let mut events: Vec<EventOverview> = EVENTSTORE
|
||||
.get_upcoming_events()
|
||||
.await
|
||||
@ -24,7 +24,7 @@ cfg_if! {
|
||||
.map(|data| data.clone().into())
|
||||
.collect();
|
||||
|
||||
events.sort_by(|a, b| a.time.cmp(&b.time));
|
||||
events.sort_by(|a, b| a.time.cmp(&b.time)) ;
|
||||
|
||||
Ok(UpcomingEventsOverview { events })
|
||||
}
|
||||
@ -33,9 +33,12 @@ cfg_if! {
|
||||
.get_event(event_id)
|
||||
.await
|
||||
.map_err(|e| ServerFnError::ServerError(e.to_string()))?;
|
||||
|
||||
Ok(event)
|
||||
}
|
||||
|
||||
pub async fn boostrap() -> Result<(), ServerFnError> {
|
||||
EVENTSTORE.bootstrap().await.map_err(|e| ServerFnError::ServerError(e.to_string()))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
18
src/main.rs
18
src/main.rs
@ -1,16 +1,24 @@
|
||||
#[cfg(feature = "ssr")]
|
||||
#[tokio::main]
|
||||
async fn main() {
|
||||
use axum::{
|
||||
extract::{Extension, Path},
|
||||
routing::{get, post},
|
||||
Router,
|
||||
};
|
||||
use axum::{extract::Extension, routing::post, Router};
|
||||
use leptos::*;
|
||||
use leptos_axum::{generate_route_list, LeptosRoutes};
|
||||
use ssr_modes_axum::app::*;
|
||||
use ssr_modes_axum::fallback::file_and_error_handler;
|
||||
use std::sync::Arc;
|
||||
use tracing::metadata::LevelFilter;
|
||||
|
||||
std::env::set_var(
|
||||
"BITE_ARTICLE_REPO_URL",
|
||||
"git@git.front.kjuulh.io:kjuulh/articles.git",
|
||||
);
|
||||
|
||||
tracing_subscriber::fmt()
|
||||
.with_max_level(LevelFilter::TRACE)
|
||||
.init();
|
||||
|
||||
ssr_modes_axum::api::events::boostrap().await.unwrap();
|
||||
|
||||
let conf = get_configuration(None).await.unwrap();
|
||||
let addr = conf.leptos_options.site_addr;
|
||||
|
Loading…
Reference in New Issue
Block a user