# Due to the recent spike in people considering themselves developers because AI can do the work for them, this project is not currently accepting any new PR contributions.
Old contributing guide # Contributing to Cleanuparr Thanks for your interest in contributing to Cleanuparr! This guide will help you get started with development. ## Before You Start ### AI usage In this ever-evolving field of work, AI is now the shiny new tool to help programmers work faster and there's nothing wrong with that. But it is **very** wrong to rely solely on AI tools to write, review and test your code. **If you do not have a background in programming and you do not intend to test your code properly, please do not submit AI-generated code.** If you still want to help in other ways such as testing features, that would also help a lot! ### Announce Your Intent Before starting any work, please let us know what you want to contribute: - For existing issues: Comment on the issue stating you'd like to work on it - For new features/changes: Create a new issue first and mention that you want to work on it This helps us avoid redundant work, git conflicts, and contributions that may not align with the project's direction. **Wait for approval from the maintainers before proceeding with your contribution.** ## Development Setup ### Prerequisites - [.NET 10.0 SDK](https://dotnet.microsoft.com/download/dotnet/10.0) - [Node.js 26+](https://nodejs.org/) - [Git](https://git-scm.com/) - (Optional) [Make](https://www.gnu.org/software/make/) for database migrations - (Optional) IDE: [JetBrains Rider](https://www.jetbrains.com/rider/) or [Visual Studio](https://visualstudio.microsoft.com/) ### Repository Setup 1. Fork the repository on GitHub 2. Clone your fork locally: ```bash git clone https://github.com/YOUR_USERNAME/Cleanuparr.git cd Cleanuparr ``` 3. Add the upstream repository: ```bash git remote add upstream https://github.com/Cleanuparr/Cleanuparr.git ``` ## Backend Development ### Initial Setup #### 1. Create a GitHub Personal Access Token (PAT) Cleanuparr uses GitHub Packages for NuGet dependencies. You'll need a PAT with `read:packages` permission: 1. Go to [GitHub Settings > Developer Settings > Personal Access Tokens > Tokens (classic)](https://github.com/settings/tokens) 2. Click "Generate new token" → "Generate new token (classic)" 3. Give it a descriptive name (e.g., "Cleanuparr NuGet Access") 4. Set an expiration (recommend 90 days or longer for development) 5. Select only the `read:packages` scope 6. Click "Generate token" and copy it #### 2. Configure NuGet Source Add the Cleanuparr NuGet repository: ```bash dotnet nuget add source \ --username YOUR_GITHUB_USERNAME \ --password YOUR_GITHUB_PAT \ --store-password-in-clear-text \ --name Cleanuparr \ https://nuget.pkg.github.com/Cleanuparr/index.json ``` Replace `YOUR_GITHUB_USERNAME` and `YOUR_GITHUB_PAT` with your GitHub username and the PAT you created. ### Running the Backend #### Option 1: Using .NET CLI Navigate to the backend directory: ```bash cd code/backend ``` Build the application: ```bash dotnet build Cleanuparr.Api/Cleanuparr.Api.csproj ``` Run the application: ```bash dotnet run --project Cleanuparr.Api/Cleanuparr.Api.csproj ``` Run tests: ```bash dotnet test ``` The API will be available at http://localhost:5000 #### Option 2: Using an IDE For JetBrains Rider or Visual Studio: 1. Open the solution file: `code/backend/cleanuparr.sln` 2. Set `Cleanuparr.Api` as the startup project 3. Press `F5` to start the application ### Database Migrations Cleanuparr uses two separate database contexts: `DataContext` and `EventsContext`. #### Prerequisites Install Make if not already installed: - Windows: Install via [Chocolatey](https://chocolatey.org/) (`choco install make`) or use [WSL](https://docs.microsoft.com/windows/wsl/) - macOS: Install via Homebrew (`brew install make`) - Linux: Usually pre-installed, or install via package manager (`apt install make`, `yum install make`, etc.) #### Creating Migrations From the `code` directory: For data migrations (DataContext): ```bash make migrate-data name=YourMigrationName ``` For events migrations (EventsContext): ```bash make migrate-events name=YourMigrationName ``` Example: ```bash make migrate-data name=AddUserPreferences make migrate-events name=AddAuditLogEvents ``` ## Frontend Development ### Setup 1. Navigate to the frontend directory: ```bash cd code/frontend ``` 2. Install dependencies: ```bash npm install ``` 3. Start the development server: ```bash npm start ``` The UI will be available at http://localhost:4200 ### Testing Unit tests run on [Vitest](https://vitest.dev/) through the Angular `@angular/build:unit-test` builder, in a jsdom environment. No browser download is required. ```bash cd code/frontend # Watch mode, re-runs on save npm test # Single run with a coverage report, written to coverage/ui/. This is what CI runs npm run test:ci # Single run without coverage npm test -- --watch=false # Run a single spec npm test -- --include src/app/ui/chip-input/chip-input.component.spec.ts # Lint, also a CI gate npm run lint ``` `npm test` is Angular's `ng test`, which watches by default in an interactive terminal and runs once when stdout is not a TTY. CI therefore needs no extra flag, but do not rely on that locally: in your terminal `npm test` stays open until you quit it. #### Writing specs Specs live next to the code they cover, named `{feature}.component.spec.ts`. The Angular schematics in `angular.json` are configured with `skipTests: true`, so `ng generate` will not create a spec for you. Write it by hand. House style, follow the existing specs as reference: - Vitest globals (`describe`, `it`, `expect`, `vi`) are enabled via `tsconfig.spec.json`. Do not import them. - Use `TestBed.createComponent` and drive the rendered DOM. Assert on output, not on private internals. - For a component with inputs and outputs, declare a small standalone host component in the spec file and test through it. See `src/app/ui/chip-input/chip-input.component.spec.ts`. - Stub API classes with a plain object of methods returning `of(...)` from RxJS. Do not mock `HttpClient` and do not use `provideHttpClientTesting`. See `src/app/features/settings/seeker/seeker.component.spec.ts`. - Keep stub observables synchronous. An `rxResource` backed by `of(...)` resolves within a single `fixture.detectChanges()`, while an async source would need `await fixture.whenStable()`. - To flush a bare `effect()` outside a component, call it inside `TestBed.runInInjectionContext(...)` and flush with `TestBed.tick()`. See `src/app/core/services/overlay-stack.service.spec.ts`. - Put shared setup in a local `function setup()` inside the `describe` rather than in `beforeEach`, so each test reads top to bottom. - Components are zoneless and `OnPush`, so call `fixture.detectChanges()` after every interaction that should update the view. Two consequences of the zoneless, non-isolated test environment are worth knowing before you debug something strange: - `fakeAsync`, `tick()` and `flush()` from `@angular/core/testing` require Zone.js and **cannot** be used. Use `vi.useFakeTimers()` and `vi.advanceTimersByTime()` instead, and restore with `vi.useRealTimers()`. - The Angular `@angular/build` unit-test runner sets Vitest's `isolate` option to `false` to match the old Karma behaviour. Vitest's own default is `isolate: true`, so its documentation will tell you the opposite. In practice module-level state, `localStorage`, fake timers and anything written to `document.documentElement` leak into other spec files. Always undo them in `afterEach`. ## Documentation Development ### Setup 1. Navigate to the docs directory: ```bash cd docs ``` 2. Install dependencies: ```bash npm install ``` 3. Start the development server: ```bash npm start ``` The documentation site will be available at http://localhost:3000 ## Building with Docker ### Building a Local Docker Image To build the Docker image locally for testing: 1. Navigate to the `code` directory: ```bash cd code ``` 2. Build the image: ```bash export PACKAGES_PAT=YOUR_GITHUB_PAT docker build \ --build-arg PACKAGES_USERNAME=YOUR_GITHUB_USERNAME \ --secret id=packages_pat,env=PACKAGES_PAT \ -t cleanuparr:local \ -f Dockerfile . ``` Replace `YOUR_GITHUB_USERNAME` and `YOUR_GITHUB_PAT` with your credentials. 3. Run the container: ```bash docker run -d \ --name cleanuparr-dev \ -p 11011:11011 \ -v /path/to/config:/config \ -e PUID=1000 \ -e PGID=1000 \ -e TZ=Etc/UTC \ cleanuparr:local ``` 4. Access the application at http://localhost:11011 ### Building for Multiple Architectures Use Docker Buildx for multi-platform builds: ```bash export PACKAGES_PAT=YOUR_GITHUB_PAT docker buildx build \ --platform linux/amd64,linux/arm64 \ --build-arg PACKAGES_USERNAME=YOUR_GITHUB_USERNAME \ --secret id=packages_pat,env=PACKAGES_PAT \ -t cleanuparr:local \ -f Dockerfile . ``` ## Code Standards ### Backend (.NET/C#) - Follow existing conventions and [Microsoft C# Coding Conventions](https://docs.microsoft.com/dotnet/csharp/fundamentals/coding-style/coding-conventions) - Use meaningful variable and method names - Add XML documentation comments for public APIs - Write unit tests whenever possible ### Frontend (Angular/TypeScript) - Follow existing conventions and the [Angular Style Guide](https://angular.io/guide/styleguide) - Use TypeScript strict mode - Write unit tests whenever possible, see [Frontend Development > Testing](#testing) ### Documentation - Use clear, concise language - Include code examples where appropriate - Update relevant documentation when adding/changing features - Check for spelling and grammar ## Submitting Your Contribution ### 1. Create a Feature Branch ```bash git checkout -b feature/your-feature-name # or git checkout -b fix/your-bug-fix-name ``` ### 2. Make Your Changes - Write clean, well-documented code - Follow the code standards outlined above - **Test your changes thoroughly!** ### 3. Commit Your Changes Write clear, descriptive commit messages: ```bash git add . git commit -m "Add feature: brief description of your changes" ``` ### 4. Keep Your Branch Updated ```bash git fetch upstream git rebase upstream/main ``` ### 5. Push to Your Fork ```bash git push origin feature/your-feature-name ``` ### 6. Create a Pull Request 1. Go to the [Cleanuparr repository](https://github.com/Cleanuparr/Cleanuparr) 2. Click "New Pull Request" 3. Select your fork and branch 4. Fill out the PR template with: - A descriptive title (e.g., "Add support for Prowlarr integration" or "Fix memory leak in download client polling") - Description of changes - Related issue number - Testing performed - Screenshots (if applicable) ### 7. Code Review Process - Maintainers will review your PR - Address any feedback or requested changes - Once approved, your PR will be merged ## Other Ways to Contribute ### Help Test New Features We're always looking for testers to help validate new features before they are released. If you'd like to help test upcoming changes: 1. Join our [Discord community](https://discord.gg/SCtMCgtsc4) 2. Let us know you're interested in testing 3. We'll provide you with pre-release builds and testing instructions Your feedback helps us catch issues early and deliver better releases. ## Getting Help - Discord: Join our [Discord community](https://discord.gg/SCtMCgtsc4) for real-time help - Issues: Check existing [GitHub issues](https://github.com/Cleanuparr/Cleanuparr/issues) or create a new one - Documentation: Review the [complete documentation](https://cleanuparr.github.io/Cleanuparr/) ## License By contributing to Cleanuparr, you agree that your contributions will be licensed under the same license as the project. --- Thanks for contributing to Cleanuparr!