Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 27 additions & 0 deletions .github/agents/planner.agent.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
---
name: planner
description: Plans cross-cutting changes spanning the Maestro, DARC, and Product Construction Service components. Use for architecture/design work before implementation; hands off to implementers.
tools: ['read', 'search']
handoffs: ['test-specialist']
---

# Planner

Produces an implementation plan for changes that touch multiple components without editing code itself.

## Scope
- `src/Maestro/` (legacy shared libraries)
- `src/Microsoft.DotNet.Darc/` (DARC CLI + DarcLib)
- `src/ProductConstructionService/` (PCS service, Aspire/Docker)

## Process
<!-- TODO: Describe how dependency flow data moves between BAR, PCS, and DARC for this repo -->
<!-- TODO: List the cross-component contracts to check before proposing changes (e.g. generated PCS client) -->

## Output
- A step-by-step plan identifying affected projects, contracts, and tests.
- Explicit hand-off notes for the implementer / test-specialist.

## Constraints
- Read-only — do not modify code.
- Flag any change that requires regenerating the `Microsoft.DotNet.ProductConstructionService.Client`.
25 changes: 25 additions & 0 deletions .github/agents/test-specialist.agent.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
---
name: test-specialist
description: Writes and expands unit tests for arcade-services using the repo's NUnit + Moq + AwesomeAssertions conventions. Use when asked to add tests, improve coverage, or test a specific class.
tools: ['read', 'edit', 'search', 'runTerminalCommand']
---

# Test Specialist

Focused on producing high-value unit tests that follow this repo's testing conventions.

## Conventions
- NUnit (`[Test]`, `[TestFixture]`), Moq for mocks, AwesomeAssertions for fluent assertions.
- Arrange-Act-Assert (AAA) structure.
- Mirror the existing `test/` project layout (Darc, Maestro, ProductConstructionService).

## Process
<!-- TODO: Describe how to locate the right test project for a given source file -->
<!-- TODO: Note any shared test fixtures/helpers that should be reused -->

## Constraints
- Do NOT add tests to `test/ProductConstructionService.ScenarioTests` — they require a deployed service.
- Never weaken assertions just to make a test pass.

## Validation
- `dotnet test --no-build` passes for the affected test project.
4 changes: 2 additions & 2 deletions .github/copilot-instructions.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ The .NET Arcade Services repository contains the Product Construction Service (p
## Working Effectively

### Prerequisites and Environment Setup
- Install .NET 8 SDK (the build script will download the specific required version automatically)
- Install .NET 10 SDK (the build script will download the specific required version automatically)
- For full local development: Install Docker Desktop (required for Product Construction Service)
- For Windows development: Install Visual Studio with Azure Development and ASP.NET workloads
- Configure git for long paths: `git config --global core.longpaths true`
Expand Down Expand Up @@ -89,7 +89,7 @@ After making changes, validate by testing these workflows:
- `.github/` - GitHub workflows and templates

## Key Technologies
- .NET 8 (see global.json for exact version)
- .NET 10 (see global.json for exact version)
- Azure DevOps APIs
- ASP.NET Core for web APIs
- Entity Framework Core for data access
Expand Down
15 changes: 0 additions & 15 deletions .github/copilot-setup-steps.yml

This file was deleted.

10 changes: 10 additions & 0 deletions .github/hooks/security.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"version": 1,
"hooks": {
"preToolUse": [{
"type": "command",
"bash": "./scripts/security-check.sh",
"powershell": "pwsh -File scripts/security-check.ps1"
}]
}
}
Comment thread
dkurepa marked this conversation as resolved.
8 changes: 8 additions & 0 deletions .github/instructions/ef-migrations.instructions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
applyTo: 'src/Maestro/Maestro.Data/Migrations/**'
---
# EF Core Migrations
**When to read:** Changing the data model or migrations.

- These files are generated by `dotnet ef migrations add` — do not hand-edit the generated `*.Designer.cs` or snapshot files.
- Create a new migration for model changes rather than editing existing ones. See `docs/DevGuide.md` for the exact EF commands.
14 changes: 14 additions & 0 deletions .github/instructions/testing.instructions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
---
applyTo: 'test/**/*.cs'
---
# Testing Conventions
**When to read:** Writing or modifying test files.

- Use NUnit (`[Test]`, `[TestFixture]`), Moq for mocks, AwesomeAssertions for fluent assertions.
- Follow the Arrange-Act-Assert (AAA) pattern.
- Do NOT add tests to `test/ProductConstructionService.ScenarioTests` unless intentionally writing deployed-service scenarios — they require a full service deployment and are excluded from local/agent verification.

## Codeflow tests
- `test/Darc/Microsoft.DotNet.DarcLib.Codeflow.Tests` are local end-to-end tests: they create real on-disk git repositories and exercise the real codeflow classes through a real `ServiceProvider` (no mocks except the BAR/API client). They require `git` on PATH.
- Extend `CodeFlowTestsBase` for these; reuse its repo/VMR setup and `GitOperations` helper rather than rolling your own.
- They are slower than ordinary unit tests — keep them deterministic and clean up their temp directories.
15 changes: 15 additions & 0 deletions .github/prompts/generate-tests.prompt.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
---
description: Generate NUnit unit tests for the active file following repo conventions.
---

# Generate Tests

Generate unit tests for `${file}` using this repo's conventions.

- Framework: NUnit (`[Test]`, `[TestFixture]`).
- Mocking: Moq. Assertions: AwesomeAssertions (fluent).
- Structure each test with the Arrange-Act-Assert (AAA) pattern.
- Place the test in the matching `test/` project; reuse existing fixtures/helpers where available.
- Do NOT target `test/ProductConstructionService.ScenarioTests` (requires a deployed service).

<!-- TODO: Add any repo-specific test naming or fixture rules you want enforced -->
43 changes: 43 additions & 0 deletions .github/skills/add-darc-command/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
---
name: add-darc-command
description: 'Add a new command (verb) to the DARC CLI. Use when asked to "add a darc command", "create a new darc verb", "add a darc operation", or extend the darc tool with a new subcommand.'
---

# Add a DARC CLI Command

Adds a new verb to the DARC CLI by creating a paired CommandLineOptions class and an Operation class. The `CommandLine` library auto-discovers verbs via the `[Verb]` attribute.

## When to Use

- Adding a new `darc <verb>` subcommand.
- Exposing a new BAR / configuration operation through the CLI.

## Process

### Step 1: Create the options class
Create `src/Microsoft.DotNet.Darc/Darc/Options/<Verb>CommandLineOptions.cs`.
- Decorate with `[Verb("my-verb", HelpText = "...")]`.
- Inherit the appropriate base (e.g. `CommandLineOptions<TOperation>`, `ConfigurationManagementCommandLineOptions<TOperation>`) — pick the base used by sibling commands with the same auth/context needs.
- Add `[Option(...)]` properties for each argument; mark required ones `Required = true`.
<!-- TODO: List the options this command needs and which base class is correct -->

### Step 2: Create the operation class
Create `src/Microsoft.DotNet.Darc/Darc/Operations/<Verb>Operation.cs`.
- Inherit the matching operation base used by the options' generic parameter.
- Inject services via the constructor (e.g. `IBarApiClient`, `ILogger<TOperation>`).
- Implement `protected override async Task<int> ExecuteInternalAsync()` and return a process exit code.
<!-- TODO: Document which services this operation needs and the core logic -->

### Step 3: Wire up dependencies
<!-- TODO: Confirm how options map to operations (generic type param) and whether any DI registration is required for new services. Check an existing pair like AddChannelCommandLineOptions / AddChannelOperation. -->

## Constraints
- Async methods must end in `Async`; never block with `.Result`/`.Wait()`.
- Use `ILogger<T>` and structural logging; each method logs its own actions.
- Never throw generic `Exception`.
- Match the existing options/operation base-class conventions — do not invent a new pattern.

## Validation
- `dotnet build` succeeds (warnings are errors in this repo).
- `dotnet run --project src/Microsoft.DotNet.Darc/Darc -- my-verb --help` shows the new command and its options.
- Add/extend unit tests under `test/` (NUnit + Moq + AwesomeAssertions, AAA pattern).
19 changes: 19 additions & 0 deletions .github/workflows/copilot-setup-steps.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
name: "Copilot Setup Steps"

on: workflow_dispatch

jobs:
copilot-setup-steps:
runs-on: ubuntu-latest
environment: copilot
timeout-minutes: 30
permissions:
contents: read
id-token: write
steps:
- uses: actions/checkout@v5
with:
fetch-depth: 0
- name: Restore dependencies
run: ./eng/common/build.sh -restore
shell: bash
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -236,3 +236,4 @@ node_modules/


/eng/git-commit-diagram.mmd

35 changes: 35 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# AGENTS.md

## Verification
- Build & test: `dotnet build` then `dotnet test --no-build`
- The required .NET SDK is pinned in `global.json` — assume it is installed.
- If verification fails, fix the root cause and re-run.
Comment thread
dkurepa marked this conversation as resolved.

## Environment
- .NET 10 (see `global.json`). `Directory.Build.props` sets `TreatWarningsAsErrors=true` — unused usings and warnings break the build.
- Build via `dotnet build`, `Build.cmd` (Windows), or `./build.sh` (Linux/macOS); the repo uses the Arcade SDK.

## Guardrails
- Async methods must have an `Async` suffix; prefer async/await over `.Result`/`.Wait()`.
- Never throw generic `Exception`; use structural logging and `ILogger<T>` (not `ILogger`).
- Prefer immutable types (records / readonly); annotate nullable reference types.
- Tests: NUnit + Moq + AwesomeAssertions, AAA pattern.
- Do NOT run `test/ProductConstructionService.ScenarioTests` — they require a deployed service.

## Constraints
- Keep diffs minimal and scoped to the request.
- Update or add tests for any behavior change.
- Do not modify CI, dependency versions, or security settings unless asked.
- Never print, log, or commit secrets.

## Learning from corrections
- When the user corrects you, rejects an approach, or states a durable preference or convention, store it with Copilot Memory (the `store_memory` tool) so it persists across sessions.
- Only store durable, generally-applicable facts — not ephemeral, task-specific instructions ("for this PR…", "just this once…").
- Before storing, check the surfaced memories; if a similar fact exists, upvote/refine it instead of adding a near-duplicate.
- Keep each memory atomic and short, and don't store anything already covered by AGENTS.md, `.github/instructions/`, or inferable from code — prefer in-repo docs for team conventions, reserving memory for cross-session preferences.
- If a correction contradicts an existing memory, update it: downvote the outdated memory and store the corrected fact.

## Where to find more
- Detailed conventions & build guide: `.github/copilot-instructions.md` and `docs/DevGuide.md`
- Path-specific rules: `.github/instructions/`
- Multi-step workflows: `.github/skills/*/SKILL.md`
10 changes: 10 additions & 0 deletions scripts/security-check.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
$ErrorActionPreference = 'Stop'
# Block destructive commands — customize this blocklist for your repo
$blockedPatterns = @('rm -rf /', 'DROP DATABASE', 'format C:', 'mkfs', 'git push --force')
$commandText = $args -join ' '
foreach ($pattern in $blockedPatterns) {
if ($commandText -match [regex]::Escape($pattern)) {
Write-Error "Blocked: destructive pattern detected ($pattern)"
exit 1
}
}
10 changes: 10 additions & 0 deletions scripts/security-check.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
#!/usr/bin/env bash
set -euo pipefail
# Block destructive commands — customize this blocklist for your repo
BLOCKED_PATTERNS=("rm -rf /" "DROP DATABASE" "format C:" "mkfs" "git push --force")
for pattern in "${BLOCKED_PATTERNS[@]}"; do
if echo "$*" | grep -qi "$pattern"; then
echo "❌ Blocked: destructive pattern detected ($pattern)" >&2
exit 1
fi
done
Comment on lines +1 to +10
5 changes: 5 additions & 0 deletions scripts/verify
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
#!/usr/bin/env bash
set -euo pipefail
# Verify: repeatable health check. Assumes the required .NET SDK (see global.json) is installed.
dotnet build
dotnet test --no-build
Comment thread
dkurepa marked this conversation as resolved.
6 changes: 6 additions & 0 deletions scripts/verify.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
$ErrorActionPreference = 'Stop'
# Verify: repeatable health check. Assumes the required .NET SDK (see global.json) is installed.
dotnet build
if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE }
dotnet test --no-build

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will this mean it's going to run this to verify the state? If yes, this is probably too much as the codeflow tests and scenario tests run for quite long

if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE }
Comment on lines +1 to +6

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I prefer using global dotnet tbh. I find it works better for me

27 changes: 27 additions & 0 deletions src/AGENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# AGENTS.md — `src/` project map

Scope: `src/`. Extends the root AGENTS.md. A brief orientation of what lives where; much dependency-flow work spans several of these projects.

## DARC CLI — `Microsoft.DotNet.Darc/`
- `Darc` — the DARC command-line tool (verbs = Operations + CommandLineOptions pairs).
- `DarcLib` — the core dependency-flow library (VMR / codeflow, git operations, version files) shared by DARC and PCS.

## Maestro libraries — `Maestro/`
(Former Maestro service; now shared libraries consumed by PCS.)
- `Maestro.Data` — EF Core data layer and the Build Asset Registry (BAR) `DbContext` + migrations.
- `Maestro.DataProviders` — BAR data-access implementations (SQL BAR client, remote/token factories).
- `Maestro.Common` — shared utilities (git URL helpers, caching, logging, version constants).
- `Maestro.Services.Common` — shared host/service wiring (database, Key Vault, data protection, service defaults).
- `Maestro.WorkItems` — background work-item and reminder infrastructure.
- `Maestro.MergePolicies` / `Maestro.MergePolicyEvaluation` — merge policy definitions and their evaluation logic/models.
- `Microsoft.DotNet.Maestro.Tasks` — MSBuild tasks used by builds to publish build/asset metadata to the BAR.

## Product Construction Service — `ProductConstructionService/`
See `ProductConstructionService/AGENTS.md` for run/convention details.
- `ProductConstructionService.Api` — main service host (ASP.NET Core API + background workers, Dockerized).
- `ProductConstructionService.AppHost` — .NET Aspire orchestration for running the service locally.
- `ProductConstructionService.DependencyFlow` — core dependency-flow logic: subscription triggering, PR updaters/targets, merge policy evaluation.
- `ProductConstructionService.SubscriptionTriggerer` — job that triggers subscriptions on a schedule.
- `ProductConstructionService.FeedCleaner` — job that cleans up stale package feeds.
- `ProductConstructionService.BarViz` — Blazor web UI for visualizing the Build Asset Registry.
- `Microsoft.DotNet.ProductConstructionService.Client` — generated client for the PCS API; regenerate when API contracts change.
14 changes: 14 additions & 0 deletions src/ProductConstructionService/AGENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# AGENTS.md — Product Construction Service (PCS)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we have a setup agent that would follow DevGuide and prepare your env from zero?


Scope: `src/ProductConstructionService/`. Extends the root AGENTS.md. See `src/AGENTS.md` for the project map.

## Running locally
- Run the service via the Aspire AppHost: `dotnet run --project ProductConstructionService.AppHost`.
- Requires Docker Desktop running. Do not assume a plain `dotnet run` on the Api project is sufficient.

## Conventions
- The API uses Newtonsoft.Json with camelCase properties and camelCase string enums; dates are ISO-8601 UTC (`yyyy-MM-ddTHH:mm:ssZ`). Match this when adding contracts.
- API controllers live in `ProductConstructionService.Api/Api/`.

## Safety
- `test/ProductConstructionService.ScenarioTests` require a fully deployed service — never run them locally or in agent verification.
Loading