diff --git a/.github/workflows/publish-public-npm.yml b/.github/workflows/publish-public-npm.yml index 95612d1f..dd6bece9 100644 --- a/.github/workflows/publish-public-npm.yml +++ b/.github/workflows/publish-public-npm.yml @@ -36,6 +36,11 @@ on: required: false type: boolean default: true + create_version_pr_only: + description: "Skip publish and only create version bump PR" + required: false + type: boolean + default: false skip_slack_notification: description: "Skip Slack notification" required: false @@ -45,6 +50,7 @@ on: permissions: contents: write id-token: write + pull-requests: write jobs: publish: @@ -53,6 +59,7 @@ jobs: permissions: contents: write id-token: write + pull-requests: write steps: - name: Checkout repository @@ -76,7 +83,9 @@ jobs: run: pnpm install --frozen-lockfile - name: Build packages - run: pnpm run build + run: | + pnpm --filter @auth0/universal-components-core build + pnpm --filter @auth0/universal-components-react build - name: Detect versions and npm tags id: detect @@ -211,7 +220,8 @@ jobs: - name: Publish Core package to public npm id: publish-core if: | - (env.PACKAGES_INPUT == 'both' || env.PACKAGES_INPUT == 'core') + (env.PACKAGES_INPUT == 'both' || env.PACKAGES_INPUT == 'core') && + github.event.inputs.create_version_pr_only != 'true' working-directory: ./packages/core env: NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} @@ -237,7 +247,8 @@ jobs: - name: Publish React package to public npm id: publish-react if: | - (env.PACKAGES_INPUT == 'both' || env.PACKAGES_INPUT == 'react') + (env.PACKAGES_INPUT == 'both' || env.PACKAGES_INPUT == 'react') && + github.event.inputs.create_version_pr_only != 'true' working-directory: ./packages/react env: NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} @@ -373,6 +384,205 @@ jobs: prerelease: ${{ env.REACT_TAG != 'latest' }} draft: false + - name: Create PR to update package versions + id: create-version-pr + if: | + (github.event.inputs.dry_run != 'true' && + (steps.publish-core.outputs.published == 'true' || + steps.publish-react.outputs.published == 'true')) || + github.event.inputs.create_version_pr_only == 'true' + env: + GH_TOKEN: ${{ github.token }} + run: | + echo "Creating PR to update package.json versions..." + + # Configure git with GitHub Actions bot (creates the PR) + git config user.name "github-actions[bot]" + git config user.email "github-actions[bot]@users.noreply.github.com" + + # Create a new branch + BRANCH_NAME="chore/update-package-versions-$(date +%s)" + git checkout -b "$BRANCH_NAME" + + # Update package.json files with target versions + if [ "${{ github.event.inputs.create_version_pr_only }}" = "true" ]; then + # PR-only mode: use input versions directly + if [ "$PACKAGES_INPUT" = "both" ] || [ "$PACKAGES_INPUT" = "core" ]; then + cd packages/core + node -e " + const pkg = require('./package.json'); + pkg.version = process.env.CORE_VER; + require('fs').writeFileSync('./package.json', JSON.stringify(pkg, null, 2) + '\n'); + " + git add package.json + cd ../.. + fi + + if [ "$PACKAGES_INPUT" = "both" ] || [ "$PACKAGES_INPUT" = "react" ]; then + cd packages/react + node -e " + const pkg = require('./package.json'); + pkg.version = process.env.REACT_VER; + if (pkg.dependencies && pkg.dependencies['@auth0/universal-components-core']) { + pkg.dependencies['@auth0/universal-components-core'] = process.env.CORE_VER; + } + require('fs').writeFileSync('./package.json', JSON.stringify(pkg, null, 2) + '\n'); + " + git add package.json + cd ../.. + fi + else + # Normal mode: use published versions + if [ "${{ steps.publish-core.outputs.published }}" = "true" ]; then + cd packages/core + node -e " + const pkg = require('./package.json'); + pkg.version = '${{ steps.publish-core.outputs.version }}'; + require('fs').writeFileSync('./package.json', JSON.stringify(pkg, null, 2) + '\n'); + " + git add package.json + cd ../.. + fi + + if [ "${{ steps.publish-react.outputs.published }}" = "true" ]; then + cd packages/react + node -e " + const pkg = require('./package.json'); + pkg.version = '${{ steps.publish-react.outputs.version }}'; + if (pkg.dependencies && pkg.dependencies['@auth0/universal-components-core']) { + pkg.dependencies['@auth0/universal-components-core'] = '${{ steps.publish-core.outputs.version }}'; + } + require('fs').writeFileSync('./package.json', JSON.stringify(pkg, null, 2) + '\n'); + " + git add package.json + cd ../.. + fi + fi + + # Check if there are changes to commit + if ! git diff --staged --quiet; then + # Commit and push changes + if [ "${{ github.event.inputs.create_version_pr_only }}" = "true" ]; then + COMMIT_MSG="chore: bump package versions + + - @auth0/universal-components-core: $CORE_VER + - @auth0/universal-components-react: $REACT_VER" + else + COMMIT_MSG="chore: update package versions after npm publish + + - @auth0/universal-components-core: ${{ steps.publish-core.outputs.version }} + - @auth0/universal-components-react: ${{ steps.publish-react.outputs.version }} + + Published to npm with tags: + - Core: ${{ env.CORE_TAG }} + - React: ${{ env.REACT_TAG }}" + fi + + git commit -m "$COMMIT_MSG" + git push origin "$BRANCH_NAME" + + # Create PR using GitHub CLI + if [ "${{ github.event.inputs.create_version_pr_only }}" = "true" ]; then + PR_TITLE="chore: bump package versions" + PR_BODY="## Summary + + Bumps package.json versions for upcoming release. + + ## Changes + + " + + if [ "$PACKAGES_INPUT" = "both" ] || [ "$PACKAGES_INPUT" = "core" ]; then + PR_BODY="${PR_BODY}- \`@auth0/universal-components-core\`: \`$CORE_VER\` + " + fi + + if [ "$PACKAGES_INPUT" = "both" ] || [ "$PACKAGES_INPUT" = "react" ]; then + PR_BODY="${PR_BODY}- \`@auth0/universal-components-react\`: \`$REACT_VER\` + " + fi + + PR_BODY="${PR_BODY} + --- + *Auto-generated by publish workflow (version bump only): [\`${{ github.run_id }}\`](${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }})*" + else + PR_TITLE="chore: update package versions after npm publish" + PR_BODY="## Summary + + Updates package.json versions to match the packages published to npm. + + ## Changes + + " + + if [ "${{ steps.publish-core.outputs.published }}" = "true" ]; then + PR_BODY="${PR_BODY}- \`@auth0/universal-components-core\`: \`${{ steps.publish-core.outputs.version }}\` (tag: \`${{ env.CORE_TAG }}\`) + " + fi + + if [ "${{ steps.publish-react.outputs.published }}" = "true" ]; then + PR_BODY="${PR_BODY}- \`@auth0/universal-components-react\`: \`${{ steps.publish-react.outputs.version }}\` (tag: \`${{ env.REACT_TAG }}\`) + " + fi + + PR_BODY="${PR_BODY} + ## Published Packages + + " + + if [ "${{ steps.publish-core.outputs.published }}" = "true" ]; then + PR_BODY="${PR_BODY}- [View @auth0/universal-components-core on npm](https://www.npmjs.com/package/@auth0/universal-components-core/v/${{ steps.publish-core.outputs.version }}) + " + fi + + if [ "${{ steps.publish-react.outputs.published }}" = "true" ]; then + PR_BODY="${PR_BODY}- [View @auth0/universal-components-react on npm](https://www.npmjs.com/package/@auth0/universal-components-react/v/${{ steps.publish-react.outputs.version }}) + " + fi + + PR_BODY="${PR_BODY} + --- + *Auto-generated by publish workflow: [\`${{ github.run_id }}\`](${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }})*" + fi + + # Create PR + PR_URL=$(gh pr create \ + --title "$PR_TITLE" \ + --body "$PR_BODY" \ + --base main \ + --head "$BRANCH_NAME") + + echo "Created PR: $PR_URL" + + # Extract PR number + PR_NUMBER=$(echo "$PR_URL" | grep -oE '[0-9]+$') + + echo "PR #$PR_NUMBER created by github-actions[bot]" + echo "pr_number=$PR_NUMBER" >> $GITHUB_OUTPUT + echo "pr_url=$PR_URL" >> $GITHUB_OUTPUT + else + echo "No version changes to commit" + fi + + - name: Approve and merge PR + id: approve-pr + if: | + steps.create-version-pr.outputs.pr_number != '' && + (github.event.inputs.dry_run != 'true' || github.event.inputs.create_version_pr_only == 'true') + env: + GH_TOKEN: ${{ secrets.SVC_PAT }} + run: | + PR_NUMBER="${{ steps.create-version-pr.outputs.pr_number }}" + echo "Approving and merging PR #$PR_NUMBER using service account..." + + # Auto-approve PR using service account token + gh pr review "$PR_NUMBER" --approve --body "✅ Auto-approved by service account after successful npm publish" + + # Merge PR immediately + gh pr merge "$PR_NUMBER" --squash --delete-branch + + echo "PR #$PR_NUMBER approved and merged" + - name: Restore package.json files if: always() run: |