Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
205 changes: 205 additions & 0 deletions .github/workflows/docker.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,205 @@
name: Build and Push Docker Images

on:
pull_request:
types:
- closed
branches:
- main

jobs:
check_version_update:
name: Check Version Updates
if: github.event.pull_request.merged
runs-on: ubuntu-latest
outputs:
build_backend: ${{ steps.version_check.outputs.build_backend }}
build_frontend: ${{ steps.version_check.outputs.build_frontend }}
backend_version: ${{ steps.version_check.outputs.backend_version }}
frontend_version: ${{ steps.version_check.outputs.frontend_version }}
steps:
- name: Check out the repo
uses: actions/checkout@v5
with:
fetch-depth: 2 # Need at least 2 commits to compare

- name: Detect version changes
id: version_check
run: |
echo "🔍 Checking for version changes..."

# Get current commit and previous commit
CURRENT_COMMIT=$(git rev-parse HEAD)
# Previous commit refers to the latest commit on main before the PR
# was merged
PREVIOUS_COMMIT=$(git rev-parse HEAD~1)

echo "Current commit: $CURRENT_COMMIT"
echo "Previous commit: $PREVIOUS_COMMIT"

# Initialize build flags and version variables
BUILD_BACKEND=false
BUILD_FRONTEND=false
# Extract current versions for backend and frontend
BACKEND_VERSION=$(grep '^version = ' backend-agent/pyproject.toml | sed "s/version = '\(.*\)'/\1/")
FRONTEND_VERSION=$(grep '"version":' frontend/package.json | sed 's/.*"version": "\(.*\)".*/\1/')

# Check if backend version file changed
if git diff --name-only $PREVIOUS_COMMIT $CURRENT_COMMIT | grep -q 'backend-agent/pyproject.toml'; then
# Extract previous backend version
PREVIOUS_BACKEND_VERSION=$(git show $PREVIOUS_COMMIT:backend-agent/pyproject.toml | grep '^version = ' | sed "s/version = '\(.*\)'/\1/")
echo "Backend version - Current: $BACKEND_VERSION, Previous: $PREVIOUS_BACKEND_VERSION"

if [ "$BACKEND_VERSION" != "$PREVIOUS_BACKEND_VERSION" ]; then
# The version has changed, set flag to build backend
BUILD_BACKEND=true
echo "✅ Backend version changed: $PREVIOUS_BACKEND_VERSION → $BACKEND_VERSION"
else
echo "❎ Backend version unchanged: $BACKEND_VERSION. Skip docker backend."
fi
fi

# Check if frontend version file changed
if git diff --name-only $PREVIOUS_COMMIT $CURRENT_COMMIT | grep -q 'frontend/package.json'; then
# Extract previous frontend version
PREVIOUS_FRONTEND_VERSION=$(git show $PREVIOUS_COMMIT:frontend/package.json | grep '"version":' | sed 's/.*"version": "\(.*\)".*/\1/')
echo "Frontend version - Current: $FRONTEND_VERSION, Previous: $PREVIOUS_FRONTEND_VERSION"

if [ "$FRONTEND_VERSION" != "$PREVIOUS_FRONTEND_VERSION" ]; then
# The version has changed, set flag to build frontend
BUILD_FRONTEND=true
echo "✅ Frontend version changed: $PREVIOUS_FRONTEND_VERSION → $FRONTEND_VERSION"
else
echo "❎ Frontend version unchanged: $FRONTEND_VERSION. Skip docker backend."
fi
fi

# Set build outputs
echo "build_backend=$BUILD_BACKEND" >> $GITHUB_OUTPUT
echo "build_frontend=$BUILD_FRONTEND" >> $GITHUB_OUTPUT
echo "backend_version=$BACKEND_VERSION" >> $GITHUB_OUTPUT
echo "frontend_version=$FRONTEND_VERSION" >> $GITHUB_OUTPUT

if [ "$BUILD_BACKEND" = "false" ] && [ "$BUILD_FRONTEND" = "false" ]; then
echo "⚠️ No version changes detected. Skipping builds."
fi

build-backend:
name: Build and Push Backend Docker Image
if: github.event.pull_request.merged && needs.check_version_update.outputs.build_backend == 'true'
needs: check_version_update
runs-on: ubuntu-latest
steps:
- name: Check out the repo
uses: actions/checkout@v5

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3

- name: Log in to Docker Registry
uses: docker/login-action@v3
with:
registry: ${{ secrets.DOCKER_REGISTRY_URL }}
username: ${{ secrets.DOCKER_REGISTRY_USERNAME }}
password: ${{ secrets.DOCKER_REGISTRY_TOKEN }}

- name: 🐳 Build and push Backend Docker image
uses: docker/build-push-action@v6
with:
context: ./backend-agent
file: ./backend-agent/Dockerfile
push: true
tags: |
${{ secrets.DOCKER_REGISTRY_URL }}/stars-backend:${{ needs.check_version_update.outputs.backend_version }}
${{ secrets.DOCKER_REGISTRY_URL }}/stars-backend:latest
cache-from: type=gha
cache-to: type=gha,mode=max

- name: Backend Build Summary
run: |
echo "Backend Build Complete"
echo "✅ Backend: stars-backend:${{ needs.check_version_update.outputs.backend_version }}"

build-frontend:
name: Build and Push Frontend Docker Image
if: github.event.pull_request.merged && needs.check_version_update.outputs.build_frontend == 'true'
needs: check_version_update
runs-on: ubuntu-latest
steps:
- name: Check out the repo
uses: actions/checkout@v5

- name: Set up Node.js for Frontend build
uses: actions/setup-node@v5
with:
node-version: '24'
cache: 'npm'
cache-dependency-path: frontend/package-lock.json

- name: Build Angular application
run: |
cd frontend
npm ci
npm run build -- --configuration production
# Verify build output exists
ls -la dist/

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3

- name: Log in to Docker Registry
uses: docker/login-action@v3
with:
registry: ${{ secrets.DOCKER_REGISTRY_URL }}
username: ${{ secrets.DOCKER_REGISTRY_USERNAME }}
password: ${{ secrets.DOCKER_REGISTRY_TOKEN }}

- name: 🐳 Build and push Frontend Docker image
uses: docker/build-push-action@v6
with:
context: ./frontend
file: ./frontend/Dockerfile
push: true
tags: |
${{ secrets.DOCKER_REGISTRY_URL }}/stars-frontend:${{ needs.check_version_update.outputs.frontend_version }}
${{ secrets.DOCKER_REGISTRY_URL }}/stars-frontend:latest
cache-from: type=gha
cache-to: type=gha,mode=max

- name: Frontend Build Summary
run: |
echo "Frontend Build Complete"
echo "✅ Frontend: stars-frontend:${{ needs.check_version_update.outputs.frontend_version }}"

build-summary:
name: Build Pipeline Summary
needs: [check_version_update, build-backend, build-frontend]
runs-on: ubuntu-latest
# Allow this job to run even if backend or frontend jobs are skipped
if: always() && github.event.pull_request.merged
steps:
- name: Pipeline Summary
run: |
echo "STARS Build Pipeline Summary"
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
# Backend
if [ "${{ needs.check_version_update.outputs.build_backend }}" = "true" ]; then
if [ "${{ needs.build-backend.result }}" = "success" ]; then
echo "✅ Backend: stars-backend:${{ needs.check_version_update.outputs.backend_version }}"
else
echo "❌ Backend: Build failed"
fi
else
echo "⏭️ (SKIP) Backend: No version change detected"
fi
# Frontend
if [ "${{ needs.check_version_update.outputs.build_frontend }}" = "true" ]; then
if [ "${{ needs.build-frontend.result }}" = "success" ]; then
echo "✅ Frontend: stars-frontend:${{ needs.check_version_update.outputs.frontend_version }}"
else
echo "❌ Frontend: Build failed"
fi
else
echo "⏭️ (SKIP) Frontend: No version change detected"
fi
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
56 changes: 52 additions & 4 deletions backend-agent/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,11 +1,59 @@
FROM python:3.11
FROM astral/uv:python3.11-trixie AS builder

# Install build dependencies including Rust for packages that need it
RUN apt-get update && apt-get install -y \
build-essential \
curl \
pkg-config \
libssl-dev \
&& curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y \
&& . ~/.cargo/env \
&& rm -rf /var/lib/apt/lists/*

# Add Rust to PATH
ENV PATH="/root/.cargo/bin:${PATH}"

WORKDIR /app

# Copy dependency files first for better Docker layer caching
COPY pyproject.toml uv.lock ./

# Set environment variables to use CPU-only versions and reduce download size
ENV UV_EXTRA_INDEX_URL="https://download.pytorch.org/whl/cpu"
ENV TORCH_INDEX_URL="https://download.pytorch.org/whl/cpu"

# Install dependencies using uv with proper build environment
RUN . ~/.cargo/env && \
uv sync --frozen --no-dev --no-cache && \
# Clean up any temporary files to reduce layer size
rm -rf /root/.cache/uv /tmp/* /var/tmp/* && \
# Remove Rust toolchain after build to reduce image size
rustup self uninstall -y

# ----------------------------------------

FROM python:3.11-slim-trixie

# Install only runtime dependencies
RUN apt-get update && apt-get install -y \
libssl3 \
libffi8 \
&& rm -rf /var/lib/apt/lists/*

WORKDIR /app

COPY requirements.txt .
RUN pip install -r requirements.txt --no-cache-dir
# Copy the virtual environment from builder stage
COPY --from=builder /app/.venv /app/.venv

# Copy dependency files
COPY pyproject.toml uv.lock ./

# Copy the rest of the application
COPY . .

# Make sure we use the virtual environment
ENV PATH="/app/.venv/bin:$PATH"
ENV PYTHONPATH="/app"

EXPOSE 8080
CMD [ "python", "main.py" ]
CMD ["python", "main.py"]
2 changes: 1 addition & 1 deletion backend-agent/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ name = 'stars'
version = '0.4.0'
description = 'Smart Threat AI Reporting Scanner (STARS)'
readme = 'README.md'
license = 'Apache-2.0'
license = {text = 'Apache-2.0'}
authors = [
{name = 'SAP SE'}
]
Expand Down
6 changes: 6 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
@@ -1,16 +1,22 @@
services:
frontend:
platform: linux/amd64
build:
context: ./frontend
dockerfile: Dockerfile
ports:
- "3000:8080"
environment:
- BACKEND_URL=http://localhost:8080
- BACKEND_WS_URL=ws://localhost:8080/agent
- API_URL=http://localhost:8080
depends_on:
- backend
networks:
- stars-network

backend:
platform: linux/amd64
build:
context: ./backend-agent
dockerfile: Dockerfile
Expand Down
5 changes: 0 additions & 5 deletions frontend/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,6 @@ launch.json
# dependencies
/node_modules

# config
src/assets/configs/config.json
src/environments/environment.ts
src/environments/environment.k8s.ts

# System Files
.DS_Store

Expand Down
20 changes: 19 additions & 1 deletion frontend/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,26 @@ FROM nginxinc/nginx-unprivileged
# Use default Nginx config (listens on port 8080)
COPY ./nginx.conf /etc/nginx/conf.d/default.conf

# Copy the built Angular application
COPY ./dist/stars /usr/share/nginx/html
COPY ./src/assets/configs/config.local.json /usr/share/nginx/html/assets/configs/config.json

# Copy the config generation script
COPY ./generate-config.sh /usr/local/bin/generate-config.sh

# Make the script executable and create config directory with proper permissions
USER root
RUN chmod +x /usr/local/bin/generate-config.sh && \
mkdir -p /usr/share/nginx/html/assets/configs && \
chown -R nginx:nginx /usr/share/nginx/html/assets/configs
USER nginx

# Set environment variables with default values
ENV BACKEND_URL=http://localhost:8080
ENV BACKEND_WS_URL=ws://localhost:8080/agent
ENV API_URL=http://localhost:8080

EXPOSE 8080

# Use the script as entrypoint to generate config before starting nginx
ENTRYPOINT ["/usr/local/bin/generate-config.sh"]
CMD ["nginx", "-g", "daemon off;"]
36 changes: 3 additions & 33 deletions frontend/angular.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,8 @@
"budgets": [
{
"type": "initial",
"maximumWarning": "500kb",
"maximumError": "1mb"
"maximumWarning": "1mb",
"maximumError": "3mb"
},
{
"type": "anyComponentStyle",
Expand All @@ -51,31 +51,7 @@
"vendorChunk": true,
"extractLicenses": false,
"sourceMap": true,
"namedChunks": true,
"fileReplacements": [
{
"replace": "src/environments/environment.ts",
"with": "src/environments/environment.development.ts"
}
]
},
"docker": {
"fileReplacements": [
{
"replace": "src/environments/environment.ts",
"with": "src/environments/environment.docker.ts"
}
],
"outputHashing": "all"
},
"k8s": {
"fileReplacements": [
{
"replace": "src/environments/environment.ts",
"with": "src/environments/environment.k8s.ts"
}
],
"outputHashing": "all"
"namedChunks": true
}
},
"defaultConfiguration": "production"
Expand All @@ -88,12 +64,6 @@
},
"development": {
"buildTarget": "stars:build:development"
},
"docker": {
"buildTarget": "stars:build:docker"
},
"k8s": {
"buildTarget": "stars:build:k8s"
}
},
"defaultConfiguration": "development"
Expand Down
Loading
Loading