Merge pull request #115 from proyecto26/feature/semantic-release #1
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 | |
| on: | |
| push: | |
| branches: | |
| - master | |
| workflow_dispatch: | |
| inputs: | |
| version_bump: | |
| description: 'Version bump type' | |
| required: true | |
| default: 'patch' | |
| type: choice | |
| options: | |
| - patch | |
| - minor | |
| - major | |
| release_notes: | |
| description: 'Additional release notes (optional)' | |
| required: false | |
| type: string | |
| permissions: | |
| contents: write | |
| jobs: | |
| release: | |
| name: Create Release | |
| runs-on: ubuntu-latest | |
| outputs: | |
| new_version: ${{ steps.version.outputs.new_version }} | |
| steps: | |
| - uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 | |
| token: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Get current version | |
| id: current | |
| run: | | |
| CURRENT=$(node -p "require('./src/package.json').version") | |
| echo "version=$CURRENT" >> $GITHUB_OUTPUT | |
| echo "Current version: $CURRENT" | |
| - name: Determine version bump from commits | |
| id: bump | |
| run: | | |
| if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then | |
| echo "type=${{ inputs.version_bump }}" >> $GITHUB_OUTPUT | |
| else | |
| LAST_TAG=$(git describe --tags --abbrev=0 2>/dev/null || echo "") | |
| if [ -z "$LAST_TAG" ]; then RANGE="HEAD"; else RANGE="${LAST_TAG}..HEAD"; fi | |
| COMMITS=$(git log $RANGE --pretty=format:"%s" 2>/dev/null || echo "") | |
| if echo "$COMMITS" | grep -qiE "^(feat|feature)(\(.+\))?!:|BREAKING CHANGE"; then | |
| echo "type=major" >> $GITHUB_OUTPUT | |
| elif echo "$COMMITS" | grep -qiE "^(feat|feature)(\(.+\))?:"; then | |
| echo "type=minor" >> $GITHUB_OUTPUT | |
| else | |
| echo "type=patch" >> $GITHUB_OUTPUT | |
| fi | |
| fi | |
| - name: Calculate new version | |
| id: version | |
| run: | | |
| IFS='.' read -r MAJOR MINOR PATCH <<< "${{ steps.current.outputs.version }}" | |
| case "${{ steps.bump.outputs.type }}" in | |
| major) MAJOR=$((MAJOR + 1)); MINOR=0; PATCH=0 ;; | |
| minor) MINOR=$((MINOR + 1)); PATCH=0 ;; | |
| patch) PATCH=$((PATCH + 1)) ;; | |
| esac | |
| NEW_VERSION="${MAJOR}.${MINOR}.${PATCH}" | |
| echo "new_version=$NEW_VERSION" >> $GITHUB_OUTPUT | |
| echo "New version: $NEW_VERSION" | |
| - name: Generate changelog entry | |
| id: changelog | |
| run: | | |
| LAST_TAG=$(git describe --tags --abbrev=0 2>/dev/null || echo "") | |
| if [ -z "$LAST_TAG" ]; then RANGE="HEAD"; else RANGE="${LAST_TAG}..HEAD"; fi | |
| TODAY=$(date +%Y-%m-%d) | |
| NEW_VERSION="${{ steps.version.outputs.new_version }}" | |
| ADDED="" CHANGED="" FIXED="" REMOVED="" | |
| while IFS= read -r line; do | |
| HASH=$(echo "$line" | cut -d'|' -f1) | |
| MSG=$(echo "$line" | cut -d'|' -f2-) | |
| SHORT_HASH=$(echo "$HASH" | cut -c1-7) | |
| PR_NUM=$(echo "$MSG" | grep -oP '\(#\K[0-9]+(?=\))' | head -1) | |
| if [ -n "$PR_NUM" ]; then | |
| ATTR="([#${PR_NUM}](https://github.com/proyecto26/nativescript-inappbrowser/pull/${PR_NUM}))" | |
| else | |
| ATTR="([${SHORT_HASH}](https://github.com/proyecto26/nativescript-inappbrowser/commit/${HASH}))" | |
| fi | |
| CLEAN_MSG=$(echo "$MSG" | sed -E 's/^(feat|fix|perf|refactor|chore|docs|style|test|build|ci)(\([^)]*\))?(!)?:\s*//') | |
| CLEAN_MSG=$(echo "$CLEAN_MSG" | sed -E 's/\s*\(#[0-9]+\)\s*$//') | |
| if echo "$MSG" | grep -qiE "^(feat|feature)(\(.+\))?:"; then | |
| ADDED="${ADDED}- ${CLEAN_MSG} ${ATTR}.\n" | |
| elif echo "$MSG" | grep -qiE "^fix(\(.+\))?:"; then | |
| FIXED="${FIXED}- ${CLEAN_MSG} ${ATTR}.\n" | |
| elif echo "$MSG" | grep -qiE "^(perf|refactor|chore|docs|style|build|ci)(\(.+\))?:"; then | |
| CHANGED="${CHANGED}- ${CLEAN_MSG} ${ATTR}.\n" | |
| elif echo "$MSG" | grep -qiE "^(revert)(\(.+\))?:"; then | |
| REMOVED="${REMOVED}- ${CLEAN_MSG} ${ATTR}.\n" | |
| else | |
| CHANGED="${CHANGED}- ${CLEAN_MSG} ${ATTR}.\n" | |
| fi | |
| done < <(git log $RANGE --pretty=format:"%H|%s" --no-merges 2>/dev/null) | |
| if [ -n "${{ inputs.release_notes }}" ]; then | |
| ADDED="${ADDED}- ${{ inputs.release_notes }}\n" | |
| fi | |
| BODY="" | |
| [ -n "$ADDED" ] && BODY="${BODY}### Added\n${ADDED}\n" | |
| [ -n "$CHANGED" ] && BODY="${BODY}### Changed\n${CHANGED}\n" | |
| [ -n "$FIXED" ] && BODY="${BODY}### Fixed\n${FIXED}\n" | |
| [ -n "$REMOVED" ] && BODY="${BODY}### Removed\n${REMOVED}\n" | |
| [ -z "$BODY" ] && BODY="### Changed\n- Release version ${NEW_VERSION}.\n" | |
| echo -e "$BODY" > /tmp/release_body.md | |
| # Update CHANGELOG.md | |
| PREV_VERSION="${{ steps.current.outputs.version }}" | |
| HEADER="## [${NEW_VERSION}] - ${TODAY}" | |
| LINK="[${NEW_VERSION}]: https://github.com/proyecto26/nativescript-inappbrowser/compare/v${PREV_VERSION}...v${NEW_VERSION}" | |
| sed -i "/^## \[Unreleased\]/a\\\\n${HEADER}\\n" CHANGELOG.md | |
| sed -i "/^## \[${NEW_VERSION}\]/r /tmp/release_body.md" CHANGELOG.md | |
| sed -i "s|\[Unreleased\]: .*|[Unreleased]: https://github.com/proyecto26/nativescript-inappbrowser/compare/v${NEW_VERSION}...HEAD|" CHANGELOG.md | |
| sed -i "/^\[Unreleased\]:/a ${LINK}" CHANGELOG.md | |
| - name: Update version in src/package.json | |
| run: | | |
| node -e " | |
| const pkg = require('./src/package.json'); | |
| pkg.version = '${{ steps.version.outputs.new_version }}'; | |
| require('fs').writeFileSync('./src/package.json', JSON.stringify(pkg, null, '\t') + '\n'); | |
| " | |
| - name: Commit version bump | |
| run: | | |
| git config --global user.name 'github-actions[bot]' | |
| git config --global user.email 'github-actions[bot]@users.noreply.github.com' | |
| git add -A | |
| git commit -m "chore(release): v${{ steps.version.outputs.new_version }} | |
| - Updated src/package.json | |
| - Updated CHANGELOG.md" | |
| git tag "v${{ steps.version.outputs.new_version }}" | |
| git push origin master --follow-tags | |
| - name: Create GitHub Release | |
| uses: softprops/action-gh-release@v2 | |
| with: | |
| tag_name: v${{ steps.version.outputs.new_version }} | |
| name: Release ${{ steps.version.outputs.new_version }} | |
| body_path: /tmp/release_body.md | |
| draft: false | |
| prerelease: false | |
| publish-npm: | |
| name: Publish to npm | |
| needs: release | |
| runs-on: ubuntu-latest | |
| if: needs.release.outputs.new_version != '' | |
| steps: | |
| - uses: actions/checkout@v4 | |
| with: | |
| ref: master | |
| - name: Pull latest (includes version bump commit) | |
| run: git pull origin master | |
| - name: Setup Node.js | |
| uses: actions/setup-node@v4 | |
| with: | |
| node-version: '20' | |
| registry-url: 'https://registry.npmjs.org' | |
| - name: Build and publish | |
| run: | | |
| cd src | |
| npm install | |
| npm run build || true | |
| npm publish | |
| env: | |
| NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} |