diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml new file mode 100644 index 0000000..34f5130 --- /dev/null +++ b/.github/workflows/publish.yml @@ -0,0 +1,41 @@ +name: Publish + +# Publishes tag v to pub.dev, then creates the GitHub release from that version's CHANGELOG section. +# pub.dev authenticates the run with GitHub's OIDC token (no stored secret), and only accepts tag-push runs. +# One-time setup: enable "Publishing from GitHub Actions" on pub.dev (repository optimizely/optimizely-flutter-sdk, +# tag pattern v{{version}}, required environment pub.dev), and add required reviewers to the pub.dev environment here. +on: + push: + tags: [ 'v[0-9]+.[0-9]+.[0-9]+*' ] + +jobs: + publish: + runs-on: ubuntu-latest + environment: pub.dev + permissions: + contents: write + id-token: write + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + persist-credentials: false + # Exchanges the OIDC token for a pub.dev credential used by `flutter pub publish` + - uses: dart-lang/setup-dart@v1 + - uses: subosito/flutter-action@v2 + with: + flutter-version: '3.44.0' + channel: 'stable' + - name: Publish to pub.dev + run: flutter pub publish --force + - name: Create GitHub release + env: + GH_TOKEN: ${{ github.token }} + run: | + VERSION="${GITHUB_REF_NAME#v}" + awk -v h="## $VERSION" '$0==h{f=1;next} /^## [0-9]/{if(f)exit} f' CHANGELOG.md > notes.md + FLAGS=() + [[ "$VERSION" == *-* ]] && FLAGS+=(--prerelease) + git merge-base --is-ancestor "$GITHUB_SHA" origin/master || FLAGS+=(--latest=false) + gh release create "$GITHUB_REF_NAME" --verify-tag --title "Release $VERSION" \ + --notes-file notes.md "${FLAGS[@]}" diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..998c405 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,52 @@ +name: Release + +# Merging a version change in pubspec.yaml into master (or a maintenance branch like 3.x) +# pushes tag v, which triggers publish.yml. +# On a release PR it only validates, so a missing CHANGELOG section or a version mismatch fails before merge. +# Run manually (workflow_dispatch) to retry a failed release from the branch's latest commit. +on: + workflow_dispatch: + push: + branches: [ master, '[0-9]+.x' ] + paths: [ pubspec.yaml ] + pull_request: + branches: [ master, '[0-9]+.x' ] + paths: [ pubspec.yaml ] + +permissions: + contents: read + +jobs: + tag: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + persist-credentials: false + - name: Validate version + id: version + run: | + VERSION=$(sed -nE 's/^version: *([^ ]+).*/\1/p' pubspec.yaml) + [[ "$VERSION" =~ ^[0-9]+\.[0-9]+\.[0-9]+(-[0-9A-Za-z.]+)?$ ]] || { echo "Invalid version: $VERSION"; exit 1; } + grep -qF "version = '$VERSION';" lib/package_info.dart || { echo "lib/package_info.dart does not match $VERSION"; exit 1; } + grep -qF "optimizely_flutter_sdk: ^$VERSION" README.md || { echo "README.md does not match $VERSION"; exit 1; } + if git ls-remote --exit-code --tags origin "refs/tags/v$VERSION" >/dev/null; then + echo "v$VERSION already released"; exit 0 + fi + grep -qxF "## $VERSION" CHANGELOG.md || { echo "CHANGELOG.md has no '## $VERSION' section"; exit 1; } + echo "version=$VERSION" >> "$GITHUB_OUTPUT" + - uses: subosito/flutter-action@v2 + if: steps.version.outputs.version + with: + flutter-version: '3.44.0' + channel: 'stable' + - name: Validate package + if: steps.version.outputs.version + run: flutter pub publish --dry-run + - name: Push tag + if: steps.version.outputs.version && github.event_name != 'pull_request' + env: + # A tag pushed with GITHUB_TOKEN would not trigger publish.yml + GH_TOKEN: ${{ secrets.CI_USER_TOKEN }} + VERSION: ${{ steps.version.outputs.version }} + run: gh api "repos/$GITHUB_REPOSITORY/git/refs" -f ref="refs/tags/v$VERSION" -f sha="$GITHUB_SHA" diff --git a/CHANGELOG.md b/CHANGELOG.md index ff3e70b..efceee3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,12 @@ # Optimizely Flutter SDK Changelog +## 4.0.0 +October 15th, 2026 + +### Notes + +* Test entry for release workflow dry-run. DO NOT MERGE. + ## 3.8.0 October 13th, 2026 diff --git a/CLAUDE.md b/CLAUDE.md index 69badbf..e8ce890 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -99,6 +99,13 @@ Claude will execute the full workflow: - ✅ Commit and push - ✅ Create PR +### After the release PR merges (automated) + +- `release.yml` validates the version (pubspec.yaml, package_info.dart, README.md, CHANGELOG section) on the PR, and on merge pushes tag `vX.Y.Z` +- `publish.yml` runs on the tag: publishes to pub.dev (waits for approval in the `pub.dev` environment), then creates the GitHub release from the CHANGELOG section +- Versions with a `-` suffix (e.g. `4.0.0-rc.1`) are released as prereleases +- If either workflow fails, re-run it from the Actions tab + ### Manual Release ```bash @@ -117,11 +124,7 @@ Co-Authored-By: Claude Sonnet 4.5 " git push -u origin prepare-X.Y.Z gh pr create --title "[FSSDK-XXXXX] prepare for release X.Y.Z" -# 6. After merge, create GitHub release -gh release create vX.Y.Z --title "Release X.Y.Z" --draft --target master - -# 7. Publish to pub.dev -flutter pub publish +# 6. After merge, the tag, pub.dev publish and GitHub release are automated (see above) ``` ### CHANGELOG Format diff --git a/README.md b/README.md index c7708c8..101ac04 100644 --- a/README.md +++ b/README.md @@ -37,7 +37,7 @@ Other Flutter platforms are not currently supported by this SDK. To add the flutter-sdk to your project dependencies, include the following in your app's pubspec.yaml: ``` - optimizely_flutter_sdk: ^3.8.0 + optimizely_flutter_sdk: ^4.0.0 ``` Then run diff --git a/lib/package_info.dart b/lib/package_info.dart index 13ad91e..92c31d1 100644 --- a/lib/package_info.dart +++ b/lib/package_info.dart @@ -3,5 +3,5 @@ class PackageInfo { static const String name = 'optimizely_flutter_sdk'; - static const String version = '3.8.0'; + static const String version = '4.0.0'; } diff --git a/pubspec.yaml b/pubspec.yaml index cf731a6..c2414c4 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,6 +1,6 @@ name: optimizely_flutter_sdk description: This repository houses the Flutter SDK for use with Optimizely Feature Experimentation, Optimizely Full Stack (legacy), and Optimizely Rollouts. -version: 3.8.0 +version: 4.0.0 homepage: https://github.com/optimizely/optimizely-flutter-sdk environment: