Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
71 changes: 62 additions & 9 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -68,11 +68,62 @@ jobs:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
NODE_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }}

- name: Determine Release Finalization
id: finalize
if: steps.changesets.outputs.hasChangesets == 'false'
env:
BEFORE_SHA: ${{ github.event.before }}
PUBLISHED: ${{ steps.changesets.outputs.published }}
run: |
RELEASE_VERSION=$(node -p "require('./package.json').version")
echo "release_version=${RELEASE_VERSION}" >> "$GITHUB_OUTPUT"

CHANGE_RANGE_START="${BEFORE_SHA}"
if [ -z "${CHANGE_RANGE_START}" ] || [ "${CHANGE_RANGE_START}" = "0000000000000000000000000000000000000000" ]; then
CHANGE_RANGE_START="$(git rev-list --max-count=1 HEAD^ 2>/dev/null || true)"
fi

if [ -n "${CHANGE_RANGE_START}" ]; then
CHANGED_FILES="$(git diff --name-only "${CHANGE_RANGE_START}" "${GITHUB_SHA}")"
else
CHANGED_FILES="$(git show --pretty='' --name-only "${GITHUB_SHA}")"
fi

ROOT_VERSION_CHANGED=false
PACKAGE_RELEASE_FILES_CHANGED=false

if printf '%s\n' "${CHANGED_FILES}" | grep -qx 'package.json'; then
ROOT_VERSION_CHANGED=true
fi

if printf '%s\n' "${CHANGED_FILES}" | grep -Eq '^packages/[^/]+/(CHANGELOG\.md|package\.json)$|^NEXT-CHANGELOG-ENTRY\.md$'; then
PACKAGE_RELEASE_FILES_CHANGED=true
fi

TAG_EXISTS=false
if git rev-parse -q --verify "refs/tags/${RELEASE_VERSION}" >/dev/null; then
TAG_EXISTS=true
fi

SHOULD_FINALIZE=false
if [ "${PUBLISHED}" = "true" ]; then
SHOULD_FINALIZE=true
elif [ "${ROOT_VERSION_CHANGED}" = "true" ] && [ "${PACKAGE_RELEASE_FILES_CHANGED}" = "true" ] && [ "${TAG_EXISTS}" = "false" ]; then
SHOULD_FINALIZE=true
fi

echo "root_version_changed=${ROOT_VERSION_CHANGED}" >> "$GITHUB_OUTPUT"
echo "package_release_files_changed=${PACKAGE_RELEASE_FILES_CHANGED}" >> "$GITHUB_OUTPUT"
echo "tag_exists=${TAG_EXISTS}" >> "$GITHUB_OUTPUT"
echo "should_finalize=${SHOULD_FINALIZE}" >> "$GITHUB_OUTPUT"

- name: Publishing Process
id: publish
if: steps.changesets.outputs.published == 'true'
if: steps.finalize.outputs.should_finalize == 'true'
env:
RELEASE_VERSION: ${{ steps.finalize.outputs.release_version }}
TAG_EXISTS: ${{ steps.finalize.outputs.tag_exists }}
run: |
RELEASE_VERSION=$(node -p "require('./package.json').version")
echo "release_version=${RELEASE_VERSION}" >> "$GITHUB_OUTPUT"

if [ -s NEXT-CHANGELOG-ENTRY.md ]; then
Expand All @@ -81,19 +132,21 @@ jobs:
pnpm exec git-cliff --unreleased --output RELEASE_NOTES.md --strip header --bump
fi

pnpm exec git-cliff --unreleased --bump --output CHANGELOG.md
: > NEXT-CHANGELOG-ENTRY.md
if [ "${TAG_EXISTS}" = "false" ]; then
pnpm exec git-cliff --unreleased --bump --output CHANGELOG.md
: > NEXT-CHANGELOG-ENTRY.md

git add CHANGELOG.md NEXT-CHANGELOG-ENTRY.md
git commit -m "chore(release): update changelog for ${RELEASE_VERSION}"
git add CHANGELOG.md NEXT-CHANGELOG-ENTRY.md
git commit -m "chore(release): update changelog for ${RELEASE_VERSION}"

git tag -a "${RELEASE_VERSION}" -m "Release ${RELEASE_VERSION}"
git push origin main --follow-tags
git tag -a "${RELEASE_VERSION}" -m "Release ${RELEASE_VERSION}"
git push origin main --follow-tags
fi

echo "release_body_path=RELEASE_NOTES.md" >> "$GITHUB_OUTPUT"

- name: Create GitHub Release
if: steps.changesets.outputs.published == 'true'
if: steps.finalize.outputs.should_finalize == 'true'
uses: softprops/action-gh-release@v2
with:
tag_name: ${{ steps.publish.outputs.release_version }}
Expand Down
12 changes: 8 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ Its key feature is a two-step release process:

2. Publish: Once the PR is merged, the action publishes non-private packages, regenerates the
root `CHANGELOG.md`, creates a Git tag, and publishes a polished GitHub Release.
If a package version was already published during validation, the workflow still finalizes the
repository release as long as the version PR landed and the root tag does not exist yet.

Key Features:
- 🚀 **Turborepo-Optimized**: High-speed CI leveraging Turborepo's caching and task orchestration.
Expand Down Expand Up @@ -88,10 +90,12 @@ graph TD
H -- Has changesets --> I["Create or update<br/>Version Packages PR"];
I --> J[PR Merged by User];

H -- No changesets, publishable package changed --> K["pnpm changeset publish"];
K --> L["git-cliff regenerates<br/>root CHANGELOG.md"];
L --> M["Commit changelog<br/>Create and push tag"];
M --> N[🚀 Create GitHub Release];
H -- No changesets --> K["pnpm changeset publish"];
K --> L{"Published now or<br/>version PR landed<br/>without root tag?"};
L -- Yes --> M["git-cliff regenerates<br/>root CHANGELOG.md"];
L -- No --> O["No repository release update"];
M --> P["Commit changelog<br/>Create and push tag"];
P --> N[🚀 Create GitHub Release];
end

E --> F;
Expand Down
Loading