flea/CLAUDE.md
ruberoid 029319e7c1 docs: Add NuGet Package Management section to CLAUDE.md
- Document Central Package Management (CPM) with Package Source Mapping
- Explain package source configuration (nuget.org vs musk private feed)
- Describe how nuget.config is used across different environments
- Add troubleshooting context for NU1507 warning resolution

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-17 12:40:43 +04:00

8.2 KiB

CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

Project Overview

This is a microservices-based Telegram bot system for text monitoring and notifications. The system consists of 4 main services that communicate via RabbitMQ:

  • telegram-listener: Scans open Telegram channels and chats for messages
  • telegram-client: Bot interface for user interactions
  • text-matcher: Matches incoming messages against user subscriptions
  • users: Manages users and their preferences

Important: This repository is the parent project containing all services as git submodules. Each service (telegram-listener, telegram-client, text-matcher, users) is a separate repository added as a submodule. Git tags are created at the parent repository level, which triggers the Drone CI/CD pipeline to automatically build and publish NuGet packages with versions based on the git tag.

Architecture

The services follow a message bus pattern using RabbitMQ for async communication:

  • TelegramListener publishes:
    • MessageReceived events (for new messages)
    • MessageEdited events (for edited messages)
  • TextMatcher subscribes to MessageReceived and MessageEdited, stores match history in database, and publishes:
    • TextSubscriptionMatched events (for first-time matches)
    • TextSubscriptionUpdated events (for updates to previously matched messages)
  • TelegramClient subscribes to both TextSubscriptionMatched and TextSubscriptionUpdated events and notifies users

Note: WTelegram sends both UpdateNewChannelMessage and UpdateEditChannelMessage for the same message. TelegramListener publishes separate events to avoid duplicate notifications downstream.

Each service follows Clean Architecture with separate projects for:

  • Host (API/entry point)
  • AppServices (business logic)
  • Core (shared utilities)
  • Api.Contracts (REST API contracts)
  • Async.Api.Contracts (event contracts)
  • Persistence (database layer, where applicable)
  • Migrator (database migrations, where applicable)

Development Commands

Running the System

# Start all services with Docker Compose
docker-compose up

# Start individual services for development
cd telegram-client && dotnet run --project src/Nocr.TelegramClient.Host
cd telegram-listener && dotnet run --project src/Nocr.TelegramListener.Host  
cd text-matcher && dotnet run --project src/Nocr.TextMatcher.Host
cd users && dotnet run --project src/Nocr.Users.Host

Building

# Build individual services
cd <service-name> && dotnet build

# Build specific projects
dotnet build src/Nocr.<ServiceName>.Host

Testing

# Run unit tests (only text-matcher has tests currently)
cd text-matcher && dotnet test

Database Migrations

For text-matcher and users services:

# Add new migration (from service root directory)
cd text-matcher && ./src/Nocr.TextMatcher.Migrator/AddMigration.sh MyMigrationName
cd users && ./src/Nocr.Users.Migrator/AddMigration.sh MyMigrationName

# Apply migrations (handled automatically by migrator containers in docker-compose)

Configuration

📖 See CONFIGURATION.md for detailed configuration guide.

Quick Start

The system uses ASP.NET Core's layered configuration with Environment Variables having highest priority.

Configuration priority (lowest → highest):

  1. appsettings.json (base settings, committed)
  2. appsettings.{Environment}.json (environment-specific, some committed via .example files)
  3. User Secrets (Development only)
  4. Environment Variables (ALWAYS WINS)

Three Deployment Modes

  1. VS Code (Local Development)

    • Copy appsettings.Development.json.exampleappsettings.Development.json in each service
    • Or use environment variables in .vscode/launch.json
    • Start infrastructure: docker-compose up nocr-rabbitmq nocr-text-matcher-db nocr-users-db -d
  2. Docker Compose (Local Full Stack)

    • Copy .nocr.env.example.nocr.env in project root
    • Fill in your Telegram API credentials and Bot token
    • Run: docker-compose up
  3. Kubernetes (Production)

    • Create K8s Secrets (do NOT use .nocr.env)
    • Reference secrets in deployment manifests via envFrom

Debug Mode

Enable configuration debug logging on startup:

export NOCR_DEBUG_MODE=true

This prints masked configuration values to help troubleshoot issues.

Important Notes

  • Never commit secrets - use .example files as templates
  • Environment variables override all appsettings files
  • All services use .example files for documentation
  • Docker Compose uses .nocr.env file (gitignored)

Service Ports

When running with docker-compose:

Key Technologies

  • .NET 8
  • ASP.NET Core Web APIs
  • Entity Framework Core with MariaDB
  • WTelegramClient for Telegram API
  • Rebus for message bus (RabbitMQ)
  • Docker & Docker Compose for containerization
  • Drone CI/CD on Kubernetes

NuGet Package Management

The project uses Central Package Management (CPM) with Package Source Mapping to manage NuGet dependencies:

Package Sources

  • nuget.org: All public packages (Microsoft., Serilog., etc.)
  • musk (private): Internal Nocr.* contract packages

Configuration

The nuget.config file in the project root defines package source mapping:

<packageSourceMapping>
  <packageSource key="musk">
    <package pattern="Nocr.*" />
  </packageSource>
  <packageSource key="nuget.org">
    <package pattern="*" />
  </packageSource>
</packageSourceMapping>

How It Works

  1. Local Development: Copy nuget.config to each submodule root when needed
  2. CI/CD: Drone automatically copies nuget.config to /root/.nuget/NuGet/NuGet.Config
  3. Docker Builds: Kaniko copies nuget.config to submodule root before building

This eliminates NuGet warning NU1507 and ensures consistent package resolution across all environments.

CI/CD Pipeline

📖 See _deploy/README.md for full CI/CD documentation.

The project uses Drone CI with 5 specialized pipelines:

1. Feature Validation (feature/*, fix/* branches)

  • Triggered on push to feature/fix branches
  • Runs build + tests with Testcontainers support
  • Provides fast feedback before merge
  • Duration: ~3-5 minutes

2. Main Validation (main branch)

  • Triggered on push to main
  • Same checks as feature validation
  • Ensures main branch stays healthy
  • Duration: ~3-5 minutes

3. Contracts-Only Publish (tags with contracts_only:)

  • Triggered by tag + commit message containing contracts_only:<service>
  • Publishes NuGet contracts without building Docker images
  • Fast iteration on contract changes
  • Duration: ~2 minutes
  • Example: git commit -m "contracts_only:telegram_listener - Add MessageEdited event"

4. Full Release (clean tags)

  • Triggered by tag without special markers
  • Complete release cycle:
    1. Publish all NuGet contracts (parallel)
    2. Build all Docker images with Kaniko (parallel, after contracts)
    3. Deploy to Kubernetes (automatic for v* tags)
  • Duration: ~8-10 minutes
  • Example: git tag v1.3.0

5. Deploy-Only (tags with deploy_only:)

  • Triggered by tag + commit message containing deploy_only:
  • Skips building, only deploys existing images
  • Useful for rollbacks and hotfixes
  • Duration: ~1 minute
  • Example: git commit --allow-empty -m "deploy_only: Deploy v1.2.9"

Deployment Scripts

Located in _deploy/scripts/:

  • deploy.sh - Deploy services to Kubernetes with health checks
  • rollback.sh - Rollback deployments to previous version
  • health-check.sh - Check health of all services

Key Optimizations

  • Shared NuGet cache across pipeline steps (~60% faster builds)
  • Parallel execution for independent operations
  • Proper dependency order: Contracts → Images → Deploy
  • Kaniko layer caching for faster Docker builds
  • Docker-in-Docker support for Testcontainers in tests