From fd3f4a957844bcd6208cb15c9eb8accd6370f45e Mon Sep 17 00:00:00 2001 From: codingsh Date: Tue, 26 Nov 2024 14:35:47 +0000 Subject: [PATCH 1/5] feat(docker): ghcr version --- .github/workflows/docker.yml | 57 +++++++++--------- .github/workflows/ghcr.yml | 108 +++++++++++++++++++++++++++++++++++ Dockerfile | 62 +++++++++++--------- docker-compose.yml | 9 ++- 4 files changed, 175 insertions(+), 61 deletions(-) create mode 100644 .github/workflows/ghcr.yml diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index 396e17a..6c7d30e 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -1,4 +1,4 @@ -name: Docker CI with Enhanced Checks +name: Docker CI/CD on: push: @@ -9,10 +9,9 @@ on: env: REGISTRY: ghcr.io IMAGE_NAME: ${{ github.repository }} - RUST_LOG: info jobs: - lint-and-test: + build-and-test: runs-on: ubuntu-latest permissions: contents: read @@ -22,37 +21,17 @@ jobs: - name: Checkout repository uses: actions/checkout@v4 - - name: Install Rust toolchain - uses: actions-rs/toolchain@v1 - with: - profile: minimal - toolchain: nightly - override: true - components: rustfmt, clippy - - - name: Rust cache - uses: Swatinem/rust-cache@v2 - - - name: Check formatting - run: cargo fmt -- --check - - - name: Run clippy - run: cargo clippy -- -D warnings - - - name: Run tests - run: cargo test - - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3 - - name: Log in to Registry + - name: Log in to the Container registry uses: docker/login-action@v3 with: registry: ${{ env.REGISTRY }} username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} - - name: Extract Docker metadata + - name: Extract metadata (tags, labels) for Docker id: meta uses: docker/metadata-action@v5 with: @@ -61,8 +40,10 @@ jobs: type=ref,event=branch type=ref,event=pr type=semver,pattern={{version}} + type=semver,pattern={{major}}.{{minor}} type=sha + - name: Build and test Docker image uses: docker/build-push-action@v5 with: @@ -73,17 +54,20 @@ jobs: labels: ${{ steps.meta.outputs.labels }} cache-from: type=gha cache-to: type=gha,mode=max - build-args: | - RUST_LOG=info target: builder load: true + - name: Test the image + run: | + docker compose -f docker-compose.yml run test + + - name: Set up QEMU uses: docker/setup-qemu-action@v3 - - name: Build and push final image - if: github.event_name != 'pull_request' + - name: Build and push final multi-platform image uses: docker/build-push-action@v5 + if: github.event_name != 'pull_request' with: context: . platforms: linux/amd64,linux/arm64 @@ -92,5 +76,16 @@ jobs: labels: ${{ steps.meta.outputs.labels }} cache-from: type=gha cache-to: type=gha,mode=max - build-args: | - RUST_LOG=info \ No newline at end of file + + + - name: Build final image for PR + uses: docker/build-push-action@v5 + if: github.event_name == 'pull_request' + with: + context: . + platforms: linux/amd64 + push: false + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} + cache-from: type=gha + cache-to: type=gha,mode=max \ No newline at end of file diff --git a/.github/workflows/ghcr.yml b/.github/workflows/ghcr.yml new file mode 100644 index 0000000..ed47aba --- /dev/null +++ b/.github/workflows/ghcr.yml @@ -0,0 +1,108 @@ +name: Container Registry Deploy + +on: + push: + branches: ["main"] + tags: ["v*"] + pull_request: + branches: ["main"] + +env: + REGISTRY: ghcr.io + IMAGE_NAME: ${{ github.repository }} + CARGO_TERM_COLOR: always + RUST_LOG: info + +permissions: + contents: read + packages: write + +jobs: + build-and-push: + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Install system dependencies + run: | + sudo apt-get update + sudo apt-get install -y \ + pkg-config \ + libgtk-3-dev \ + libwebkit2gtk-4.0-dev \ + libayatana-appindicator3-dev \ + librsvg2-dev \ + libgdk3.0-cil \ + libgdk-pixbuf2.0-dev \ + libglib2.0-dev \ + cmake \ + libxdo-dev \ + libssl-dev + + - name: Install Rust toolchain + uses: dtolnay/rust-toolchain@nightly + with: + components: rustfmt, clippy + + - name: Rust cache + uses: Swatinem/rust-cache@v2 + with: + shared-key: "rust-cache" + + - name: Run tests + run: cargo test + + - name: Check formatting + run: cargo fmt --all -- --check + + - name: Clippy + run: cargo clippy -- -D warnings + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Log in to GHCR + uses: docker/login-action@v3 + with: + registry: ${{ env.REGISTRY }} + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Extract metadata + id: meta + uses: docker/metadata-action@v5 + with: + images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} + tags: | + type=raw,value=latest,enable={{is_default_branch}} + type=ref,event=branch + type=ref,event=pr + type=semver,pattern={{version}} + type=semver,pattern={{major}}.{{minor}} + type=sha + + - name: Build and test + uses: docker/build-push-action@v5 + with: + context: . + load: true + tags: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:test + cache-from: type=gha + cache-to: type=gha,mode=max + target: builder + + - name: Test the container + run: | + docker compose -f docker-compose.yml run test + + - name: Build and push + uses: docker/build-push-action@v5 + with: + context: . + platforms: linux/amd64,linux/arm64 + push: ${{ github.event_name != 'pull_request' }} + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} + cache-from: type=gha + cache-to: type=gha,mode=max \ No newline at end of file diff --git a/Dockerfile b/Dockerfile index 0680f0e..8f3a87d 100644 --- a/Dockerfile +++ b/Dockerfile @@ -3,15 +3,18 @@ FROM rustlang/rust:nightly AS builder RUN apt-get update && \ apt-get install -y \ - pkg-config \ - libssl-dev \ - libgtk-3-dev \ - libwebkit2gtk-4.0-dev \ - libayatana-appindicator3-dev \ - librsvg2-dev \ - cmake \ - libxdo-dev && \ - rm -rf /var/lib/apt/lists/* + pkg-config \ + libgtk-3-dev \ + libwebkit2gtk-4.0-dev \ + libayatana-appindicator3-dev \ + librsvg2-dev \ + libgdk3.0-cil \ + libgdk-pixbuf2.0-dev \ + libglib2.0-dev \ + cmake \ + libxdo-dev \ + libssl-dev \ + && rm -rf /var/lib/apt/lists/* WORKDIR /usr/src/app @@ -27,33 +30,34 @@ RUN mkdir src && \ COPY src src/ +COPY rust-toolchain.toml . ARG RUST_LOG=info ENV RUST_LOG=${RUST_LOG} -RUN echo "Building application with RUST_LOG=${RUST_LOG}" && \ +RUN echo "Building with RUST_LOG=${RUST_LOG}" && \ cargo build --release && \ cargo test --no-run FROM debian:bookworm-slim - RUN apt-get update && \ apt-get install -y \ - ca-certificates \ - libwebkit2gtk-4.0-37 \ - libjavascriptcoregtk-4.0-18 \ - libsoup2.4-1 \ - gstreamer1.0-plugins-base \ - gstreamer1.0-plugins-good \ - gstreamer1.0-x \ - libgtk-3-0 \ - curl \ - librsvg2-2 \ - libxdo3 && \ - rm -rf /var/lib/apt/lists/* + ca-certificates \ + libgtk-3-0 \ + libwebkit2gtk-4.0-37 \ + libayatana-appindicator3-1 \ + librsvg2-2 \ + gstreamer1.0-plugins-base \ + gstreamer1.0-plugins-good \ + gstreamer1.0-x \ + libgdk3.0-cil \ + libgdk-pixbuf2.0-0 \ + curl \ + libxdo3 \ + && rm -rf /var/lib/apt/lists/* COPY --from=builder /usr/src/app/target/release/titanium /usr/local/bin/ @@ -62,14 +66,16 @@ COPY --from=builder /usr/src/app/target/release/titanium /usr/local/bin/ ENV RUST_LOG=info -COPY <<'EOF' /usr/local/bin/start.sh +COPY <<'EOF' /usr/local/bin/healthcheck.sh #!/bin/bash -echo "Starting Titanium server with RUST_LOG=${RUST_LOG}" -exec titanium +curl -f http://localhost:3000/health || exit 1 EOF -RUN chmod +x /usr/local/bin/start.sh +RUN chmod +x /usr/local/bin/healthcheck.sh + +HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \ + CMD ["/usr/local/bin/healthcheck.sh"] EXPOSE 3000 -CMD ["/usr/local/bin/start.sh"] \ No newline at end of file +CMD ["titanium"] \ No newline at end of file diff --git a/docker-compose.yml b/docker-compose.yml index 21a23fa..45cdb21 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,10 +1,15 @@ services: app: - build: . + image: ${REGISTRY:-ghcr.io}/${IMAGE_NAME:developerfred/titanium}:${TAG:-latest} + build: + context: . + args: + RUST_LOG: ${RUST_LOG:-info} ports: - "3000:3000" environment: - - RUST_LOG=info + - RUST_LOG=${RUST_LOG:-info} + - RUST_BACKTRACE=1 healthcheck: test: ["CMD", "curl", "-f", "http://localhost:3000/health"] interval: 30s From 905852d41114becc8cd985ffa02e364e92067271 Mon Sep 17 00:00:00 2001 From: codingsh Date: Tue, 26 Nov 2024 15:00:49 +0000 Subject: [PATCH 2/5] update dockerfile --- Dockerfile | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/Dockerfile b/Dockerfile index 8f3a87d..4789f74 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,6 +1,13 @@ +# Builder stage FROM rustlang/rust:nightly AS builder +ENV CARGO_HOME=/usr/local/cargo +ENV RUSTUP_HOME=/usr/local/rustup +ENV PATH=/usr/local/cargo/bin:$PATH +ENV RUST_LOG=info + + RUN apt-get update && \ apt-get install -y \ pkg-config \ @@ -16,29 +23,28 @@ RUN apt-get update && \ libssl-dev \ && rm -rf /var/lib/apt/lists/* -WORKDIR /usr/src/app +WORKDIR /app COPY Cargo.toml Cargo.lock* ./ RUN mkdir src && \ - echo "fn main() { println!(\"Initializing build...\"); }" > src/main.rs && \ + echo 'fn main() { println!("dummy") }' > src/main.rs && \ cargo build --release && \ cargo build --tests && \ - rm -rf src + rm -rf src target/release/deps/titanium* COPY src src/ COPY rust-toolchain.toml . -ARG RUST_LOG=info -ENV RUST_LOG=${RUST_LOG} - -RUN echo "Building with RUST_LOG=${RUST_LOG}" && \ +RUN --mount=type=cache,target=/usr/local/cargo/registry \ + --mount=type=cache,target=/app/target \ cargo build --release && \ - cargo test --no-run + cargo test --no-run && \ + cp target/release/titanium /app/titanium FROM debian:bookworm-slim @@ -60,7 +66,7 @@ RUN apt-get update && \ && rm -rf /var/lib/apt/lists/* -COPY --from=builder /usr/src/app/target/release/titanium /usr/local/bin/ +COPY --from=builder /app/titanium /usr/local/bin/titanium ENV RUST_LOG=info From ba05007453f7ae17fda84db5362d187c5fa2cdea Mon Sep 17 00:00:00 2001 From: codingsh Date: Mon, 2 Dec 2024 10:31:43 +0000 Subject: [PATCH 3/5] chore(github): clean actions and fix docker action --- .github/workflows/docker.yml | 54 +++--------------- Dockerfile | 34 ++++++++--- docker-compose.yml | 42 ++++++++++++-- src/main.rs | 106 ++++++++++++++++++++++++++++------- 4 files changed, 157 insertions(+), 79 deletions(-) diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index 6c7d30e..185c1e8 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -1,17 +1,18 @@ -name: Docker CI/CD +name: Docker Build and Push on: push: - branches: [ "main" ] + branches: [ main ] + tags: [ 'v*.*.*' ] pull_request: - branches: [ "main" ] + branches: [ main ] env: REGISTRY: ghcr.io IMAGE_NAME: ${{ github.repository }} jobs: - build-and-test: + build-and-push: runs-on: ubuntu-latest permissions: contents: read @@ -21,9 +22,6 @@ jobs: - name: Checkout repository uses: actions/checkout@v4 - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v3 - - name: Log in to the Container registry uses: docker/login-action@v3 with: @@ -43,48 +41,14 @@ jobs: type=semver,pattern={{major}}.{{minor}} type=sha - - - name: Build and test Docker image - uses: docker/build-push-action@v5 - with: - context: . - platforms: linux/amd64 - push: false - tags: ${{ steps.meta.outputs.tags }} - labels: ${{ steps.meta.outputs.labels }} - cache-from: type=gha - cache-to: type=gha,mode=max - target: builder - load: true - - - name: Test the image - run: | - docker compose -f docker-compose.yml run test - - - - name: Set up QEMU - uses: docker/setup-qemu-action@v3 - - - name: Build and push final multi-platform image - uses: docker/build-push-action@v5 - if: github.event_name != 'pull_request' - with: - context: . - platforms: linux/amd64,linux/arm64 - push: true - tags: ${{ steps.meta.outputs.tags }} - labels: ${{ steps.meta.outputs.labels }} - cache-from: type=gha - cache-to: type=gha,mode=max + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 - - - name: Build final image for PR + - name: Build and push Docker image uses: docker/build-push-action@v5 - if: github.event_name == 'pull_request' with: context: . - platforms: linux/amd64 - push: false + push: ${{ github.event_name != 'pull_request' }} tags: ${{ steps.meta.outputs.tags }} labels: ${{ steps.meta.outputs.labels }} cache-from: type=gha diff --git a/Dockerfile b/Dockerfile index 4789f74..25767d3 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,12 +1,12 @@ # Builder stage FROM rustlang/rust:nightly AS builder - ENV CARGO_HOME=/usr/local/cargo ENV RUSTUP_HOME=/usr/local/rustup ENV PATH=/usr/local/cargo/bin:$PATH -ENV RUST_LOG=info - +ENV RUST_LOG=debug +ENV RUST_BACKTRACE=full +ENV RUST_LIB_BACKTRACE=1 RUN apt-get update && \ apt-get install -y \ @@ -25,28 +25,26 @@ RUN apt-get update && \ WORKDIR /app +# Create logs directory +RUN mkdir -p /app/logs COPY Cargo.toml Cargo.lock* ./ - RUN mkdir src && \ echo 'fn main() { println!("dummy") }' > src/main.rs && \ cargo build --release && \ cargo build --tests && \ rm -rf src target/release/deps/titanium* - COPY src src/ COPY rust-toolchain.toml . - RUN --mount=type=cache,target=/usr/local/cargo/registry \ --mount=type=cache,target=/app/target \ cargo build --release && \ cargo test --no-run && \ cp target/release/titanium /app/titanium - FROM debian:bookworm-slim RUN apt-get update && \ @@ -65,12 +63,29 @@ RUN apt-get update && \ libxdo3 \ && rm -rf /var/lib/apt/lists/* +# Create logs directory and set permissions +RUN mkdir -p /app/logs && \ + chown -R nobody:nogroup /app/logs COPY --from=builder /app/titanium /usr/local/bin/titanium +ENV RUST_LOG=debug +ENV RUST_BACKTRACE=full +ENV RUST_LIB_BACKTRACE=1 + +# Add logging script +COPY <<'EOF' /usr/local/bin/start.sh +#!/bin/bash +set -e -ENV RUST_LOG=info +# Redirect stdout/stderr to both console and file +exec &> >(tee -a "/app/logs/titanium.log") + +# Start the application +exec titanium +EOF +RUN chmod +x /usr/local/bin/start.sh COPY <<'EOF' /usr/local/bin/healthcheck.sh #!/bin/bash @@ -82,6 +97,7 @@ RUN chmod +x /usr/local/bin/healthcheck.sh HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \ CMD ["/usr/local/bin/healthcheck.sh"] +VOLUME ["/app/logs"] EXPOSE 3000 -CMD ["titanium"] \ No newline at end of file +CMD ["/usr/local/bin/start.sh"] \ No newline at end of file diff --git a/docker-compose.yml b/docker-compose.yml index 45cdb21..0d5d970 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,21 +1,39 @@ services: app: - image: ${REGISTRY:-ghcr.io}/${IMAGE_NAME:developerfred/titanium}:${TAG:-latest} + image: ${REGISTRY:-ghcr.io}/${IMAGE_NAME:-developerfred/titanium}:${TAG:-latest} build: context: . args: - RUST_LOG: ${RUST_LOG:-info} + RUST_LOG: ${RUST_LOG:-debug} ports: - "3000:3000" environment: - - RUST_LOG=${RUST_LOG:-info} - - RUST_BACKTRACE=1 + - RUST_LOG=${RUST_LOG:-debug} + - RUST_BACKTRACE=full + - RUST_LIB_BACKTRACE=1 + logging: + driver: "json-file" + options: + max-size: "100m" + max-file: "5" + compress: "true" + mode: "non-blocking" + tag: "{{.Name}}" + restart: unless-stopped healthcheck: test: ["CMD", "curl", "-f", "http://localhost:3000/health"] interval: 30s timeout: 10s retries: 3 start_period: 40s + deploy: + resources: + limits: + memory: 1G + reservations: + memory: 512M + volumes: + - ./logs:/app/logs test: build: @@ -24,11 +42,23 @@ services: command: cargo test --all-features -- --nocapture environment: - RUST_LOG=debug - - RUST_BACKTRACE=1 + - RUST_BACKTRACE=full + - RUST_LIB_BACKTRACE=1 volumes: - .:/usr/src/app - cargo-cache:/usr/local/cargo/registry + - ./logs:/app/logs + logging: + driver: "json-file" + options: + max-size: "100m" + max-file: "5" + compress: "true" + mode: "non-blocking" + tag: "{{.Name}}" profiles: ["test"] volumes: - cargo-cache: {} \ No newline at end of file + cargo-cache: {} + logs: + driver: local \ No newline at end of file diff --git a/src/main.rs b/src/main.rs index 37cc6e0..0a0ab37 100644 --- a/src/main.rs +++ b/src/main.rs @@ -5,7 +5,12 @@ use serde::Deserialize; use std::{net::SocketAddr, time::Instant}; use tokio::task::block_in_place; use tower_http::trace::TraceLayer; -use tracing::{info, Level}; +use tracing::{debug, error, info, warn, Level}; +use tracing_subscriber::{ + fmt::format::FmtSpan, + prelude::*, + EnvFilter, +}; use url::Url; #[derive(Debug, Deserialize, PartialEq)] @@ -16,42 +21,76 @@ struct RenderParams { } fn decode_base64_url(encoded: &str) -> Result { + debug!("Attempting to decode base64 URL: {}", encoded); URL_SAFE .decode(encoded) - .map_err(|_| "Invalid base64".to_string()) - .and_then(|bytes| String::from_utf8(bytes).map_err(|_| "Invalid URL encoding".to_string())) + .map_err(|e| { + error!("Base64 decoding error: {}", e); + "Invalid base64".to_string() + }) + .and_then(|bytes| { + String::from_utf8(bytes).map_err(|e| { + error!("UTF-8 decoding error: {}", e); + "Invalid URL encoding".to_string() + }) + }) } fn validate_url(url_str: &str) -> Result { - Url::parse(url_str).map_err(|_| "Invalid URL".to_string()) + debug!("Validating URL: {}", url_str); + Url::parse(url_str).map_err(|e| { + error!("URL parsing error: {}", e); + "Invalid URL".to_string() + }) } -async fn render_html(url: &Url, _width: u32, _height: u32) -> Result, String> { +async fn render_html(url: &Url, width: u32, height: u32) -> Result, String> { + info!("Starting HTML render for URL: {} ({}x{})", url, width, height); + let start = Instant::now(); + let html_content = reqwest::blocking::get(url.as_str()) - .and_then(|response| response.text()) - .map_err(|e| format!("Failed to fetch URL: {}", e))?; + .and_then(|response| { + debug!("Received response from URL: {:?}", response.status()); + response.text() + }) + .map_err(|e| { + error!("Failed to fetch URL {}: {}", url, e); + format!("Failed to fetch URL: {}", e) + })?; let config = Config { stylesheets: Vec::new(), base_url: Some(url.to_string()), }; - tokio::task::spawn_blocking(move || { + let result = tokio::task::spawn_blocking(move || { + debug!("Launching Dioxus renderer"); dioxus_native::launch_static_html_cfg(&html_content, config); Ok(Vec::new()) }) .await - .map_err(|e| format!("Task failed: {}", e))? + .map_err(|e| { + error!("Task execution failed: {}", e); + format!("Task failed: {}", e) + })?; + + let duration = start.elapsed(); + info!("Render completed in {:?}", duration); + Ok(result) } async fn render_url(Query(params): Query) -> impl IntoResponse { let start = Instant::now(); + info!("Received render request with params: {:?}", params); let result = decode_base64_url(¶ms.url) - .and_then(|decoded| validate_url(&decoded)) + .and_then(|decoded| { + debug!("Decoded URL: {}", decoded); + validate_url(&decoded) + }) .and_then(|url| { info!("Starting render for URL: {}", url); - + let result = block_in_place(|| { tokio::runtime::Handle::current().block_on(render_html(&url, params.w, params.h)) }); @@ -63,23 +102,41 @@ async fn render_url(Query(params): Query) -> impl IntoResponse { }); match result { - Ok(png_data) => (StatusCode::OK, png_data).into_response(), - Err(error) => (StatusCode::BAD_REQUEST, error).into_response(), + Ok(png_data) => { + info!("Successfully rendered PNG ({} bytes)", png_data.len()); + (StatusCode::OK, png_data).into_response() + } + Err(error) => { + warn!("Render request failed: {}", error); + (StatusCode::BAD_REQUEST, error).into_response() + } } } async fn health_check() -> impl IntoResponse { + debug!("Health check requested"); (StatusCode::OK, "OK") } #[tokio::main] async fn main() { + // Initialize logging with detailed configuration tracing_subscriber::fmt() - .with_target(false) - .with_level(true) - .with_max_level(Level::INFO) + .with_env_filter( + EnvFilter::try_from_default_env() + .unwrap_or_else(|_| EnvFilter::new("debug")) + ) + .with_target(true) + .with_thread_ids(true) + .with_thread_names(true) + .with_file(true) + .with_line_number(true) + .with_span_events(FmtSpan::FULL) + .with_timer(tracing_subscriber::fmt::time::UtcTime::rfc_3339()) .init(); + info!("Initializing Titanium service"); + let app = Router::new() .route("/render.png", get(render_url)) .route("/health", get(health_check)) @@ -88,8 +145,19 @@ async fn main() { info!("Starting server on port 3000"); let addr = SocketAddr::from(([0, 0, 0, 0], 3000)); - let listener = tokio::net::TcpListener::bind(addr).await.unwrap(); - axum::serve(listener, app).await.unwrap(); + match tokio::net::TcpListener::bind(addr).await { + Ok(listener) => { + info!("Server listening on http://{}", addr); + if let Err(e) = axum::serve(listener, app).await { + error!("Server error: {}", e); + std::process::exit(1); + } + } + Err(e) => { + error!("Failed to bind to address {}: {}", addr, e); + std::process::exit(1); + } + } } #[cfg(test)] @@ -130,4 +198,4 @@ mod tests { let response = health_check().await.into_response(); assert_eq!(response.status(), StatusCode::OK); } -} +} \ No newline at end of file From 9e30f1a2e83971763d4e1e54ed764adaf12344e1 Mon Sep 17 00:00:00 2001 From: codingsh Date: Mon, 2 Dec 2024 10:48:14 +0000 Subject: [PATCH 4/5] chore(github): update Dockerfile --- .github/workflows/ci.yml | 92 ----------------------------- .github/workflows/docker.yml | 18 ++++-- .github/workflows/ghcr.yml | 108 ----------------------------------- Dockerfile | 17 ++++-- 4 files changed, 24 insertions(+), 211 deletions(-) delete mode 100644 .github/workflows/ci.yml delete mode 100644 .github/workflows/ghcr.yml diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml deleted file mode 100644 index 9b89ac0..0000000 --- a/.github/workflows/ci.yml +++ /dev/null @@ -1,92 +0,0 @@ -name: Rust CI/CD - -on: - push: - branches: [ main ] - pull_request: - branches: [ main ] - -env: - CARGO_TERM_COLOR: always - RUST_VERSION: nightly-2024-03-20 # Updated to a newer nightly that includes rustc 1.79.0 - -jobs: - test: - name: Test - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - - name: Install system dependencies - run: | - sudo apt-get update - sudo apt-get install -y \ - pkg-config \ - libssl-dev \ - libgtk-3-dev \ - libwebkit2gtk-4.0-dev \ - libayatana-appindicator3-dev \ - librsvg2-dev \ - cmake - - - name: Install Rust toolchain - uses: dtolnay/rust-toolchain@master - with: - toolchain: nightly-2024-03-20 - components: rustfmt, clippy - - - name: Show Rust version - run: rustc --version - - - name: Cache dependencies - uses: actions/cache@v3 - with: - path: | - ~/.cargo/registry - ~/.cargo/git - target - key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }} - - - name: Check formatting - run: cargo fmt -- --check - - - name: Clippy - run: cargo clippy -- -D warnings - - - name: Run tests - run: cargo test --all-features - - build: - name: Build - needs: test - runs-on: ubuntu-latest - if: github.ref == 'refs/heads/main' - steps: - - uses: actions/checkout@v4 - - - name: Install system dependencies - run: | - sudo apt-get update - sudo apt-get install -y \ - pkg-config \ - libssl-dev \ - libgtk-3-dev \ - libwebkit2gtk-4.0-dev \ - libayatana-appindicator3-dev \ - librsvg2-dev \ - cmake - - - name: Install Rust toolchain - uses: dtolnay/rust-toolchain@master - with: - toolchain: nightly-2024-03-20 - components: rustfmt, clippy - - - name: Build - run: cargo build --release - - - name: Upload artifacts - uses: actions/upload-artifact@v3 - with: - name: titanium - path: target/release/titanium \ No newline at end of file diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index 185c1e8..fc4e7f4 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -22,14 +22,21 @@ jobs: - name: Checkout repository uses: actions/checkout@v4 + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + with: + platforms: linux/amd64 + buildkitd-flags: --debug + - name: Log in to the Container registry + if: github.event_name != 'pull_request' uses: docker/login-action@v3 with: registry: ${{ env.REGISTRY }} username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} - - name: Extract metadata (tags, labels) for Docker + - name: Extract Docker metadata id: meta uses: docker/metadata-action@v5 with: @@ -41,9 +48,6 @@ jobs: type=semver,pattern={{major}}.{{minor}} type=sha - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v3 - - name: Build and push Docker image uses: docker/build-push-action@v5 with: @@ -51,5 +55,7 @@ jobs: push: ${{ github.event_name != 'pull_request' }} tags: ${{ steps.meta.outputs.tags }} labels: ${{ steps.meta.outputs.labels }} - cache-from: type=gha - cache-to: type=gha,mode=max \ No newline at end of file + platforms: linux/amd64 + cache-from: type=gha,scope=${{ github.workflow }} + cache-to: type=gha,mode=max,scope=${{ github.workflow }} + outputs: type=docker,dest=/tmp/image.tar \ No newline at end of file diff --git a/.github/workflows/ghcr.yml b/.github/workflows/ghcr.yml deleted file mode 100644 index ed47aba..0000000 --- a/.github/workflows/ghcr.yml +++ /dev/null @@ -1,108 +0,0 @@ -name: Container Registry Deploy - -on: - push: - branches: ["main"] - tags: ["v*"] - pull_request: - branches: ["main"] - -env: - REGISTRY: ghcr.io - IMAGE_NAME: ${{ github.repository }} - CARGO_TERM_COLOR: always - RUST_LOG: info - -permissions: - contents: read - packages: write - -jobs: - build-and-push: - runs-on: ubuntu-latest - steps: - - name: Checkout repository - uses: actions/checkout@v4 - - - name: Install system dependencies - run: | - sudo apt-get update - sudo apt-get install -y \ - pkg-config \ - libgtk-3-dev \ - libwebkit2gtk-4.0-dev \ - libayatana-appindicator3-dev \ - librsvg2-dev \ - libgdk3.0-cil \ - libgdk-pixbuf2.0-dev \ - libglib2.0-dev \ - cmake \ - libxdo-dev \ - libssl-dev - - - name: Install Rust toolchain - uses: dtolnay/rust-toolchain@nightly - with: - components: rustfmt, clippy - - - name: Rust cache - uses: Swatinem/rust-cache@v2 - with: - shared-key: "rust-cache" - - - name: Run tests - run: cargo test - - - name: Check formatting - run: cargo fmt --all -- --check - - - name: Clippy - run: cargo clippy -- -D warnings - - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v3 - - - name: Log in to GHCR - uses: docker/login-action@v3 - with: - registry: ${{ env.REGISTRY }} - username: ${{ github.actor }} - password: ${{ secrets.GITHUB_TOKEN }} - - - name: Extract metadata - id: meta - uses: docker/metadata-action@v5 - with: - images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} - tags: | - type=raw,value=latest,enable={{is_default_branch}} - type=ref,event=branch - type=ref,event=pr - type=semver,pattern={{version}} - type=semver,pattern={{major}}.{{minor}} - type=sha - - - name: Build and test - uses: docker/build-push-action@v5 - with: - context: . - load: true - tags: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:test - cache-from: type=gha - cache-to: type=gha,mode=max - target: builder - - - name: Test the container - run: | - docker compose -f docker-compose.yml run test - - - name: Build and push - uses: docker/build-push-action@v5 - with: - context: . - platforms: linux/amd64,linux/arm64 - push: ${{ github.event_name != 'pull_request' }} - tags: ${{ steps.meta.outputs.tags }} - labels: ${{ steps.meta.outputs.labels }} - cache-from: type=gha - cache-to: type=gha,mode=max \ No newline at end of file diff --git a/Dockerfile b/Dockerfile index 25767d3..333e06a 100644 --- a/Dockerfile +++ b/Dockerfile @@ -8,6 +8,7 @@ ENV RUST_LOG=debug ENV RUST_BACKTRACE=full ENV RUST_LIB_BACKTRACE=1 +# Install system dependencies RUN apt-get update && \ apt-get install -y \ pkg-config \ @@ -28,23 +29,29 @@ WORKDIR /app # Create logs directory RUN mkdir -p /app/logs +# Copy manifests COPY Cargo.toml Cargo.lock* ./ +# Cache dependencies RUN mkdir src && \ echo 'fn main() { println!("dummy") }' > src/main.rs && \ - cargo build --release && \ + CARGO_NET_GIT_FETCH_WITH_CLI=true cargo fetch + +# Build dependencies +RUN cargo build --release && \ cargo build --tests && \ rm -rf src target/release/deps/titanium* +# Copy source code COPY src src/ COPY rust-toolchain.toml . -RUN --mount=type=cache,target=/usr/local/cargo/registry \ - --mount=type=cache,target=/app/target \ - cargo build --release && \ - cargo test --no-run && \ +# Build application +RUN CARGO_NET_GIT_FETCH_WITH_CLI=true cargo build --release && \ + CARGO_NET_GIT_FETCH_WITH_CLI=true cargo test --no-run && \ cp target/release/titanium /app/titanium +# Runtime stage FROM debian:bookworm-slim RUN apt-get update && \ From 2ca3befd6669f9fe53ffa3f616e7a462b7f42d31 Mon Sep 17 00:00:00 2001 From: codingsh Date: Mon, 2 Dec 2024 11:01:59 +0000 Subject: [PATCH 5/5] chore(github): update Dockerfile --- Dockerfile | 120 ++++++++++++++++------------------------------------- 1 file changed, 35 insertions(+), 85 deletions(-) diff --git a/Dockerfile b/Dockerfile index 333e06a..04b506b 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,110 +1,60 @@ -# Builder stage FROM rustlang/rust:nightly AS builder -ENV CARGO_HOME=/usr/local/cargo -ENV RUSTUP_HOME=/usr/local/rustup -ENV PATH=/usr/local/cargo/bin:$PATH -ENV RUST_LOG=debug -ENV RUST_BACKTRACE=full -ENV RUST_LIB_BACKTRACE=1 - -# Install system dependencies RUN apt-get update && \ apt-get install -y \ - pkg-config \ - libgtk-3-dev \ - libwebkit2gtk-4.0-dev \ - libayatana-appindicator3-dev \ - librsvg2-dev \ - libgdk3.0-cil \ - libgdk-pixbuf2.0-dev \ - libglib2.0-dev \ - cmake \ - libxdo-dev \ - libssl-dev \ - && rm -rf /var/lib/apt/lists/* - -WORKDIR /app + pkg-config \ + libssl-dev \ + libgtk-3-dev \ + libwebkit2gtk-4.0-dev \ + libayatana-appindicator3-dev \ + librsvg2-dev \ + cmake \ + libxdo-dev && \ + rm -rf /var/lib/apt/lists/* + +WORKDIR /usr/src/app -# Create logs directory -RUN mkdir -p /app/logs - -# Copy manifests COPY Cargo.toml Cargo.lock* ./ -# Cache dependencies -RUN mkdir src && \ - echo 'fn main() { println!("dummy") }' > src/main.rs && \ - CARGO_NET_GIT_FETCH_WITH_CLI=true cargo fetch - -# Build dependencies -RUN cargo build --release && \ - cargo build --tests && \ - rm -rf src target/release/deps/titanium* - -# Copy source code COPY src src/ -COPY rust-toolchain.toml . -# Build application -RUN CARGO_NET_GIT_FETCH_WITH_CLI=true cargo build --release && \ - CARGO_NET_GIT_FETCH_WITH_CLI=true cargo test --no-run && \ - cp target/release/titanium /app/titanium +ARG RUST_LOG=info +ENV RUST_LOG=${RUST_LOG} + +RUN echo "Building application with RUST_LOG=${RUST_LOG}" && \ + cargo build --release && \ + cargo test --no-run -# Runtime stage FROM debian:bookworm-slim RUN apt-get update && \ apt-get install -y \ - ca-certificates \ - libgtk-3-0 \ - libwebkit2gtk-4.0-37 \ - libayatana-appindicator3-1 \ - librsvg2-2 \ - gstreamer1.0-plugins-base \ - gstreamer1.0-plugins-good \ - gstreamer1.0-x \ - libgdk3.0-cil \ - libgdk-pixbuf2.0-0 \ - curl \ - libxdo3 \ - && rm -rf /var/lib/apt/lists/* - -# Create logs directory and set permissions -RUN mkdir -p /app/logs && \ - chown -R nobody:nogroup /app/logs - -COPY --from=builder /app/titanium /usr/local/bin/titanium + bash \ + ca-certificates \ + libwebkit2gtk-4.0-37 \ + libjavascriptcoregtk-4.0-18 \ + libsoup2.4-1 \ + gstreamer1.0-plugins-base \ + gstreamer1.0-plugins-good \ + gstreamer1.0-x \ + libgtk-3-0 \ + curl \ + librsvg2-2 \ + libxdo3 && \ + rm -rf /var/lib/apt/lists/* + +COPY --from=builder /usr/src/app/target/release/titanium /usr/local/bin/ + +ENV RUST_LOG=info -ENV RUST_LOG=debug -ENV RUST_BACKTRACE=full -ENV RUST_LIB_BACKTRACE=1 - -# Add logging script COPY <<'EOF' /usr/local/bin/start.sh #!/bin/bash -set -e - -# Redirect stdout/stderr to both console and file -exec &> >(tee -a "/app/logs/titanium.log") - -# Start the application +echo "Starting Titanium server with RUST_LOG=${RUST_LOG}" exec titanium EOF RUN chmod +x /usr/local/bin/start.sh -COPY <<'EOF' /usr/local/bin/healthcheck.sh -#!/bin/bash -curl -f http://localhost:3000/health || exit 1 -EOF - -RUN chmod +x /usr/local/bin/healthcheck.sh - -HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \ - CMD ["/usr/local/bin/healthcheck.sh"] - -VOLUME ["/app/logs"] EXPOSE 3000 CMD ["/usr/local/bin/start.sh"] \ No newline at end of file