Priority: MANDATORY Follow these conventions for all commits and deployments.
- 50 characters max for the subject line (tag + scope + message combined)
- Everything after the tag MUST be lowercase
- No trailing period
- Use imperative mood ("add" not "added")
When a commit targets a specific package or library, include the scope:
feat(rn): add offer redemption
fix(expo): resolve purchase crash
fix(flutter): correct discount mapping
feat(kmp): add subscription flow
chore(godot): bump openiap dep
fix(apple): handle StoreKit edge case
fix(google): update billing client
For cross-cutting or monorepo-wide changes:
feat: add RC promote to releases
fix: update repo URLs in package.json
chore: update CI workflow names
First letter MUST be uppercase:
Add user authentication system
Fix purchase validation error
| Scope | Package/Library |
|---|---|
apple |
packages/apple |
google |
packages/google |
spec |
packages/gql |
docs |
packages/docs |
rn |
libraries/react-native-iap |
expo |
libraries/expo-iap |
flutter |
libraries/flutter_inapp_purchase |
kmp |
libraries/kmp-iap |
godot |
libraries/godot-iap |
| Tag | Usage |
|---|---|
feat: |
New feature |
fix: |
Bug fix |
docs: |
Documentation changes |
style: |
Code style changes (formatting) |
refactor: |
Code refactoring |
test: |
Adding or updating tests |
chore: |
Maintenance tasks |
Via GitHub Actions UI:
- Go to Actions -> "Apple Release"
- Click "Run workflow"
- Enter version (e.g.,
1.2.24) - Click "Run workflow"
What happens:
- Updates
openiap-versions.json - Commits version change to main
- Creates Git tag
apple-v1.2.24 - Builds and tests Swift package
- Validates and publishes to CocoaPods
- Creates GitHub Release
Result:
- CocoaPods:
pod 'openiap', '~> 1.2.24' - Swift Package Manager:
.package(url: "https://github.com/hyodotdev/openiap.git", from: "1.2.24")
Via GitHub Actions UI:
- Go to Actions -> "Google Release"
- Click "Run workflow"
- Enter version (e.g.,
1.2.14) - Click "Run workflow"
What happens:
- Updates
openiap-versions.json - Commits version change to main
- Creates Git tag
google-v1.2.14 - Builds and tests Android library
- Publishes to Maven Central
- Creates GitHub Release with artifacts (AAR, JAR)
Result:
- Maven Central:
implementation("io.github.hyochan.openiap:openiap-google:1.2.14")
# From monorepo root
npm run deployThis will:
- Build and deploy documentation to Vercel
- Trigger GitHub Actions workflow to:
- Regenerate types for all platforms
- Create release artifacts (TypeScript, Dart, Kotlin, Swift)
- Create Git tag
v<spec> - Create GitHub Release with artifacts
npm run deploy uses the current spec value from
openiap-versions.json. To deploy a different spec version, pass it
explicitly:
npm run deploy 1.2.0Each package uses a different tag format for GitHub Releases:
| Package | Tag Format | Example |
|---|---|---|
| Apple | {version} (no prefix) |
2.1.0 |
google-{version} |
google-2.1.0 |
|
| React Native | react-native-iap-{version} |
react-native-iap-15.2.0 |
| Expo | expo-iap-{version} |
expo-iap-4.1.0 |
| Flutter | flutter-iap-{version} |
flutter-iap-9.2.0 |
| KMP | kmp-iap-{version} |
kmp-iap-2.2.0 |
| Godot | godot-iap-{version} |
godot-iap-2.2.0 |
| Docs | docs-{version} |
docs-1.2.0 |
Apple is the exception — it tags with the bare semver version because CocoaPods and Swift Package Manager resolve directly from the Git tag.
When documenting release package versions in
packages/docs/src/pages/docs/updates/releases.tsx, do not infer versions from
adjacent release notes or assume every package moved in lockstep.
Use these checks before writing a release list:
| Package | Metadata / Tag Check |
|---|---|
| Apple | jq -r '.apple' openiap-versions.json; tag {version} |
jq -r '.google' openiap-versions.json; tag google-{version} |
|
| React Native | jq -r '.version' libraries/react-native-iap/package.json; tag react-native-iap-{version} |
| Expo | jq -r '.version' libraries/expo-iap/package.json; tag expo-iap-{version} |
| Flutter | awk '/^version:/{print $2}' libraries/flutter_inapp_purchase/pubspec.yaml; tag flutter-iap-{version} |
| Godot | sed -n 's/^version="\\(.*\\)"/\\1/p' libraries/godot-iap/addons/godot-iap/plugin.cfg; tag godot-iap-{version} |
| KMP | sed -n 's/^libraryVersion=//p' libraries/kmp-iap/gradle.properties; tag kmp-iap-{version} |
| MAUI | read <PackageVersion> from libraries/maui-iap/src/OpenIap.Maui/OpenIap.Maui.csproj; tag maui-iap-{version} |
If the release is not published yet, use planned wording and plain text. If the
release is published, verify the tag exists with gh release view <tag> before
linking it. This prevents stale Package Releases tables such as documenting
maui-iap 1.0.1 when the actual release tag is maui-iap-1.0.2.
- Deprecated repositories:
openiap-appleandopeniap-googleare no longer used - Monorepo only: All releases are now managed from this monorepo
- Separate versioning: Apple and Google packages have independent versions
- Swift Package Manager: Automatically works via Git tags, no separate deployment step
CRITICAL: NEVER manually edit openiap-versions.json
This file is automatically managed by CI/CD workflows during releases:
- Apple releases update
appleversion - Google releases update
googleversion - GQL releases update
specversion - Deploy script (
npm run deploy) uses the currentspecversion by default, and updatesspeconly when an explicit version is passed
The manifest is only for the shared spec and native platform packages:
spec, google, and apple. Framework library package versions
(react-native-iap, expo-iap, flutter_inapp_purchase, godot-iap,
kmp-iap, maui-iap) must stay in each library's own package metadata and
release workflow, not as extra keys in openiap-versions.json.
Manual edits will cause version conflicts and deployment issues. Always use the GitHub Actions workflows or deploy script to update versions.
Why this matters: If a feature PR sets apple: "2.1.1" manually, and then CI auto-bumps on release, CI sees "current is 2.1.1" and bumps to 2.1.2 — skipping 2.1.1 entirely. The published tag becomes 2.1.2 with no 2.1.1 ever existing.
Rule: Feature PRs must NEVER touch version fields in openiap-versions.json. Version bumps happen only via:
- Release workflows (Apple Release, Google Release)
- Deploy script (
npm run deploy, optionallynpm run deploy <version>) - CI auto-bump after merge