Skip to content

feat: disk-usage, file-count endpoints + OpenAPI CI artifact#178

Merged
ng merged 4 commits into
devfrom
feat/api-endpoints-ci-contracts
Mar 15, 2026
Merged

feat: disk-usage, file-count endpoints + OpenAPI CI artifact#178
ng merged 4 commits into
devfrom
feat/api-endpoints-ci-contracts

Conversation

@ng

@ng ng commented Mar 15, 2026

Copy link
Copy Markdown
Contributor

Summary

Test plan

  • pnpm tsc passes with new endpoints
  • Push to dev/main triggers OpenAPI artifact workflow
  • New endpoints appear in /api/openapi.json

🤖 Generated with Claude Code

ng and others added 2 commits March 15, 2026 14:30
64M was insufficient when scanning 6 hours of RAW data for calibration
baselines. The calibrator was killed by systemd OOM (signal 9).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Implements #166, #164, #163:

- system.getDiskUsage: root filesystem usage via df -B1 / with graceful fallback
- biometrics.getFileCount: RAW file count and total size for iOS Status screen
- Export listRawFiles from raw.ts for reuse in biometrics router
- OpenAPI spec published as CI artifact on push to dev/main (90-day retention)
- Swift contract tests decode REST responses against iOS model types
- Snapshot script curls 11 REST endpoints; seed script populates test data

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Mar 15, 2026

Copy link
Copy Markdown
📝 Walkthrough

Walkthrough

This PR establishes a contract testing framework by adding GitHub Actions workflows for running tests and publishing OpenAPI specs, introducing a Swift test suite with helper scripts for seeding data and snapshotting API responses, and adding new server endpoints (getFileCount, getDiskUsage) while exporting an internal function (listRawFiles) to support the contract tests. The calibrator service memory limit is also increased.

Changes

Cohort / File(s) Summary
CI/CD Workflows
.github/workflows/contract-test.yml, .github/workflows/openapi.yml
New GitHub Actions workflows: contract-test runs contract tests on PRs affecting server routers or schema; openapi publishes OpenAPI spec on main/dev pushes. Both workflows start a background server, poll health endpoints, and clean up resources.
Swift Contract Test Suite
contract-tests/Package.swift, contract-tests/Tests/ContractTests/ContractTests.swift
New Swift package manifest and extensive test suite with JSON fixture decoding tests across healthcheck, system, biometrics, and health sections. Tests verify API response shapes and basic value assertions.
Test Helper Scripts
contract-tests/scripts/seed-test-data.sh, contract-tests/scripts/snapshot-responses.sh
New Bash scripts: seed-test-data populates SQLite database with test records; snapshot-responses fetches API endpoints and saves responses as JSON fixtures for contract tests.
Server Endpoints
src/server/routers/biometrics.ts, src/server/routers/system.ts
Added new public endpoints: getFileCount returns raw biometrics file counts and total size; getDiskUsage exposes disk usage metrics (total, used, available bytes and percentage).
Function Export
src/server/routers/raw.ts
Exported listRawFiles function to make it part of the module's public API for use by the new getFileCount endpoint.
Service Configuration
modules/calibrator/sleepypod-calibrator.service
Increased calibrator systemd service MemoryMax from 64M to 256M.

Sequence Diagram(s)

sequenceDiagram
    actor GHA as GitHub Actions
    participant Server as Node.js Server
    participant DB as SQLite Database
    participant Swift as Swift Tests
    
    GHA->>GHA: Checkout code & setup
    GHA->>Server: Start server (background)
    GHA->>Server: Poll /api/health (max 60s)
    Server-->>GHA: Health OK
    GHA->>DB: Execute seed-test-data.sh
    DB-->>GHA: Test records inserted
    GHA->>Server: Snapshot API endpoints
    Server->>DB: Query biometrics, health, system
    Server-->>GHA: API responses (JSON fixtures)
    GHA->>GHA: Save fixtures locally
    GHA->>Swift: Run contract tests
    Swift->>Swift: Load & decode fixtures
    Swift->>Swift: Assert expected shapes
    Swift-->>GHA: Test results
    GHA->>Server: Terminate background process
Loading

Estimated Code Review Effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly Related PRs

Poem

🐰 Hop, hop! New tests are hopping in,
Contracts dancing, fixtures thin,
Swift and Bash scripts play,
API specs are here to stay!
From seeds to snapshots, tests take flight,

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 35.71% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main changes: adding disk-usage and file-count API endpoints plus an OpenAPI CI artifact workflow, matching the primary objectives.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/api-endpoints-ci-contracts
📝 Coding Plan
  • Generate coding plan for human review comments

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

Adds new API surface area and CI checks to support iOS “Status” UX and keep the server/iOS models aligned via contract testing, plus a small calibrator resource bump.

Changes:

  • Add /system/disk-usage and /biometrics/file-count endpoints for status/telemetry.
  • Introduce Swift-based contract tests + scripts to snapshot real server responses into fixtures, and a CI workflow to run them.
  • Add a CI workflow to publish the generated OpenAPI spec as an artifact; increase calibrator service memory limit.

Reviewed changes

Copilot reviewed 10 out of 12 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
src/server/routers/system.ts Adds getDiskUsage endpoint for root filesystem usage.
src/server/routers/raw.ts Exports listRawFiles() for reuse outside the raw router.
src/server/routers/biometrics.ts Adds getFileCount endpoint using RAW file stats.
modules/calibrator/sleepypod-calibrator.service Raises MemoryMax to 256M.
contract-tests/Tests/ContractTests/ContractTests.swift Adds Swift contract tests that decode JSON fixtures.
contract-tests/scripts/snapshot-responses.sh Snapshots live API responses into JSON fixtures.
contract-tests/scripts/seed-test-data.sh Seeds biometrics SQLite with test rows for non-empty responses.
contract-tests/Package.swift Defines SwiftPM package for contract tests + fixtures resources.
.github/workflows/openapi.yml Builds/starts server and downloads OpenAPI spec as artifact.
.github/workflows/contract-test.yml Runs end-to-end contract test flow on PRs (start server, seed, snapshot, swift test).

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

You can also share your feedback on Copilot code review. Take the survey.

Comment thread .github/workflows/openapi.yml Outdated
Comment on lines +32 to +33
- name: Start server
run: pnpm start &
Comment thread .github/workflows/openapi.yml Outdated
Comment on lines +50 to +51
- name: Stop server
run: kill %1 2>/dev/null || true
Comment thread .github/workflows/contract-test.yml Outdated
Comment on lines +20 to +28
- name: Checkout iOS models
uses: actions/checkout@v4
with:
repository: sleepypod/ios
token: ${{ secrets.IOS_REPO_TOKEN }}
path: ios-checkout
sparse-checkout: Sleepypod/Models
sparse-checkout-cone-mode: false

Comment thread .github/workflows/contract-test.yml Outdated
Comment on lines +51 to +53
- name: Start server
run: pnpm start &

Comment thread .github/workflows/contract-test.yml Outdated
Comment on lines +75 to +77
- name: Stop server
if: always()
run: kill %1 2>/dev/null || true
# Timestamps are unix epoch (seconds) — matching the integer column mode in the schema.
set -euo pipefail

DB_PATH="${BIOMETRICS_DB_PATH:-biometrics.dev.db}"

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🧹 Nitpick comments (1)
contract-tests/Tests/ContractTests/ContractTests.swift (1)

29-31: Assert usedPercent upper bound as part of the contract.

Line 30 only checks non-negative values. Add <= 100 so impossible percentages fail the contract test.

💡 Proposed fix
     let result = try JSONDecoder().decode(DiskUsage.self, from: data)
     `#expect`(result.usedPercent >= 0)
+    `#expect`(result.usedPercent <= 100)
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@contract-tests/Tests/ContractTests/ContractTests.swift` around lines 29 - 31,
Update the contract test assertion to enforce an upper bound for DiskUsage
percentages: change the single non-negative check on result.usedPercent to
assert it is within 0 and 100 (inclusive). Locate the test that decodes
DiskUsage (where result is assigned from JSONDecoder().decode(DiskUsage.self,
from: data)) and replace the lone usedPercent >= 0 expectation with a combined
expectation that validates 0 <= result.usedPercent <= 100 so impossible
percentages fail the contract.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In @.github/workflows/contract-test.yml:
- Around line 51-53: The "Start server" step currently backgrounds the process
with `pnpm start &` but doesn't record its PID, so later use of `%1` is
unreliable; update the "Start server" step (the step named "Start server") to
capture the background PID with `$!` and persist it to the workflow environment
(e.g. `pnpm start & echo "SERVER_PID=$!" >> $GITHUB_ENV`), and then update the
later step that references the job-control token `%1` to instead use the
persisted env var `${{ env.SERVER_PID }}` (or shell `$SERVER_PID`) when killing
or waiting for the process.

In @.github/workflows/openapi.yml:
- Around line 50-51: The "Stop server" step currently uses "kill %1", which
fails in non-interactive GitHub Action shells; replace job-control usage by
tracking the server PID when you start it (capture $! into a file like
server.pid) and then in the "Stop server" step read and kill that PID (e.g.,
kill $(cat server.pid) 2>/dev/null || true), or alternatively use a safer
pattern such as pkill -f "<server command>" to terminate by command name; update
the start step to write the PID and the stop step to use that PID file or pkill
instead of "kill %1".

In `@contract-tests/Tests/ContractTests/ContractTests.swift`:
- Around line 6-8: The helper loadFixture(_:) currently force-unwraps the URL
which will crash if the JSON is missing; change loadFixture to safely unwrap
Bundle.module.url(forResource:withExtension:subdirectory:) and, if nil, throw a
descriptive error (including the fixture name and subdirectory) instead of
force-unwrapping so tests fail with a clear message; keep the existing try
Data(contentsOf:) to propagate file-read errors once the URL is validated.

---

Nitpick comments:
In `@contract-tests/Tests/ContractTests/ContractTests.swift`:
- Around line 29-31: Update the contract test assertion to enforce an upper
bound for DiskUsage percentages: change the single non-negative check on
result.usedPercent to assert it is within 0 and 100 (inclusive). Locate the test
that decodes DiskUsage (where result is assigned from
JSONDecoder().decode(DiskUsage.self, from: data)) and replace the lone
usedPercent >= 0 expectation with a combined expectation that validates 0 <=
result.usedPercent <= 100 so impossible percentages fail the contract.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 4b9f4420-bace-4c0c-8071-95a459907795

📥 Commits

Reviewing files that changed from the base of the PR and between 7a02338 and c9dc8f8.

📒 Files selected for processing (12)
  • .github/workflows/contract-test.yml
  • .github/workflows/openapi.yml
  • contract-tests/Package.swift
  • contract-tests/Sources/SleepypodModels/.gitkeep
  • contract-tests/Tests/ContractTests/ContractTests.swift
  • contract-tests/Tests/ContractTests/Fixtures/.gitkeep
  • contract-tests/scripts/seed-test-data.sh
  • contract-tests/scripts/snapshot-responses.sh
  • modules/calibrator/sleepypod-calibrator.service
  • src/server/routers/biometrics.ts
  • src/server/routers/raw.ts
  • src/server/routers/system.ts

Comment thread .github/workflows/contract-test.yml Outdated
Comment thread .github/workflows/openapi.yml Outdated
Comment thread contract-tests/Tests/ContractTests/ContractTests.swift Outdated
ng and others added 2 commits March 15, 2026 15:09
- Track server PID via $GITHUB_ENV instead of kill %1 (broken across
  GHA steps) in both contract-test.yml and openapi.yml
- Guard fixture URL unwrap in Swift tests to fail with a clear message
  instead of crashing
- Assert usedPercent <= 100 in disk usage contract test
- Align seed script to read BIOMETRICS_DATABASE_URL (strip file: prefix)
  matching the server's env var, with fallback chain
Contract tests gate iOS model changes against the core API, so the
CI workflow belongs in the iOS repo where it blocks iOS PRs that
break decoding. Core publishes the OpenAPI spec artifact (#164) as
the shared reference.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@ng ng changed the title feat: disk-usage, file-count endpoints + OpenAPI CI + contract tests feat: disk-usage, file-count endpoints + OpenAPI CI artifact Mar 15, 2026
@ng
ng merged commit 2fa427c into dev Mar 15, 2026
6 checks passed
@ng
ng deleted the feat/api-endpoints-ci-contracts branch March 15, 2026 22:28
@github-actions

Copy link
Copy Markdown

🎉 This PR is included in version 1.1.0 🎉

The release is available on GitHub release

Your semantic-release bot 📦🚀

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants