diff --git a/.github/workflows/prepare-release.yml b/.github/workflows/prepare-release.yml new file mode 100644 index 000000000..9ea4cc892 --- /dev/null +++ b/.github/workflows/prepare-release.yml @@ -0,0 +1,95 @@ +name: Prepare Release + +on: + workflow_dispatch: + inputs: + version: + description: 'Version number (e.g., 3.6.0)' + required: true + type: string + ticket: + description: 'Jira ticket number (e.g., 1234 for SDK-1234)' + required: true + type: string + +permissions: + contents: write + pull-requests: write + +jobs: + prepare-release: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + ref: master + token: ${{ secrets.GITHUB_TOKEN }} + + - name: Validate version format + run: | + if ! [[ "${{ github.event.inputs.version }}" =~ ^[0-9]+\.[0-9]+\.[0-9]+(-[a-zA-Z0-9]+)?$ ]]; then + echo "::error::Invalid version format. Use semantic versioning (e.g., 3.6.0 or 3.6.0-beta1)" + exit 1 + fi + + - uses: actions/setup-node@v4 + with: + node-version: '22' + + - name: Update Changelog + id: update_changelog + run: | + version="${{ github.event.inputs.version }}" + changelog_file="CHANGELOG.md" + + # RN has no [Unreleased] section -- insert a new ## version header at the top + temp_file=$(mktemp) + { + echo "## $version" + echo "" + cat "$changelog_file" + } > "$temp_file" + mv "$temp_file" "$changelog_file" + + echo "See CHANGELOG.md for release notes." > "$RUNNER_TEMP/release-notes.md" + + - name: Bump package.json version + run: npm --no-git-tag-version --allow-same-version version "${{ github.event.inputs.version }}" + + - name: Regenerate build info + run: node scripts/autoCreatePackageInfo.js + + - name: Create Pull Request + uses: peter-evans/create-pull-request@4e1beaa7521e8b457b572c090b25bd3db56bf1c5 # v5 + with: + token: ${{ secrets.GITHUB_TOKEN }} + title: "SDK-${{ github.event.inputs.ticket }}: Prepare for Release ${{ github.event.inputs.version }}" + body: | + # Prepare for Release ${{ github.event.inputs.version }} + + ## SDK Release Checklist + - [ ] CHANGELOG.md updated with release notes under the new version header + - [ ] Version bumped in package.json + - [ ] src/itblBuildInfo.ts regenerated + - [ ] README.md reviewed (if needed) + - [ ] All tests passing + - [ ] Documentation updated (if needed) + branch: "release/SDK-${{ github.event.inputs.ticket }}-${{ github.event.inputs.version }}" + commit-message: "[SDK-${{ github.event.inputs.ticket }}]: Prepare for release ${{ github.event.inputs.version }}" + labels: release + delete-branch: true + + - name: Create Draft GitHub Release + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + version="${{ github.event.inputs.version }}" + + if gh release view "$version" &>/dev/null; then + echo "Draft release $version already exists, skipping." + else + gh release create "$version" \ + --draft \ + --title "$version" \ + --notes-file "$RUNNER_TEMP/release-notes.md" + fi diff --git a/.github/workflows/publish-release.yml b/.github/workflows/publish-release.yml new file mode 100644 index 000000000..599326f57 --- /dev/null +++ b/.github/workflows/publish-release.yml @@ -0,0 +1,76 @@ +name: Publish Release + +on: + workflow_dispatch: + inputs: + version: + description: 'Version to publish (e.g., 3.6.0)' + required: true + type: string + +env: + VERSION: ${{ github.event.inputs.version }} + +permissions: + contents: write + id-token: write + +jobs: + publish-release: + runs-on: ubuntu-latest + environment: npm + steps: + - uses: actions/checkout@v4 + with: + ref: master + + - name: Verify release is ready + run: | + if ! grep -qE "^## $VERSION\b" CHANGELOG.md; then + echo "::error::CHANGELOG.md has no entry for $VERSION. Merge the prepare-release PR to master before running this workflow." + exit 1 + fi + + - uses: actions/setup-node@v4 + with: + node-version: '22' + cache: 'yarn' + registry-url: 'https://registry.npmjs.org' + + - name: Update npm for OIDC support + run: npm install -g npm@latest + + - run: yarn install --frozen-lockfile + + - run: yarn test --maxWorkers=2 + + - run: yarn prepare + + - name: Publish to npm + run: npm publish --provenance + + - name: Publish draft GitHub release and tag main + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + gh release edit "$VERSION" \ + --draft=false \ + --target "$(git rev-parse HEAD)" \ + --latest + + - name: Slack notification + run: | + release_url="https://github.com/${{ github.repository }}/releases/tag/$VERSION" + payload=$(jq -n \ + --arg text ":package: *React Native SDK ${VERSION}* has been released. <${release_url}|View release notes>." \ + '{"text": $text}') + curl -sS -X POST -H 'Content-type: application/json' --data "$payload" "${{ secrets.SLACK_WEBHOOK }}" + + - name: Slack failure notification + if: failure() + run: | + run_url="${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}/attempts/${{ github.run_attempt }}" + payload=$(jq -n \ + --arg text ":alert: React Native SDK release ${VERSION} failed (attempt ${{ github.run_attempt }}). Run: ${run_url}" \ + '{"text": $text}') + curl -sS -X POST -H 'Content-type: application/json' --data "$payload" "${{ secrets.SLACK_WEBHOOK }}"