Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
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
16 changes: 13 additions & 3 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,18 @@ jobs:

- uses: actions/setup-node@v4
with:
node-version: 20
node-version: 24
cache: 'npm'
cache-dependency-path: |
frontend/package-lock.json
api/package-lock.json
worker/package-lock.json

- name: Install Flutter
uses: subosito/flutter-action@v2
with:
channel: stable

- run: ./scripts/lint.sh

build:
Expand All @@ -31,7 +36,7 @@ jobs:

- uses: actions/setup-node@v4
with:
node-version: 20
node-version: 24
cache: 'npm'
cache-dependency-path: |
frontend/package-lock.json
Expand All @@ -55,13 +60,18 @@ jobs:

- uses: actions/setup-node@v4
with:
node-version: 20
node-version: 24
cache: 'npm'
cache-dependency-path: |
frontend/package-lock.json
api/package-lock.json
worker/package-lock.json

- name: Install Flutter
uses: subosito/flutter-action@v2
with:
channel: stable

- run: ./scripts/test.sh

release-scripts:
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ jobs:
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
node-version: '24'
cache: 'npm'
cache-dependency-path: frontend/package-lock.json

Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/provision-worker.yml
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ jobs:
- name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version: 20
node-version: 24

- name: Install root dependencies
run: npm ci
Expand Down
2 changes: 2 additions & 0 deletions .jules/forge.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,5 @@
- **[2026-06-15]**: Removed obsolete Python/`uv` tooling from `AGENTS.md` as the project is now fully Node.js. Identified a gap where `worker` build checks were missing from `.github/workflows/ci.yml`. Added a `worker` job to `ci.yml` to run `npm ci` and `npm run build`, ensuring type safety and parity with `AGENTS.md` intent.
- **[2026-04-08]**: Updated `google-github-actions/auth` from v2 to v3 in `provision-worker.yml` to prevent deprecation issues. Extracted inline YAML scripts for Doppler secrets, Forge version resolution, worker notifications, and worker host config into reusable `scripts/` to enforce execution parity and Kickstart principles. Refined `AGENTS.md` to expose CI parity scripts (`./scripts/test.sh`, etc.) alongside targeted commands.
- **[2026-04-11]**: Updated `google-github-actions/auth` from v2 to v3 in `rollout-safety-net.yml` to prevent deprecation issues. Extracted inline YAML scripts for rollout safety net polling, setting image names, checking docker tags, and extracting GCP project IDs into reusable `scripts/` to enforce execution parity and Kickstart verification principles. Refined `scripts/run-analysis.js` to mitigate command injection risks by removing `shell: true` from `child_process.spawn`.
- **[2026-04-12]**: Resolved Dart SDK version conflict in `worker_flutter/pubspec.yaml` by downgrading `^3.11.5` to `^3.11.0` to match Flutter stable channel. Calibrated `scripts/lint.sh` and `scripts/test.sh` to include Flutter checks, and updated `.github/workflows/ci.yml` jobs with `subosito/flutter-action@v2` for pipeline parity. Updated `AGENTS.md` instructions.
- **[2026-06-03]**: Upgraded Node.js version from 20 to 24 in `.github/workflows` (ci.yml, deploy.yml, provision-worker.yml) and shared verification scripts (`scripts/lint.sh`, `scripts/build.sh`, `scripts/test.sh`) to resolve GitHub Actions deprecation failures. Updated `AGENTS.md` Tooling requirement to Node.js 24+. Fixed an unused import (`macos/activation_policy.dart`) in `worker_flutter/lib/main.dart` that caused Flutter lint failures.
5 changes: 4 additions & 1 deletion AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
- **Executable:** If it isn't an executable command or a hard constraint, it doesn't belong here.

## Tooling
- **Node.js**: 20+ (managed by `npm`)
- **Node.js**: 24+ (managed by `npm`)
- **Docker**: Required for simulation engine
- **Package Manager**: `npm` (Node)

Expand All @@ -29,6 +29,8 @@
- **Worker Install**: `cd worker && npm install`
- **Worker Dev**: `cd worker && npm run dev`
- **Worker Test**: `cd worker && npm run test:unit`
- **Worker Flutter Test**: `cd worker_flutter && flutter test`
- **Worker Flutter Lint**: `cd worker_flutter && flutter analyze --no-fatal-infos`

## Deployment
- **CI**: `.github/workflows/ci.yml` (Runs on PR)
Expand All @@ -38,3 +40,4 @@
- `frontend/`: React app
- `api/`: Next.js API, ingestion, and analysis
- `worker/`: Node.js + Docker simulation runner
- `worker_flutter/`: Cross-platform desktop worker (macOS/Windows)
2 changes: 1 addition & 1 deletion scripts/build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ set -euo pipefail
if command -v nvm &>/dev/null || [ -s "$HOME/.nvm/nvm.sh" ]; then
export NVM_DIR="${NVM_DIR:-$HOME/.nvm}"
[ -s "$NVM_DIR/nvm.sh" ] && . "$NVM_DIR/nvm.sh"
nvm install 20 && nvm use 20
nvm install 24 && nvm use 24
fi

# Frontend and worker builds in parallel (background)
Expand Down
6 changes: 5 additions & 1 deletion scripts/lint.sh
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ set -euo pipefail
if command -v nvm &>/dev/null || [ -s "$HOME/.nvm/nvm.sh" ]; then
export NVM_DIR="${NVM_DIR:-$HOME/.nvm}"
[ -s "$NVM_DIR/nvm.sh" ] && . "$NVM_DIR/nvm.sh"
nvm install 20 && nvm use 20
nvm install 24 && nvm use 24
fi

# Frontend
Expand All @@ -15,3 +15,7 @@ cd frontend && npm ci && npm run lint && cd ..
# API
echo "=== API lint ==="
cd api && npm ci && npm run lint && cd ..

# Worker Flutter
echo "=== Worker Flutter lint ==="
cd worker_flutter && flutter pub get && flutter analyze --no-fatal-infos && cd ..
6 changes: 5 additions & 1 deletion scripts/test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ set -euo pipefail
if command -v nvm &>/dev/null || [ -s "$HOME/.nvm/nvm.sh" ]; then
export NVM_DIR="${NVM_DIR:-$HOME/.nvm}"
[ -s "$NVM_DIR/nvm.sh" ] && . "$NVM_DIR/nvm.sh"
nvm install 20 && nvm use 20
nvm install 24 && nvm use 24
fi

# Frontend tests
Expand All @@ -22,3 +22,7 @@ npm run test:ingestion && cd ..
# Worker tests
echo "=== Worker unit tests ==="
cd worker && npm ci && npm run test:unit && cd ..

# Worker Flutter tests
echo "=== Worker Flutter tests ==="
cd worker_flutter && flutter pub get && flutter test && cd ..
3 changes: 2 additions & 1 deletion worker_flutter/lib/auth/desktop_oauth.dart
Original file line number Diff line number Diff line change
Expand Up @@ -324,5 +324,6 @@ class GoogleRefreshTokenException implements Exception {
}

@override
String toString() => 'GoogleRefreshTokenException: Google token endpoint returned $statusCode: $body';
String toString() =>
'GoogleRefreshTokenException: Google token endpoint returned $statusCode: $body';
}
13 changes: 6 additions & 7 deletions worker_flutter/lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ import 'installer/install_progress_app.dart';
import 'installer/installer.dart';
import 'launch/auto_start_service.dart';
import 'launch/mode_picker_screen.dart';
import 'macos/activation_policy.dart';
import 'offline/offline_app.dart';
import 'sentry_setup.dart';
import 'telemetry.dart';
Expand Down Expand Up @@ -634,12 +633,12 @@ class _WorkerAppState extends State<_WorkerApp> {
),
)
: (_user == null
? AuthGateScreen(
authService: _auth,
onAuthed: _onAuthed,
onSwitchToOffline: _switchToOffline,
)
: Dashboard(engine: widget.engine, config: widget.config)),
? AuthGateScreen(
authService: _auth,
onAuthed: _onAuthed,
onSwitchToOffline: _switchToOffline,
)
: Dashboard(engine: widget.engine, config: widget.config)),
);
}
}
14 changes: 7 additions & 7 deletions worker_flutter/lib/models/sim.dart
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,13 @@ class SimDoc {
String get compositeId => '$jobId:$simId';

Map<String, dynamic> toJson() => {
'simId': simId,
'jobId': jobId,
'index': index,
'state': state,
if (workerId != null) 'workerId': workerId,
if (workerName != null) 'workerName': workerName,
};
'simId': simId,
'jobId': jobId,
'index': index,
'state': state,
if (workerId != null) 'workerId': workerId,
if (workerName != null) 'workerName': workerName,
};
}

/// Result of running a single simulation (output from sim_runner).
Expand Down
11 changes: 9 additions & 2 deletions worker_flutter/lib/ui/dashboard.dart
Original file line number Diff line number Diff line change
Expand Up @@ -253,7 +253,10 @@ class _DashboardState extends State<Dashboard> {
child: Tooltip(
message: 'View on GitHub',
child: Container(
padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 4),
padding: const EdgeInsets.symmetric(
horizontal: 10,
vertical: 4,
),
decoration: BoxDecoration(
color: const Color(0xFF1F2937),
borderRadius: BorderRadius.circular(12),
Expand All @@ -262,7 +265,11 @@ class _DashboardState extends State<Dashboard> {
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
const Icon(Icons.code, size: 12, color: Color(0xFF60A5FA)),
const Icon(
Icons.code,
size: 12,
color: Color(0xFF60A5FA),
),
const SizedBox(width: 6),
Text(
_getVersionText(),
Expand Down
5 changes: 4 additions & 1 deletion worker_flutter/lib/worker/lease_writer.dart
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,10 @@ class LeaseWriter {
} catch (_) {
// _writeOnce already swallows; this is belt-and-suspenders.
}
_timer = Timer.periodic(tickInterval, (_) => _writeOnce(status: _activeStatus()));
_timer = Timer.periodic(
tickInterval,
(_) => _writeOnce(status: _activeStatus()),
);
}

Future<void> stop() async {
Expand Down
18 changes: 10 additions & 8 deletions worker_flutter/lib/worker/sim_claim.dart
Original file line number Diff line number Diff line change
Expand Up @@ -84,14 +84,16 @@ class SimClaimer {
// jobId is the parent of the parent of the sim doc
final jobId = simRef.parent.parent!.id;

return ClaimSucceeded(SimDoc(
simId: simRef.id,
jobId: jobId,
index: (data['index'] as num?)?.toInt() ?? 0,
state: 'RUNNING',
workerId: workerId,
workerName: workerName,
));
return ClaimSucceeded(
SimDoc(
simId: simRef.id,
jobId: jobId,
index: (data['index'] as num?)?.toInt() ?? 0,
state: 'RUNNING',
workerId: workerId,
workerName: workerName,
),
);
});
} on FirebaseException catch (e) {
return ClaimLostRace('firestore: ${e.code}');
Expand Down
10 changes: 5 additions & 5 deletions worker_flutter/pubspec.lock
Original file line number Diff line number Diff line change
Expand Up @@ -692,10 +692,10 @@ packages:
dependency: transitive
description:
name: matcher
sha256: dc0b7dc7651697ea4ff3e69ef44b0407ea32c487a39fff6a4004fa585e901861
sha256: "12956d0ad8390bbcc63ca2e1469c0619946ccb52809807067a7020d57e647aa6"
url: "https://pub.dev"
source: hosted
version: "0.12.19"
version: "0.12.18"
material_color_utilities:
dependency: transitive
description:
Expand Down Expand Up @@ -1193,10 +1193,10 @@ packages:
dependency: transitive
description:
name: test_api
sha256: "8161c84903fd860b26bfdefb7963b3f0b68fee7adea0f59ef805ecca346f0c7a"
sha256: "93167629bfc610f71560ab9312acdda4959de4df6fac7492c89ff0d3886f6636"
url: "https://pub.dev"
source: hosted
version: "0.7.10"
version: "0.7.9"
tray_manager:
dependency: "direct main"
description:
Expand Down Expand Up @@ -1374,5 +1374,5 @@ packages:
source: hosted
version: "3.1.3"
sdks:
dart: ">=3.11.5 <4.0.0"
dart: ">=3.11.0 <4.0.0"
flutter: ">=3.38.4"
2 changes: 1 addition & 1 deletion worker_flutter/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ publish_to: 'none'
version: 0.2.0+1

environment:
sdk: ^3.11.5
sdk: ^3.11.0

dependencies:
flutter:
Expand Down
7 changes: 5 additions & 2 deletions worker_flutter/test/worker/lease_writer_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -83,8 +83,11 @@ void main() {
final doc = await firestore.collection('workers').doc('w1').get();
final lease = doc.data()!['lease'] as Map<String, dynamic>;
final expiresAt = DateTime.parse(lease['expiresAt'] as String);
expect(expiresAt.isAfter(DateTime.now().toUtc()), true,
reason: 'lease should not be already-expired immediately after write');
expect(
expiresAt.isAfter(DateTime.now().toUtc()),
true,
reason: 'lease should not be already-expired immediately after write',
);
});
});
}
Loading
Loading