Update Shadcn/UI Components #370
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
| # Automated Shadcn/UI Component Updates | |
| # | |
| # Runs daily to update shadcn/ui components and creates pull requests when changes are detected. | |
| # Can also be triggered manually from the GitHub Actions tab. | |
| # | |
| # Uses the default GITHUB_TOKEN - no additional setup required. | |
| name: Update Shadcn/UI Components | |
| on: | |
| schedule: | |
| # Run daily at 2 AM UTC | |
| - cron: '0 2 * * *' | |
| workflow_dispatch: # Allow manual trigger | |
| permissions: | |
| contents: write | |
| pull-requests: write | |
| actions: read | |
| jobs: | |
| update-shadcn-components: | |
| runs-on: ubuntu-latest | |
| env: | |
| HUSKY: 0 # Disable Husky hooks in CI - we run checks explicitly | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@v6 | |
| with: | |
| token: ${{ secrets.GITHUB_TOKEN }} | |
| fetch-depth: 0 | |
| persist-credentials: false | |
| - name: Setup Bun | |
| uses: oven-sh/setup-bun@v2 | |
| # Automatically reads from .bun-version file | |
| - name: Install dependencies | |
| run: bun install | |
| - name: Update shadcn/ui components | |
| run: | | |
| echo "π€ Updating all shadcn/ui components..." | |
| bunx shadcn@canary add -a -y -o | |
| echo "β All components updated successfully!" | |
| - name: Format code with Prettier | |
| run: | | |
| echo "π¨ Formatting code with Prettier..." | |
| bun run format | |
| - name: Lint code with ESLint | |
| run: | | |
| echo "π Linting code with ESLint..." | |
| bun run lint | |
| - name: Check for file changes | |
| id: check-changes | |
| run: | | |
| # Reset any workflow file changes (prevent permission issues) | |
| git checkout -- .github/workflows/ 2>/dev/null || true | |
| if git diff --quiet; then | |
| echo "No file changes detected" | |
| echo "has_changes=false" >> $GITHUB_OUTPUT | |
| else | |
| echo "File changes detected" | |
| echo "has_changes=true" >> $GITHUB_OUTPUT | |
| # Get list of changed files | |
| echo "Changed files:" | |
| git diff --name-only | tee changed_files.txt | |
| # Create a summary of changes | |
| SUMMARY="## Changed Components\n\n" | |
| while IFS= read -r file; do | |
| if [[ $file == components/ui/* ]]; then | |
| component_name=$(basename "$file" .tsx) | |
| SUMMARY="${SUMMARY}- **$component_name**: Updated to latest version\n" | |
| fi | |
| done < changed_files.txt | |
| SUMMARY="${SUMMARY}\n## Summary of Changes\n\`\`\`\n" | |
| SUMMARY="${SUMMARY}$(git diff --stat)\n\`\`\`" | |
| # Save summary to output (using delimiter for multi-line) | |
| echo "change_summary<<EOF" >> $GITHUB_OUTPUT | |
| echo -e "$SUMMARY" >> $GITHUB_OUTPUT | |
| echo "EOF" >> $GITHUB_OUTPUT | |
| # Clean up temporary files | |
| rm -f changed_files.txt | |
| fi | |
| - name: Generate timestamp for branch | |
| if: steps.check-changes.outputs.has_changes == 'true' | |
| id: timestamp | |
| run: | | |
| TIMESTAMP=$(date +'%Y%m%d-%H%M%S') | |
| echo "value=$TIMESTAMP" >> $GITHUB_OUTPUT | |
| - name: Check for existing open PR | |
| if: steps.check-changes.outputs.has_changes == 'true' | |
| id: check-pr | |
| run: | | |
| # Check if there's already an open PR with the shadcn-ui label | |
| EXISTING_PR=$(gh pr list --label "shadcn-ui" --state open --json number --jq '.[0].number') | |
| if [ -n "$EXISTING_PR" ]; then | |
| echo "Found existing open PR #$EXISTING_PR with shadcn-ui updates" | |
| echo "should_create=false" >> $GITHUB_OUTPUT | |
| echo "existing_pr=$EXISTING_PR" >> $GITHUB_OUTPUT | |
| else | |
| echo "No existing open PR found, will create new one" | |
| echo "should_create=true" >> $GITHUB_OUTPUT | |
| fi | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Create Pull Request | |
| if: steps.check-changes.outputs.has_changes == 'true' && steps.check-pr.outputs.should_create == 'true' | |
| id: create-pr | |
| uses: peter-evans/create-pull-request@v8 | |
| with: | |
| token: ${{ secrets.GITHUB_TOKEN }} | |
| commit-message: | | |
| chore: update shadcn/ui components to latest versions | |
| - Automated update via GitHub Actions | |
| - Updated components to match latest shadcn/ui registry | |
| - No breaking changes expected (please review) | |
| title: 'π€ Update Shadcn/UI Components (${{ steps.timestamp.outputs.value }})' | |
| body: | | |
| ## π€ Automated Shadcn/UI Component Update | |
| This PR contains automated updates to shadcn/ui components to keep them in sync with the latest versions from the official registry. | |
| ### π What's Changed | |
| ${{ steps.check-changes.outputs.change_summary || 'Updated shadcn/ui components to latest versions' }} | |
| ### π Review Guidelines | |
| - **Breaking Changes**: Review the diff carefully for any breaking changes | |
| - **Custom Modifications**: Check if any of your custom modifications were overwritten | |
| - **Dependencies**: Verify that no new dependencies need to be installed | |
| - **Testing**: Run your test suite to ensure everything works as expected | |
| ### π Update Details | |
| - **Triggered**: ${{ github.event_name == 'schedule' && 'Scheduled run' || 'Manual trigger' }} | |
| - **Timestamp**: ${{ steps.timestamp.outputs.value }} | |
| - **CLI Version**: Latest | |
| --- | |
| *This PR was automatically created by the Shadcn/UI update workflow.* | |
| branch: feature/update-shadcn-components-${{ steps.timestamp.outputs.value }} | |
| delete-branch: true | |
| labels: | | |
| dependencies | |
| automated | |
| shadcn-ui | |
| enhancement | |
| draft: false | |
| - name: Report results | |
| if: always() | |
| run: | | |
| echo "## Workflow Summary" >> $GITHUB_STEP_SUMMARY | |
| echo "- **File Changes**: ${{ steps.check-changes.outputs.has_changes }}" >> $GITHUB_STEP_SUMMARY | |
| if [[ "${{ steps.check-changes.outputs.has_changes }}" == "true" ]]; then | |
| if [[ "${{ steps.check-pr.outputs.should_create }}" == "false" ]]; then | |
| echo "- **Pull Request**: Skipped (existing open PR #${{ steps.check-pr.outputs.existing_pr }})" >> $GITHUB_STEP_SUMMARY | |
| echo "- **Note**: Updates will be included in the existing PR when it's merged and a new update is needed" >> $GITHUB_STEP_SUMMARY | |
| elif [[ "${{ steps.check-pr.outputs.should_create }}" == "true" ]]; then | |
| echo "- **Pull Request**: Created successfully" >> $GITHUB_STEP_SUMMARY | |
| fi | |
| if [ -f changed_files.txt ]; then | |
| FILE_COUNT=$(cat changed_files.txt | wc -l) | |
| echo "- **Files Changed**: $FILE_COUNT" >> $GITHUB_STEP_SUMMARY | |
| fi | |
| else | |
| echo "- **Pull Request**: Not needed (no changes)" >> $GITHUB_STEP_SUMMARY | |
| fi | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| echo "View the [Actions tab](https://github.com/${{ github.repository }}/actions) for detailed logs." >> $GITHUB_STEP_SUMMARY | |
| - name: Notify Slack - Skipped (PR Already Open) | |
| if: steps.check-changes.outputs.has_changes == 'true' && steps.check-pr.outputs.should_create == 'false' | |
| run: | | |
| curl -X POST --data "{\"text\":\"βοΈ Shadcn/UI Components Update Skipped\nReason: PR already open (#${{ steps.check-pr.outputs.existing_pr }})\nPR: https://github.com/${{ github.repository }}/pull/${{ steps.check-pr.outputs.existing_pr }}\"}" ${{ secrets.SLACK_WEBHOOK_URL }} | |
| - name: Notify Slack - Success | |
| if: success() && !(steps.check-changes.outputs.has_changes == 'true' && steps.check-pr.outputs.should_create == 'false') | |
| run: | | |
| PR_URL="" | |
| if [[ "${{ steps.create-pr.outputs.pull-request-number }}" != "" ]]; then | |
| PR_URL="https://github.com/${{ github.repository }}/pull/${{ steps.create-pr.outputs.pull-request-number }}" | |
| fi | |
| curl -X POST --data "{\"text\":\"β Shadcn/UI Components Updated Successfully\n${PR_URL}\"}" ${{ secrets.SLACK_WEBHOOK_URL }} | |
| - name: Notify Slack - Failure | |
| if: failure() | |
| run: | | |
| curl -X POST --data "{\"text\":\"β Shadcn/UI Components Update Failed\nAction: https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}\"}" ${{ secrets.SLACK_WEBHOOK_URL }} |