CI/CD¶
FindRomCover uses GitHub Actions for continuous integration, code scanning, documentation publishing, and releases. Four workflows live in .github/workflows, and Dependabot keeps their dependencies current.
| Workflow | Purpose |
|---|---|
ci.yml |
Build, test, formatting, InspectCode, and dependency review |
codeql.yml |
CodeQL code scanning |
docs.yml |
GitHub Pages and GitHub wiki |
release.yml |
Validate, test, and publish a tagged release |
CI — build, test, and formatting¶
ci.yml runs on every push to master, every pull request targeting master, and manually via workflow_dispatch.
Build and test job¶
| Step | Detail |
|---|---|
| Runner | windows-latest |
| SDK | .NET 10.0.x |
| Cache | NuGet packages, keyed by the project files |
| Restore | dotnet restore CSharp_FindRomCover.sln |
| Build | dotnet build --configuration Release --no-restore -warnaserror |
| Test | dotnet test --configuration Release --no-build with Cobertura coverage and TRX results |
| Artifacts | test-results (TRX + coverage.cobertura.xml, kept for 14 days) |
The test project targets net10.0-windows, so the suite always runs on Windows even though the application itself is cross-platform.
The build treats warnings as errors. This enforces the warning-free policy for the Meziantou, Roslynator, and Microsoft.CodeAnalysis analyzers configured in the projects.
Coverage is summarized in the workflow run page and uploaded as an artifact. It is informational: there is no coverage threshold gate, so the report shows trends without blocking unrelated changes.
Cross-platform build job¶
The application is cross-platform, so a matrix job builds FindRomCover/FindRomCover.csproj on ubuntu-latest and macos-latest with the same Release configuration and warning-as-error setting. This catches platform-specific compile errors before the release workflow publishes bundles on those runners. The test project is excluded because it targets net10.0-windows.
Formatting and analyzers job¶
A separate Windows job runs:
It verifies whitespace, style, and analyzer fixes together. Run the same command locally before pushing. To apply the fixes:
InspectCode job¶
A Windows job installs the pinned JetBrains ReSharper command-line tools package
(JetBrains.ReSharper.GlobalTools), restores the solution, and runs:
The job fails when the report contains any finding, so errors, warnings, and
suggestions stay at zero. The text report is uploaded as the inspectcode-report
artifact for 7 days. Run the same command locally after installing the tool:
dotnet tool install --global JetBrains.ReSharper.GlobalTools --version 2026.2.3.1
jb inspectcode CSharp_FindRomCover.sln --output=inspectcode.txt --format=Text --no-updates
Dependency review job¶
Pull requests run actions/dependency-review-action. It compares the dependency graph before and after the PR and fails on newly introduced dependencies with a high or critical advisory.
Concurrency is configured with cancel-in-progress, so a new push cancels an in-progress run for the same branch.
CodeQL¶
codeql.yml scans the C# sources on pushes to master, pull requests, a weekly schedule (Mondays at 03:17 UTC), and manual dispatch.
- Installs the .NET 10 SDK.
- Initializes CodeQL with
build-mode: manual. - Restores and builds the solution in Release so the extractor sees the compiled code.
- Uploads the results as the
/language:csharpanalysis category.
Findings appear under Security > Code scanning. CodeQL needs the security-events: write permission, which is declared in the workflow and available to public repositories.
Docs — GitHub Pages and wiki¶
docs.yml runs on every push to master, every pull request targeting master, and manual dispatch. It is intentionally not path-filtered: the documentation build and wiki generation are required checks, so they must run for every change.
Documentation build job¶
- Checks out the repository and installs Python 3.13 with a cached
pipdownload directory. - Installs MkDocs Material from
docs/requirements.txt. - Builds the site with
mkdocs build --strict. - Uploads the
site/artifact.
On non-pull-request runs, the deploy job publishes the artifact with the official actions/deploy-pages action.
Required repository setting:
- Open Settings > Pages.
- Set Source to GitHub Actions.
After the first successful run the site is available at:
The left-hand navigation is generated from the nav section of mkdocs.yml.
Wiki generation and sync jobs¶
Every run generates the wiki pages with scripts/Sync-Wiki.ps1 and uploads them as the wiki-pages artifact. The Generate wiki pages job is a required check, so a broken wiki conversion fails the pull request before merge.
On non-pull-request runs, the sync job additionally:
- Checks whether the
WIKI_TOKENsecret is configured; if not, the job stops with a clear message instead of failing. - Downloads the generated
wiki-pagesartifact. - Clones
<owner>/<repo>.wiki.gitusing the token. - Copies the generated pages,
_Sidebar.md, and_Footer.mdinto the wiki repository. - Commits and pushes only when something changed.
The sidebar is generated by the same script, so the wiki gets the same section-based side menu as the site.
One-time wiki setup¶
- Open the repository's Wiki tab and create the first page (for example
Home). GitHub only creates the wiki Git repository after the first page exists. - Create a fine-grained personal access token or a classic token with the
reposcope that can push to the wiki. - Add it as an Actions secret named
WIKI_TOKENunder Settings > Secrets and variables > Actions.
Note: The default
GITHUB_TOKENcannot push to wiki repositories, which is why a personal access token is required.
Manual wiki sync¶
Then copy the contents of wiki-out into a clone of the wiki repository and push.
Release process¶
Releases are produced by release.yml, which runs when a tag named release_* (for example release_3.5.1) is pushed.
Before tagging¶
- Update the version in
FindRomCover/FindRomCover.csproj(Version,AssemblyVersion, andFileVersion) and inFindRomCover.Tests/FindRomCover.Tests.csproj(AssemblyVersionandFileVersion) — keep both in sync. The release workflow fails when any of them differs from the tag. - Update
README.md,WhatsNew.md, anddocs/release-notes.md. - Build, test, and format locally, then push to
masterand confirm CI is green. This push also redeploys the documentation site and the wiki throughdocs.yml. - Create and push the tag:
Release workflow jobs¶
- Validate — parses the tag, requires
release_<major>.<minor>.<patch>, and compares it withVersion,AssemblyVersion, andFileVersionin both project files. - Test — builds with warnings as errors and runs the full suite on
windows-latestbefore any bundle is produced. - Build — publishes five framework-dependent single-file bundles (the native libraries are embedded into the executable; the .NET runtime is never bundled):
| Runner | Bundles |
|---|---|
windows-latest |
release_<version>_win-x64.zip, release_<version>_win-arm64.zip |
ubuntu-latest |
release_<version>_linux-x64.zip, release_<version>_linux-arm64.zip |
macos-latest |
release_<version>_osx-arm64.zip |
There is no Intel-Mac (osx-x64) bundle because Magick.NET 15 no longer ships a macOS x64 native library.
Each archive contains the published application plus LICENSE.txt, README.md, and WhatsNew.md.
4. Release — downloads the bundles and creates the GitHub release. The body is the version's own # FindRomCover <version> — What's New section from WhatsNew.md; it falls back to a changelog link only when the section cannot be found.
The in-app update checker picks up the new release automatically: it reads the latest release's tag_name from the GitHub API and parses the version after the release_ prefix, so tags must keep the release_<major>.<minor>.<patch> format.
Note: The release job needs
contents: writepermission (declared on that job only) to create the GitHub release. No extra secrets are required.
Dependabot¶
.github/dependabot.yml opens grouped weekly pull requests, on Mondays, for:
- NuGet packages in the solution (minor and patch updates are grouped);
- GitHub Actions used by the workflows;
- Python packages in
docs/requirements.txt.
Every Dependabot pull request runs the same CI, CodeQL, and dependency-review checks as a human contribution.
Branch protection¶
master is protected by two repository rulesets:
- master safety blocks force pushes and branch deletion for everyone, including repository administrators.
- master status checks requires these checks before a pull request can merge:
Build and test (Windows)Build app (ubuntu-latest)Build app (macos-latest)Formatting and analyzersInspectCodeAnalyze C#(CodeQL)Build documentation siteGenerate wiki pages
The status-check ruleset has an administrator bypass so direct pushes keep working; every push still runs the full check suite, and collaborators without the admin role must use a pull request. The branch does not have to be up to date before merging, so unrelated pull requests are not forced to rebase. Both rulesets are managed under Settings > Rules > Rulesets.
Dependency review is intentionally not a required check: it depends on GitHub's advisory service and should not block an otherwise healthy pull request when that service is unavailable.
Versioning¶
Versions follow a major.minor.patch scheme. Tags use the release_ prefix (for example release_3.5.1). The application version lives in the project file, and the documentation release notes mirror the GitHub releases. release.yml refuses to publish a tag that does not match the project files.