From 68154af806aeb37191f87ff76f911612f60bb2e9 Mon Sep 17 00:00:00 2001 From: codez0mb1e Date: Mon, 10 Nov 2025 17:51:39 +0100 Subject: [PATCH 1/4] Add Build Pipeline --- .github/workflows/build.yml | 93 +++++++++++++++++++++++++++++++++++++ 1 file changed, 93 insertions(+) create mode 100644 .github/workflows/build.yml diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 0000000..5b88d81 --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,93 @@ +name: BinanceBot Build Pipeline + +on: + workflow_dispatch: + push: + pull_request: + branches: [ "master" ] + +permissions: + contents: read + +concurrency: + group: build-${{ github.ref }} + cancel-in-progress: true + +defaults: + run: + working-directory: ./src + +jobs: + build: + + runs-on: ubuntu-latest + + strategy: + matrix: + configuration: [Debug, Release] + dotnet-version: ["9.0.x"] + + steps: + - uses: actions/checkout@v4 + + - name: Set up .NET SDK + uses: actions/setup-dotnet@v4 + with: + dotnet-version: ${{ matrix.dotnet-version }} + cache: true + cache-dependency-path: | + src/**/*.csproj + src/**/global.json + src/**/NuGet.Config + + - name: .NET info + run: dotnet --info + + - name: Restore dependencies + run: dotnet restore --verbosity minimal + + - name: Build + run: dotnet build --no-restore --configuration ${{ matrix.configuration }} --nologo + + - name: Test + run: dotnet test --no-build --configuration ${{ matrix.configuration }} --collect:"XPlat Code Coverage" --logger "trx;LogFileName=test_results.trx" || echo "No tests found" + + - name: Upload test results (TRX) + if: always() + uses: actions/upload-artifact@v4 + with: + name: test-results-${{ matrix.configuration }} + path: | + **/TestResults/**/*.trx + if-no-files-found: warn + + - name: Upload code coverage (Cobertura) + if: always() + uses: actions/upload-artifact@v4 + with: + name: coverage-cobertura-${{ matrix.configuration }} + path: | + **/TestResults/**/coverage.cobertura.xml + if-no-files-found: warn + + - name: Publish artifacts (Release only) + if: matrix.configuration == 'Release' + run: | + dotnet publish BinanceBot.MarketBot.Console/BinanceBot.MarketBot.Console.csproj \ + -c Release \ + -o ./publish/MarketBot \ + --no-build + dotnet publish BinanceBot.MarketViewer.Console/BinanceBot.MarketViewer.Console.csproj \ + -c Release \ + -o ./publish/MarketViewer \ + --no-build + + - name: Upload published artifacts + if: matrix.configuration == 'Release' + uses: actions/upload-artifact@v4 + with: + name: binance-bot-binaries + path: | + src/publish/MarketBot/ + src/publish/MarketViewer/ + retention-days: 7 From 2c55d253364aa39a94906313a255a2a68c3f72a1 Mon Sep 17 00:00:00 2001 From: codez0mb1e Date: Mon, 10 Nov 2025 17:52:22 +0100 Subject: [PATCH 2/4] Add Release pipeline --- .github/workflows/release.yml | 92 +++++++++++++++++++++++++++++++++++ Dockerfile.marketbot | 51 +++++++++++++++++++ Dockerfile.marketviewer | 51 +++++++++++++++++++ compose.yml | 28 +++++++++++ 4 files changed, 222 insertions(+) create mode 100644 .github/workflows/release.yml create mode 100644 Dockerfile.marketbot create mode 100644 Dockerfile.marketviewer create mode 100644 compose.yml diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..bb0d106 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,92 @@ +name: BinanceBot Release Pipeline + +on: + workflow_dispatch: + push: + branches: [ "master" ] + tags: + - 'v*.*.*' + +permissions: + contents: read + packages: write + id-token: write + +concurrency: + group: release-${{ github.ref }} + cancel-in-progress: true + +jobs: + build-and-push-images: + + name: Build and push Docker images + + runs-on: ubuntu-latest + + env: + DOCKER_BUILDKIT: 1 + + strategy: + matrix: + app: + - name: marketbot + dockerfile: Dockerfile.marketbot + project: BinanceBot.MarketBot.Console + - name: marketviewer + dockerfile: Dockerfile.marketviewer + project: BinanceBot.MarketViewer.Console + + steps: + - name: Check out the repo + uses: actions/checkout@v4 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Login to GitHub Container Registry + uses: docker/login-action@v3 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.CONTAINER_REGISTRY_TOKEN }} + + - name: Docker metadata + id: meta + uses: docker/metadata-action@v5 + with: + images: | + ghcr.io/${{ github.repository_owner }}/binancebot-${{ matrix.app.name }} + tags: | + type=raw,value=latest + type=ref,event=branch + type=semver,pattern={{version}} + type=semver,pattern={{major}}.{{minor}} + type=sha + labels: | + org.opencontainers.image.source=${{ github.repository }} + org.opencontainers.image.created=${{ github.event.head_commit.timestamp }} + org.opencontainers.image.revision=${{ github.sha }} + org.opencontainers.image.title=BinanceBot ${{ matrix.app.name }} + org.opencontainers.image.description=BinanceBot ${{ matrix.app.project }} + + - name: Build and push + uses: docker/build-push-action@v6 + with: + context: . + file: ./${{ matrix.app.dockerfile }} + push: true + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} + cache-from: type=gha,scope=${{ matrix.app.name }} + cache-to: type=gha,mode=max,scope=${{ matrix.app.name }} + build-args: | + PROJECT_NAME=${{ matrix.app.project }} + + - name: Run Trivy vulnerability scanner + uses: aquasecurity/trivy-action@0.31.0 + with: + image-ref: ghcr.io/${{ github.repository_owner }}/binancebot-${{ matrix.app.name }}:latest + format: 'table' + ignore-unfixed: true + vuln-type: 'library' + severity: 'CRITICAL,HIGH' diff --git a/Dockerfile.marketbot b/Dockerfile.marketbot new file mode 100644 index 0000000..0638cd7 --- /dev/null +++ b/Dockerfile.marketbot @@ -0,0 +1,51 @@ +# Build stage +FROM mcr.microsoft.com/dotnet/sdk:9.0-alpine AS build +ARG BUILD_CONFIGURATION=Release +ARG PROJECT_NAME=BinanceBot.MarketBot.Console +WORKDIR /src + +# Copy solution and project files for better layer caching +COPY src/*.sln ./ +COPY src/BinanceBot.Market/*.csproj ./BinanceBot.Market/ +COPY src/BinanceBot.MarketBot.Console/*.csproj ./BinanceBot.MarketBot.Console/ +COPY src/BinanceBot.MarketViewer.Console/*.csproj ./BinanceBot.MarketViewer.Console/ + +# Restore dependencies as a separate layer +RUN dotnet restore "${PROJECT_NAME}/${PROJECT_NAME}.csproj" \ + --runtime linux-musl-x64 + +# Copy remaining source files +COPY src/. ./ + +# Build and publish +WORKDIR /src/${PROJECT_NAME} +RUN dotnet publish "${PROJECT_NAME}.csproj" \ + -c $BUILD_CONFIGURATION \ + -o /app/publish \ + --no-restore \ + --runtime linux-musl-x64 \ + --self-contained false \ + /p:UseAppHost=false + +# Runtime stage +FROM mcr.microsoft.com/dotnet/aspnet:9.0-alpine AS final +ARG PROJECT_NAME=BinanceBot.MarketBot.Console +WORKDIR /app + +# Create non-root user +RUN addgroup -g 1000 appuser && \ + adduser -u 1000 -G appuser -s /bin/sh -D appuser && \ + chown -R appuser:appuser /app + +# Copy published output +COPY --from=build --chown=appuser:appuser /app/publish . + +# Security: Run as non-root +USER appuser + +# Set environment variables +ENV DOTNET_RUNNING_IN_CONTAINER=true \ + DOTNET_SYSTEM_GLOBALIZATION_INVARIANT=false + +# Note: Set BINANCE_API_KEY and BINANCE_SECRET via environment variables or .env file at runtime +ENTRYPOINT dotnet "${PROJECT_NAME}.dll" diff --git a/Dockerfile.marketviewer b/Dockerfile.marketviewer new file mode 100644 index 0000000..11d619e --- /dev/null +++ b/Dockerfile.marketviewer @@ -0,0 +1,51 @@ +# Build stage +FROM mcr.microsoft.com/dotnet/sdk:9.0-alpine AS build +ARG BUILD_CONFIGURATION=Release +ARG PROJECT_NAME=BinanceBot.MarketViewer.Console +WORKDIR /src + +# Copy solution and project files for better layer caching +COPY src/*.sln ./ +COPY src/BinanceBot.Market/*.csproj ./BinanceBot.Market/ +COPY src/BinanceBot.MarketBot.Console/*.csproj ./BinanceBot.MarketBot.Console/ +COPY src/BinanceBot.MarketViewer.Console/*.csproj ./BinanceBot.MarketViewer.Console/ + +# Restore dependencies as a separate layer +RUN dotnet restore "${PROJECT_NAME}/${PROJECT_NAME}.csproj" \ + --runtime linux-musl-x64 + +# Copy remaining source files +COPY src/. ./ + +# Build and publish +WORKDIR /src/${PROJECT_NAME} +RUN dotnet publish "${PROJECT_NAME}.csproj" \ + -c $BUILD_CONFIGURATION \ + -o /app/publish \ + --no-restore \ + --runtime linux-musl-x64 \ + --self-contained false \ + /p:UseAppHost=false + +# Runtime stage +FROM mcr.microsoft.com/dotnet/aspnet:9.0-alpine AS final +ARG PROJECT_NAME=BinanceBot.MarketViewer.Console +WORKDIR /app + +# Create non-root user +RUN addgroup -g 1000 appuser && \ + adduser -u 1000 -G appuser -s /bin/sh -D appuser && \ + chown -R appuser:appuser /app + +# Copy published output +COPY --from=build --chown=appuser:appuser /app/publish . + +# Security: Run as non-root +USER appuser + +# Set environment variables +ENV DOTNET_RUNNING_IN_CONTAINER=true \ + DOTNET_SYSTEM_GLOBALIZATION_INVARIANT=false + +# Note: Set BINANCE_API_KEY and BINANCE_SECRET via environment variables or .env file at runtime +ENTRYPOINT dotnet "${PROJECT_NAME}.dll" diff --git a/compose.yml b/compose.yml new file mode 100644 index 0000000..01575a9 --- /dev/null +++ b/compose.yml @@ -0,0 +1,28 @@ +services: + marketbot: + image: ghcr.io/${GITHUB_REPOSITORY_OWNER:-codez0mb1e}/binancebot-marketbot:latest + container_name: binancebot-marketbot + restart: unless-stopped + environment: + - BINANCE_API_KEY=${BINANCE_API_KEY} + - BINANCE_SECRET=${BINANCE_SECRET} + env_file: + - .env + networks: + - binancebot-network + + marketviewer: + image: ghcr.io/${GITHUB_REPOSITORY_OWNER:-codez0mb1e}/binancebot-marketviewer:latest + container_name: binancebot-marketviewer + restart: unless-stopped + environment: + - BINANCE_API_KEY=${BINANCE_API_KEY} + - BINANCE_SECRET=${BINANCE_SECRET} + env_file: + - .env + networks: + - binancebot-network + +networks: + binancebot-network: + driver: bridge From af69934b26d1c114dfa2f31d720b6477750798f6 Mon Sep 17 00:00:00 2001 From: codez0mb1e Date: Mon, 10 Nov 2025 17:52:41 +0100 Subject: [PATCH 3/4] Consolidate .env.example files --- .env.example | 3 +++ src/BinanceBot.MarketBot.Console/.env.example | 5 ----- src/BinanceBot.MarketViewer.Console/.env.example | 5 ----- 3 files changed, 3 insertions(+), 10 deletions(-) create mode 100644 .env.example delete mode 100644 src/BinanceBot.MarketBot.Console/.env.example delete mode 100644 src/BinanceBot.MarketViewer.Console/.env.example diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..a501852 --- /dev/null +++ b/.env.example @@ -0,0 +1,3 @@ +# Binance API credentials +BINANCE_API_KEY=your_api_key_here +BINANCE_SECRET=your_secret_key_here diff --git a/src/BinanceBot.MarketBot.Console/.env.example b/src/BinanceBot.MarketBot.Console/.env.example deleted file mode 100644 index 0252472..0000000 --- a/src/BinanceBot.MarketBot.Console/.env.example +++ /dev/null @@ -1,5 +0,0 @@ -# Binance API Credentials -# Copy this file to .env and fill in your actual credentials - -BINANCE_API_KEY=your_api_key_here -BINANCE_SECRET=your_secret_key_here diff --git a/src/BinanceBot.MarketViewer.Console/.env.example b/src/BinanceBot.MarketViewer.Console/.env.example deleted file mode 100644 index 0252472..0000000 --- a/src/BinanceBot.MarketViewer.Console/.env.example +++ /dev/null @@ -1,5 +0,0 @@ -# Binance API Credentials -# Copy this file to .env and fill in your actual credentials - -BINANCE_API_KEY=your_api_key_here -BINANCE_SECRET=your_secret_key_here From dc03032e624a3f0dee621989b5620d6f62a2754a Mon Sep 17 00:00:00 2001 From: codez0mb1e Date: Mon, 10 Nov 2025 17:58:49 +0100 Subject: [PATCH 4/4] Remove CheckEnvFileExists target from project files --- .../BinanceBot.MarketBot.Console.csproj | 4 ---- .../BinanceBot.MarketViewer.Console.csproj | 3 --- 2 files changed, 7 deletions(-) diff --git a/src/BinanceBot.MarketBot.Console/BinanceBot.MarketBot.Console.csproj b/src/BinanceBot.MarketBot.Console/BinanceBot.MarketBot.Console.csproj index 5409c87..11affff 100644 --- a/src/BinanceBot.MarketBot.Console/BinanceBot.MarketBot.Console.csproj +++ b/src/BinanceBot.MarketBot.Console/BinanceBot.MarketBot.Console.csproj @@ -22,8 +22,4 @@ PreserveNewest - - - - diff --git a/src/BinanceBot.MarketViewer.Console/BinanceBot.MarketViewer.Console.csproj b/src/BinanceBot.MarketViewer.Console/BinanceBot.MarketViewer.Console.csproj index 3631770..88bff0f 100644 --- a/src/BinanceBot.MarketViewer.Console/BinanceBot.MarketViewer.Console.csproj +++ b/src/BinanceBot.MarketViewer.Console/BinanceBot.MarketViewer.Console.csproj @@ -23,7 +23,4 @@ PreserveNewest - - -