# Contributing to SysManager Thanks for wanting to help! SysManager is a small, solo-maintained project and every clean PR is welcome โ€” bug fixes, docs, tests, new features, or even just a well-written bug report. This document describes how to get set up, the conventions the codebase follows, and what to expect when you open a pull request. ## Table of contents - [Ways to contribute](#ways-to-contribute) - [Development setup](#development-setup) - [Project layout](#project-layout) - [Coding conventions](#coding-conventions) - [Running tests](#running-tests) - [Commit messages](#commit-messages) - [Pull request process](#pull-request-process) - [Reporting bugs](#reporting-bugs) - [Requesting features](#requesting-features) - [Security issues](#security-issues) ## Ways to contribute - ๐Ÿ› **Report a bug** โ€” open an issue with the bug template. Crash logs, repro steps, and Windows version are gold. - ๐Ÿ’ก **Suggest a feature** โ€” open an issue with the feature template. Small, targeted suggestions land faster than big design proposals. - ๐Ÿงช **Improve tests** โ€” more edge cases, more fixtures. The suite is the spec for this project. - ๐Ÿ“š **Improve docs** โ€” typos, clearer wording, fresh screenshots, better examples. Doc-only PRs are merged fast. - ๐Ÿ›  **Fix a bug or implement a feature** โ€” see [open issues](https://github.com/laurentiu021/SystemManager/issues). Please comment on the issue before starting significant work so we don't both build the same thing. ## Development setup **Prerequisites** - Windows 10 or later (WPF + Windows APIs won't build elsewhere). - [.NET 10 SDK](https://dotnet.microsoft.com/download/dotnet/10.0). - Git 2.40+. - A Windows account with admin rights (needed to test elevated features; the app itself runs fine unelevated for everything else). **Clone and build** ```powershell git clone https://github.com/laurentiu021/SystemManager.git cd SystemManager # Build the app project directly โ€” this is what CI does. A SysManager.sln also # exists (SysManager/SysManager.sln) if you prefer the full solution in Visual Studio / Rider. dotnet build SysManager/SysManager/SysManager.csproj -c Debug ``` **Run the app** ```powershell dotnet run --project SysManager/SysManager/SysManager.csproj ``` **Run the tests** (see [Running tests](#running-tests) for more) ```powershell dotnet test --project SysManager/SysManager.Tests/SysManager.Tests.csproj -c Release ``` **Check the formatting** โ€” CI runs this on all four projects and fails the PR on any difference. A clean build does not catch it, so run it before you push: ```powershell # All four, because CI checks all four โ€” a single-project run passes while the PR fails. foreach ($p in @( 'SysManager/SysManager/SysManager.csproj', 'SysManager/SysManager.Tests/SysManager.Tests.csproj', 'SysManager/SysManager.IntegrationTests/SysManager.IntegrationTests.csproj', 'SysManager/SysManager.UITests/SysManager.UITests.csproj')) { dotnet format $p --verify-no-changes } # drop --verify-no-changes to let it fix the files in place ``` ## Project layout ``` SysManager/ โ”œโ”€โ”€ SysManager/ # main WPF app โ”‚ โ”œโ”€โ”€ Data/ # static data (ProcessDescriptions.json) โ”‚ โ”œโ”€โ”€ Models/ # POCOs (no logic) โ”‚ โ”œโ”€โ”€ Services/ # Windows / PowerShell / CLI wrappers โ”‚ โ”œโ”€โ”€ ViewModels/ # MVVM, one per tab โ”‚ โ”œโ”€โ”€ Views/ # XAML + minimal code-behind โ”‚ โ”œโ”€โ”€ Helpers/ # small utilities, converters โ”‚ โ””โ”€โ”€ Resources/ # icons, generated assets โ”œโ”€โ”€ SysManager.Tests/ # xUnit unit tests โ”œโ”€โ”€ SysManager.IntegrationTests/ # integration tests (CI, non-blocking) โ””โ”€โ”€ SysManager.UITests/ # FlaUI UI-automation tests ``` See [ARCHITECTURE.md](ARCHITECTURE.md) for the deeper tour. ## Coding conventions The codebase is small enough that the existing files are the best style guide. That said, a few explicit rules: - **MVVM strict**: business logic lives in view models and services, not in code-behind. Views are XAML with bindings; `.xaml.cs` should be empty or near-empty. - **CommunityToolkit.Mvvm source generators** (`[ObservableProperty]`, `[RelayCommand]`) โ€” use them. No manual `INotifyPropertyChanged` or `ICommand` boilerplate. - **Services are testable**: prefer constructor-injectable seams over statics. If a service must be static, keep it pure (`HealthAnalyzer`, `EventExplainer`). - **No silent failures**: catch exceptions close to the boundary (PowerShell, file I/O, network) and surface them as log lines or UI state. Never swallow. - **4 spaces, no tabs.** Braces on their own line (standard .NET style). - **`var` freely** when the type is obvious from the right-hand side. - **Async all the way down** for anything that touches I/O. - **AutomationId on every nav item and primary button** so UI tests can find them. - **Admin elevation is opt-in**: never demand admin unless the feature genuinely requires it. Show a banner, never a modal. ### XAML conventions - Resources in `App.xaml` for anything reused more than once. - Dark-gradient theme stays consistent; no hard-coded colours โ€” use the existing brushes. - Accessibility: every interactive control has a label or `AutomationProperties.Name`. ### Author headers Every source file opens with an attribution block, and a test fails the build if a new file doesn't โ€” so copy the shape exactly. In `.cs` files (the `โ€” summary` after the class name is optional): ```csharp // SysManager ยท UpdateService โ€” GitHub releases client // Author: laurentiu021 ยท https://github.com/laurentiu021/SystemManager // License: MIT ``` In `.xaml` files, one comment line above the root element: ```xml ``` Keep `Author:` as `laurentiu021` even in a PR you wrote โ€” it names the project's maintainer, not the commit author, which Git already records. Your contribution is credited in the release notes and in `git log`. ## Running tests Unit tests run their collections in parallel (`"parallelMode": "collections"` in `xunit.runner.json`). Tests that share process-wide state or touch OS resources are isolated via xUnit collection definitions in `TestCollections.cs` (each `DisableParallelization = true`), so they never run beside each other or beside a test that needs the same static. The integration suite runs sequentially. [TESTING.md](TESTING.md) has the details. Full run: ```powershell dotnet test --project SysManager/SysManager.Tests/SysManager.Tests.csproj -c Release dotnet test --project SysManager/SysManager.IntegrationTests/SysManager.IntegrationTests.csproj -c Release dotnet test --project SysManager/SysManager.UITests/SysManager.UITests.csproj -c Release ``` `--project` is required: under Microsoft.Testing.Platform, which `global.json` selects, `dotnet test` does not take a project path on its own. The integration tests touch the live system, so run them locally rather than over SSH/Remote PowerShell. CI runs the unit tests as the merge gate, and both the integration and UI-automation suites as separate **non-blocking** jobs โ€” a failure there raises a warning annotation and uploads its results, but does not block a merge, because a runner difference should not. Put a test that needs the live system in the integration project; put anything pure in `SysManager.Tests`, where it gates merges. Run one class while iterating by starting the test project's own executable (build the project the class lives in first โ€” `PingMonitorServiceTests` is an integration test): ```powershell dotnet build SysManager/SysManager.IntegrationTests/SysManager.IntegrationTests.csproj -c Release ./SysManager/SysManager.IntegrationTests/bin/Release/net10.0-windows/SysManager.IntegrationTests.exe ` -class SysManager.IntegrationTests.PingMonitorServiceTests ``` `-method` narrows to one test; [TESTING.md](TESTING.md#running-one-class-or-one-test) has the rest. Generate a coverage report: ```powershell dotnet test --project SysManager/SysManager.Tests/SysManager.Tests.csproj -c Release --coverage --coverage-output-format cobertura ``` **Every non-trivial PR should include at least one test.** If you're unsure where it belongs, look at the closest existing `*ServiceTests` or `*ViewModelTests` file and match the pattern. ## Commit messages Keep them short and imperative. The first line is the headline (โ‰ค 72 chars), then a blank line, then optional detail. Good: ``` Add SHA256 verification to UpdateService Downloads now compare the advertised hash against the local file and refuse to install on mismatch. Covered by UpdateServiceHashTests. ``` Bad: ``` fixed stuff ``` Prefixes aren't required, but if you want a convention: `fix:`, `feat:`, `docs:`, `test:`, `refactor:`, `ci:`, `chore:` are all understood. One of them is more than a convention: the **PR title** decides whether merging publishes a release. `feat:` bumps the minor, `fix:` the patch, `feat!:`/`fix!:` the major; every other prefix merges without releasing. That is why a releasing PR must also bump the version and add a CHANGELOG entry, and a non-releasing one must do neither โ€” the PR template splits the checklist along exactly that line. Don't worry about getting it right on a first contribution; say what your change does and the prefix can be adjusted before the squash merge. ## Pull request process 1. **Fork** the repo and create a branch from `main`: `git checkout -b feat/my-feature`. 2. **Build and run the tests locally.** PRs that don't build or break existing tests will be asked to fix that first. 3. **Add or update tests** for your change. 4. **Update docs** if the change is user-visible (README, CHANGELOG, ARCHITECTURE where relevant). 5. **Open the PR** against `main`. Fill out the PR template honestly โ€” if you didn't add tests, say why. 6. **CI must be green** before review starts. On a Windows runner, CI checks the formatting of all four projects, builds them, and runs the unit tests as the merge gate. The integration and UI-automation suites run as separate non-blocking jobs on pull requests from this repository; a pull request from a fork gets the build and the unit tests. 7. **Review and iterate.** I try to respond within a few days. If a PR goes silent, ping me with a comment. 8. **Squash merge** is the default. Your individual commits are preserved in the PR but the `main` history stays linear. ### What makes a PR easy to merge - Focused on one thing. - Tests that fail before the fix and pass after. - No unrelated reformatting or style churn. - A clear "why" in the description (link the issue if there is one). ## Reporting bugs Open an issue with the **Bug report** template. The template asks for: - Which tab and which action. - What you expected vs. what happened. - Steps to reproduce (if deterministic). - SysManager version (at the top of the About tab, and at the bottom of the sidebar) and Windows build. - Logs, if possible: `%LOCALAPPDATA%\SysManager\logs\`. The About tab has a **"Copy environment info"** button that copies most of this in a format ready to paste, **Save diagnostics bundle**, which puts the logs, the system report and that environment info into one zip you can attach, and **Report a problem**, which opens the bug template with your version and administrator state already filled in. ## Requesting features Open an issue with the **Feature request** template. Tell me: - The problem you're trying to solve (not the solution you imagine). - Who else this would help. - Any constraints โ€” admin required? offline? specific Windows version? Small, focused requests beat big open-ended ones. ## Security issues Do not open a public issue for a security vulnerability. See [SECURITY.md](SECURITY.md) for how to report privately. --- Thanks again โ€” and welcome aboard!