From 586d10971476a892e66a1c3d6aed0de1aafbae46 Mon Sep 17 00:00:00 2001 From: Market Data <112879596+MarketDataApp@users.noreply.github.com> Date: Thu, 17 Sep 2026 12:59:27 -0400 Subject: [PATCH 1/4] chore: the code review bot's policy for this repository --- .github/code-review/policy.yml | 43 ++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 .github/code-review/policy.yml diff --git a/.github/code-review/policy.yml b/.github/code-review/policy.yml new file mode 100644 index 0000000..ae7629e --- /dev/null +++ b/.github/code-review/policy.yml @@ -0,0 +1,43 @@ +# Code review bot, sdk-csharp. Overrides the bot's defaults; anything absent +# keeps the default. See +# MarketData-App/code-review-bot/reviewbot/defaults/policy.yml + +# Codex reviews this repository; Claude catches it when Codex cannot. +# +# `fallback`, NOT `first`. Under `first` the run is [ready[0].review(brief)] +# and a BackendError goes straight to _fail -- Claude is never tried, because it +# was dropped into `missing` the moment Codex probed live. Since +# CodexBackend.probe() returns true as soon as $CODEX_HOME/auth.json EXISTS, a +# stale borrowed credential is live-but-broken, and that would end the review +# with a neutral "Bot error" and no comment. +# +# Codex must stay FIRST for a second reason: credential-checkout declines the +# shared credential lease when codex is not the first backend, because a later +# backend is reached rarely or never and holding one plan's lease for it starves +# the repositories that use it on every run. +backends: [codex, claude] +mode: fallback + +# The check is advisory until someone adds it to a branch rule, so a blocked +# review costs nothing yet and means something later. +gate: true +require_ci_green: true + +# The review rules are in REVIEW.md beside this file. Its two `@include` lines +# pull in the bot's shared rule sets and section 9 describes what the public +# surface is in C#, so there is nothing to add here. + +ignore_paths: + - "docs/**" + - "*.md" + - ".github/**/*.md" + - "**/*.lock" + - "**/dist/**" + # Build output. A restored or published tree puts compiled assemblies and + # generated files here, and they would spend the diff budget ahead of the + # source sitting beside them. + - "**/bin/**" + - "**/obj/**" + +check_name: "Code review" +timeout_minutes: 15 From deed96e14f634f2bf4f89701ac27ec5e9e075bf3 Mon Sep 17 00:00:00 2001 From: Market Data <112879596+MarketDataApp@users.noreply.github.com> Date: Thu, 17 Sep 2026 12:59:28 -0400 Subject: [PATCH 2/4] chore: call the code review bot, on dispatch for now --- .github/workflows/code-review.yml | 67 +++++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) create mode 100644 .github/workflows/code-review.yml diff --git a/.github/workflows/code-review.yml b/.github/workflows/code-review.yml new file mode 100644 index 0000000..1e228fc --- /dev/null +++ b/.github/workflows/code-review.yml @@ -0,0 +1,67 @@ +name: Code review + +# DISPATCH ONLY FOR NOW, DELIBERATELY. +# +# The automatic trigger is written out below and commented. It is held back so +# the first review on this repository is read by a person before every open +# pull request gets one: this repository has never been reviewed by the bot, and +# whether the rules say useful things about sdk-csharp is the one thing nobody +# has measured yet. +# +# TO ARM IT: delete the `workflow_run` comment markers below, and delete this +# banner. Nothing else changes. Read docs/setup.md section 4 in +# MarketData-App/code-review-bot first -- it explains why the trigger is CI's +# completion and not the push. +on: + # workflow_run: + # # The `name:` of this repository's pull-request CI, not its filename. + # workflows: ["Tests", "Lint"] + # types: [completed] + issue_comment: + types: [created] + workflow_dispatch: + inputs: + pr: + description: Pull request number + required: true + force: + description: > + Review a commit that has already been reviewed. The bot skips an + unchanged head, so without this a re-dispatch is a no-op that reports + success. + type: boolean + default: false + +jobs: + review: + # Guards, each of which cost a failed run elsewhere to learn: + # 1. workflow_run fires for default-branch pushes too, where there is no + # pull request. `workflow_run.event` is what triggered the UPSTREAM + # run, so 'pull_request' is the precise discriminator. + # 2. A comment only starts a review when it is addressed to the bot. + if: > + (github.event_name != 'workflow_run' || + github.event.workflow_run.event == 'pull_request') && + (github.event_name != 'issue_comment' || + (github.event.issue.pull_request != null && + startsWith(github.event.comment.body, '@marketdata-code-review'))) + uses: MarketData-App/code-review-bot/.github/workflows/review.yml@main + # NOT `secrets: inherit`. That only passes secrets to a reusable workflow in + # the SAME organisation. This repository is on the MarketDataApp user account + # and the bot is owned by MarketData-App, so inherit crosses an owner + # boundary and delivers nothing -- the call fails at evaluation naming a + # secret that is sitting in this repository's settings. + secrets: + CODE_REVIEW_APP_PRIVATE_KEY: ${{ secrets.CODE_REVIEW_APP_PRIVATE_KEY }} + CLAUDE_CODE_OAUTH_TOKEN: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }} + with: + # REQUIRED: this repository is public and on the MarketDataApp user + # account, so it can never reach the organisation's self-hosted runner -- + # that runner group is visibility=all with + # allows_public_repositories=false. A job that asks for it is not refused, + # it queues forever with no runner and nothing saying why. + runs-on: '["ubuntu-latest"]' + # `|| false` is load-bearing: `inputs` exists only for workflow_dispatch, + # and a null against a boolean-typed input fails the ENTIRE workflow at + # evaluation -- no job, no log. + force: ${{ inputs.force || false }} From b520a910f013cd135a48a01f81946df9c3b1e1a5 Mon Sep 17 00:00:00 2001 From: Market Data <112879596+MarketDataApp@users.noreply.github.com> Date: Thu, 17 Sep 2026 12:59:29 -0400 Subject: [PATCH 3/4] chore: name this workflow Tests, which is the interface the bot reads --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 462605c..f895375 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,4 +1,4 @@ -name: CI +name: Tests on: push: From 90a61dabc5446460c03092db8a9ef4ca23d620e5 Mon Sep 17 00:00:00 2001 From: Market Data <112879596+MarketDataApp@users.noreply.github.com> Date: Thu, 17 Sep 2026 12:59:31 -0400 Subject: [PATCH 4/4] docs: the badge label follows the workflow's new name --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index dd12532..616af1a 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ [![Twitter](https://img.shields.io/twitter/follow/MarketDataApp?style=social)](https://twitter.com/MarketDataApp) [![Helpdesk](https://img.shields.io/badge/Support-Ticketing-ff69b4.svg?logo=TicketTailor&logoColor=white)](https://www.marketdata.app/dashboard/) -[![CI](https://github.com/MarketDataApp/sdk-csharp/actions/workflows/ci.yml/badge.svg)](https://github.com/MarketDataApp/sdk-csharp/actions/workflows/ci.yml) +[![Tests](https://github.com/MarketDataApp/sdk-csharp/actions/workflows/ci.yml/badge.svg)](https://github.com/MarketDataApp/sdk-csharp/actions/workflows/ci.yml) [![codecov](https://codecov.io/gh/MarketDataApp/sdk-csharp/graph/badge.svg)](https://codecov.io/gh/MarketDataApp/sdk-csharp) [![NuGet](https://img.shields.io/nuget/v/MarketDataApp?logo=nuget&label=NuGet)](https://www.nuget.org/packages/MarketDataApp) [![Downloads](https://img.shields.io/nuget/dt/MarketDataApp?logo=nuget&label=downloads)](https://www.nuget.org/packages/MarketDataApp)