fix: update bin entry to enable default npx command #26
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: AI Task Orchestration | |
| # Centralized timeout configuration | |
| env: | |
| WORKFLOW_TIMEOUT_MINUTES: 30 | |
| CLI_INSTALL_TIMEOUT_MINUTES: 5 | |
| AI_EXECUTION_TIMEOUT_MINUTES: 10 | |
| # This workflow uses github.token for all operations | |
| # | |
| # Required permissions (declared below): | |
| # - contents: write (for code modifications) | |
| # - issues: write (for issue operations) | |
| # - pull-requests: write (for PR creation) | |
| # - actions: read (for workflow status) | |
| # | |
| # Note: GitHub does not allow workflows to modify other workflow files | |
| # using GITHUB_TOKEN. If workflow modifications are needed, use GH_PAT. | |
| # | |
| # Note: Using github.token means this workflow will NOT trigger other workflows | |
| # This is a GitHub security restriction. If you need cross-workflow triggering: | |
| # 1. Create a Personal Access Token (PAT) with 'repo' scope | |
| # 2. Add it as a secret named 'GH_PAT' | |
| # 3. Update the checkout and PR creation steps to use: token: ${{ secrets.GH_PAT }} | |
| 'on': | |
| issues: | |
| types: [labeled] | |
| issue_comment: | |
| types: [created] | |
| # Concurrency control to prevent parallel runs | |
| concurrency: | |
| group: ai-workflows-feature-ai-task-${{ github.event.issue.number }} | |
| cancel-in-progress: false | |
| # Minimal permissions for security | |
| permissions: | |
| contents: write | |
| issues: write | |
| pull-requests: write | |
| actions: read | |
| jobs: | |
| ai-task: | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 30 # Using direct value as env vars not available at job level | |
| if: contains(github.event.issue.labels.*.name, 'ai-task') | |
| env: | |
| GITHUB_TOKEN: ${{ github.token }} | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@v4 | |
| with: | |
| token: ${{ github.token }} | |
| fetch-depth: 0 | |
| - name: Validate GitHub token permissions | |
| run: | | |
| echo "π Validating GitHub token permissions..." | |
| if ! gh auth status > /dev/null 2>&1; then | |
| echo "β GitHub token authentication failed" | |
| exit 1 | |
| fi | |
| echo "β GitHub token is valid and authenticated" | |
| - name: Ensure required labels exist | |
| run: ./scripts/setup-labels.sh | |
| - name: Setup Node.js | |
| uses: actions/setup-node@v4 | |
| with: | |
| node-version: '18' | |
| - name: Setup environment for OpenRouter API | |
| env: | |
| OPENROUTER_API_KEY: ${{ secrets.OPENROUTER_API_KEY }} | |
| run: | | |
| # Validate required secrets | |
| if [[ -z "$OPENROUTER_API_KEY" ]]; then | |
| echo "ERROR: OPENROUTER_API_KEY secret is required" | |
| exit 1 | |
| fi | |
| # Set default model if not specified | |
| echo "AI_MODEL=${{ vars.AI_MODEL || 'anthropic/claude-sonnet-4' }}" >> $GITHUB_ENV | |
| echo "β OpenRouter API key configured" | |
| echo "π Using OpenRouter API" | |
| - name: Extract task details | |
| id: extract | |
| env: | |
| HAS_BUG_LABEL: ${{ contains(github.event.issue.labels.*.name, 'bug') }} | |
| HAS_REFACTORING_LABEL: ${{ contains(github.event.issue.labels.*.name, 'refactoring') }} | |
| HAS_DOCUMENTATION_LABEL: ${{ contains(github.event.issue.labels.*.name, 'documentation') }} | |
| HAS_TESTING_LABEL: ${{ contains(github.event.issue.labels.*.name, 'testing') }} | |
| ISSUE_NUMBER: ${{ github.event.issue.number }} | |
| ISSUE_TITLE: ${{ github.event.issue.title }} | |
| run: | | |
| echo "issue_number=$ISSUE_NUMBER" >> $GITHUB_OUTPUT | |
| echo "issue_title=$ISSUE_TITLE" >> $GITHUB_OUTPUT | |
| ./scripts/determine-branch-prefix.sh | |
| - name: Create feature branch | |
| run: | | |
| git config --local user.email "[email protected]" | |
| git config --local user.name "GitHub Action" | |
| git checkout -b ${{ steps.extract.outputs.branch_prefix }}/ai-task-${{ steps.extract.outputs.issue_number }} | |
| - name: Execute AI task | |
| id: ai-task | |
| timeout-minutes: ${{ fromJSON(env.AI_EXECUTION_TIMEOUT_MINUTES) }} | |
| env: | |
| OPENROUTER_API_KEY: ${{ secrets.OPENROUTER_API_KEY }} | |
| GITHUB_TOKEN: ${{ github.token }} | |
| AI_MODEL: ${{ env.AI_MODEL }} | |
| GITHUB_REPOSITORY: ${{ github.repository }} | |
| AI_EXECUTION_TIMEOUT_MINUTES: ${{ env.AI_EXECUTION_TIMEOUT_MINUTES }} | |
| MAX_PROMPT_SIZE: ${{ secrets.MAX_PROMPT_SIZE || '50000' }} | |
| run: | | |
| echo "π° COST WARNING: This AI task may incur API costs" | |
| echo "π SECURITY: AI output will be sanitized to prevent data exposure" | |
| echo "β° TIMEOUT: Task limited to ${AI_EXECUTION_TIMEOUT_MINUTES} minutes" | |
| echo "π€ AI MODEL: ${AI_MODEL}" | |
| echo "π MAX PROMPT SIZE: ${MAX_PROMPT_SIZE} chars" | |
| echo "" | |
| ./scripts/execute-ai-task.sh "${{ steps.extract.outputs.issue_number }}" | |
| - name: Commit changes | |
| if: steps.ai-task.outputs.has_changes == 'true' | |
| env: | |
| ISSUE_TITLE: ${{ steps.extract.outputs.issue_title }} | |
| ISSUE_NUMBER: ${{ steps.extract.outputs.issue_number }} | |
| run: ./scripts/commit-changes.sh | |
| - name: Comment on issue when no changes made | |
| if: steps.ai-task.outputs.has_changes == 'false' | |
| env: | |
| ISSUE_NUMBER: ${{ steps.extract.outputs.issue_number }} | |
| run: ./scripts/comment-no-changes.sh | |
| - name: Remove ai-task label when no changes made | |
| if: steps.ai-task.outputs.has_changes == 'false' | |
| run: | | |
| echo "Removing ai-task label from issue #${{ steps.extract.outputs.issue_number }} (no changes made)" | |
| gh issue edit "${{ steps.extract.outputs.issue_number }}" --remove-label "ai-task" | |
| gh issue edit "${{ steps.extract.outputs.issue_number }}" --add-label "ai-no-changes" 2>/dev/null || echo "Note: 'ai-no-changes' label not found" | |
| echo "β Updated labels for no-changes scenario" | |
| - name: Push changes | |
| id: push | |
| if: steps.ai-task.outputs.has_changes == 'true' | |
| env: | |
| BRANCH_NAME: ${{ steps.extract.outputs.branch_prefix }}/ai-task-${{ steps.extract.outputs.issue_number }} | |
| run: ./scripts/push-changes.sh | |
| - name: Create Pull Request | |
| id: pr | |
| if: success() && steps.ai-task.outputs.has_changes == 'true' | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GH_PAT }} | |
| BRANCH_NAME: ${{ steps.push.outputs.branch_name }} | |
| ISSUE_TITLE: ${{ steps.extract.outputs.issue_title }} | |
| ISSUE_NUMBER: ${{ steps.extract.outputs.issue_number }} | |
| run: | | |
| echo "π Creating pull request..." | |
| ./scripts/create-pr.sh | |
| - name: Remove ai-task label after PR creation | |
| if: success() && steps.ai-task.outputs.has_changes == 'true' && steps.pr.outputs.pull_request_number != '' | |
| run: | | |
| echo "Removing ai-task label from issue #${{ steps.extract.outputs.issue_number }}" | |
| gh issue edit "${{ steps.extract.outputs.issue_number }}" --remove-label "ai-task" | |
| echo "β Successfully removed ai-task label" | |
| - name: Add ai-completed label | |
| if: success() && steps.ai-task.outputs.has_changes == 'true' && steps.pr.outputs.pull_request_number != '' | |
| run: | | |
| echo "Adding ai-completed label to issue #${{ steps.extract.outputs.issue_number }}" | |
| gh issue edit "${{ steps.extract.outputs.issue_number }}" --add-label "ai-completed" 2>/dev/null || \ | |
| echo "Note: 'ai-completed' label not found, will be created automatically" | |
| echo "β Successfully added ai-completed label" | |
| - name: Comment on issue with PR link | |
| if: success() && steps.ai-task.outputs.has_changes == 'true' && steps.pr.outputs.pull_request_number != '' | |
| run: | | |
| gh issue comment "${{ steps.extract.outputs.issue_number }}" --body "π€ **AI Task Completed!** | |
| I've successfully implemented the requested changes and created a pull request for review. | |
| **Pull Request:** ${{ steps.pr.outputs.pr_url }} | |
| ### What happens next? | |
| 1. The PR is ready for your review | |
| 2. Check the implementation and tests | |
| 3. Merge when you're satisfied with the changes | |
| 4. The issue will be automatically closed when the PR is merged | |
| The \`ai-task\` label has been removed and replaced with \`ai-completed\` to indicate the task is done." |