Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
68 commits
Select commit Hold shift + click to select a range
6aea970
Purchase connector for flutter
pazlavi Jun 13, 2024
d92976e
runOnUi
pazlavi Jun 16, 2024
7b3f4e5
Nullable
pazlavi Jun 16, 2024
cc4dc4a
handle callbacks
pazlavi Jun 16, 2024
f201299
ui thread callback
pazlavi Jun 16, 2024
03db5e4
swift bridge file
pazlavi Jun 16, 2024
8729a3d
register callback
pazlavi Jun 16, 2024
7d78d0c
docs
pazlavi Jun 17, 2024
6529458
fixed the issue with MediationNetwork enums on Android
Dani-Koza-AF Oct 27, 2024
b85b1a4
Merge pull request #353 from AppsFlyerSDK/dev/DELIVERY-71973/mediatio…
Dani-Koza-AF Oct 28, 2024
a58a49b
Merge remote-tracking branch 'origin/development' into development
Dani-Koza-AF Oct 28, 2024
25fb530
This should fix the NullPointerException
Dani-Koza-AF Oct 30, 2024
4f4ee27
Merge pull request #357 from AppsFlyerSDK/DELIVERY-63011/fix-android-…
Dani-Koza-AF Oct 30, 2024
fa71c23
Merge remote-tracking branch 'origin/development' into development
Dani-Koza-AF Oct 31, 2024
5dab6aa
Delivery 76214/update purchase connector version (#363)
Dani-Koza-AF Dec 2, 2024
2922511
adding a note on the supported StoreKit to docs
Dani-Koza-AF Jan 13, 2025
cc74ddb
typo fix
Dani-Koza-AF Jan 13, 2025
b27f469
Squashed commit of the following:
Dani-Koza-AF Jan 16, 2025
b5ff928
Merge branch 'development' into feature/add_purchase_connector
Dani-Koza-AF Feb 19, 2025
96560ec
Merge branch 'feature/add_purchase_connector' into development
Dani-Koza-AF Feb 19, 2025
e01cc25
closing potential memory leaks
Dani-Koza-AF Feb 19, 2025
93a6b03
removed duplicated declarations =
Dani-Koza-AF Feb 19, 2025
fa40e5b
updated example project dependencies
Dani-Koza-AF Feb 20, 2025
ac1d0ae
Push notification data collection documentation updates (#381)
Dani-Koza-AF Mar 27, 2025
0f124f9
reverting addition of PC
Dani-Koza-AF Apr 9, 2025
f14a8b9
post revert fixes
Dani-Koza-AF Apr 10, 2025
ec30faa
lint
Dani-Koza-AF Apr 10, 2025
ca4743d
Fixes of tests and typos
Dani-Koza-AF Apr 10, 2025
e086a26
Dev/update manual consent api (#383)
Dani-Koza-AF Apr 28, 2025
c97b5af
Merge branch 'master' into development
Dani-Koza-AF Jun 26, 2025
49c64e1
fixed Locale issue by forcing toUpperCase(Locale.ENGLISH) (#395)
Dani-Koza-AF Jun 26, 2025
83789ce
Doc fix (#400)
Dani-Koza-AF Jul 14, 2025
5f04fa3
Add purchase connector to development branch (#402)
Dani-Koza-AF Jul 27, 2025
85c3360
Immediate actions to prevent NullPointerExceptions (#403)
Dani-Koza-AF Jul 30, 2025
cbf7c67
Latest release updates - Docs + new API for Android (#406)
Dani-Koza-AF Aug 3, 2025
5a5a390
Merge branch 'master' into development
Dani-Koza-AF Aug 20, 2025
12f7a35
Updated to AppsFlyer SDK v6.17.3 for both Android and iOS (#410)
Dani-Koza-AF Aug 24, 2025
3313a9a
Merge branch 'master' into development
Dani-Koza-AF Sep 29, 2025
8b923b1
Added an important note to deep-links docs (#416)
Dani-Koza-AF Sep 29, 2025
bdf22a6
versions bumped + docs updated (#417)
Dani-Koza-AF Sep 30, 2025
c3b40c8
Setting up the full CI/CD (#419)
Dani-Koza-AF Oct 9, 2025
43d01e9
test: verify CI workflow (#420)
Dani-Koza-AF Oct 15, 2025
67a015f
CI fix - Jira ntegration
Dani-Koza-AF Oct 15, 2025
b362556
CI fix
Dani-Koza-AF Oct 15, 2025
0b3d079
yet another fix to CI
Dani-Koza-AF Oct 15, 2025
b720c78
Hope it's the last CI fix
Dani-Koza-AF Oct 15, 2025
0e4fa80
fix: update Jira API to use /search/jql endpoint (fixes HTTP 410)
Dani-Koza-AF Oct 15, 2025
f968d64
readme update and dart analyze fix
Dani-Koza-AF Oct 21, 2025
9455db3
verions bumps + modernized to flutter lint
Dani-Koza-AF Oct 21, 2025
9a41db1
Documentation Updates - regarding push notifications
Dani-Koza-AF Oct 21, 2025
5073a6c
Merge branch 'master' into development
Dani-Koza-AF Nov 2, 2025
1430c23
bumped up Android version (#425)
Dani-Koza-AF Nov 2, 2025
48a0b00
refine CI
Dani-Koza-AF Nov 2, 2025
2bb1183
Merge branch 'master' into development
Dani-Koza-AF Nov 12, 2025
cc9c19b
moved the init to the right place
ShakedEilatAF Dec 10, 2025
a2efb97
Merge pull request #428 from AppsFlyerSDK/dev/DELIVERY106333/StrictMo…
ShakedEilatAF Dec 10, 2025
1730b4e
Fix/ci adjustments (#427)
Dani-Koza-AF Dec 28, 2025
d46bc2b
SDK updates deprecate V1 purchase validation, improve iOS error handl…
Dani-Koza-AF Dec 29, 2025
e7d6be8
fix: remove toJSON() causing extra quotes in PR creation
Dani-Koza-AF Dec 30, 2025
f9f12c5
fix: add .pubignore and handle RC dry-run warnings gracefully
Dani-Koza-AF Dec 30, 2025
c42df62
lint
Dani-Koza-AF Dec 30, 2025
ed44a6a
fix: redesign promote-release workflow for org constraints
Dani-Koza-AF Dec 30, 2025
bef7454
fix: handle exit code 65 (warnings) in production-release validation
Dani-Koza-AF Dec 30, 2025
4ecbc37
untrack files that should be gitignored
Dani-Koza-AF Dec 30, 2025
dabf605
fix: remove secrets from if condition in promote-release workflow
Dani-Koza-AF Dec 30, 2025
f301f67
fix(ios): adopt FlutterSceneLifeCycleDelegate for UIScene deep link s…
Kobikg78 Mar 25, 2026
ecf01cd
chore: bump plugin to 6.17.9, Android SDK to 6.17.6, iOS SDK to 6.17.9
Kobikg78 Mar 25, 2026
ff81b32
Merge branch 'master' into releases/6.x.x/6.17.x/6.17.9-rc1
Kobikg78 Mar 25, 2026
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
17 changes: 17 additions & 0 deletions .github/workflows/production-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -220,7 +220,24 @@ jobs:
- name: 🔍 Validate package
run: |
echo "Running pub publish dry-run to validate package..."
# Run dry-run and capture exit code
# Exit code 65 = warnings only (acceptable, e.g., gitignored files)
# Exit code 0 = success
# Other exit codes = real errors
set +e
flutter pub publish --dry-run
EXIT_CODE=$?
set -e

if [ $EXIT_CODE -eq 0 ]; then
echo "✅ Package validation passed with no warnings"
elif [ $EXIT_CODE -eq 65 ]; then
echo "⚠️ Package validation passed with warnings (acceptable)"
echo "Warnings don't prevent publishing"
else
echo "❌ Package validation failed with exit code $EXIT_CODE"
exit $EXIT_CODE
fi

- name: 📝 Check pub.dev credentials
run: |
Expand Down
263 changes: 187 additions & 76 deletions .github/workflows/promote-release.yml
Original file line number Diff line number Diff line change
@@ -1,97 +1,208 @@
name: Promote Release - Merge on QA Pass and Publish
# =============================================================================
# Promote Release - Prepare Release Branch for Production
# =============================================================================
#
# Purpose: When QA approves an RC, this workflow prepares the release branch
# for production by removing the -rc suffix from version numbers.
#
# IMPORTANT: This workflow does NOT merge the PR (org rules prevent bot merges).
# Instead, it updates the release branch so when a human merges, the version
# is clean (e.g., 6.17.8 instead of 6.17.8-rc1).
#
# Flow:
# 1. QA tests the RC version
# 2. QA adds label "pass QA ready for deploy" to the PR
# 3. This workflow triggers and:
# - Updates the release branch to remove -rcN suffix
# - Updates all version files
# - Commits changes to the release branch
# 4. Human reviews and manually merges the PR
# 5. production-release.yml triggers on merge
#
# =============================================================================

name: Promote Release - Prepare for Production

on:
pull_request:
types: [labeled, synchronize, reopened, ready_for_review]
branches:
- master
pull_request_review:
types: [submitted]
types: [labeled]
branches:
- master

concurrency:
group: promote-release-${{ github.event.pull_request.number || github.run_id }}
group: promote-release-${{ github.event.pull_request.number }}
cancel-in-progress: true

jobs:
gate-and-merge:
name: 🔐 Gate, Verify Checks, and Merge
if: >-
${ { github.event.pull_request.head.ref } } == '' || startsWith(github.event.pull_request.head.ref, 'releases/')
# ===========================================================================
# Job 1: Prepare Release Branch for Production
# ===========================================================================
prepare-for-production:
name: 🚀 Prepare Release for Production
# Only run when the specific label is added AND it's from a releases/ branch
if: |
github.event.label.name == 'pass QA ready for deploy' &&
startsWith(github.event.pull_request.head.ref, 'releases/')
runs-on: ubuntu-latest
permissions:
contents: write
pull-requests: write
checks: read
statuses: read

outputs:
merged: ${{ steps.merge.outputs.merged }}
version: ${{ steps.version.outputs.version }}
version: ${{ steps.compute-version.outputs.version }}
release_branch: ${{ steps.compute-version.outputs.release_branch }}

steps:
- name: 🧠 Evaluate conditions
id: eval
uses: actions/github-script@v7
- name: 📥 Checkout release branch
uses: actions/checkout@v4
with:
script: |
const core = require('@actions/core');
const pr = context.payload.pull_request || (await github.rest.pulls.get({owner: context.repo.owner, repo: context.repo.repo, pull_number: context.payload.pull_request?.number || context.issue.number})).data;
if (!pr) core.setFailed('No PR context');
const hasLabel = pr.labels.some(l => l.name === 'pass QA ready for deploy');
if (!hasLabel) core.setFailed('Required label not present: pass QA ready for deploy');
// Check approvals
const reviews = await github.rest.pulls.listReviews({owner: context.repo.owner, repo: context.repo.repo, pull_number: pr.number});
const approved = reviews.data.some(r => r.state === 'APPROVED');
if (!approved) core.setFailed('No approval found on the PR');
core.setOutput('pr_number', pr.number.toString());
- name: ⏳ Wait for required status checks to pass
ref: ${{ github.event.pull_request.head.ref }}
fetch-depth: 0
token: ${{ secrets.GITHUB_TOKEN }}

- name: 🔍 Compute production version
id: compute-version
run: |
RELEASE_BRANCH="${{ github.event.pull_request.head.ref }}"
echo "Release branch: $RELEASE_BRANCH"

# Get current version from pubspec.yaml
CURRENT_VERSION=$(grep "^version:" pubspec.yaml | sed 's/version: //' | tr -d ' ')
echo "Current version: $CURRENT_VERSION"

# Remove -rcN suffix to get production version
PROD_VERSION=$(echo "$CURRENT_VERSION" | sed 's/-rc[0-9]*$//')
echo "Production version: $PROD_VERSION"

# Validate it's different (was an RC version)
if [[ "$CURRENT_VERSION" == "$PROD_VERSION" ]]; then
echo "⚠️ Version doesn't have -rc suffix. Already production ready?"
echo "Current: $CURRENT_VERSION"
fi

echo "version=$PROD_VERSION" >> $GITHUB_OUTPUT
echo "current_version=$CURRENT_VERSION" >> $GITHUB_OUTPUT
echo "release_branch=$RELEASE_BRANCH" >> $GITHUB_OUTPUT

- name: 📝 Update pubspec.yaml to production version
run: |
VERSION='${{ steps.compute-version.outputs.version }}'
echo "Updating pubspec.yaml to production version: $VERSION"
sed -i "s/^version: .*/version: $VERSION/" pubspec.yaml
grep "^version:" pubspec.yaml

- name: 📝 Update plugin version constants (Android)
run: |
VERSION='${{ steps.compute-version.outputs.version }}'
FILE="android/src/main/java/com/appsflyer/appsflyersdk/AppsFlyerConstants.java"
if [ -f "$FILE" ]; then
sed -i "s/kPluginVersion = \".*\"/kPluginVersion = \"$VERSION\"/" "$FILE"
echo "Updated Android constants:"
grep "kPluginVersion" "$FILE"
fi

- name: 📝 Update plugin version constants (iOS)
run: |
VERSION='${{ steps.compute-version.outputs.version }}'
FILE="ios/Classes/AppsflyerSdkPlugin.m"
if [ -f "$FILE" ]; then
sed -i "s/kPluginVersion = @\".*\"/kPluginVersion = @\"$VERSION\"/" "$FILE"
echo "Updated iOS constants:"
grep "kPluginVersion" "$FILE"
fi

- name: 💾 Commit and push version changes
run: |
VERSION='${{ steps.compute-version.outputs.version }}'
CURRENT='${{ steps.compute-version.outputs.current_version }}'

git config user.email "github-actions[bot]@users.noreply.github.com"
git config user.name "github-actions[bot]"

if [[ -n $(git status -s) ]]; then
git add pubspec.yaml android/ ios/
git commit -m "chore: prepare production release $VERSION (from $CURRENT)"
git push
echo "✅ Pushed version update to release branch"
else
echo "ℹ️ No version changes needed"
fi

- name: 📝 Update PR description
uses: actions/github-script@v7
with:
script: |
const prNumber = Number(core.getInput('pr_number', { required: false })) || ${{ steps.eval.outputs.pr_number || '0' }};
const { data: pr } = await github.rest.pulls.get({ owner: context.repo.owner, repo: context.repo.repo, pull_number: prNumber });
const ref = pr.head.sha;
const start = Date.now();
const timeoutMs = 60*60*1000; // 60 minutes
const sleep = ms => new Promise(r => setTimeout(r, ms));
while (true) {
const { data: combined } = await github.rest.repos.getCombinedStatusForRef({ owner: context.repo.owner, repo: context.repo.repo, ref });
const checksOk = combined.state === 'success';
if (checksOk) break;
if (Date.now() - start > timeoutMs) throw new Error('Timeout waiting for status checks to pass');
core.info(`Waiting for checks. Current state: ${combined.state}`);
await sleep(15000);
}
- name: 📥 Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: 🔀 Merge PR immediately
id: merge
const version = '${{ steps.compute-version.outputs.version }}';
const currentVersion = '${{ steps.compute-version.outputs.current_version }}';
const pr = context.payload.pull_request;

const newBody = `### Production Release ${version}

**Status:** ✅ Ready for manual merge

**Version updated:** ${currentVersion} → ${version}

---

${pr.body || ''}

---

**Next steps:**
1. ✅ QA approved (label added)
2. ✅ Version updated to production (${version})
3. ⏳ **Awaiting manual merge** by a maintainer
4. ⏳ Production release will trigger automatically after merge
`;

await github.rest.pulls.update({
owner: context.repo.owner,
repo: context.repo.repo,
pull_number: pr.number,
body: newBody
});

- name: 📢 Add comment to PR
uses: actions/github-script@v7
with:
script: |
const prNumber = Number(${ { steps.eval.outputs.pr_number } });
const { data: pr } = await github.rest.pulls.get({ owner: context.repo.owner, repo: context.repo.repo, pull_number: prNumber });
if (pr.merged) { core.setOutput('merged', 'true'); return; }
const method = 'merge'; // use repo default merge method
await github.rest.pulls.merge({ owner: context.repo.owner, repo: context.repo.repo, pull_number: pr.number, merge_method: method });
core.setOutput('merged', 'true');
- name: 📝 Read version from pubspec on master
id: version
run: |
git fetch origin master:master
git checkout master
VER=$(grep '^version:' pubspec.yaml | sed 's/version: //' | tr -d ' ')
echo "version=$VER" >> $GITHUB_OUTPUT
const version = '${{ steps.compute-version.outputs.version }}';

await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.payload.pull_request.number,
body: `## 🚀 Ready for Production Release

call-production:
name: 🚀 Production Release
needs: gate-and-merge
if: needs.gate-and-merge.outputs.merged == 'true'
uses: ./.github/workflows/production-release.yml
with:
version: ${{ needs.gate-and-merge.outputs.version }}
skip_tests: false
dry_run: false
secrets: inherit
The release branch has been updated:
- **Version:** \`${version}\` (removed -rc suffix)
- **All version files updated**

### Next Steps
1. **Review the changes** in this PR
2. **Merge this PR** when ready
3. The production release workflow will automatically:
- Publish \`${version}\` to pub.dev
- Create GitHub release
- Send notifications

> ⚠️ **Note:** This PR requires manual merge due to branch protection rules.`
});

# ===========================================================================
# Job 2: Notify Team
# ===========================================================================
notify-ready:
name: 📢 Notify Ready for Merge
needs: prepare-for-production
runs-on: ubuntu-latest
if: always() && needs.prepare-for-production.result == 'success'

steps:
- name: 📨 Send Slack notification
uses: slackapi/slack-github-action@v1
with:
payload: |
{
"text": "<!here>\n:white_check_mark: *Flutter Plugin Ready for Production*\n\nVersion: ${{ needs.prepare-for-production.outputs.version }}\nPR: ${{ github.event.pull_request.html_url }}\n\n*Action Required:* A maintainer needs to manually merge the PR to trigger the production release."
}
env:
SLACK_WEBHOOK_URL: ${{ secrets.CI_SLACK_WEBHOOK_URL }}
continue-on-error: true # Will gracefully fail if webhook not configured
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -115,3 +115,8 @@ node_modules/
covBadgeGen.js
coverage/
.env

# AI agent tooling and E2E scripts (not part of plugin release)
.claude/
scripts/
example/
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
# Versions

## 6.17.9

- Updated Android SDK from 6.17.5 to 6.17.6
- Updated iOS SDK from 6.17.8 to 6.17.9
- Updated iOS Purchase Connector from 6.17.8 to 6.17.9

## 6.17.8

- Updated Android SDK from 6.17.4 to 6.17.5
Expand Down
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,13 @@ To do so, please follow [this article](https://support.appsflyer.com/hc/en-us/ar

## SDK Versions

- Android AppsFlyer SDK **v6.17.5**
- iOS AppsFlyer SDK **v6.17.8**
- Android AppsFlyer SDK **v6.17.6**
- iOS AppsFlyer SDK **v6.17.9**

### Purchase Connector versions

- Android 2.2.0
- iOS 6.17.8
- iOS 6.17.9

## ❗❗ Breaking changes when updating to v6.x.x❗❗

Expand Down
2 changes: 1 addition & 1 deletion android/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ android {
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'androidx.appcompat:appcompat:1.0.0'
implementation 'com.appsflyer:af-android-sdk:6.17.5'
implementation 'com.appsflyer:af-android-sdk:6.17.6'
implementation 'com.android.installreferrer:installreferrer:2.2'
// implementation 'androidx.core:core-ktx:1.13.1'
if (includeConnector) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package com.appsflyer.appsflyersdk;

public final class AppsFlyerConstants {
final static String PLUGIN_VERSION = "6.17.8";
final static String PLUGIN_VERSION = "6.17.9";
final static String AF_APP_INVITE_ONE_LINK = "appInviteOneLink";
final static String AF_HOST_PREFIX = "hostPrefix";
final static String AF_HOST_NAME = "hostName";
Expand Down
20 changes: 0 additions & 20 deletions covBadgeGen.js

This file was deleted.

2 changes: 0 additions & 2 deletions example/.env

This file was deleted.

Loading
Loading