deps: bump the minor-and-patch group with 2 updates (#266) #210
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: Auto Release | |
| on: | |
| push: | |
| branches: [main] | |
| paths-ignore: ['**.md', 'docs/**', 'LICENSE', '.gitignore'] | |
| workflow_dispatch: | |
| permissions: | |
| contents: write | |
| concurrency: | |
| group: release | |
| cancel-in-progress: false | |
| jobs: | |
| release: | |
| name: Bump version and release | |
| runs-on: ubuntu-latest | |
| if: "!contains(github.event.head_commit.message, '[skip ci]')" | |
| outputs: | |
| new_tag: ${{ steps.version.outputs.new_tag }} | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v6 | |
| with: | |
| fetch-depth: 0 | |
| - name: Setup Node.js | |
| uses: actions/setup-node@v6 | |
| with: | |
| node-version: 22 | |
| - name: Install dependencies | |
| run: npm ci | |
| - name: Validate release artifacts before tagging | |
| run: | | |
| npm run typecheck | |
| npm run lint | |
| npm test | |
| npm run build | |
| test -f dist/cli.js | |
| node dist/cli.js --version | |
| npm pack --dry-run | |
| - name: Determine version bump | |
| id: version | |
| run: | | |
| LATEST=$(git tag -l "v*" --sort=-version:refname | head -1) | |
| if [ -z "$LATEST" ]; then | |
| LATEST="v0.0.0" | |
| fi | |
| echo "latest=$LATEST" >> "$GITHUB_OUTPUT" | |
| VERSION="${LATEST#v}" | |
| MAJOR=$(echo "$VERSION" | cut -d. -f1) | |
| MINOR=$(echo "$VERSION" | cut -d. -f2) | |
| PATCH=$(echo "$VERSION" | cut -d. -f3) | |
| # Check commit messages since last tag for bump type. | |
| # COMMITS = subject lines (drives the no-bump exit + feat/fix detection). | |
| # BODIES = full messages (subject + body) so a "BREAKING CHANGE:" footer | |
| # in the body is detected, not only a "!" in the subject. | |
| COMMITS=$(git log "$LATEST"..HEAD --pretty=format:"%s" 2>/dev/null | grep -v "\[skip ci\]" || true) | |
| BODIES=$(git log "$LATEST"..HEAD --pretty=format:"%B" 2>/dev/null || true) | |
| if [ -z "$COMMITS" ]; then | |
| echo "No meaningful commits since $LATEST — skipping release" | |
| echo "new_tag=" >> "$GITHUB_OUTPUT" | |
| exit 0 | |
| fi | |
| # Breaking changes MUST win → test them FIRST. A breaking change is | |
| # either a "!" in a conventional subject (e.g. "feat!:", "fix(api)!:") | |
| # OR a "BREAKING CHANGE" / "BREAKING-CHANGE" token anywhere in a body. | |
| if echo "$COMMITS" | grep -qE "^(feat|fix|refactor|perf|chore)(\(.+\))?!:" \ | |
| || echo "$BODIES" | grep -qE "BREAKING[ -]CHANGE"; then | |
| # Breaking change → major bump | |
| NEW_MAJOR=$((MAJOR + 1)) | |
| NEW_TAG="v${NEW_MAJOR}.0.0" | |
| elif echo "$COMMITS" | grep -qiE "^feat(\(|:)"; then | |
| # feat: or feat(scope): → minor bump | |
| NEW_MINOR=$((MINOR + 1)) | |
| NEW_TAG="v${MAJOR}.${NEW_MINOR}.0" | |
| else | |
| # fix/chore/docs/etc → patch bump | |
| NEW_PATCH=$((PATCH + 1)) | |
| NEW_TAG="v${MAJOR}.${MINOR}.${NEW_PATCH}" | |
| fi | |
| echo "new_tag=$NEW_TAG" >> "$GITHUB_OUTPUT" | |
| echo "Bumping $LATEST -> $NEW_TAG" | |
| - name: Sync package.json version and tag | |
| if: steps.version.outputs.new_tag != '' | |
| run: | | |
| VERSION="${{ steps.version.outputs.new_tag }}" | |
| VERSION="${VERSION#v}" | |
| git config user.name "github-actions[bot]" | |
| git config user.email "github-actions[bot]@users.noreply.github.com" | |
| CURRENT=$(node -p "require('./package.json').version") | |
| if [ "$CURRENT" != "$VERSION" ]; then | |
| npm version "$VERSION" --no-git-tag-version | |
| git add package.json package-lock.json | |
| git commit -m "chore: bump version to $VERSION [skip ci]" | |
| # Retry push with rebase to handle concurrent merges | |
| for i in 1 2 3; do | |
| git pull --rebase origin main && git push origin HEAD:main && break | |
| echo "Push attempt $i failed, retrying..." | |
| sleep 5 | |
| done | |
| fi | |
| git tag -a "${{ steps.version.outputs.new_tag }}" -m "Release ${{ steps.version.outputs.new_tag }}" | |
| git push origin "${{ steps.version.outputs.new_tag }}" | |
| - name: Generate changelog | |
| if: steps.version.outputs.new_tag != '' | |
| run: | | |
| VERSION="${{ steps.version.outputs.new_tag }}" | |
| PREV_TAG="${{ steps.version.outputs.latest }}" | |
| if [ "$PREV_TAG" = "v0.0.0" ]; then | |
| PREV_TAG=$(git rev-list --max-parents=0 HEAD) | |
| fi | |
| { | |
| echo "## What's Changed" | |
| echo "" | |
| FEATURES=$(git log $PREV_TAG..$VERSION --pretty=format:"- %s" --grep="^feat" 2>/dev/null || true) | |
| if [ -n "$FEATURES" ]; then | |
| echo "### Features" | |
| echo "$FEATURES" | head -20 | |
| echo "" | |
| fi | |
| FIXES=$(git log $PREV_TAG..$VERSION --pretty=format:"- %s" --grep="^fix" 2>/dev/null || true) | |
| if [ -n "$FIXES" ]; then | |
| echo "### Bug Fixes" | |
| echo "$FIXES" | head -20 | |
| echo "" | |
| fi | |
| OTHERS=$(git log $PREV_TAG..$VERSION --pretty=format:"- %s" --invert-grep --grep="^feat" --invert-grep --grep="^fix" 2>/dev/null | head -10 || true) | |
| if [ -n "$OTHERS" ]; then | |
| echo "### Other Changes" | |
| echo "$OTHERS" | |
| echo "" | |
| fi | |
| echo "---" | |
| echo "" | |
| echo "**Full Changelog**: https://github.com/${{ github.repository }}/compare/$PREV_TAG...$VERSION" | |
| } > changelog.md | |
| - name: Create GitHub Release | |
| if: steps.version.outputs.new_tag != '' | |
| uses: softprops/action-gh-release@v3 | |
| with: | |
| tag_name: ${{ steps.version.outputs.new_tag }} | |
| body_path: changelog.md | |
| draft: false | |
| prerelease: false | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| docker: | |
| name: Build and push Docker image | |
| needs: release | |
| if: needs.release.outputs.new_tag != '' | |
| uses: ./.github/workflows/docker.yml | |
| with: | |
| version: ${{ needs.release.outputs.new_tag }} | |
| secrets: | |
| DOCKERHUB_USERNAME: ${{ secrets.DOCKERHUB_USERNAME }} | |
| DOCKERHUB_TOKEN: ${{ secrets.DOCKERHUB_TOKEN }} | |
| notify: | |
| name: Telegram notification | |
| needs: release | |
| if: needs.release.outputs.new_tag != '' | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout for changelog | |
| uses: actions/checkout@v6 | |
| with: | |
| fetch-depth: 0 | |
| - name: Build message | |
| id: msg | |
| run: | | |
| TAG="${{ needs.release.outputs.new_tag }}" | |
| PREV_TAG=$(git tag -l "v*" --sort=-version:refname | grep -v "^${TAG}$" | head -1) | |
| COMMITS=$(git log "${PREV_TAG}..${TAG}" --pretty=format:"• %s" 2>/dev/null | grep -v "\[skip ci\]" | head -10) | |
| MSG=$(cat <<MSGEOF | |
| 🚀 *DeclaRenta ${TAG}* | |
| ${COMMITS} | |
| [Ver release](https://github.com/${{ github.repository }}/releases/tag/${TAG}) · [Usar online](https://declarenta.com) | |
| MSGEOF | |
| ) | |
| # Escape for GitHub Actions | |
| echo "text<<EOF" >> "$GITHUB_OUTPUT" | |
| echo "$MSG" >> "$GITHUB_OUTPUT" | |
| echo "EOF" >> "$GITHUB_OUTPUT" | |
| - name: Send to Telegram | |
| run: | | |
| curl -s -X POST "https://api.telegram.org/bot${{ secrets.TELEGRAM_BOT_TOKEN }}/sendMessage" \ | |
| -d chat_id="${{ secrets.TELEGRAM_CHAT_ID }}" \ | |
| -d parse_mode="Markdown" \ | |
| -d disable_web_page_preview="true" \ | |
| --data-urlencode "text=${{ steps.msg.outputs.text }}" |