From c58c5b083cb33a32e56885440bc7de68dbe4736c Mon Sep 17 00:00:00 2001 From: Patrick Mahnke-Hartmann Date: Thu, 18 Sep 2025 19:49:18 +0200 Subject: [PATCH] added rust --- .github/workflows/build.yml | 301 +++++++++++++++++++++++------------- Dockerfile.linux | 2 +- 2 files changed, 193 insertions(+), 110 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index d3dff62..ff4df15 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -3,16 +3,22 @@ name: Rust Cross-Platform Build on: workflow_dispatch: push: - branches: [ "development", "main", "feature/*", bug/*, enhancement/* ] + branches: [ "development", "main", "feature/*", "bugfix/*", "enhancement/*" ] + tags: [ "v*.*.*" ] pull_request: branches: [ "development", "main" ] env: CARGO_TERM_COLOR: always + RUST_BACKTRACE: 1 REGISTRY: git.triggermeelmo.com IMAGE_NAME: donpat1to/watcher-agent - TAG: development - + TAG: ${{ github.ref == 'refs/heads/main' && 'latest' || github.ref == 'refs/heads/development' && 'development' || github.ref_type == 'tag' && github.ref_name || 'pr' }} + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + jobs: detect-project: name: Detect Rust Project @@ -22,144 +28,221 @@ jobs: project-name: ${{ steps.detect.outputs.project-name }} steps: - uses: actions/checkout@v4 + with: + fetch-depth: 0 - - name: Find Cargo.toml + - name: Detect Rust project id: detect run: | - # Look for Cargo.toml in root or subdirectories if [ -f "Cargo.toml" ]; then echo "project-dir=." >> $GITHUB_OUTPUT - PROJECT_NAME=$(grep -m1 '^name =' "Cargo.toml" | cut -d'"' -f2) + PROJECT_NAME=$(grep -m1 '^name =' "Cargo.toml" | sed -n 's/^name = "\(.*\)"/\1/p') echo "project-name=${PROJECT_NAME}" >> $GITHUB_OUTPUT else for dir in */; do - if [ -f "$dir/Cargo.toml" ]; then + if [ -f "${dir}Cargo.toml" ]; then echo "project-dir=${dir%/}" >> $GITHUB_OUTPUT - PROJECT_NAME=$(grep -m1 '^name =' "$dir/Cargo.toml" | cut -d'"' -f2) + PROJECT_NAME=$(grep -m1 '^name =' "${dir}Cargo.toml" | sed -n 's/^name = "\(.*\)"/\1/p') echo "project-name=${PROJECT_NAME}" >> $GITHUB_OUTPUT break fi done fi - if [ -z "$PROJECT_NAME" ]; then - echo "No Rust project found!" + + if [ -z "$(grep 'project-name=' $GITHUB_OUTPUT | cut -d= -f2)" ]; then + echo "::error::No Rust project found!" exit 1 fi - native-build: - name: Native Linux Build + setup-rust: + name: Setup Rust Toolchain needs: detect-project - runs-on: ubuntu-latest - timeout-minutes: 15 - steps: - - uses: actions/checkout@v3 - - - name: Install Rust - uses: actions-rs/toolchain@v1 - with: - toolchain: stable - target: x86_64-unknown-linux-gnu - profile: minimal - override: true - - - name: Build Linux binary - id: build - working-directory: ${{ needs.detect-project.outputs.project-dir }} - run: | - set -e - cargo build --release --target x86_64-unknown-linux-gnu - binary_name=$(grep -m1 '^name =' Cargo.toml | cut -d'"' -f2) - echo "binary_name=$binary_name" >> $GITHUB_OUTPUT - - - name: Strip debug symbols - if: success() - working-directory: ${{ needs.detect-project.outputs.project-dir }} - run: | - set -e - strip target/x86_64-unknown-linux-gnu/release/$(grep -m1 '^name =' Cargo.toml | cut -d'"' -f2) - - - name: Upload Linux artifact - uses: actions/upload-artifact@v3 - with: - name: linux-binary - path: ${{ needs.detect-project.outputs.project-dir }}/target/x86_64-unknown-linux-gnu/release/${{ needs.detect-project.outputs.project-name }} - - windows-cross: - name: Windows Cross-Compile - needs: detect-project - runs-on: ubuntu-latest - timeout-minutes: 15 - steps: - - uses: actions/checkout@v3 - - - name: Install Rust and Windows target - uses: actions-rs/toolchain@v1 - with: - toolchain: stable - target: x86_64-pc-windows-gnu - profile: minimal - override: true - - - name: Install mingw cross-compiler - run: | - set -e - sudo apt-get update && sudo apt-get install -y gcc-mingw-w64-x86-64 - - - name: Build Windows binary - working-directory: ${{ needs.detect-project.outputs.project-dir }} - id: build - run: | - set -e - cargo build --release --target x86_64-pc-windows-gnu - binary_name=$(grep -m1 '^name =' Cargo.toml | cut -d'"' -f2) - x86_64-w64-mingw32-strip target/x86_64-pc-windows-gnu/release/$binary_name.exe - echo "binary_name=$binary_name" >> $GITHUB_OUTPUT - - - name: Upload Windows artifact - uses: actions/upload-artifact@v3 - with: - name: windows-binary - path: ${{ needs.detect-project.outputs.project-dir }}/target/x86_64-pc-windows-gnu/release/${{ needs.detect-project.outputs.project-name }}.exe - - docker-build: - name: Build Linux Docker Image - needs: [native-build, windows-cross, detect-project] + if: ${{ !failure() && !cancelled() }} runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 + - name: Install Rust + uses: dtolnay/rust-toolchain@stable + with: + toolchain: stable + targets: x86_64-unknown-linux-gnu, x86_64-pc-windows-gnu + components: rustfmt, clippy + + test: + name: Run Tests + needs: [detect-project, setup-rust] + if: ${{ !failure() && !cancelled() }} + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Install Rust + uses: dtolnay/rust-toolchain@stable + with: + toolchain: stable + + - name: Run tests + working-directory: ${{ needs.detect-project.outputs.project-dir }} + run: cargo test --verbose --no-fail-fast + + - name: Run clippy + working-directory: ${{ needs.detect-project.outputs.project-dir }} + run: cargo clippy -- -D warnings + + audit: + name: Security Audit + needs: [detect-project, setup-rust] + if: ${{ !failure() && !cancelled() }} + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Install Rust + uses: dtolnay/rust-toolchain@stable + with: + toolchain: stable + + - name: Install cargo-audit + run: cargo install cargo-audit + + - name: Audit dependencies + working-directory: ${{ needs.detect-project.outputs.project-dir }} + run: cargo audit --ignore RUSTSEC-2020-0071 --ignore RUSTSEC-2020-0159 + + build: + name: Build (${{ matrix.target }}) + needs: [detect-project, setup-rust, test, audit] + if: ${{ !failure() && !cancelled() }} + runs-on: ubuntu-latest + strategy: + matrix: + include: + - target: x86_64-unknown-linux-gnu + os: linux + artifact-name: linux-binary + strip-command: strip + - target: x86_64-pc-windows-gnu + os: windows + artifact-name: windows-binary + strip-command: x86_64-w64-mingw32-strip + timeout-minutes: 30 + + steps: + - uses: actions/checkout@v4 + + - name: Install Rust and target + uses: dtolnay/rust-toolchain@stable + with: + toolchain: stable + target: ${{ matrix.target }} + + - name: Install cross-compilation tools + if: matrix.target == 'x86_64-pc-windows-gnu' + run: | + sudo apt-get update && sudo apt-get install -y gcc-mingw-w64-x86-64 + + - name: Build release binary + working-directory: ${{ needs.detect-project.outputs.project-dir }} + run: | + cargo build --release --target ${{ matrix.target }} + echo "Built ${{ matrix.target }} successfully" + + - name: Strip debug symbols + working-directory: ${{ needs.detect-project.outputs.project-dir }} + run: | + binary_name="${{ needs.detect-project.outputs.project-name }}" + if [ "${{ matrix.os }}" = "windows" ]; then + ${{ matrix.strip-command }} "target/${{ matrix.target }}/release/$binary_name.exe" + else + ${{ matrix.strip-command }} "target/${{ matrix.target }}/release/$binary_name" + fi + + - name: Upload artifact + uses: actions/upload-artifact@v3 + with: + name: ${{ matrix.artifact-name }} + path: | + ${{ needs.detect-project.outputs.project-dir }}/target/${{ matrix.target }}/release/${{ needs.detect-project.outputs.project-name }}${{ matrix.os == 'windows' && '.exe' || '' }} + + docker-build: + name: Build and Push Docker Image + needs: [detect-project, build] + if: | + always() && + needs.detect-project.result == 'success' && + needs.build.result == 'success' && + github.event_name != 'pull_request' + runs-on: ubuntu-latest + environment: production + steps: + - uses: actions/checkout@v4 + - name: Download Linux artifact - id: download-linux uses: actions/download-artifact@v3 with: name: linux-binary - path: linux-bin + path: dist/ + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v2 - - name: Verify artifacts - run: | - echo "Linux binary:" - ls -la linux-bin/ - - name: Login to Docker Registry - uses: docker/login-action@v3 + if: ${{ env.REGISTRY != '' }} + uses: docker/login-action@v2 with: registry: ${{ env.REGISTRY }} username: ${{ secrets.DOCKER_USERNAME }} password: ${{ secrets.DOCKER_PASSWORD }} - - - name: Linux build using Docker Buildx + + - name: Extract metadata for Docker + id: meta run: | - docker buildx build \ - --platform linux/amd64 \ - -f Dockerfile.linux \ - --build-arg BINARY_NAME=${{ needs.detect-project.outputs.project-name }} \ - --load \ - -t ${{ env.IMAGE_NAME }}:linux-${{ env.TAG }} . + if [ "${{ github.ref_type }}" = "tag" ]; then + echo "tags=${{ env.IMAGE_NAME }}:${{ github.ref_name }},${{ env.IMAGE_NAME }}:latest" >> $GITHUB_OUTPUT + elif [ "${{ github.ref }}" = "refs/heads/main" ]; then + echo "tags=${{ env.IMAGE_NAME }}:latest,${{ env.IMAGE_NAME }}:$(date +%Y%m%d)" >> $GITHUB_OUTPUT + elif [ "${{ github.ref }}" = "refs/heads/development" ]; then + echo "tags=${{ env.IMAGE_NAME }}:development,${{ env.IMAGE_NAME }}:$(date +%Y%m%d)" >> $GITHUB_OUTPUT + else + echo "tags=${{ env.IMAGE_NAME }}:pr-$(echo ${{ github.ref }} | sed 's/refs\/heads\///' | tr '/' '-')" >> $GITHUB_OUTPUT + fi + + - name: Build Docker image + uses: docker/build-push-action@v4 + with: + context: . + file: Dockerfile.linux + platforms: linux/amd64 + build-args: | + BINARY_NAME=${{ needs.detect-project.outputs.project-name }} + tags: ${{ steps.meta.outputs.tags }} + push: ${{ env.REGISTRY != '' }} + load: ${{ env.REGISTRY == '' }} - - name: Tag and Push Linux Docker image - if: ${{ success() }} + summary: + name: Workflow Summary + needs: [test, audit, build, docker-build] + if: always() + runs-on: ubuntu-latest + steps: + - name: Create summary run: | - echo "Tagging Linux Docker image" - docker tag ${{ env.IMAGE_NAME }}:linux-${{ env.TAG }} ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:linux-${{ env.TAG }} - echo "Pushing Linux Docker image to registry: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:linux-${{ env.TAG }}" - docker push ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:linux-${{ env.TAG }} \ No newline at end of file + echo "# 🚀 Build Summary" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + echo "## 📊 Job Results" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + echo "| Job | Status |" >> $GITHUB_STEP_SUMMARY + echo "|-----|--------|" >> $GITHUB_STEP_SUMMARY + echo "| Project Detection | ${{ needs.detect-project.result }} |" >> $GITHUB_STEP_SUMMARY + echo "| Tests | ${{ needs.test.result }} |" >> $GITHUB_STEP_SUMMARY + echo "| Security Audit | ${{ needs.audit.result }} |" >> $GITHUB_STEP_SUMMARY + echo "| Build | ${{ needs.build.result }} |" >> $GITHUB_STEP_SUMMARY + echo "| Docker Build | ${{ needs.docker-build.result || 'skipped' }} |" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + + if [ "${{ needs.test.result }}" == "success" ] && [ "${{ needs.audit.result }}" == "success" ] && [ "${{ needs.build.result }}" == "success" ]; then + echo "✅ All checks passed!" >> $GITHUB_STEP_SUMMARY + else + echo "❌ Some checks failed. Please review the logs." >> $GITHUB_STEP_SUMMARY + fi \ No newline at end of file diff --git a/Dockerfile.linux b/Dockerfile.linux index 16e1c55..a625f9e 100644 --- a/Dockerfile.linux +++ b/Dockerfile.linux @@ -34,7 +34,7 @@ ARG SERVER_PORT ENV SERVER_PORT=${SERVER_PORT:-5000} ARG SERVER_URL ENV SERVER_URL=${SERVER_URL:-http://localhost:${SERVER_PORT}} -ARG CLIENt + ARG LOG_LEVEL