Skip to content
Merged
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
28 changes: 28 additions & 0 deletions .flywheel.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# Flywheel release configuration.
#
# `release: production` cuts a release on every push to the managed branch.
# `auto_merge` lists the conventional-commit types that merge without review;
# every other type gates on a human. `!`-suffixed types are separate entries,
# so `fix` does not imply `fix!`.
#
# Every version-bumping type — feat, fix, perf, and any breaking variant —
# routes to human review, so a release is never cut unattended. Non-bumping
# types auto-merge once required checks pass.
#
# `chore` covers dependency bumps, so listing it means Dependabot updates can
# land unreviewed. Flywheel gates that separately: those PRs auto-merge only
# once the App private key is also registered in the Dependabot secret store.
flywheel:
streams:
- name: main-line
branches:
- name: main
release: production
auto_merge: [chore, docs, style, test, ci, build, refactor]

release_files:
# release-please owned pubspec.yaml under its `dart` release type;
# flywheel keeps it current for the same reader — pub.dev.
- path: pubspec.yaml
pattern: '^version: .*'
replacement: 'version: ${version}'
18 changes: 0 additions & 18 deletions .github/workflows/auto-merge-release.yml

This file was deleted.

34 changes: 0 additions & 34 deletions .github/workflows/ci.yml

This file was deleted.

35 changes: 35 additions & 0 deletions .github/workflows/flywheel-pr.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
name: Flywheel — PR

on:
pull_request:
types: [opened, synchronize, reopened, ready_for_review, edited]

concurrency:
group: flywheel-pr-${{ github.event.pull_request.number }}
cancel-in-progress: true

jobs:
conduct:
# Only run on 'edited' events when a human triggered the edit. Bot-driven
# edits (the Flywheel App rewriting titles/bodies, push-flow upserting
# promotion PR bodies) would otherwise flap conduct <-> push-flow writes on
# every promotion-source push.
if: |
github.event.pull_request.draft == false &&
(github.event.action != 'edited' || github.event.sender.type == 'User')
# The degraded empty-key path (Dependabot PRs, where the App key is absent)
# posts the conventional-commit check with the built-in token, so the token
# needs checks:write.
permissions:
contents: read
checks: write
runs-on: ubuntu-latest
steps:
# SHA-pinned, not @v2: this action receives a GitHub App private key,
# and a floating tag lets its repository repoint that credential at new
# code without review. Bump the pin deliberately.
- uses: point-source/flywheel@59758d1940ebe054ce9fdd4b7a7dc79a0cf235e0 # v2.1.0
with:
event: pull_request
app-id: ${{ vars.FLYWHEEL_GH_APP_ID }}
app-private-key: ${{ secrets.FLYWHEEL_GH_APP_PRIVATE_KEY }}
27 changes: 27 additions & 0 deletions .github/workflows/flywheel-push.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
name: Flywheel — Push

on:
push:
branches: ["**"]

concurrency:
group: flywheel-push-${{ github.ref_name }}
cancel-in-progress: false

jobs:
release:
# Flywheel mints its own App installation token for every write, so the
# built-in token needs read only. Without this block the job inherits the
# repository default, which on older repos is write on everything.
permissions:
contents: read
runs-on: ubuntu-latest
steps:
# SHA-pinned, not @v2: this action receives a GitHub App private key,
# and a floating tag lets its repository repoint that credential at new
# code without review. Bump the pin deliberately.
- uses: point-source/flywheel@59758d1940ebe054ce9fdd4b7a7dc79a0cf235e0 # v2.1.0
with:
event: push
app-id: ${{ vars.FLYWHEEL_GH_APP_ID }}
app-private-key: ${{ secrets.FLYWHEEL_GH_APP_PRIVATE_KEY }}
16 changes: 16 additions & 0 deletions .github/workflows/governance-lint.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
name: Governance Lint

on:
push:
branches: [main]
pull_request:
merge_group: # required for merge-queue compatibility

jobs:
# Job id `governance` makes the check-run name `governance / lint`, the
# context registered as a required status check. Renaming it means
# re-pointing the ruleset entry.
governance:
uses: repentsinner/symphonize/.github/workflows/governance-lint.yml@notation--v0
with:
readme-type: "library"
44 changes: 44 additions & 0 deletions .github/workflows/quality.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
# quality — everything this repository verifies, behind one required check.
#
# GitHub names a check run after the JOB, so the job id `quality` is the
# context registered in the branch ruleset. The work is one job because it
# is one setup: splitting analyze, format and test would pay for the Dart
# SDK and libudev three times over for no extra signal.
name: quality

on:
pull_request:
merge_group: # required for merge-queue compatibility

jobs:
quality:
runs-on: ubuntu-latest
steps:
# Classify the triggering commit so Flywheel's own commits
# (chore(release):, back-merge) skip the suite. A step-level `if:`
# that evaluates false still reports `success`, so the required check
# stays satisfied rather than hanging — which is why this is a single
# job with guarded steps and not a job-level `if:`.
- id: classify
uses: point-source/flywheel/classify@59758d1940ebe054ce9fdd4b7a7dc79a0cf235e0 # v2.1.0
- uses: actions/checkout@v4
if: steps.classify.outputs.derived_release_commit != 'true'
- uses: dart-lang/setup-dart@v1
if: steps.classify.outputs.derived_release_commit != 'true'
with:
sdk: '3.10.0'
- name: Install libudev
if: steps.classify.outputs.derived_release_commit != 'true'
run: sudo apt-get update && sudo apt-get install -y libudev-dev
- name: Resolve dependencies
if: steps.classify.outputs.derived_release_commit != 'true'
run: dart pub get
- name: Analyze
if: steps.classify.outputs.derived_release_commit != 'true'
run: dart analyze --fatal-infos
- name: Format
if: steps.classify.outputs.derived_release_commit != 'true'
run: dart format --output=none --set-exit-if-changed .
- name: Test
if: steps.classify.outputs.derived_release_commit != 'true'
run: dart test
21 changes: 0 additions & 21 deletions .github/workflows/release-please.yml

This file was deleted.

3 changes: 0 additions & 3 deletions .release-please-manifest.json

This file was deleted.

42 changes: 28 additions & 14 deletions SPEC.md
Original file line number Diff line number Diff line change
@@ -1,13 +1,17 @@
# Spec: hidapi Dart bindings

## Problem
## Problem §spec:problem

*Status: complete*

No Dart package provides complete, cross-platform access to USB and
Bluetooth HID devices. Developers resort to platform channels (Flutter
only) or incomplete FFI wrappers that require prebuilt binaries or
system-installed libraries.

## Scope
## Scope §spec:scope

*Status: complete*

This package wraps the upstream [hidapi](https://github.com/libusb/hidapi)
C library. It shall expose every public function, struct, and enum from
Expand All @@ -20,9 +24,11 @@ consuming packages.

---

## 1. API surface
## API surface §spec:api-surface

*Status: complete — PR #1, #4, 2026-02-22*
*Status: complete*

Delivered in PR #1, #4, 2026-02-22.

The package shall expose an idiomatic Dart API that maps 1:1 to every
public function, struct, and enum in upstream `hidapi/hidapi.h`.
Expand All @@ -43,19 +49,23 @@ Deviations from the C API:

---

## 2. Platform support
## Platform support §spec:platform-support

*Status: complete*

*Status: complete — PR #1, 2026-02-22*
Delivered in PR #1, 2026-02-22.

The package shall support every platform supported by upstream hidapi.
The build hook shall select the correct backend source file, frameworks,
and link libraries as defined by the upstream build system.

---

## 3. Native source acquisition
## Native source acquisition §spec:native-source-acquisition

*Status: complete — PR #2, 2026-02-22*
*Status: complete*

Delivered in PR #2, 2026-02-22.

Git submodules are not viable: `dart pub get` does not recursively init
submodules, so consumers that depend on this package via pub.dev or a git
Expand All @@ -74,9 +84,11 @@ Instead, the package acquires native source via a Dart 3.10 build hook

---

## 4. Testing
## Testing §spec:testing

*Status: complete*

*Status: complete — PR #1, #7, 2026-02-22*
Delivered in PR #1, #7, 2026-02-22.

HID devices require physical hardware. CI runners have none, so the test
strategy splits into two tiers:
Expand All @@ -89,9 +101,11 @@ strategy splits into two tiers:

---

## 5. CI/CD
## CI/CD §spec:ci-cd

*Status: complete*

*Status: complete — PR #1, #5, #7, #8, #9, #11, 2026-02-22*
Delivered in PR #1, #5, #7, #8, #9, #11, 2026-02-22.

This is a single-maintainer project. Releases should not require manual
steps beyond merging a PR. pub.dev requires semver; conventional commits
Expand All @@ -109,7 +123,7 @@ let release-please derive the correct version bump automatically.

---

## 6. macOS exclusive device access
## macOS exclusive device access §spec:macos-exclusive-device-access

*Status: in progress*

Expand Down Expand Up @@ -138,7 +152,7 @@ imports.

---

## 7. Publishing
## Publishing §spec:publishing

*Status: not started*

Expand Down
10 changes: 0 additions & 10 deletions release-please-config.json

This file was deleted.

Loading