Release Package #7
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Release Package | |
| on: | |
| workflow_dispatch: | |
| inputs: | |
| dry_run: | |
| description: 'Dry run (skip actual publish)' | |
| required: true | |
| type: boolean | |
| default: true | |
| npm_tag: | |
| description: 'NPM tag (e.g., latest, beta, next)' | |
| required: true | |
| type: string | |
| default: 'latest' | |
| version: | |
| description: 'Version override (optional, e.g., 3.0.0, or "auto" to auto-increment)' | |
| required: false | |
| type: string | |
| default: 'auto' | |
| jobs: | |
| release: | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 10 | |
| permissions: | |
| contents: write | |
| id-token: write | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v5 | |
| with: | |
| fetch-depth: 0 | |
| token: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Setup Node.js | |
| uses: actions/setup-node@v4 | |
| with: | |
| node-version: 20 | |
| cache: yarn | |
| - name: Configure git | |
| run: | | |
| git config user.name "github-actions[bot]" | |
| git config user.email "github-actions[bot]@users.noreply.github.com" | |
| - name: Install dependencies | |
| run: yarn install --frozen-lockfile | |
| - name: Build library | |
| run: yarn prepare | |
| - name: Check linting and formatting | |
| run: yarn precommit | |
| - name: Determine version | |
| id: determine_version | |
| run: | | |
| PACKAGE_NAME=$(cat package.json | grep '"name"' | head -1 | awk -F: '{ print $2 }' | sed 's/[",]//g' | xargs) | |
| CURRENT_VERSION=$(cat package.json | grep '"version"' | head -1 | awk -F: '{ print $2 }' | sed 's/[",]//g' | xargs) | |
| VERSION_INPUT="${{ inputs.version }}" | |
| if [ "$VERSION_INPUT" = "auto" ]; then | |
| echo "Auto-increment mode enabled" | |
| # Check if current version is already published | |
| if npm view "$PACKAGE_NAME@$CURRENT_VERSION" version 2>/dev/null; then | |
| echo "⚠️ Version $CURRENT_VERSION is already published, auto-incrementing..." | |
| # Parse version (supports beta.X format) | |
| if [[ $CURRENT_VERSION =~ ^(.+)-beta\.([0-9]+)$ ]]; then | |
| BASE="${BASH_REMATCH[1]}" | |
| BETA_NUM="${BASH_REMATCH[2]}" | |
| NEW_BETA=$((BETA_NUM + 1)) | |
| NEW_VERSION="$BASE-beta.$NEW_BETA" | |
| echo "Incrementing beta version: $CURRENT_VERSION -> $NEW_VERSION" | |
| elif [[ $CURRENT_VERSION =~ ^([0-9]+)\.([0-9]+)\.([0-9]+)$ ]]; then | |
| MAJOR="${BASH_REMATCH[1]}" | |
| MINOR="${BASH_REMATCH[2]}" | |
| PATCH="${BASH_REMATCH[3]}" | |
| NEW_PATCH=$((PATCH + 1)) | |
| NEW_VERSION="$MAJOR.$MINOR.$NEW_PATCH" | |
| echo "Incrementing patch version: $CURRENT_VERSION -> $NEW_VERSION" | |
| else | |
| echo "❌ Unable to parse version format: $CURRENT_VERSION" | |
| exit 1 | |
| fi | |
| # Update package.json | |
| sed -i "s/\"version\": \"$CURRENT_VERSION\"/\"version\": \"$NEW_VERSION\"/" package.json | |
| echo "version=$NEW_VERSION" >> $GITHUB_OUTPUT | |
| echo "version_changed=true" >> $GITHUB_OUTPUT | |
| else | |
| echo "✅ Version $CURRENT_VERSION is not yet published, using as-is" | |
| echo "version=$CURRENT_VERSION" >> $GITHUB_OUTPUT | |
| echo "version_changed=false" >> $GITHUB_OUTPUT | |
| fi | |
| elif [ -n "$VERSION_INPUT" ]; then | |
| echo "Using specified version: $VERSION_INPUT" | |
| sed -i "s/\"version\": \"$CURRENT_VERSION\"/\"version\": \"$VERSION_INPUT\"/" package.json | |
| echo "version=$VERSION_INPUT" >> $GITHUB_OUTPUT | |
| echo "version_changed=true" >> $GITHUB_OUTPUT | |
| else | |
| echo "Using version from package.json: $CURRENT_VERSION" | |
| echo "version=$CURRENT_VERSION" >> $GITHUB_OUTPUT | |
| echo "version_changed=false" >> $GITHUB_OUTPUT | |
| fi | |
| - name: Check if version already published | |
| id: check_published | |
| run: | | |
| PACKAGE_NAME=$(cat package.json | grep '"name"' | head -1 | awk -F: '{ print $2 }' | sed 's/[",]//g' | xargs) | |
| VERSION="${{ steps.determine_version.outputs.version }}" | |
| if npm view "$PACKAGE_NAME@$VERSION" version 2>/dev/null; then | |
| echo "published=true" >> $GITHUB_OUTPUT | |
| echo "⚠️ Version $VERSION is already published to NPM" | |
| else | |
| echo "published=false" >> $GITHUB_OUTPUT | |
| echo "✅ Version $VERSION is not yet published" | |
| fi | |
| - name: Generate release notes | |
| id: release_notes | |
| run: | | |
| VERSION="${{ steps.determine_version.outputs.version }}" | |
| PREV_TAG=$(git describe --tags --abbrev=0 2>/dev/null || echo "") | |
| # Get commits and save to temp file | |
| if [ -z "$PREV_TAG" ]; then | |
| echo "No previous tag found, using all commits" | |
| git log --pretty=format:"%s (%h)" --no-merges > commits.txt | |
| else | |
| echo "Generating changelog from $PREV_TAG to HEAD" | |
| git log $PREV_TAG..HEAD --pretty=format:"%s (%h)" --no-merges > commits.txt | |
| fi | |
| # Categorize commits into separate files | |
| touch features.txt fixes.txt docs.txt chores.txt refactors.txt others.txt | |
| while IFS= read -r commit; do | |
| if [[ $commit =~ ^feat(\(|:) ]]; then | |
| echo "- $commit" >> features.txt | |
| elif [[ $commit =~ ^fix(\(|:) ]]; then | |
| echo "- $commit" >> fixes.txt | |
| elif [[ $commit =~ ^docs?(\(|:) ]]; then | |
| echo "- $commit" >> docs.txt | |
| elif [[ $commit =~ ^chore(\(|:) ]]; then | |
| echo "- $commit" >> chores.txt | |
| elif [[ $commit =~ ^refactor(\(|:) ]]; then | |
| echo "- $commit" >> refactors.txt | |
| else | |
| echo "- $commit" >> others.txt | |
| fi | |
| done < commits.txt | |
| # Build release notes | |
| echo "## What's Changed" > release_notes.txt | |
| echo "" >> release_notes.txt | |
| if [ -s features.txt ]; then | |
| echo "### ✨ Features" >> release_notes.txt | |
| echo "" >> release_notes.txt | |
| cat features.txt >> release_notes.txt | |
| echo "" >> release_notes.txt | |
| echo "" >> release_notes.txt | |
| fi | |
| if [ -s fixes.txt ]; then | |
| echo "### 🐛 Bug Fixes" >> release_notes.txt | |
| echo "" >> release_notes.txt | |
| cat fixes.txt >> release_notes.txt | |
| echo "" >> release_notes.txt | |
| echo "" >> release_notes.txt | |
| fi | |
| if [ -s refactors.txt ]; then | |
| echo "### ♻️ Refactors" >> release_notes.txt | |
| echo "" >> release_notes.txt | |
| cat refactors.txt >> release_notes.txt | |
| echo "" >> release_notes.txt | |
| echo "" >> release_notes.txt | |
| fi | |
| if [ -s docs.txt ]; then | |
| echo "### 📚 Documentation" >> release_notes.txt | |
| echo "" >> release_notes.txt | |
| cat docs.txt >> release_notes.txt | |
| echo "" >> release_notes.txt | |
| echo "" >> release_notes.txt | |
| fi | |
| if [ -s chores.txt ]; then | |
| echo "### 🧹 Chores" >> release_notes.txt | |
| echo "" >> release_notes.txt | |
| cat chores.txt >> release_notes.txt | |
| echo "" >> release_notes.txt | |
| echo "" >> release_notes.txt | |
| fi | |
| if [ -s others.txt ]; then | |
| echo "### 📦 Other Changes" >> release_notes.txt | |
| echo "" >> release_notes.txt | |
| cat others.txt >> release_notes.txt | |
| echo "" >> release_notes.txt | |
| echo "" >> release_notes.txt | |
| fi | |
| echo "**Full Changelog**: https://github.com/${{ github.repository }}/compare/${PREV_TAG}...v${VERSION}" >> release_notes.txt | |
| # Cleanup temp files | |
| rm -f commits.txt features.txt fixes.txt docs.txt chores.txt refactors.txt others.txt | |
| echo "notes_file=release_notes.txt" >> $GITHUB_OUTPUT | |
| - name: Commit version bump (if version was updated) | |
| if: ${{ steps.determine_version.outputs.version_changed == 'true' && !inputs.dry_run }} | |
| run: | | |
| git add package.json | |
| git commit -m "chore: bump version to ${{ steps.determine_version.outputs.version }}" || echo "No changes to commit" | |
| git push origin main | |
| - name: Create Git tag | |
| if: ${{ !inputs.dry_run }} | |
| run: | | |
| VERSION="${{ steps.determine_version.outputs.version }}" | |
| git tag -a "v$VERSION" -m "Release v$VERSION" | |
| git push origin "v$VERSION" | |
| - name: Publish to NPM (Dry Run) | |
| if: ${{ inputs.dry_run }} | |
| run: | | |
| echo "🔍 DRY RUN MODE - Would publish with:" | |
| echo " Version: ${{ steps.determine_version.outputs.version }}" | |
| echo " Tag: ${{ inputs.npm_tag }}" | |
| echo " Already published: ${{ steps.check_published.outputs.published }}" | |
| npm pack --dry-run | |
| - name: Setup NPM authentication | |
| if: ${{ !inputs.dry_run && steps.check_published.outputs.published == 'false' }} | |
| run: | | |
| echo "//registry.npmjs.org/:_authToken=${{ secrets.NPM_TOKEN }}" > ~/.npmrc | |
| - name: Publish to NPM | |
| if: ${{ !inputs.dry_run && steps.check_published.outputs.published == 'false' }} | |
| run: | | |
| npm publish --tag ${{ inputs.npm_tag }} --provenance --access public | |
| - name: Create GitHub Release (Dry Run) | |
| if: ${{ inputs.dry_run }} | |
| run: | | |
| echo "🔍 DRY RUN MODE - Would create GitHub release:" | |
| echo " Tag: v${{ steps.determine_version.outputs.version }}" | |
| echo " Title: Release v${{ steps.determine_version.outputs.version }}" | |
| echo "" | |
| echo "Release notes:" | |
| cat ${{ steps.release_notes.outputs.notes_file }} | |
| - name: Create GitHub Release | |
| if: ${{ !inputs.dry_run }} | |
| env: | |
| GH_TOKEN: ${{ github.token }} | |
| run: | | |
| VERSION="${{ steps.determine_version.outputs.version }}" | |
| gh release create "v$VERSION" \ | |
| --title "Release v$VERSION" \ | |
| --notes-file ${{ steps.release_notes.outputs.notes_file }} \ | |
| --verify-tag | |
| - name: Summary | |
| run: | | |
| echo "## Release Summary" >> $GITHUB_STEP_SUMMARY | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| echo "- **Version:** ${{ steps.determine_version.outputs.version }}" >> $GITHUB_STEP_SUMMARY | |
| echo "- **NPM Tag:** ${{ inputs.npm_tag }}" >> $GITHUB_STEP_SUMMARY | |
| echo "- **Dry Run:** ${{ inputs.dry_run }}" >> $GITHUB_STEP_SUMMARY | |
| echo "- **Already Published:** ${{ steps.check_published.outputs.published }}" >> $GITHUB_STEP_SUMMARY | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| if [ "${{ inputs.dry_run }}" == "true" ]; then | |
| echo "### ℹ️ This was a dry run - no changes were published" >> $GITHUB_STEP_SUMMARY | |
| else | |
| if [ "${{ steps.check_published.outputs.published }}" == "true" ]; then | |
| echo "### ⚠️ Version already published - skipped NPM publish" >> $GITHUB_STEP_SUMMARY | |
| else | |
| echo "### ✅ Package published successfully!" >> $GITHUB_STEP_SUMMARY | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| echo "- NPM: https://www.npmjs.com/package/react-native-unistyles/v/${{ steps.determine_version.outputs.version }}" >> $GITHUB_STEP_SUMMARY | |
| echo "- GitHub: https://github.com/${{ github.repository }}/releases/tag/v${{ steps.determine_version.outputs.version }}" >> $GITHUB_STEP_SUMMARY | |
| fi | |
| fi |