From a2607efc2220f9d359784016316b8baffa76827a Mon Sep 17 00:00:00 2001 From: Ernie3 Date: Sun, 18 Oct 2026 22:18:05 -0400 Subject: [PATCH 1/3] Add CI, Cursor cloud environment, and test toolchain GitHub Actions build on main PRs, README badge, .cursor/environment.json for Cloud Agents, and Java 17 Gradle test launcher for WPILib JNI. Co-authored-by: Cursor --- .cursor/cloud-install.sh | 7 +++++++ .cursor/environment.json | 3 +++ .github/workflows/ci.yml | 27 +++++++++++++++++++++++++++ README.md | 3 +++ build.gradle | 4 ++++ settings.gradle | 9 ++++++++- 6 files changed, 52 insertions(+), 1 deletion(-) create mode 100644 .cursor/cloud-install.sh create mode 100644 .cursor/environment.json create mode 100644 .github/workflows/ci.yml diff --git a/.cursor/cloud-install.sh b/.cursor/cloud-install.sh new file mode 100644 index 0000000..5cc31db --- /dev/null +++ b/.cursor/cloud-install.sh @@ -0,0 +1,7 @@ +#!/usr/bin/env bash +# Cloud agent Build: prepare Demonator15 (idempotent — safe on every Build). +set -euo pipefail +cd "$(dirname "$0")/.." +chmod +x gradlew +# Unit tests use Java 17 via Gradle toolchain (build.gradle). Full roboRIO cross-build runs in GitHub Actions CI. +./gradlew test --no-daemon diff --git a/.cursor/environment.json b/.cursor/environment.json new file mode 100644 index 0000000..327dc10 --- /dev/null +++ b/.cursor/environment.json @@ -0,0 +1,3 @@ +{ + "install": "bash .cursor/cloud-install.sh" +} diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..dd17bee --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,27 @@ +# Builds robot code and runs unit tests on push/PR to main. +# https://docs.wpilib.org/en/stable/docs/software/advanced-gradlerio/robot-code-ci.html +name: CI + +on: + push: + branches: [main] + pull_request: + branches: [main] + +jobs: + build: + runs-on: ubuntu-22.04 + # 2025 image is correct for 2026 per WPILib CI docs (JDK + roboRIO toolchains unchanged). + container: wpilib/roborio-cross-ubuntu:2025-22.04 + + steps: + - uses: actions/checkout@v6 + + - name: Add repository to git safe directories + run: git config --global --add safe.directory $GITHUB_WORKSPACE + + - name: Grant execute permission for gradlew + run: chmod +x gradlew + + - name: Compile and run tests on robot code + run: ./gradlew build diff --git a/README.md b/README.md index bc2e98e..21971b2 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,5 @@ # Demonator15 + +[![CI](https://github.com/KHS-Robotics/Demonator15/actions/workflows/ci.yml/badge.svg)](https://github.com/KHS-Robotics/Demonator15/actions/workflows/ci.yml) + Code repository for Demon Robotics' 2026 robot diff --git a/build.gradle b/build.gradle index f55c06c..eb2e7a5 100644 --- a/build.gradle +++ b/build.gradle @@ -78,6 +78,10 @@ dependencies { test { useJUnitPlatform() systemProperty 'junit.jupiter.extensions.autodetection.enabled', 'true' + // WPILib vendor JNI is validated on Java 17 (WPILib installer JDK). + javaLauncher = javaToolchains.launcherFor { + languageVersion = JavaLanguageVersion.of(17) + } } // Simulation configuration (e.g. environment variables). diff --git a/settings.gradle b/settings.gradle index 25f6f6e..88d7e3e 100644 --- a/settings.gradle +++ b/settings.gradle @@ -2,8 +2,8 @@ import org.gradle.internal.os.OperatingSystem pluginManagement { repositories { - mavenLocal() gradlePluginPortal() + mavenLocal() String frcYear = '2026' File frcHome if (OperatingSystem.current().isWindows()) { @@ -24,6 +24,13 @@ pluginManagement { url = frcHomeMaven } } + plugins { + id "org.gradle.toolchains.foojay-resolver-convention" version "0.9.0" + } +} + +plugins { + id "org.gradle.toolchains.foojay-resolver-convention" } Properties props = System.getProperties(); From 4dfde30ec9eceaf7b72bab7b77e3cd9d7d870de1 Mon Sep 17 00:00:00 2001 From: Ernie3 Date: Sun, 18 Oct 2026 22:32:42 -0400 Subject: [PATCH 2/3] Add Cursor rules and AGENTS.md for FRC workflow Project-wide and file-scoped rules for command-based structure, tests, and cloud agent build instructions. Co-authored-by: Cursor --- .cursor/rules/frc-commands-subsystems.mdc | 20 ++++++++++++++++++ .cursor/rules/frc-project.mdc | 13 ++++++++++++ .cursor/rules/frc-unit-tests.mdc | 13 ++++++++++++ AGENTS.md | 25 +++++++++++++++++++++++ 4 files changed, 71 insertions(+) create mode 100644 .cursor/rules/frc-commands-subsystems.mdc create mode 100644 .cursor/rules/frc-project.mdc create mode 100644 .cursor/rules/frc-unit-tests.mdc create mode 100644 AGENTS.md diff --git a/.cursor/rules/frc-commands-subsystems.mdc b/.cursor/rules/frc-commands-subsystems.mdc new file mode 100644 index 0000000..f17024f --- /dev/null +++ b/.cursor/rules/frc-commands-subsystems.mdc @@ -0,0 +1,20 @@ +--- +description: Command-based structure for FRC robot Java +globs: src/main/java/**/*.java +alwaysApply: false +--- + +# Subsystems vs commands + +- **Subsystems** (`subsystems/**`): hardware, `periodic()`, pose/closed-loop APIs (`drive()`, `stop()`, setpoints). No Xbox bindings or `Command` factories on subsystems when avoidable — use `commands/**` factories (e.g. `DriveCommands`). +- **RobotContainer:** wire default commands, triggers, and `NamedCommands.registerCommand` only; keep binding logic thin. +- **Commands:** use `run` / `runOnce` / `runEnd` / `Commands.sequence` with subsystem requirements. Name commands with `.withName(...)` for Shuffleboard and debugging. +- **Constants:** season field poses and practice coordinates in `constants/FieldConstants`, not buried in subsystems. +- **Autos:** PathPlanner uses `SwerveDrive` via `AutoBuilder` (pose, reset, chassis speeds). Do not break those method signatures without updating PathPlanner integration. + +```java +// Prefer: factory in commands/, subsystem API stays imperative +DriveCommands.driveWithXboxController(swerve, controller, () -> true, deadband, sensitivity); + +// Avoid: long teleop runEnd blocks inside SwerveDrive +``` diff --git a/.cursor/rules/frc-project.mdc b/.cursor/rules/frc-project.mdc new file mode 100644 index 0000000..71c29d8 --- /dev/null +++ b/.cursor/rules/frc-project.mdc @@ -0,0 +1,13 @@ +--- +description: Demonator15 FRC repo conventions (WPILib, Gradle, CI, safety) +alwaysApply: true +--- + +# Demonator15 — project + +- **Stack:** WPILib 2026, GradleRIO, Java **17** for compile and tests. Run `./gradlew test` or `./gradlew build` (CI uses the WPILib cross container). +- **Layout:** `src/main/java/frc/robot/` — `Robot`, `RobotContainer`, `subsystems/`, `commands/`, `constants/`, `hid/`, `util/`. CAN IDs in `RobotMap`; mechanism tuning in subsystem `*Config` classes. +- **Scope:** Prefer small, reviewable diffs. Do not refactor unrelated subsystems in the same change unless asked. +- **Secrets:** Never commit API keys, tokens, or `.env`. Use Cursor/GitHub secrets for cloud only when needed. +- **PathPlanner:** Autos and paths live under `src/main/deploy/pathplanner/`. Named command strings in Java must **exactly** match the PathPlanner GUI. +- **Docs:** [WPILib command-based](https://docs.wpilib.org/en/stable/docs/software/commandbased/index.html), [GradleRIO CI](https://docs.wpilib.org/en/stable/docs/software/advanced-gradlerio/robot-code-ci.html). diff --git a/.cursor/rules/frc-unit-tests.mdc b/.cursor/rules/frc-unit-tests.mdc new file mode 100644 index 0000000..9c76fb5 --- /dev/null +++ b/.cursor/rules/frc-unit-tests.mdc @@ -0,0 +1,13 @@ +--- +description: JUnit and WPILib simulation tests for robot code +globs: src/test/**/*.java +alwaysApply: false +--- + +# Unit tests + +- **Runner:** JUnit 5 (`org.junit.jupiter`). Use **Arrange / Act / Assert** comments in non-trivial tests. +- **Pure logic:** test helpers and math without HAL (`SwerveDynamics`, `SwerveModuleOptimization`, `SwerveTeleopInputs` package helpers, `AngleUtils`, `HIDUtils`). +- **HAL / vendor sim:** `@ExtendWith(WpilibSimulationExtension.class)` for Xbox sim, SparkMaxSim, etc. Use isolated CAN IDs in tests; call `SwerveModule.close()` in `@AfterEach` when constructing real modules. +- **Do not** instantiate full `Robot` or `SwerveDrive` in unit tests unless building a dedicated test fixture — prefer testing extracted pure functions. +- After changes, run `./gradlew test` (Java 17 toolchain from `build.gradle`). diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..c64fbd6 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,25 @@ +# Agent instructions (Demonator15) + +## Build and verify + +```bash +chmod +x gradlew +./gradlew test # local / Cursor Cloud install script +./gradlew build # full compile + tests (matches GitHub Actions CI) +``` + +Cloud environment config: `.cursor/environment.json` (runs `cloud-install.sh` → `./gradlew test`). + +## Architecture + +- WPILib **command-based** robot. Subsystems own hardware; `frc.robot.commands` holds command factories; `RobotContainer` binds controls and PathPlanner **named commands**. +- Swerve: `subsystems/drive/`, teleop commands in `commands/drive/` when present on branch. + +## Cursor rules + +See `.cursor/rules/*.mdc` for FRC-specific conventions. + +## PR expectations + +- Keep robot behavior changes scoped and describe driver/auto impact in the PR. +- Ensure CI (`build`) passes before merge. From 761f8cab1ac1539c95caa03a48ce8e73ceacf97d Mon Sep 17 00:00:00 2001 From: Ernie3 Date: Sun, 18 Oct 2026 22:39:13 -0400 Subject: [PATCH 3/3] Use UTF-8 encoding for Java compile in CI Set JavaCompile encoding and CI locale so Unicode in source comments does not fail javac on Linux US-ASCII defaults. Co-authored-by: Cursor --- .github/workflows/ci.yml | 3 +++ build.gradle | 5 +++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index dd17bee..2150ab3 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -13,6 +13,9 @@ jobs: runs-on: ubuntu-22.04 # 2025 image is correct for 2026 per WPILib CI docs (JDK + roboRIO toolchains unchanged). container: wpilib/roborio-cross-ubuntu:2025-22.04 + env: + LANG: C.UTF-8 + JAVA_TOOL_OPTIONS: -Dfile.encoding=UTF-8 steps: - uses: actions/checkout@v6 diff --git a/build.gradle b/build.gradle index eb2e7a5..def5be0 100644 --- a/build.gradle +++ b/build.gradle @@ -105,7 +105,8 @@ deployArtifact.jarTask = jar wpi.java.configureExecutableTasks(jar) wpi.java.configureTestTasks(test) -// Configure string concat to always inline compile -tasks.withType(JavaCompile) { +// Configure string concat to always inline compile; UTF-8 for CI/Linux (US-ASCII breaks on Unicode in comments). +tasks.withType(JavaCompile).configureEach { + options.encoding = 'UTF-8' options.compilerArgs.add '-XDstringConcat=inline' }