Skip to content

Commit 7e40bda

Browse files
committed
feat!: rewrite everything
1 parent 5eb9ed9 commit 7e40bda

67 files changed

Lines changed: 2176 additions & 250 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/deploy.yml

Lines changed: 79 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -2,30 +2,90 @@ name: CI
22

33
on:
44
push:
5-
branches: [ "main" ]
6-
pull_request:
7-
branches: [ "main" ]
5+
branches: ["main"]
86

9-
workflow_dispatch:
7+
jobs:
8+
build-frontend:
9+
name: Build & Push Frontend Image
10+
runs-on: ubuntu-latest
11+
environment: production
12+
13+
steps:
14+
- name: Login to Docker Hub
15+
uses: docker/login-action@v3
16+
with:
17+
username: ${{ vars.DOCKERHUB_USERNAME }}
18+
password: ${{ secrets.DOCKERHUB_TOKEN }}
19+
20+
- name: Build Docker image
21+
uses: docker/bake-action@v6
22+
env:
23+
CF_SITEKEY: ${{ vars.CF_SITEKEY }}
24+
GRAPHQL_GITHUB_API_TOKEN: ${{ secrets.GRAPHQL_GITHUB_API_TOKEN }}
25+
with:
26+
files: |
27+
docker-bake.hcl
28+
docker-bake.prod.hcl
29+
push: true
30+
no-cache: true
31+
targets: frontend
32+
33+
build-backend:
34+
name: Build & Push Backend Image
35+
runs-on: ubuntu-latest
36+
environment: production
37+
38+
steps:
39+
- name: Login to Docker Hub
40+
uses: docker/login-action@v3
41+
with:
42+
username: ${{ vars.DOCKERHUB_USERNAME }}
43+
password: ${{ secrets.DOCKERHUB_TOKEN }}
44+
45+
- name: Build Docker image
46+
uses: docker/bake-action@v6
47+
env:
48+
GRAPHQL_GITHUB_API_TOKEN: ${{ secrets.GRAPHQL_GITHUB_API_TOKEN }}
49+
with:
50+
files: |
51+
docker-bake.hcl
52+
docker-bake.prod.hcl
53+
push: true
54+
no-cache: true
55+
targets: backend
1056

11-
jobs:
1257
deploy:
13-
name: Deploy
58+
name: Deploy Stack
1459
runs-on: ubuntu-latest
1560
environment: production
16-
61+
needs: [build-frontend, build-backend]
62+
1763
steps:
18-
- name: Deploy to Oracle Cloud server via SSH
19-
uses: appleboy/ssh-action@v0.1.10
64+
- name: Checkout repository
65+
uses: actions/checkout@v3
66+
67+
- name: Deploy stack
68+
uses: ibiixie/stack-deploy-action@feature/multiple-compose-inputs
2069
with:
2170
host: ${{ secrets.REMOTE_HOST }}
22-
username: ${{ secrets.REMOTE_USERNAME }}
23-
key: ${{ secrets.SSH_PRIVATE_KEY }}
24-
port: ${{ secrets.REMOTE_PORT }}
25-
script: |
26-
cd ${{ secrets.REMOTE_WORKING_DIRECTORY }}
27-
echo "Pulling changes..."
28-
git pull
29-
echo "Running deployment script..."
30-
sh deploy.sh
31-
echo "Deployment complete!"
71+
user: ${{ vars.REMOTE_USER }}
72+
ssh_key: ${{ secrets.SSH_PRIVATE_KEY }}
73+
file: ./compose.yaml;./compose.prod.yaml
74+
name: biixie-website
75+
mode: compose
76+
env:
77+
CF_TURNSTILE_SECRET: ${{ secrets.CF_TURNSTILE_SECRET }}
78+
KVP_REDACTED_TERMS: ${{ secrets.REDACTED_TERMS }}
79+
80+
purge-cache:
81+
name: Purge Cloudflare Cache
82+
runs-on: ubuntu-latest
83+
environment: production
84+
needs: ["deploy"]
85+
86+
steps:
87+
- name: Purge cache
88+
uses: nathanvaughn/actions-cloudflare-purge@v3.1.0
89+
with:
90+
cf_zone: ${{ secrets.CLOUDFLARE_ZONE }}
91+
cf_auth: ${{ secrets.CLOUDFLARE_AUTH_KEY }}

.gitignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
.vscode
2+
**/secrets/**
3+
.env
4+
env.hcl

.vscode/launch.json

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
{
2+
"version": "0.2.0",
3+
"configurations": [
4+
{
5+
"type": "lldb",
6+
"request": "launch",
7+
"name": "Debug backend",
8+
"program": "${workspaceFolder}/backend/target/debug/backend.exe",
9+
"args": [],
10+
"cwd": "${workspaceFolder}",
11+
"env": {
12+
"DEBUG": "true",
13+
"MAILJET_API_KEY": "a501f1868ef147dcdb574468b6adc04a",
14+
"MAILJET_API_SECRET": "07f351e44ed65942b51ca1df485e4681",
15+
}
16+
},
17+
{
18+
"command": "./node_modules/.bin/astro dev",
19+
"name": "Debug frontend",
20+
"request": "launch",
21+
"type": "node-terminal"
22+
}
23+
]
24+
}

backend/.gitignore

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
debug/
2+
target/
3+
4+
Cargo.lock
5+
6+
**/*.rs.bk
7+
*.pdb
8+
9+
kvp_secrets/

backend/Cargo.toml

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
[package]
2+
name = "backend"
3+
version = "0.1.0"
4+
edition = "2021"
5+
6+
[dependencies]
7+
serde = { version = "1.0.215", features = ["derive"] }
8+
serde_json = "1.0.133"
9+
tokio = { version = "1.41.1", features = ["rt-multi-thread", "signal"] }
10+
axum = { version = "0.7.9", features = ["macros"] }
11+
tower = { version = "0.5.2", features = ["limit", "buffer"] }
12+
tower-http = { version = "0.6.2", features = ["cors", "limit", "timeout"] }
13+
reqwest = { version = "0.12.9", features = ["json"] }
14+
chrono = { version = "0.4.38", features = ["serde"] }
15+
log = "0.4.22"
16+
simplelog = "0.12.2"
17+
graphql_client = "0.14.0"

backend/Dockerfile

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
FROM rust:1 AS builder
2+
COPY ./backend /app
3+
WORKDIR /app
4+
RUN cargo build --release
5+
6+
FROM gcr.io/distroless/cc-debian12
7+
COPY --from=builder /app/target/release/backend /
8+
CMD ["./backend"]
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
2+
email=hi@biixie.com
3+
discord_handle=ibiixie
4+
discord_id=197846420080951296

backend/src/config.rs

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
#[derive(Debug, Clone)]
2+
pub struct Config {
3+
pub debug_mode: bool,
4+
pub backend_port: u32,
5+
pub state_mutex_timeout: u64,
6+
pub request_body_limit: usize,
7+
pub rate_limit_count: u64,
8+
pub rate_limit_duration: u64,
9+
pub request_timeout: u64,
10+
}
11+
12+
impl Config {
13+
pub fn from_env() -> Self {
14+
Self {
15+
debug_mode: Self::env("DEBUG").unwrap_or(false),
16+
backend_port: Self::env("BACKEND_PORT").unwrap_or(3000),
17+
state_mutex_timeout: Self::env("STATE_MUTEX_TIMEOUT").unwrap_or(30),
18+
request_body_limit: Self::env("REQUEST_BODY_LIMIT").unwrap_or(3072),
19+
rate_limit_count: Self::env("RATE_LIMIT_COUNT").unwrap_or(100),
20+
rate_limit_duration: Self::env("RATE_LIMIT_DURATION").unwrap_or(10 * 60),
21+
request_timeout: Self::env("REQUEST_TIMEOUT").unwrap_or(30),
22+
}
23+
}
24+
25+
fn env<T: std::str::FromStr>(key: &str) -> Option<T> {
26+
let Ok(value) = std::env::var(key) else {
27+
return None;
28+
};
29+
30+
let Ok(parsed) = value.parse::<T>() else {
31+
return None;
32+
};
33+
34+
Some(parsed)
35+
}
36+
}

backend/src/main.rs

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
#![allow(clippy::cargo_common_metadata)]
2+
#![allow(clippy::multiple_crate_versions)]
3+
4+
mod config;
5+
mod middleware;
6+
mod routes;
7+
mod secrets;
8+
mod shared_state;
9+
10+
#[macro_use]
11+
extern crate log;
12+
13+
use std::str::FromStr;
14+
15+
#[tokio::main]
16+
async fn main() {
17+
let log_level = std::env::var("BACKEND_LOG_LEVEL").unwrap_or("Info".into());
18+
19+
simplelog::TermLogger::init(
20+
log::LevelFilter::from_str(&log_level)
21+
.expect("BACKEND_LOG_LEVEL exists in environment but is malformed"),
22+
simplelog::Config::default(),
23+
simplelog::TerminalMode::Mixed,
24+
simplelog::ColorChoice::Auto,
25+
)
26+
.unwrap();
27+
28+
info!("Starting backend server");
29+
info!("Log level set to {}", log::max_level());
30+
31+
let state: shared_state::SharedState = shared_state::SharedState::new();
32+
let port = state.config.backend_port;
33+
let router = routes::setup_routes(state);
34+
let listener = tokio::net::TcpListener::bind(format!("0.0.0.0:{port}"))
35+
.await
36+
.unwrap();
37+
38+
axum::serve(listener, router)
39+
.with_graceful_shutdown(shutdown_signal())
40+
.await
41+
.unwrap();
42+
43+
info!("Stopped backend server");
44+
}
45+
46+
async fn shutdown_signal() {
47+
let ctrl_c = async {
48+
tokio::signal::ctrl_c()
49+
.await
50+
.expect("failed to install CTRL+C shutdown handler");
51+
};
52+
53+
#[cfg(unix)]
54+
let terminate = async {
55+
tokio::signal::unix::signal(tokio::signal::unix::SignalKind::terminate())
56+
.expect("failed to install termination signal handler")
57+
.recv()
58+
.await;
59+
};
60+
61+
#[cfg(not(unix))]
62+
let terminate = std::future::pending::<()>();
63+
64+
tokio::select! {
65+
() = ctrl_c => {},
66+
() = terminate => {},
67+
};
68+
}
69+

backend/src/middleware.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
pub mod error;
2+
pub mod turnstile;
3+
4+
pub use turnstile::turnstile;

0 commit comments

Comments
 (0)