JamReady is a free roller derby jam timer app with local and remote scoreboard-compatible modes.
Sports & fitnessDart · ShellGitHub @tanzoniteblackOnlineOwner unconfirmed
Have you tried it? One tap is enough. No sign-in needed.
Owners of public repositories under a personal GitHub account can sign in to verify ownership and manage the introduction themselves. No administrator approval is needed.
Sign in, generate a verification file, and commit it to this repository’s default branch within 30 minutes. Files on other branches or forks do not count. Then check the file below to manage the project without administrator approval. Keep the file to retain your access.
If needed, you will go to sign-in. After signing in, return here and press your chosen verification button again.
Run /nomorevibe verify in your project folder to verify ownership and manage the introduction yourself.
Verify in one minuteAsk about other verification options
Roller Derby Jam Timer
Translation pending
Loading the full README.
Read the full README ↗JamReady is a Flutter app for managing a Roller Derby jam timer. It supports both standalone (offline) mode and remote mode, where it connects to a CRG Derby Scoreboard instance over WebSocket and acts as a remote control.
Verify your environment:
flutter doctor
flutter pub get --enforce-lockfile
List connected devices:
flutter devices
Run on a device:
flutter run -d <device-id>
make unit # unit and widget tests (no device required)
make integration # offline integration test (requires a connected device or emulator)
make test # both of the above
The scoreboard tests connect to a real CRG scoreboard over WebSocket and verify compatibility across multiple versions. They require Docker and git (the scoreboard build runs entirely inside Docker — no local JDK or Ant needed).
Build the scoreboard images once before running either suite. You can build every supported version or select specific versions:
make build-scoreboards
./scripts/build-scoreboard-images.sh --versions v2025.9,v2025.8
The source for each scoreboard version is cloned and compiled inside a multi-stage Docker build (scripts/scoreboard.Dockerfile).
Run both suites and create one version-first Allure report:
./scripts/test-scoreboards.sh --jobs 4 --emulator-jobs 2
--jobs controls headless remote-engine workers. --emulator-jobs is independently capped at the number of running Android emulators, so it cannot overcommit devices. The coordinator runs the headless suite first, then the emulator suite, and writes one report to test-results/scoreboards-<timestamp>-<pid>/allure-report/index.html.
The fast suite exercises RemoteGameEngine and ScoreboardState directly, without building the app or launching an emulator. Local runs can fan out versions across independent Flutter workers; each worker uses an isolated copy of the current checkout, so uncommitted changes are included and concurrent Flutter builds do not share build/ or .dart_tool/.
./scripts/test-remote-engine-scoreboards.sh
./scripts/test-remote-engine-scoreboards.sh --versions v2025.9,v2025.8
./scripts/test-remote-engine-scoreboards.sh --jobs 2
Useful options:
--versions Comma-separated list of versions to test
--host Host address the tests connect to (default: 127.0.0.1)
--port First Docker host port to try (default: 8001)
--jobs Versions to run concurrently locally (default: 1)
--results-dir Parent directory for local reports (default: test-results)
--no-html Leave raw Allure result files without generating HTML
The runner finds an available Docker port for each worker, including a retry if Docker loses a port-binding race. A local run writes logs and raw Allure results to test-results/remote-engine-<timestamp>-<pid>/, plus a self-contained report at allure-report/index.html that can be opened directly from Finder. Report generation uses npx -y allure@3, so it requires Node.js 20+; use --no-html to skip it.
Arguments after -- are passed to flutter test. GitHub Actions continues to emit its existing per-version JSON files for the GitHub test reporter.
The UI-driven suite builds and controls the Flutter app on Android emulators. When several emulators are already running, it fans versions out across them; each concurrent worker uses an isolated copy of the current checkout, an independent Docker port, and a distinct Docker container. If no emulator is running, the script starts one and runs sequentially.
make test-scoreboards
./scripts/test-all-scoreboards.sh --versions v2025.9,v2025.8
./scripts/test-all-scoreboards.sh --jobs 2
Useful options:
--versions Comma-separated list of versions to test
--avd AVD name (default: first from `emulator -list-avds`)
--host Host address the tests connect to (default: 10.0.2.2)
--port First Docker host port to try (default: 8001)
--jobs Maximum emulator workers to use (default: all running emulators)
--results-dir Parent directory for local reports (default: test-results)
--no-html Leave raw Allure result files without generating HTML
--jobs is capped at the number of available emulators (and test versions), so asking for more never starts extra emulators. The runner selects an available Docker port for each worker and retries after a binding race. It writes logs and raw Allure results to test-results/scoreboard-integration-<timestamp>-<pid>/, plus a self-contained report at allure-report/index.html when Node.js 20+ is available.
Arguments after -- are passed to flutter test.
The main CI workflow runs static analysis and unit/widget tests on pushes and pull requests to main. Test results are uploaded as JSON artifacts and published as a GitHub Check. Pull requests also run the headless remote-engine suite as a matrix across the supported CRG scoreboard versions, with a separate artifact and check for each version.
The release script handles versioning, changelog generation, and tagging. It requires the claude CLI to generate the changelog.
./scripts/release.sh
It will ask whether this is a stable or pre-release, which version component to bump, and (for pre-releases) a suffix like rc1 or beta1. It then generates a changelog from commits since the last release using Claude, shows it for confirmation, commits the version bump to pubspec.yaml, creates an annotated git tag, and offers to push. Pushing the tag triggers the GitHub Actions release workflow, which publishes a GitHub release with the changelog as the release notes.
The GitHub release contains release notes only — store builds must be created and uploaded manually using make release, which runs all tests (including scoreboard compatibility tests) and then builds both artifacts:
make release
This requires:
android/key.properties pointing to your upload keystore (not checked in) for the Android build:
storeFile=/path/to/upload-keystore.jks
storePassword=...
keyAlias=upload
keyPassword=...
Once built, upload the artifacts via their respective consoles:
build/app/outputs/bundle/release/app-release.aab → Play Consolebuild/ios/ipa/*.ipa → Xcode Organizer or xcrun altoolflutter analyze
lib/ app source (screens, widgets, models, services)
test/ unit and widget tests
integration_test/ integration tests (run separately)
remote_engine_test/ headless CRG scoreboard compatibility tests
assets/ app assets
scripts/ build and test utilities