diff --git a/.github/workflows/snyk.yml b/.github/workflows/snyk.yml index 2a57a79915..3afbede301 100644 --- a/.github/workflows/snyk.yml +++ b/.github/workflows/snyk.yml @@ -71,6 +71,9 @@ jobs: with: go-version: "1.26.1" + - name: Build + run: make build + - name: Install Snyk CLI uses: maximhq/snyk-actions/setup@9adf32b1121593767fc3c057af55b55db032dc04 # v1.0.0 with: @@ -79,7 +82,7 @@ jobs: - name: Snyk test (all projects) env: SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }} - run: snyk test --all-projects --detection-depth=4 --sarif-file-output=snyk.sarif || true + run: snyk test --all-projects --detection-depth=4 --exclude=examples,tests/scripts --sarif-file-output=snyk.sarif || true - name: Upload SARIF if: always() && hashFiles('snyk.sarif') != '' diff --git a/transports/Dockerfile b/transports/Dockerfile index afc2357b7a..4789eb60bf 100644 --- a/transports/Dockerfile +++ b/transports/Dockerfile @@ -1,94 +1,106 @@ # --- UI Build Stage: Build the Next.js frontend --- -FROM node:25-alpine3.23@sha256:cf38e1f3c28ac9d81cdc0c51d8220320b3b618780e44ef96a39f76f7dbfef023 AS ui-builder -WORKDIR /app - -# Copy UI package files and install dependencies -COPY ui/package*.json ./ -RUN npm ci - -# Copy UI source code -COPY ui/ ./ - -# Build UI (skip the copy-build step) -RUN npx next build -RUN node scripts/fix-paths.js -# Skip the copy-build step since we'll copy the files in the Go build stage - -# --- Go Build Stage: Compile the Go binary --- -FROM golang:1.26.1-alpine3.23@sha256:2389ebfa5b7f43eeafbd6be0c3700cc46690ef842ad962f6c5bd6be49ed82039 AS builder -WORKDIR /app - -# Install dependencies including gcc for CGO and sqlite -RUN apk add --no-cache gcc musl-dev sqlite-dev binutils binutils-gold - -# Set environment for CGO-enabled build (required for go-sqlite3) -ENV CGO_ENABLED=1 GOOS=linux - -COPY transports/go.mod transports/go.sum ./ -RUN ls -RUN cat go.mod -RUN go mod download - -# Copy source code and dependencies -COPY transports/ ./ - -COPY --from=ui-builder /app/out ./bifrost-http/ui - -# Build the binary with CGO enabled and static SQLite linking -ENV GOWORK=off -ARG VERSION=unknown -RUN go build \ - -ldflags="-w -s -X main.Version=v${VERSION} -extldflags '-static'" \ - -a -trimpath \ - -tags "sqlite_static" \ - -o /app/main \ - ./bifrost-http - -# Verify build succeeded and prepare entrypoint -RUN test -f /app/main || (echo "Build failed" && exit 1) -RUN chmod +x /build/transports/docker-entrypoint.sh - -# --- Runtime Stage: Minimal runtime image --- -FROM bifrosthq/dhi-alpine-base:3.22-fips_bifrost-v27032026 -WORKDIR /app - -# Create data directory and set up user -COPY --from=builder /app/main . -COPY --from=builder /app/docker-entrypoint.sh . - -# Getting arguments -ARG ARG_APP_PORT=8080 -ARG ARG_APP_HOST=0.0.0.0 -ARG ARG_LOG_LEVEL=info -ARG ARG_LOG_STYLE=json -ARG ARG_APP_DIR=/app/data - -# Environment variables with defaults (can be overridden at runtime) -ENV APP_PORT=$ARG_APP_PORT \ - APP_HOST=$ARG_APP_HOST \ - LOG_LEVEL=$ARG_LOG_LEVEL \ - LOG_STYLE=$ARG_LOG_STYLE \ - APP_DIR=$ARG_APP_DIR - -# Go runtime performance tuning (override at runtime for your workload) -# GOGC: GC target percentage. Higher = less frequent GC, more memory usage. -# Default: 100. For high-throughput with available memory, try 200-400. -# GOMEMLIMIT: Soft memory limit for Go runtime. Set to ~90% of container memory limit. -# Example: "1800MiB" for a 2GB container, "3600MiB" for 4GB. -# When set, Go will be more aggressive about GC as it approaches this limit. -# Note: GOMAXPROCS is automatically detected from cgroup CPU limits via automaxprocs. -ENV GOGC="" \ - GOMEMLIMIT="" - - -RUN mkdir -p $APP_DIR/logs -USER appuser - - -# Declare volume for data persistence -VOLUME ["/app/data"] -EXPOSE $APP_PORT - -# Use entrypoint script that handles volume permissions and argument processing -ENTRYPOINT ["/app/docker-entrypoint.sh"] -CMD ["/app/main"] + FROM node:25-alpine3.23@sha256:cf38e1f3c28ac9d81cdc0c51d8220320b3b618780e44ef96a39f76f7dbfef023 AS ui-builder + WORKDIR /app + + # Copy UI package files and install dependencies + COPY ui/package*.json ./ + RUN npm ci + + # Copy UI source code + COPY ui/ ./ + + # Build UI (skip the copy-build step) + RUN npx next build + RUN node scripts/fix-paths.js + # Skip the copy-build step since we'll copy the files in the Go build stage + + # --- Go Build Stage: Compile the Go binary --- + FROM golang:1.26.1-alpine3.23@sha256:2389ebfa5b7f43eeafbd6be0c3700cc46690ef842ad962f6c5bd6be49ed82039 AS builder + WORKDIR /app + + # Install dependencies including gcc for CGO and sqlite + RUN apk add --no-cache gcc musl-dev sqlite-dev binutils binutils-gold + + # Set environment for CGO-enabled build (required for go-sqlite3) + ENV CGO_ENABLED=1 GOOS=linux + + COPY transports/go.mod transports/go.sum ./ + RUN ls + RUN cat go.mod + RUN go mod download + + # Copy source code and dependencies + COPY transports/ ./ + + COPY --from=ui-builder /app/out ./bifrost-http/ui + + # Build the binary with CGO enabled and static SQLite linking + ENV GOWORK=off + ARG VERSION=unknown + RUN go build \ + -ldflags="-w -s -X main.Version=v${VERSION} -extldflags '-static'" \ + -a -trimpath \ + -tags "sqlite_static" \ + -o /app/main \ + ./bifrost-http + + # Verify build succeeded + RUN test -f /app/main || (echo "Build failed" && exit 1) + + # --- Runtime Stage: Minimal runtime image --- + FROM alpine:3.23.3@sha256:25109184c71bdad752c8312a8623239686a9a2071e8825f20acb8f2198c3f659 + WORKDIR /app + + # Install runtime dependencies for CGO-enabled binary + # musl: C standard library (required for CGO binaries) + # libgcc: GCC runtime library + # ca-certificates: For HTTPS connections + RUN apk add --no-cache musl libgcc ca-certificates wget + + # Create data directory and set up user + COPY --from=builder /app/main . + COPY --from=builder /app/docker-entrypoint.sh . + + # Getting arguments + ARG ARG_APP_PORT=8080 + ARG ARG_APP_HOST=0.0.0.0 + ARG ARG_LOG_LEVEL=info + ARG ARG_LOG_STYLE=json + ARG ARG_APP_DIR=/app/data + + # Environment variables with defaults (can be overridden at runtime) + ENV APP_PORT=$ARG_APP_PORT \ + APP_HOST=$ARG_APP_HOST \ + LOG_LEVEL=$ARG_LOG_LEVEL \ + LOG_STYLE=$ARG_LOG_STYLE \ + APP_DIR=$ARG_APP_DIR + + # Go runtime performance tuning (override at runtime for your workload) + # GOGC: GC target percentage. Higher = less frequent GC, more memory usage. + # Default: 100. For high-throughput with available memory, try 200-400. + # GOMEMLIMIT: Soft memory limit for Go runtime. Set to ~90% of container memory limit. + # Example: "1800MiB" for a 2GB container, "3600MiB" for 4GB. + # When set, Go will be more aggressive about GC as it approaches this limit. + # Note: GOMAXPROCS is automatically detected from cgroup CPU limits via automaxprocs. + ENV GOGC="" \ + GOMEMLIMIT="" + + + RUN mkdir -p $APP_DIR/logs && \ + adduser -D -s /bin/sh appuser && \ + chown -R appuser:appuser /app && \ + chmod +x /app/docker-entrypoint.sh + USER appuser + + + # Declare volume for data persistence + VOLUME ["/app/data"] + EXPOSE $APP_PORT + + # Health check for container status monitoring + HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \ + CMD wget --no-verbose --tries=1 -O /dev/null http://127.0.0.1:${APP_PORT}/health || exit 1 + + # Use entrypoint script that handles volume permissions and argument processing + ENTRYPOINT ["/app/docker-entrypoint.sh"] + CMD ["/app/main"] \ No newline at end of file diff --git a/transports/Dockerfile.local b/transports/Dockerfile.local index 2a03e34e4d..257a1e47c0 100644 --- a/transports/Dockerfile.local +++ b/transports/Dockerfile.local @@ -2,103 +2,115 @@ # For pre-release CI builds where module versions aren't published yet # --- UI Build Stage: Build the Next.js frontend --- -FROM node:25-alpine3.23 AS ui-builder -WORKDIR /app - -# Copy UI package files and install dependencies -COPY ui/package*.json ./ -RUN npm ci - -# Copy UI source code -COPY ui/ ./ - -# Build UI (skip the copy-build step) -RUN npx next build -RUN node scripts/fix-paths.js -# Skip the copy-build step since we'll copy the files in the Go build stage - -# --- Go Build Stage: Compile the Go binary using local modules --- -FROM golang:1.26.1-alpine3.23 AS builder -WORKDIR /build - -# Install dependencies including gcc for CGO and sqlite -RUN apk add --no-cache gcc musl-dev sqlite-dev binutils binutils-gold - -# Set environment for CGO-enabled build (required for go-sqlite3) -ENV CGO_ENABLED=1 GOOS=linux - -# Copy all local modules -COPY core/ ./core/ -COPY framework/ ./framework/ -COPY plugins/ ./plugins/ -COPY transports/ ./transports/ - -# Set up go workspace to resolve local module dependencies -RUN go work init && \ - go work use ./core && \ - go work use ./framework && \ - go work use ./plugins/governance && \ - go work use ./plugins/jsonparser && \ - go work use ./plugins/litellmcompat && \ - go work use ./plugins/logging && \ - go work use ./plugins/maxim && \ - go work use ./plugins/mocker && \ - go work use ./plugins/otel && \ - go work use ./plugins/semanticcache && \ - go work use ./plugins/telemetry && \ - go work use ./transports - -# Download external (non-local) dependencies -RUN cd /build/transports && go mod download - -# Copy UI build output into transports -COPY --from=ui-builder /app/out ./transports/bifrost-http/ui - -# Build the binary with CGO enabled and static SQLite linking -ARG VERSION=unknown -RUN cd /build/transports && \ - go build \ - -ldflags="-w -s -X main.Version=v${VERSION} -extldflags '-static'" \ - -a -trimpath \ - -tags "sqlite_static" \ - -o /app/main \ - ./bifrost-http - -# Verify build succeeded and prepare entrypoint -RUN test -f /app/main || (echo "Build failed" && exit 1) -RUN chmod +x /build/transports/docker-entrypoint.sh - -# --- Runtime Stage: Minimal runtime image --- -FROM bifrosthq/dhi-alpine-base:3.22-fips_bifrost-v27032026 -WORKDIR /app - -# Create data directory and set up user -COPY --from=builder /app/main . -COPY --from=builder /build/transports/docker-entrypoint.sh . - -# Getting arguments -ARG ARG_APP_PORT=8080 -ARG ARG_APP_HOST=0.0.0.0 -ARG ARG_LOG_LEVEL=info -ARG ARG_LOG_STYLE=json -ARG ARG_APP_DIR=/app/data - -# Environment variables with defaults (can be overridden at runtime) -ENV APP_PORT=$ARG_APP_PORT \ - APP_HOST=$ARG_APP_HOST \ - LOG_LEVEL=$ARG_LOG_LEVEL \ - LOG_STYLE=$ARG_LOG_STYLE \ - APP_DIR=$ARG_APP_DIR - - -RUN mkdir -p $APP_DIR/logs -USER appuser - - -# Declare volume for data persistence -VOLUME ["/app/data"] -EXPOSE $APP_PORT - -# Use entrypoint script that handles volume permissions and argument processing -ENTRYPOINT ["/app/docker-entrypoint.sh"] -CMD ["/app/main"] + FROM node:25-alpine3.23 AS ui-builder + WORKDIR /app + + # Copy UI package files and install dependencies + COPY ui/package*.json ./ + RUN npm ci + + # Copy UI source code + COPY ui/ ./ + + # Build UI (skip the copy-build step) + RUN npx next build + RUN node scripts/fix-paths.js + # Skip the copy-build step since we'll copy the files in the Go build stage + + # --- Go Build Stage: Compile the Go binary using local modules --- + FROM golang:1.26.1-alpine3.23 AS builder + WORKDIR /build + + # Install dependencies including gcc for CGO and sqlite + RUN apk add --no-cache gcc musl-dev sqlite-dev binutils binutils-gold + + # Set environment for CGO-enabled build (required for go-sqlite3) + ENV CGO_ENABLED=1 GOOS=linux + + # Copy all local modules + COPY core/ ./core/ + COPY framework/ ./framework/ + COPY plugins/ ./plugins/ + COPY transports/ ./transports/ + + # Set up go workspace to resolve local module dependencies + RUN go work init && \ + go work use ./core && \ + go work use ./framework && \ + go work use ./plugins/governance && \ + go work use ./plugins/jsonparser && \ + go work use ./plugins/litellmcompat && \ + go work use ./plugins/logging && \ + go work use ./plugins/maxim && \ + go work use ./plugins/mocker && \ + go work use ./plugins/otel && \ + go work use ./plugins/semanticcache && \ + go work use ./plugins/telemetry && \ + go work use ./transports + + # Download external (non-local) dependencies + RUN cd /build/transports && go mod download + + # Copy UI build output into transports + COPY --from=ui-builder /app/out ./transports/bifrost-http/ui + + # Build the binary with CGO enabled and static SQLite linking + ARG VERSION=unknown + RUN cd /build/transports && \ + go build \ + -ldflags="-w -s -X main.Version=v${VERSION} -extldflags '-static'" \ + -a -trimpath \ + -tags "sqlite_static" \ + -o /app/main \ + ./bifrost-http + + # Verify build succeeded + RUN test -f /app/main || (echo "Build failed" && exit 1) + + # --- Runtime Stage: Minimal runtime image --- + FROM alpine:3.23.3 + WORKDIR /app + + # Install runtime dependencies for CGO-enabled binary + # musl: C standard library (required for CGO binaries) + # libgcc: GCC runtime library + # ca-certificates: For HTTPS connections + RUN apk add --no-cache musl libgcc ca-certificates wget + + # Create data directory and set up user + COPY --from=builder /app/main . + COPY --from=builder /build/transports/docker-entrypoint.sh . + + # Getting arguments + ARG ARG_APP_PORT=8080 + ARG ARG_APP_HOST=0.0.0.0 + ARG ARG_LOG_LEVEL=info + ARG ARG_LOG_STYLE=json + ARG ARG_APP_DIR=/app/data + + # Environment variables with defaults (can be overridden at runtime) + ENV APP_PORT=$ARG_APP_PORT \ + APP_HOST=$ARG_APP_HOST \ + LOG_LEVEL=$ARG_LOG_LEVEL \ + LOG_STYLE=$ARG_LOG_STYLE \ + APP_DIR=$ARG_APP_DIR + + + RUN mkdir -p $APP_DIR/logs && \ + adduser -D -s /bin/sh appuser && \ + chown -R appuser:appuser /app && \ + chmod +x /app/docker-entrypoint.sh + USER appuser + + + # Declare volume for data persistence + VOLUME ["/app/data"] + EXPOSE $APP_PORT + + # Health check for container status monitoring + HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \ + CMD wget --no-verbose --tries=1 -O /dev/null http://127.0.0.1:${APP_PORT}/health || exit 1 + + # Use entrypoint script that handles volume permissions and argument processing + ENTRYPOINT ["/app/docker-entrypoint.sh"] + CMD ["/app/main"] \ No newline at end of file