Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
66195d2
Add comprehensive documentation for GateMonitor project, including ar…
erenken Jul 9, 2026
5d8a1c5
Modernize repo: add Blazor/.NET, CI/CD, docs, tests
erenken Jul 9, 2026
f7cc39b
Add CI workflow for .NET and Angular build/test
erenken Jul 9, 2026
a728fec
Merge origin/main: Angular 22 upgrade + agent files
erenken Jul 9, 2026
cbd6855
Update documentation for Angular 22 and new folder structure
erenken Jul 9, 2026
6657a0f
Potential fix for pull request finding 'CodeQL / Workflow does not co…
erenken Jul 9, 2026
148eb4b
Potential fix for pull request finding 'CodeQL / Workflow does not co…
erenken Jul 9, 2026
fe5471d
Potential fix for pull request finding 'CodeQL / Workflow does not co…
erenken Jul 9, 2026
e88d6b0
Fix PR workflow and add branch protection guide
erenken Jul 9, 2026
1e40099
Fix shallow clone issue for GitVersion
erenken Jul 9, 2026
bd3958f
Fix Node.js version in CI workflows for Angular CLI 22 compatibility
Copilot Jul 9, 2026
2a0d459
Set fetch-depth: 0 for all checkout steps in release CI
erenken Jul 9, 2026
7f8d1cb
Update Node.js to v24 in build and release workflows
erenken Jul 9, 2026
f3b9659
Fix Angular workflows to build library before app
erenken Jul 9, 2026
0e2ca70
Fix HomeComponent test by mocking RemootioAngularService
erenken Jul 9, 2026
451ba01
test: fix Angular component specs for CI
Copilot Jul 9, 2026
ed96cd8
Fix HomeComponent test with Material modules for PR #13
erenken Jul 9, 2026
47e7023
Add missing test imports and declarations for specs
erenken Jul 9, 2026
c3b1178
Remove duplicate declarations property in HomeComponent test
erenken Jul 9, 2026
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
135 changes: 135 additions & 0 deletions .github/BRANCH_PROTECTION.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
# Branch Protection Setup Guide

This guide explains how to configure GitHub branch protection rules to ensure PRs can't be merged until all checks pass.

## Quick Setup

1. **Go to your repository on GitHub**
- Navigate to: https://github.com/erenken/gateMonitor

2. **Open Settings**
- Click on **Settings** tab
- In the left sidebar, click **Branches** (under "Code and automation")

3. **Add Branch Protection Rule**
- Click **Add rule** or **Add branch protection rule**

4. **Configure the Rule**

**Branch name pattern:**
```
main
```

**Check these options:**
- ☑️ **Require a pull request before merging**
- ☑️ Require approvals: `1` (if you want review)
- ☑️ Dismiss stale pull request approvals when new commits are pushed

- ☑️ **Require status checks to pass before merging**
- ☑️ Require branches to be up to date before merging
- **Add required status checks:**
1. Type: `.NET Build & Test`
2. Type: `Angular Build & Test`
3. Type: `All Checks Passed`

> **Note**: These checks will only appear after you've run the workflow at least once. Push your current changes first, then come back to add these checks.

- ☑️ **Require conversation resolution before merging** (optional but recommended)

- ☑️ **Do not allow bypassing the above settings** (if you want strict enforcement)

5. **Save the Rule**
- Scroll to the bottom and click **Create** or **Save changes**

## What This Does

With branch protection enabled:
- ❌ **Can't merge** if `.NET Build & Test` fails
- ❌ **Can't merge** if `Angular Build & Test` fails
- ❌ **Can't merge** if `All Checks Passed` fails
- ✅ **Can merge** only when all checks are green

## Workflow Checks Explained

### .NET Build & Test
- Builds the .NET solution (`dotnet/GateMonitor.slnx`)
- Runs all unit tests
- Publishes test results

### Angular Build & Test
- Installs npm dependencies
- Builds the Angular app and library
- Runs Karma/Jasmine tests in headless Chrome
- Runs ESLint (non-blocking)

### All Checks Passed
- Final status check that verifies both jobs succeeded
- This is the single check you can use for branch protection if you prefer

## Testing Your Setup

1. **Push changes** to trigger the workflow:
```bash
git push origin work/vibeItUp
```

2. **Create a PR** to `main`:
- Go to GitHub and create a pull request
- You'll see the checks running

3. **Add required checks** (after first run):
- Go back to Settings → Branches → Edit rule
- The status checks will now be available in the dropdown

## Troubleshooting

### Check not appearing in the dropdown?
- Make sure the workflow has run at least once
- The check name must match exactly (case-sensitive)
- Wait a few minutes for GitHub to index the checks

### Checks failing?
- Click "Details" next to the failing check
- Review the logs to see what failed
- Common issues:
- Missing dependencies
- Test failures
- Build errors
- Linting issues

### Need to bypass temporarily?
- If you're an admin, you can temporarily disable the rule
- Or add "Allow administrators to bypass" in the settings
- **Not recommended** for production branches

## GitHub CLI Alternative

If you prefer command-line setup:

```bash
# Install GitHub CLI: https://cli.github.com/

# Create branch protection rule
gh api repos/erenken/gateMonitor/branches/main/protection \
--method PUT \
--field required_status_checks[strict]=true \
--field required_status_checks[contexts][]=".NET Build & Test" \
--field required_status_checks[contexts][]="Angular Build & Test" \
--field required_status_checks[contexts][]="All Checks Passed" \
--field enforce_admins=true \
--field required_pull_request_reviews[required_approving_review_count]=0
```

## Additional Security (Optional)

Consider also enabling:
- **Require signed commits** - Ensures commit authenticity
- **Require deployments to succeed** - If you have deployment checks
- **Restrict who can push** - Limit direct pushes to certain teams/users
- **Require linear history** - Enforces rebase or squash merges

## Learn More

- [GitHub Branch Protection Documentation](https://docs.github.com/en/repositories/configuring-branches-and-merges-in-your-repository/managing-protected-branches/about-protected-branches)
- [Status Checks](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/collaborating-on-repositories-with-code-quality-features/about-status-checks)
51 changes: 51 additions & 0 deletions .github/agents/dotnet-specialist.agent.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
---
name: GateMonitor .NET Specialist
description: "Use when working on the Blazor WASM dashboard, myNOC.Remootio library, Aspire AppHost, .NET unit tests, NuGet packaging, or the dotnet-build/dotnet-release CI pipelines."
tools: [read, edit, search, execute, todo]
model: "GPT-5 (copilot)"
---
You are the .NET specialist for the GateMonitor repository.

Your focus is the `dotnet/` subtree: the Blazor WASM app, the myNOC.Remootio library, the Aspire AppHost, and the GitHub Actions CI/CD pipelines.

## Primary Responsibilities

1. **Enforce architecture boundaries:**
- `myNOC.Remootio` — pure .NET library; no Blazor/UI dependencies allowed
- `GateMonitor.Blazor` — UI only; consumes `IRemootioService` via DI, never internal types
- `GateMonitor.AppHost` — Aspire orchestrator; no business logic

2. **Keep the library NuGet-publishable:**
- Targets `net8.0;net10.0` (drop EOL versions when needed)
- `GitVersion.MsBuild` sets versions from git tags
- `README.md` and `LICENSE.txt` bundled into the package
- `SourceLink` enabled for debugger source-stepping

3. **Keep Blazor WASM patterns correct:**
- Always use `await InvokeAsync(StateHasChanged)` from event handlers
- Dispose event subscriptions in `IDisposable.Dispose()`
- Config from `wwwroot/appsettings.json` — no secrets committed

4. **Maintain test coverage:**
- `myNOC.Tests.Remootio` — MSTest + NSubstitute, matches library TFMs
- `GateMonitor.Tests.Blazor` — MSTest + bUnit + NSubstitute, net10.0 only
- Tests run in `dotnet-build.yml` on every PR

## Working Rules

- Do not commit real Remootio API keys or device IPs.
- Prefer small targeted edits; avoid broad refactors unless requested.
- Keep `IRemootioService` public API backward-compatible unless explicitly changing it.
- Use NSubstitute (not Moq) for mocking — consistent with sibling project myNOC.WeatherLink.
- Validate changes with `dotnet build GateMonitor.slnx` and `dotnet test GateMonitor.slnx`.

## Key Files

| File | Purpose |
|------|---------|
| `dotnet/myNOC.Remootio/RemootioService.cs` | Hosted service — connection lifecycle |
| `dotnet/myNOC.Remootio/RemootioDevice.cs` | WebSocket client + protocol |
| `dotnet/myNOC.Remootio/RemootioApiCrypto.cs` | AES-CBC + HMAC-SHA256 (internal) |
| `dotnet/GateMonitor.Blazor/Components/Pages/Home.razor` | Main dashboard component |
| `dotnet/GateMonitor.AppHost/AppHost.cs` | Aspire resource declarations |
| `.github/workflows/dotnet-release.yml` | Release pipeline (NuGet + NPM + tag) |
25 changes: 17 additions & 8 deletions .github/agents/gatemonitor-specialist.agent.md
Original file line number Diff line number Diff line change
@@ -1,19 +1,19 @@
---
name: GateMonitor Specialist
description: "Use when working on the GateMonitor Angular app, remootio-angular subproject, gate state UI behavior, gate open/close control logic, or Remootio service integration."
description: "Use when working on the GateMonitor Angular app, remootio-angular subproject, gate state UI behavior, gate open/close control logic, or Remootio service integration. For .NET/Blazor/Aspire work use the GateMonitor .NET Specialist agent instead."
tools: [read, edit, search, execute, todo]
model: "GPT-5 (copilot)"
---
You are the GateMonitor project specialist for this repository.
You are the GateMonitor Angular project specialist for this repository.

Your focus is to keep the project understandable and stable while improving either:
- Main app UX and behavior in src/
- Remootio control library behavior in projects/remootio-angular/
Your focus is the `angular/` subtree: the Angular dashboard app and the `remootio-angular` Angular library.

> For work in `dotnet/` (Blazor, myNOC.Remootio, Aspire, CI pipelines) use the **GateMonitor .NET Specialist** agent instead.

## Primary Responsibilities
1. Preserve the architecture boundary:
- UI and page interactions in src/
- Device protocol and control orchestration in projects/remootio-angular/
- UI and page interactions → `angular/src/`
- Device protocol and control orchestration → `angular/projects/remootio-angular/`

2. Keep gate control behavior explicit and safe:
- Open/Close actions should remain obvious and predictable.
Expand All @@ -26,7 +26,16 @@ Your focus is to keep the project understandable and stable while improving eith
- Do not hardcode real credentials, keys, or endpoint secrets.
- Prefer small, targeted edits over broad refactors.
- Keep public library interfaces backward compatible unless asked to change them.
- Validate changes with tests when practical.
- Validate changes with tests when practical (`npm test` in `angular/`).

## Key Files

| File | Purpose |
|------|---------|
| `angular/src/app/pages/home/home.component.ts` | Main dashboard — gate state subscriptions |
| `angular/projects/remootio-angular/src/lib/services/remootio-angular.service.ts` | Angular service |
| `angular/projects/remootio-angular/src/lib/services/remootioDevice.ts` | WebSocket client |
| `angular/projects/remootio-angular/src/lib/services/remootioInterfaces.ts` | Shared types |

## Decision Heuristics
- If change request is UI-only, edit app component/template/style files under src/.
Expand Down
72 changes: 48 additions & 24 deletions .github/copilot-instructions.md
Original file line number Diff line number Diff line change
@@ -1,50 +1,74 @@
# Copilot Instructions For GateMonitor

## Purpose
This repository contains:
- A main Angular dashboard app (gate status + image + open/close controls).
- A reusable Angular library subproject for Remootio device communication and gate control.

This repository contains two equivalent front-end dashboards for a Remootio-controlled driveway gate, plus a shared .NET library:

| Subtree | Stack | Description |
|---------|-------|-------------|
| `angular/` | Angular 22 + RxJS | Original dashboard + remootio-angular NPM library |
| `dotnet/GateMonitor.Blazor` | Blazor WASM (.NET 10) | Blazor equivalent dashboard |
| `dotnet/myNOC.Remootio` | .NET 8/10 library | Remootio protocol → NuGet: myNOC.Remootio |
| `dotnet/GateMonitor.AppHost` | .NET Aspire | Dev orchestrator for the Blazor app |

## Project Intent
Generate changes that keep the app simple, reliable, and local-control focused:

- Show accurate gate state quickly.
- Keep control actions explicit and safe.
- Keep device communication details inside the remootio-angular library.
- Keep device communication details inside the libraries (not in UI components).
- Both front-ends connect directly from the browser to the Remootio WebSocket.

## Architecture Boundaries
- UI and page behavior belong in src/.
- Remootio protocol/device communication belongs in projects/remootio-angular/.
- Shared types for gate/device state should come from remootioInterfaces.ts.

Do not move low-level protocol logic into app components.
**Angular (`angular/`):**
- UI and page behavior → `src/`
- Remootio protocol/device communication → `projects/remootio-angular/`
- Shared types → `remootioInterfaces.ts`

**Blazor / .NET (`dotnet/`):**
- UI and components → `GateMonitor.Blazor/Components/`
- Remootio protocol, crypto, WebSocket → `myNOC.Remootio/` library only
- `IRemootioService` is the only public interface components should use
- `GateMonitor.AppHost` → Aspire orchestration only, no business logic

Do not move low-level protocol logic into UI components in either codebase.

## Coding Preferences
- Use Angular and RxJS idioms already present in the repo.
- Keep methods and changes small and readable.

- Angular: use Angular and RxJS idioms already present in the repo.
- Blazor: use `await InvokeAsync(StateHasChanged)` for thread-safe UI updates; dispose event subscriptions.
- Keep methods small and readable.
- Avoid broad refactors unless requested.
- Keep naming aligned with existing gate terminology (gateState, openGate, closeGate).
- Keep naming aligned with gate terminology: `gateState`, `openGate`, `closeGate`, `IsOpen`, `Description`.

## Configuration and Secrets
- Never hardcode real credentials.
- If adding config, prefer environment-based patterns.
- Preserve existing placeholder-driven setup unless asked to redesign configuration.

- Never hardcode real credentials (`deviceIp`, `apiSecretKey`, `apiAuthKey`).
- Angular: placeholders in `home.component.ts`.
- Blazor: placeholders in `wwwroot/appsettings.json`; use `appsettings.Development.json` for real values locally.

## Testing and Validation
When making changes, prefer validating with:
- Existing unit tests (npm test).
- Targeted checks for gate state flow and UI enable/disable logic.

- Angular: `npm test` in `angular/`
- .NET: `dotnet test dotnet/GateMonitor.slnx`
- Both run automatically in `pr-build-test.yml` on PRs.

## Documentation Expectations

If behavior changes, update:
- README.md (main app behavior/setup)
- projects/remootio-angular/README.md (library usage/API)
- `README.md` (repo overview)
- `angular/README.md` (Angular dashboard)
- `angular/projects/remootio-angular/README.md` (Angular library)
- `dotnet/myNOC.Remootio/README.md` (.NET library)

## Common Tasks
- UI improvements: update home component and templates/styles.
- Device control behavior: update remootio-angular service and related models.
- API surface changes: update public-api.ts and both READMEs.
## Agent Guidance

- **Angular UI / remootio-angular**: use the **GateMonitor Specialist** agent.
- **Blazor / myNOC.Remootio / Aspire / CI pipelines**: use the **GateMonitor .NET Specialist** agent.

## Out of Scope Unless Requested

- Replacing Remootio transport/protocol approach.
- Migrating framework versions.
- Large design-system or architecture rewrites.

59 changes: 59 additions & 0 deletions .github/instructions/dotnet-architecture.instructions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
---
applyTo: "dotnet/**"
---

# .NET Architecture — GateMonitor

## Solution Layout

```
dotnet/
├── GateMonitor.AppHost/ Aspire orchestrator — dev entry point
├── GateMonitor.Blazor/ Blazor WASM SPA — Components/, wwwroot/
├── myNOC.Remootio/ .NET library → NuGet package
└── tests/
├── myNOC.Tests.Remootio/ MSTest + NSubstitute — library unit tests
└── GateMonitor.Tests.Blazor/ MSTest + bUnit + NSubstitute — component tests
```

## Architecture Boundaries

- **`myNOC.Remootio`** owns ALL Remootio protocol logic: WebSocket lifecycle, AES-CBC/HMAC-SHA256 crypto, authentication flow, gate state mapping.
- Public surface: `IRemootioService`, `RemootioService`, `GateState`, `RemootioDeviceConfig`
- Internal: `RemootioDevice`, `RemootioApiCrypto` (exposed to test project via InternalsVisibleTo)
- Do NOT add Blazor/UI dependencies here — it must remain a pure .NET library.

- **`GateMonitor.Blazor`** owns the UI: Razor components, wwwroot static assets, and `Program.cs`.
- Consumes `IRemootioService` via DI injection — never references `RemootioDevice` or `RemootioApiCrypto` directly.
- Config is read from `wwwroot/appsettings.json` (public, no secrets at rest).

- **`GateMonitor.AppHost`** is the Aspire orchestrator for local development only.
- References `GateMonitor.Blazor` as an Aspire project resource.
- No business logic here — only resource declarations.

## Blazor Component Patterns

- Components use `@inject IRemootioService` and `@inject IConfiguration` — no direct `RemootioService` references.
- Subscribe to `GateStateChanged` / `ConnectionChanged` events in `OnInitialized`, unsubscribe in `Dispose()`.
- Always call `await InvokeAsync(StateHasChanged)` from event handlers (thread-safe UI updates).
- Gate image refresh uses `System.Timers.Timer` started only when `GateImageUrl` is non-empty.

## Library Versioning

- `myNOC.Remootio` uses `GitVersion.MsBuild` with `GitHubFlow/v1` workflow.
- Targets `net8.0` and `net10.0` (net9.0 removed — EOL May 2026).
- `GeneratePackageOnBuild` is `false` — pack explicitly via `dotnet pack` or the release pipeline.

## Testing

- Library tests target the same TFMs as the library (`net8.0;net10.0`).
- Component tests target `net10.0` only.
- `bUnit.TestContext` aliased as `BunitContext` to avoid ambiguity with `MSTest.TestContext`.
- `System.Timers.Timer` is not started in tests because `GateImageUrl` is set to empty string in test setup.
- Use `NSubstitute` for mocking (not Moq) — consistent with the WeatherLink sibling project.

## Secrets

- Never commit real `DeviceIp`, `ApiSecretKey`, or `ApiAuthKey` values.
- Use `appsettings.Development.json` (git-ignored) for local overrides.
- The release pipeline uses `NUGET_PUBLISH` and `npm_token` repository secrets.
Loading
Loading