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
16 changes: 4 additions & 12 deletions .claude/skills/release/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,26 +18,18 @@ Then perform these steps in order:

2. Update the version in these files:
- `pubspec.yaml` — the `version` property
- `README.md` — the `ably_flutter: ^OLD_VERSION` line in the Installation section (update to `^NEW_VERSION`)
- `README.md` — the `ably_pubsub_device_flutter: ^OLD_VERSION` line in the Installation section (update to `^NEW_VERSION`)
- `ios/ably_pubsub_device_flutter/Sources/ably_pubsub_device_flutter/codec/AblyFlutterVersion.h` — the `FLUTTER_PACKAGE_PLUGIN_VERSION` string (the iOS plugin reports it to Ably; `test/ios_plugin_version_test.dart` checks it matches `pubspec.yaml`)

3. Regenerate lock files:

a. Run `flutter pub get` in `example/` and `test_integration/` to update their `pubspec.lock` files:
3. Regenerate lock files. Run `flutter pub get` in `example/` and `test_integration/` to update their `pubspec.lock` files:
```
cd example && flutter pub get && cd ..
cd test_integration && flutter pub get && cd ..
```
If either directory doesn't exist, skip it and note it in the summary.

b. Regenerate iOS Podfile.lock files by running:
```
pod install --project-directory=example/ios
pod install --project-directory=test_integration/ios
```
If CocoaPods is not installed or either directory doesn't exist, skip that directory and note it in the summary.

4. Commit all changed files together with message: `chore: bump version to NEW_VERSION`
Stage: `pubspec.yaml`, `README.md`, `example/pubspec.lock`, `example/ios/Podfile.lock`, `test_integration/pubspec.lock`, `test_integration/ios/Podfile.lock` (only include files that actually changed).
Stage: `pubspec.yaml`, `README.md`, `ios/ably_pubsub_device_flutter/Sources/ably_pubsub_device_flutter/codec/AblyFlutterVersion.h`, `example/pubspec.lock`, `test_integration/pubspec.lock` (only include files that actually changed).

5. Fetch merged PRs since the last release tag:
```
Expand Down
9 changes: 8 additions & 1 deletion .github/workflows/check.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ jobs:

- uses: subosito/flutter-action@1a449444c387b1966244ae4d4f8c696479add0b2 # v2.23.0
with:
flutter-version: '3.24'
flutter-version: '3.47.3'
cache: true

# This step requires fetch of test_integration packages because flutter format and
Expand All @@ -37,3 +37,10 @@ jobs:

- name: 'Run unit tests'
run: flutter test --no-pub

# Runs the same validation as the publish step in release.yaml, so a
# problem that would block publishing to pub.dev (a missing CHANGELOG
# entry, an invalid pubspec, an oversized archive) fails here first.
# Warnings fail the step; hints don't.
- name: 'Check the package can be published'
run: flutter pub publish --dry-run
2 changes: 1 addition & 1 deletion .github/workflows/docs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ jobs:

- uses: subosito/flutter-action@1a449444c387b1966244ae4d4f8c696479add0b2 # v2.23.0
with:
flutter-version: '3.24'
flutter-version: '3.47.3'
cache: true

- name: Use Intro Blurb As Homepage
Expand Down
13 changes: 10 additions & 3 deletions .github/workflows/flutter_example_app.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -9,18 +9,25 @@ permissions:

jobs:
ios:
runs-on: "macos-latest"
runs-on: macos-26 # ably-pubsub-cocoa 2.0 needs Xcode 26
steps:
# Check out into a directory named after the plugin. When Flutter adds
# Swift Package Manager integration to a plugin's own example app, it
# references the plugin's package both directly (identity:
# `ably_pubsub_device_flutter`) and through a symlink named after the
# checkout directory, and package resolution fails if the two differ.
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1
with:
persist-credentials: false
path: ably_pubsub_device_flutter

- uses: subosito/flutter-action@1a449444c387b1966244ae4d4f8c696479add0b2 # v2.23.0
with:
flutter-version: "3.24"
flutter-version: "3.47.3"
cache: true

- name: "Build example app for iOS"
working-directory: ably_pubsub_device_flutter
run: |
flutter pub get
cd example && flutter build ios --no-codesign
Expand All @@ -39,7 +46,7 @@ jobs:

- uses: subosito/flutter-action@1a449444c387b1966244ae4d4f8c696479add0b2 # v2.23.0
with:
flutter-version: "3.29"
flutter-version: "3.47.3"
cache: true

- name: "Build example app for Android"
Expand Down
15 changes: 9 additions & 6 deletions .github/workflows/flutter_integration.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -10,21 +10,21 @@ permissions:

jobs:
ios:
runs-on: macos-latest
runs-on: macos-26 # ably-pubsub-cocoa 2.0 needs Xcode 26
steps:
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1
with:
persist-credentials: false

- uses: subosito/flutter-action@1a449444c387b1966244ae4d4f8c696479add0b2 # v2.23.0
with:
flutter-version: '3.29'
flutter-version: '3.47.3'
cache: true

# test_integration package depends on ably_flutter, so before we run integration
# test_integration package depends on ably_pubsub_device_flutter, so before we run integration
# tests it's best to perform dependency update in both packages, to make sure that
# integration tests are run with exactly the same dependencies as specified in
# current version of ably_flutter package
# current version of ably_pubsub_device_flutter package
- name: Update dependencies
run: |
flutter pub get
Expand Down Expand Up @@ -81,16 +81,19 @@ jobs:

- uses: subosito/flutter-action@1a449444c387b1966244ae4d4f8c696479add0b2 # v2.23.0
with:
flutter-version: '3.29'
flutter-version: '3.47.3'
cache: true

- name: 'Run Flutter Driver tests'
timeout-minutes: 30
uses: reactivecircus/android-emulator-runner@e89f39f1abbbd05b1113a29cf4db69e7540cae5a # v2.37.0
with:
api-level: ${{ matrix.api-level }}
# Flutter 3.47 treats 32-bit x86 Android devices as unsupported.
arch: x86_64
emulator-options: -no-snapshot-save -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none
disable-animations: true
script: |
flutter pub get
cd test_integration && flutter build apk && flutter drive
adb devices
cd test_integration && flutter drive -d emulator-5554
30 changes: 3 additions & 27 deletions .github/workflows/ios_unit_tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,41 +10,17 @@ permissions:

jobs:
ios-unit-tests:
runs-on: macos-latest
runs-on: macos-26 # ably-pubsub-cocoa 2.0 needs Xcode 26
steps:
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1
with:
persist-credentials: false

- uses: subosito/flutter-action@1a449444c387b1966244ae4d4f8c696479add0b2 # v2.23.0
with:
flutter-version: '3.29'
flutter-version: '3.47.3'
cache: true

- name: Set up iOS test project
# --skip-tests sets up the CocoaPods workspace (downloads all deps, generates
# the ably_flutter-Unit-Tests scheme) without booting a simulator
run: |
cd ios
pod lib lint ably_flutter.podspec \
--allow-warnings \
--skip-tests \
--validation-dir=/tmp/ably_test_build \
--no-clean

- name: Pick simulator
run: |
UDID=$(xcrun simctl list devices available | \
grep -E "iPhone" | head -n 1 | \
sed -E 's/.*\(([A-F0-9-]+)\).*/\1/')
echo "SIMULATOR_ID=$UDID" >> $GITHUB_ENV


- name: Run iOS unit tests
timeout-minutes: 30
run: |
xcodebuild test \
-workspace /tmp/ably_test_build/App.xcworkspace \
-scheme ably_flutter-Unit-Tests \
-destination "id=$SIMULATOR_ID,arch=arm64" \
CODE_SIGNING_ALLOWED=NO
run: ios/run_unit_tests.sh
17 changes: 17 additions & 0 deletions .pubignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,20 @@
# pub uses this file instead of the root .gitignore, so it repeats the
# .gitignore entries that would otherwise be published from a local checkout,
# such as build output.
.DS_Store
.dart_tool/
.packages
.pub/
build/
doc/
.fvm
.project
.classpath
.settings
.factorypath
.idea/
*.iml

# Test suite is not published for pub.dev
# See <https://github.com/ably/ably-flutter/issues/400#issuecomment-1129236627>
test/
Expand Down
2 changes: 1 addition & 1 deletion .tool-versions
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
ruby 3.4.5
flutter 3.29.0
flutter 3.47.3-stable
4 changes: 2 additions & 2 deletions API_REF_INTRO_BLURB.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# Ably Flutter Client Library SDK API Reference

The Flutter Client Library SDK supports a realtime and a REST interface. The Flutter API references are generated from the [Ably Flutter Client Library SDK source code](https://github.com/ably/ably-pubsub-flutter/) using [dartdoc](https://dart.dev/tools/dart-doc) and structured by classes.
The Flutter Client Library SDK supports a realtime interface. The Flutter API references are generated from the [Ably Flutter Client Library SDK source code](https://github.com/ably/ably-pubsub-flutter/) using [dartdoc](https://dart.dev/tools/dart-doc) and structured by classes.

The realtime interface enables a client to maintain a persistent connection to Ably and publish, subscribe and be present on channels. The REST interface is stateless and typically implemented server-side. It is used to make requests such as retrieving statistics, token authentication and publishing to a channel.
The realtime interface enables a client to maintain a persistent connection to Ably and publish, subscribe and be present on channels.

View the [Ably docs](https://ably.com/docs/) for conceptual information on using Ably, and for API references featuring all languages. The combined [API references](https://ably.com/docs/api/) are organized by features and split between the [realtime](https://ably.com/docs/api/realtime-sdk) and [REST](https://ably.com/docs/api/rest-sdk) interfaces.
48 changes: 37 additions & 11 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# Contributing to Ably Flutter

## Overview
A [Flutter](https://flutter.dev/) plugin for [Ably](https://www.ably.com), built on top of Ably's [iOS](https://github.com/ably/ably-cocoa) and [Android](https://github.com/ably/ably-java) SDKs.
A [Flutter](https://flutter.dev/) plugin for [Ably](https://www.ably.com), built on top of Ably's [iOS](https://github.com/ably/ably-pubsub-cocoa) and [Android](https://github.com/ably/ably-pubsub-java) SDKs.

## Running the example

Expand Down Expand Up @@ -49,6 +49,7 @@ The code in this repository has been constructed to be
[built as a Flutter Plugin](https://flutter.dev/docs/development/packages-and-plugins/developing-packages#plugin). In this repository the main branch contains the latest development version of the Ably SDK. All development (bug fixing, feature implementation, etc.) is done against the main branch, which you should branch from whenever you'd like to make modifications. Here's the steps to follow when contributing to this repository.

- Fork it
- Clone it into a directory named `ably_pubsub_device_flutter` (see [iOS: clone directory name](#ios-clone-directory-name))
- Install and update dependencies (`flutter pub get`)
- Create your feature branch from `main`
- Run static analysis on your changes and make sure there are no issues (`flutter analyze`)
Expand All @@ -57,6 +58,22 @@ The code in this repository has been constructed to be
- Push to the branch
- Create a new Pull Request

### iOS: clone directory name

The iOS plugin is a Swift package, at [ios/ably_pubsub_device_flutter](ios/ably_pubsub_device_flutter). When Flutter builds the example app, it references that package twice: directly, which gives it the identity `ably_pubsub_device_flutter`, and through a symlink named after the directory the repository is cloned into. Swift Package Manager rejects the build if the two identities differ, with an error like:

```
unable to override package 'ably_pubsub_device_flutter' because its identity 'ably-pubsub-flutter' doesn't match override's identity (directory name) 'ably_pubsub_device_flutter'
```

So clone the repository into a directory named `ably_pubsub_device_flutter`:

```bash
git clone https://github.com/ably/ably-pubsub-flutter.git ably_pubsub_device_flutter
```

If you've already cloned it under another name, rename the directory, then delete `example/build` and `example/ios/Flutter/ephemeral`, which cache the old name. Apps that depend on this plugin from pub.dev, and the `test_integration` app, are not affected.

### Hot restart

When performing `hot restart`, it's required to also reset the platform clients by calling:
Expand Down Expand Up @@ -87,15 +104,15 @@ After the app is launched, it can be re-launched from XCode/Android Studio with

### Testing changes in platform libraries

After making changes to `ably-java` or `ably-cocoa`, you can test changes without releasing those dependencies to users. To do this, you need a local copy of the repo with the changes you want to test.
After making changes to `ably-pubsub-java` or `ably-pubsub-cocoa`, you can test changes without releasing those dependencies to users. To do this, you need a local copy of the repo with the changes you want to test.

To test `ably-cocoa` changes, in `Podfile`, below `target 'Runner' do`, add:
To test `ably-pubsub-cocoa` changes, in [ios/ably_pubsub_device_flutter/Package.swift](ios/ably_pubsub_device_flutter/Package.swift), temporarily replace the `ably-pubsub-cocoa` dependency with a local one:

```ruby
pod 'Ably', :path => 'local/path/to/ably-cocoa'
```swift
.package(name: "ably-pubsub-cocoa", path: "local/path/to/ably-pubsub-cocoa"),
```

To test `ably-java` changes, see [Using ably-java / ably-android locally in other projects](https://github.com/ably/ably-java/blob/main/CONTRIBUTING.md#using-ably-java--ably-android-locally-in-other-projects).
To test `ably-pubsub-java` changes, publish them to your local Maven repository and point [android/build.gradle](android/build.gradle) at that version; see the [ably-pubsub-java contributing guide](https://github.com/ably/ably-pubsub-java/blob/main/CONTRIBUTING.md).

### Generating platform constants

Expand All @@ -120,9 +137,9 @@ dart codegen.dart
so new codec type is obtained from runtime type
7. Update `codecMap` in [android.src.main.java.io.ably.flutter.plugin.AblyMessageCodec](android/src/main/java/io/ably/flutter/plugin/AblyMessageCodec.java)
so new encoder/decoder is assigned for new type
8. Add new codec encoder method in [ios.Classes.codec.AblyFlutterWriter](ios/Classes/codec/AblyFlutterWriter.m)
8. Add new codec encoder method in [AblyFlutterWriter](ios/ably_pubsub_device_flutter/Sources/ably_pubsub_device_flutter/codec/AblyFlutterWriter.m)
and update `getType` and `getEncoder` so that new codec encoder is called
9. Add new codec encoder method in [ios.classes.codec.AblyFlutterReader](ios/Classes/codec/AblyFlutterReader.m)
9. Add new codec encoder method in [AblyFlutterReader](ios/ably_pubsub_device_flutter/Sources/ably_pubsub_device_flutter/codec/AblyFlutterReader.m)
and update `getDecoder` so that new codec decoder is called

### Implementing new platform methods
Expand All @@ -131,7 +148,7 @@ dart codegen.dart
2. Generate platform constants
3. Add new method in [android.src.main.java.io.ably.flutter.plugin.AblyMethodCallHandler.java](android/src/main/java/io/ably/flutter/plugin/AblyMethodCallHandler.java)
and update `_map` so that new method name is assigned to a method call
4. Add new method in [ios.classes.AblyFlutter](ios/Classes/AblyFlutter.m)
4. Add new method in [AblyFlutter](ios/ably_pubsub_device_flutter/Sources/ably_pubsub_device_flutter/AblyFlutter.m)
and update `initWithChannel` so that new method name is assigned to a method call

## Running Tests
Expand All @@ -144,6 +161,16 @@ Unit tests are located in [test](test/) directory and built on top of `flutter_t
flutter test
```

### iOS unit tests

The iOS plugin's XCTest suite lives in [ios/ably_pubsub_device_flutter/Tests](ios/ably_pubsub_device_flutter/Tests). Run it on a simulator with:

```bash
ios/run_unit_tests.sh
```

The script generates the `FlutterFramework` package the plugin's `Package.swift` expects alongside it (at `ios/FlutterFramework`, gitignored), wrapping the active Flutter SDK's engine, which a Flutter app build would otherwise provide.

### Integration tests

Integration tests are located in [test_integration](test_integration/) directory and use `flutter_test` and `flutter_driver` packages. Integration tests have to be executed on virtual machine or real device, and a dedicated test app is provided to track the test progress. To run the test app and all tests, execute:
Expand Down Expand Up @@ -196,8 +223,7 @@ The release process must include the following steps:
3. Add a commit to bump the version number
- Update the version in `pubspec.yaml`
- Update the version in the 'Installation' section of `README.md`
- Update the version of ably-flutter used in the example app and test integration app `podfile.lock` files:
- Run `pod install` in `example/ios` and `test_integration/ios`, or run `pod install --project-directory=example/ios` and `pod install --project-directory=test_integration/ios`
- Update `FLUTTER_PACKAGE_PLUGIN_VERSION` in [AblyFlutterVersion.h](ios/ably_pubsub_device_flutter/Sources/ably_pubsub_device_flutter/codec/AblyFlutterVersion.h) to match; `test/ios_plugin_version_test.dart` fails if they differ
- Commit this
4. Run [`github_changelog_generator`](https://github.com/github-changelog-generator/github-changelog-generator) to automate the update of the [CHANGELOG](./CHANGELOG.md). This may require some manual intervention, both in terms of how the command is run and how the change log file is modified. Your mileage may vary:
- The command you will need to run will look something like this: `github_changelog_generator -u ably -p ably-flutter --since-tag v1.2.2 --output delta.md --token $GITHUB_TOKEN_WITH_REPO_ACCESS`. Generate token [here](https://github.com/settings/tokens/new?description=GitHub%20Changelog%20Generator%20token).
Expand Down
Loading
Loading