feat(local-dev): native folder picker and simplified project creation #1960
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 Tagging | |
| on: | |
| pull_request_target: | |
| types: [opened, synchronize] | |
| paths: | |
| - "apps/mesh/**" | |
| - "packages/mesh-plugin-*/**" | |
| push: | |
| branches: | |
| - main | |
| paths: | |
| - "apps/mesh/**" | |
| - "packages/mesh-plugin-*/**" | |
| permissions: | |
| contents: write | |
| pull-requests: write | |
| actions: write | |
| jobs: | |
| tag-discussion: | |
| if: github.event_name == 'pull_request_target' | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout Code | |
| uses: actions/checkout@v4 | |
| with: | |
| ref: ${{ github.event.pull_request.base.ref }} | |
| repository: ${{ github.event.pull_request.base.repo.full_name }} | |
| - name: Find existing Release Options comment | |
| uses: peter-evans/find-comment@v3 | |
| id: find_comment | |
| with: | |
| issue-number: ${{ github.event.pull_request.number }} | |
| body-includes: "## Release Options" | |
| - name: Calculate new versions | |
| id: calculate_versions | |
| run: | | |
| # Get current version from package.json | |
| CURRENT_VERSION=$(node -p "require('./apps/mesh/package.json').version") | |
| echo "Current version: $CURRENT_VERSION" | |
| # Parse version components | |
| # Handle prerelease versions like 1.0.0-alpha.23 | |
| if [[ "$CURRENT_VERSION" =~ ^([0-9]+)\.([0-9]+)\.([0-9]+)(-([a-zA-Z]+)\.([0-9]+))?$ ]]; then | |
| MAJOR="${BASH_REMATCH[1]}" | |
| MINOR="${BASH_REMATCH[2]}" | |
| PATCH="${BASH_REMATCH[3]}" | |
| PRERELEASE_TAG="${BASH_REMATCH[5]}" | |
| PRERELEASE_NUM="${BASH_REMATCH[6]}" | |
| else | |
| echo "Could not parse version: $CURRENT_VERSION" | |
| exit 1 | |
| fi | |
| echo "Parsed: MAJOR=$MAJOR, MINOR=$MINOR, PATCH=$PATCH, PRERELEASE_TAG=$PRERELEASE_TAG, PRERELEASE_NUM=$PRERELEASE_NUM" | |
| # Calculate next versions | |
| if [ -n "$PRERELEASE_TAG" ]; then | |
| # Currently a prerelease version | |
| NEW_PRERELEASE_VERSION="$MAJOR.$MINOR.$PATCH-$PRERELEASE_TAG.$((PRERELEASE_NUM + 1))" | |
| else | |
| # Currently a stable version, bump to alpha.1 | |
| NEW_PRERELEASE_VERSION="$MAJOR.$MINOR.$((PATCH + 1))-alpha.1" | |
| fi | |
| NEW_PATCH_VERSION="$MAJOR.$MINOR.$((PATCH + 1))" | |
| NEW_MINOR_VERSION="$MAJOR.$((MINOR + 1)).0" | |
| NEW_MAJOR_VERSION="$((MAJOR + 1)).0.0" | |
| echo "prerelease_version=$NEW_PRERELEASE_VERSION" >> $GITHUB_OUTPUT | |
| echo "patch_version=$NEW_PATCH_VERSION" >> $GITHUB_OUTPUT | |
| echo "minor_version=$NEW_MINOR_VERSION" >> $GITHUB_OUTPUT | |
| echo "major_version=$NEW_MAJOR_VERSION" >> $GITHUB_OUTPUT | |
| echo "current_version=$CURRENT_VERSION" >> $GITHUB_OUTPUT | |
| - name: Preserve deploy checkbox state | |
| id: checkbox_state | |
| env: | |
| COMMENT_BODY: ${{ steps.find_comment.outputs.comment-body }} | |
| run: | | |
| # If an existing comment has the checkbox checked, preserve it | |
| if echo "$COMMENT_BODY" | grep -q '\[x\] Deploy to production'; then | |
| echo "deploy_checked=- [x] Deploy to production (triggers ArgoCD sync after Docker image is published)" >> $GITHUB_OUTPUT | |
| else | |
| echo "deploy_checked=- [ ] Deploy to production (triggers ArgoCD sync after Docker image is published)" >> $GITHUB_OUTPUT | |
| fi | |
| - name: Post Release Options Comment | |
| uses: peter-evans/create-or-update-comment@v4 | |
| id: comment | |
| with: | |
| token: ${{ secrets.GITHUB_TOKEN }} | |
| issue-number: ${{ github.event.pull_request.number }} | |
| comment-id: ${{ steps.find_comment.outputs.comment-id }} | |
| edit-mode: replace | |
| body: | | |
| ## Release Options | |
| Should a new version be published when this PR is merged? | |
| React with an emoji to vote on the release type: | |
| | Reaction | Type | Next Version | | |
| |----------|------|--------------| | |
| | :+1: | Prerelease | `${{ steps.calculate_versions.outputs.prerelease_version }}` | | |
| | :tada: | Patch | `${{ steps.calculate_versions.outputs.patch_version }}` | | |
| | :heart: | Minor | `${{ steps.calculate_versions.outputs.minor_version }}` | | |
| | :rocket: | Major | `${{ steps.calculate_versions.outputs.major_version }}` | | |
| Current version: `${{ steps.calculate_versions.outputs.current_version }}` | |
| ### Deployment | |
| ${{ steps.checkbox_state.outputs.deploy_checked }} | |
| determine-tag: | |
| if: github.event_name == 'push' | |
| runs-on: ubuntu-latest | |
| outputs: | |
| new_version: ${{ steps.determine_version.outputs.new_version }} | |
| deploy_to_production: ${{ steps.determine_version.outputs.deploy_to_production }} | |
| steps: | |
| - name: Checkout Code | |
| uses: actions/checkout@v4 | |
| with: | |
| token: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Find the Merged Pull Request | |
| id: find_pr | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| run: | | |
| # Find the most recently merged PR to main | |
| PR_NUMBER=$(gh pr list --state merged --base main --json number,mergedAt --jq 'sort_by(.mergedAt) | reverse | .[0].number') | |
| if [ -z "$PR_NUMBER" ] || [ "$PR_NUMBER" == "null" ]; then | |
| echo "No recently merged PR found" | |
| echo "pr_number=" >> $GITHUB_OUTPUT | |
| else | |
| echo "Found merged PR #$PR_NUMBER" | |
| echo "pr_number=$PR_NUMBER" >> $GITHUB_OUTPUT | |
| fi | |
| - name: Get current version | |
| id: get_current_version | |
| run: | | |
| CURRENT_VERSION=$(node -p "require('./apps/mesh/package.json').version") | |
| echo "current_version=$CURRENT_VERSION" >> $GITHUB_OUTPUT | |
| - name: Determine the next version based on reactions | |
| id: determine_version | |
| if: steps.find_pr.outputs.pr_number != '' | |
| env: | |
| PR_NUMBER: ${{ steps.find_pr.outputs.pr_number }} | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| CURRENT_VERSION: ${{ steps.get_current_version.outputs.current_version }} | |
| run: | | |
| # Parse current version | |
| if [[ "$CURRENT_VERSION" =~ ^([0-9]+)\.([0-9]+)\.([0-9]+)(-([a-zA-Z]+)\.([0-9]+))?$ ]]; then | |
| MAJOR="${BASH_REMATCH[1]}" | |
| MINOR="${BASH_REMATCH[2]}" | |
| PATCH="${BASH_REMATCH[3]}" | |
| PRERELEASE_TAG="${BASH_REMATCH[5]}" | |
| PRERELEASE_NUM="${BASH_REMATCH[6]}" | |
| else | |
| echo "Could not parse version: $CURRENT_VERSION" | |
| exit 1 | |
| fi | |
| # Load maintainers list | |
| if [ -f "MAINTAINERS.txt" ]; then | |
| ALLOWED_USERS=$(grep -v '^#' MAINTAINERS.txt | grep -v '^$' | jq -R -s -c 'split("\n") | map(select(length > 0))') | |
| else | |
| echo "MAINTAINERS.txt not found, skipping version bump" | |
| exit 0 | |
| fi | |
| echo "Maintainers list: $ALLOWED_USERS" | |
| # Fetch comments and find the Release Options comment | |
| COMMENT_DATA=$(gh api graphql -f query=' | |
| query { | |
| repository(owner:"${{ github.repository_owner }}", name:"${{ github.event.repository.name }}") { | |
| pullRequest(number: '${PR_NUMBER}') { | |
| comments(last: 100) { | |
| nodes { | |
| body | |
| id | |
| reactions(last: 100) { | |
| nodes { | |
| content | |
| user { | |
| login | |
| } | |
| } | |
| } | |
| } | |
| } | |
| } | |
| } | |
| }') | |
| # Extract reactions from the Release Options comment, filtered by maintainers | |
| REACTIONS=$(echo "$COMMENT_DATA" | jq -r --argjson allowed_users "$ALLOWED_USERS" ' | |
| .data.repository.pullRequest.comments.nodes[] | | |
| select(.body | contains("## Release Options")) | | |
| .reactions.nodes[] | | |
| select(.user.login | IN($allowed_users[])) | | |
| .content' | tr '[:lower:]' '[:upper:]') | |
| echo "Captured reactions: $REACTIONS" | |
| # Check for deploy checkbox in comment body | |
| COMMENT_BODY=$(echo "$COMMENT_DATA" | jq -r ' | |
| .data.repository.pullRequest.comments.nodes[] | | |
| select(.body | contains("## Release Options")) | | |
| .body') | |
| if echo "$COMMENT_BODY" | grep -q '\[x\] Deploy to production'; then | |
| DEPLOY_TO_PRODUCTION="true" | |
| echo "Deploy to production: enabled" | |
| else | |
| DEPLOY_TO_PRODUCTION="false" | |
| echo "Deploy to production: disabled" | |
| fi | |
| echo "deploy_to_production=$DEPLOY_TO_PRODUCTION" >> $GITHUB_OUTPUT | |
| # Determine version bump based on reactions (priority: major > minor > patch > prerelease) | |
| NEW_VERSION="" | |
| if echo "$REACTIONS" | grep -q "ROCKET"; then | |
| NEW_VERSION="$((MAJOR + 1)).0.0" | |
| echo "Major bump selected" | |
| elif echo "$REACTIONS" | grep -q "HEART"; then | |
| NEW_VERSION="$MAJOR.$((MINOR + 1)).0" | |
| echo "Minor bump selected" | |
| elif echo "$REACTIONS" | grep -q "HOORAY"; then | |
| NEW_VERSION="$MAJOR.$MINOR.$((PATCH + 1))" | |
| echo "Patch bump selected" | |
| elif echo "$REACTIONS" | grep -q "THUMBS_UP"; then | |
| if [ -n "$PRERELEASE_TAG" ]; then | |
| NEW_VERSION="$MAJOR.$MINOR.$PATCH-$PRERELEASE_TAG.$((PRERELEASE_NUM + 1))" | |
| else | |
| NEW_VERSION="$MAJOR.$MINOR.$((PATCH + 1))-alpha.1" | |
| fi | |
| echo "Prerelease bump selected" | |
| else | |
| echo "No valid reactions found for version bump. Exiting." | |
| echo "new_version=" >> $GITHUB_OUTPUT | |
| exit 0 | |
| fi | |
| echo "New version: $NEW_VERSION" | |
| echo "new_version=$NEW_VERSION" >> $GITHUB_OUTPUT | |
| - name: Update package.json version | |
| if: steps.determine_version.outputs.new_version != '' | |
| run: | | |
| NEW_VERSION="${{ steps.determine_version.outputs.new_version }}" | |
| # Update version in package.json using node | |
| node -e " | |
| const fs = require('fs'); | |
| const pkg = JSON.parse(fs.readFileSync('./apps/mesh/package.json', 'utf8')); | |
| pkg.version = '$NEW_VERSION'; | |
| fs.writeFileSync('./apps/mesh/package.json', JSON.stringify(pkg, null, 2) + '\n'); | |
| " | |
| echo "Updated apps/mesh/package.json to version $NEW_VERSION" | |
| - name: Commit and push version bump | |
| if: steps.determine_version.outputs.new_version != '' | |
| run: | | |
| git config user.name "github-actions[bot]" | |
| git config user.email "github-actions[bot]@users.noreply.github.com" | |
| git add apps/mesh/package.json | |
| git commit -m "[release]: bump to ${{ steps.determine_version.outputs.new_version }}" | |
| git push origin main | |
| - name: Trigger Release Workflow | |
| if: steps.determine_version.outputs.new_version != '' | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| run: | | |
| curl -X POST \ | |
| -H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" \ | |
| -H "Accept: application/vnd.github.everest-preview+json" \ | |
| "https://api.github.com/repos/${{ github.repository }}/actions/workflows/release.yaml/dispatches" \ | |
| -d '{"ref":"main", "inputs":{"deploy_to_production":"${{ steps.determine_version.outputs.deploy_to_production }}"}}' | |