fix(task-management): support git worktrees in router root detection #269
Workflow file for this run
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: Validate Registry on PR | |
| # This workflow validates the registry.json and prompt library structure on all PRs. | |
| # | |
| # For bot-created PRs (like automated version bumps), the workflow won't trigger automatically | |
| # due to GitHub's security restrictions. In those cases, you can manually trigger this workflow: | |
| # | |
| # Option 1 - Run Validation: | |
| # 1. Go to Actions > Validate Registry on PR > Run workflow | |
| # 2. Enter the PR number (e.g., 106) | |
| # 3. Leave "skip_validation" unchecked | |
| # 4. Click "Run workflow" | |
| # | |
| # Option 2 - Admin Bypass (for trusted bot PRs): | |
| # 1. Go to Actions > Validate Registry on PR > Run workflow | |
| # 2. Enter the PR number (e.g., 106) | |
| # 3. Check "skip_validation" checkbox | |
| # 4. Click "Run workflow" | |
| # 5. The check will pass immediately without running validation | |
| on: | |
| # Use pull_request_target to allow running on bot-created PRs | |
| # This also allows the workflow to write to the PR branch | |
| pull_request_target: | |
| branches: | |
| - main | |
| - dev | |
| # Removed paths filter - this check is required by repository ruleset | |
| # so it must run on ALL PRs to prevent blocking merges | |
| workflow_dispatch: | |
| inputs: | |
| pr_number: | |
| description: 'PR number to validate (for manual runs on bot-created PRs)' | |
| required: false | |
| type: number | |
| skip_validation: | |
| description: 'Skip validation checks (maintainer override)' | |
| required: false | |
| type: boolean | |
| default: false | |
| permissions: | |
| contents: write | |
| pull-requests: write | |
| jobs: | |
| validate-and-update: | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Admin bypass check | |
| if: github.event_name == 'workflow_dispatch' && github.event.inputs.skip_validation == 'true' | |
| run: | | |
| echo "## ✅ Validation Bypassed (Admin Override)" >> $GITHUB_STEP_SUMMARY | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| echo "Validation checks skipped by maintainer." >> $GITHUB_STEP_SUMMARY | |
| echo "PR: #${{ github.event.inputs.pr_number }}" >> $GITHUB_STEP_SUMMARY | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| echo "The workflow will complete successfully without running validation steps." >> $GITHUB_STEP_SUMMARY | |
| - name: Checkout repository (for manual runs) | |
| if: github.event_name == 'workflow_dispatch' && github.event.inputs.skip_validation != 'true' | |
| uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 | |
| token: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Get PR details (for manual runs) | |
| if: github.event_name == 'workflow_dispatch' && github.event.inputs.pr_number != '' && github.event.inputs.skip_validation != 'true' | |
| id: get_pr | |
| run: | | |
| PR_DATA=$(gh pr view ${{ github.event.inputs.pr_number }} --json headRefName,headRepository,headRepositoryOwner) | |
| echo "head_ref=$(echo $PR_DATA | jq -r '.headRefName')" >> $GITHUB_OUTPUT | |
| echo "head_repo=$(echo $PR_DATA | jq -r '.headRepositoryOwner.login + "/" + .headRepository.name')" >> $GITHUB_OUTPUT | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Checkout PR branch | |
| if: github.event.inputs.skip_validation != 'true' | |
| uses: actions/checkout@v4 | |
| with: | |
| # For manual runs: use PR details from get_pr step | |
| # For PR events: use event data | |
| repository: ${{ github.event_name == 'workflow_dispatch' && steps.get_pr.outputs.head_repo || github.event.pull_request.head.repo.full_name }} | |
| ref: ${{ github.event_name == 'workflow_dispatch' && steps.get_pr.outputs.head_ref || github.event.pull_request.head.ref }} | |
| fetch-depth: 0 | |
| token: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Detect fork PR | |
| if: github.event.inputs.skip_validation != 'true' | |
| id: fork_check | |
| run: | | |
| # For manual runs, use the fetched PR data | |
| if [ "${{ github.event_name }}" == "workflow_dispatch" ]; then | |
| HEAD_REPO="${{ steps.get_pr.outputs.head_repo }}" | |
| else | |
| HEAD_REPO="${{ github.event.pull_request.head.repo.full_name }}" | |
| fi | |
| if [ "$HEAD_REPO" != "${{ github.repository }}" ]; then | |
| echo "is_fork=true" >> $GITHUB_OUTPUT | |
| echo "🔀 Fork PR detected from: $HEAD_REPO" | |
| else | |
| echo "is_fork=false" >> $GITHUB_OUTPUT | |
| echo "📝 Internal PR detected" | |
| fi | |
| - name: Install dependencies | |
| if: github.event.inputs.skip_validation != 'true' | |
| run: | | |
| sudo apt-get update | |
| sudo apt-get install -y jq | |
| - name: Install Bun | |
| if: github.event.inputs.skip_validation != 'true' | |
| uses: oven-sh/setup-bun@v2 | |
| with: | |
| bun-version: latest | |
| - name: Install dependencies | |
| if: github.event.inputs.skip_validation != 'true' | |
| run: | | |
| # Install root dependencies (glob package needed for validation script) | |
| bun install --frozen-lockfile | |
| - name: Make scripts executable | |
| if: github.event.inputs.skip_validation != 'true' | |
| run: | | |
| chmod +x scripts/registry/validate-registry.sh | |
| chmod +x scripts/registry/auto-detect-components.sh | |
| chmod +x scripts/registry/register-component.sh | |
| chmod +x scripts/prompts/validate-pr.sh | |
| - name: Auto-detect new components | |
| if: github.event.inputs.skip_validation != 'true' | |
| id: auto_detect | |
| run: | | |
| echo "## 🔍 Auto-Detection Results" >> $GITHUB_STEP_SUMMARY | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| # Run auto-detect in dry-run mode first to see what would be added | |
| if ./scripts/registry/auto-detect-components.sh --dry-run > /tmp/detect-output.txt 2>&1; then | |
| cat /tmp/detect-output.txt >> $GITHUB_STEP_SUMMARY | |
| # Check if new components were found | |
| if grep -q "Found.*new component" /tmp/detect-output.txt; then | |
| echo "new_components=true" >> $GITHUB_OUTPUT | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| echo "⚠️ New components detected - will auto-add to registry" >> $GITHUB_STEP_SUMMARY | |
| else | |
| echo "new_components=false" >> $GITHUB_OUTPUT | |
| echo "✅ No new components found" >> $GITHUB_STEP_SUMMARY | |
| fi | |
| else | |
| echo "new_components=false" >> $GITHUB_OUTPUT | |
| echo "❌ Auto-detection failed" >> $GITHUB_STEP_SUMMARY | |
| fi | |
| - name: Add new components to registry | |
| if: steps.auto_detect.outputs.new_components == 'true' && github.event.inputs.skip_validation != 'true' | |
| run: | | |
| echo "## 📝 Adding New Components" >> $GITHUB_STEP_SUMMARY | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| ./scripts/registry/auto-detect-components.sh --auto-add | tee -a $GITHUB_STEP_SUMMARY | |
| - name: Validate prompt library structure | |
| if: github.event.inputs.skip_validation != 'true' | |
| id: validate_prompts | |
| run: | | |
| echo "## 🔍 Prompt Library Validation" >> $GITHUB_STEP_SUMMARY | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| if ./scripts/prompts/validate-pr.sh > /tmp/prompt-validation.txt 2>&1; then | |
| echo "prompt_validation=passed" >> $GITHUB_OUTPUT | |
| echo "✅ Prompt library structure is valid!" >> $GITHUB_STEP_SUMMARY | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| echo "\`\`\`" >> $GITHUB_STEP_SUMMARY | |
| cat /tmp/prompt-validation.txt >> $GITHUB_STEP_SUMMARY | |
| echo "\`\`\`" >> $GITHUB_STEP_SUMMARY | |
| else | |
| echo "prompt_validation=failed" >> $GITHUB_OUTPUT | |
| echo "❌ Prompt library validation failed!" >> $GITHUB_STEP_SUMMARY | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| echo "\`\`\`" >> $GITHUB_STEP_SUMMARY | |
| cat /tmp/prompt-validation.txt >> $GITHUB_STEP_SUMMARY | |
| echo "\`\`\`" >> $GITHUB_STEP_SUMMARY | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| echo "**Architecture:**" >> $GITHUB_STEP_SUMMARY | |
| echo "- Agent files (.opencode/agent/**/*.md) = Canonical defaults" >> $GITHUB_STEP_SUMMARY | |
| echo "- Prompt variants (.opencode/prompts/<agent>/<model>.md) = Model-specific" >> $GITHUB_STEP_SUMMARY | |
| echo "- default.md files should NOT exist" >> $GITHUB_STEP_SUMMARY | |
| echo "- Agents organized in category subdirectories (core/, development/, content/, etc.)" >> $GITHUB_STEP_SUMMARY | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| echo "See [CONTRIBUTING.md](docs/contributing/CONTRIBUTING.md) for details" >> $GITHUB_STEP_SUMMARY | |
| exit 1 | |
| fi | |
| - name: Validate markdown context links | |
| if: github.event.inputs.skip_validation != 'true' | |
| id: validate_context_links | |
| run: | | |
| echo "## 🔗 Context Link Validation" >> $GITHUB_STEP_SUMMARY | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| if bun run scripts/validation/validate-markdown-links.ts > /tmp/context-link-validation.txt 2>&1; then | |
| echo "context_links=passed" >> $GITHUB_OUTPUT | |
| echo "✅ Context markdown links are valid!" >> $GITHUB_STEP_SUMMARY | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| echo "\`\`\`" >> $GITHUB_STEP_SUMMARY | |
| cat /tmp/context-link-validation.txt >> $GITHUB_STEP_SUMMARY | |
| echo "\`\`\`" >> $GITHUB_STEP_SUMMARY | |
| else | |
| echo "context_links=failed" >> $GITHUB_OUTPUT | |
| echo "❌ Context markdown link validation failed!" >> $GITHUB_STEP_SUMMARY | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| echo "\`\`\`" >> $GITHUB_STEP_SUMMARY | |
| cat /tmp/context-link-validation.txt >> $GITHUB_STEP_SUMMARY | |
| echo "\`\`\`" >> $GITHUB_STEP_SUMMARY | |
| exit 1 | |
| fi | |
| - name: Validate registry | |
| if: github.event.inputs.skip_validation != 'true' | |
| id: validate | |
| run: | | |
| echo "## ✅ Registry Validation" >> $GITHUB_STEP_SUMMARY | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| # Use TypeScript validator (fast and reliable) | |
| # Run validation and capture output (show in logs AND save to file) | |
| if bun run scripts/registry/validate-registry.ts 2>&1 | tee /tmp/validation-output.txt; then | |
| echo "validation=passed" >> $GITHUB_OUTPUT | |
| echo "✅ All registry paths are valid!" >> $GITHUB_STEP_SUMMARY | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| echo "\`\`\`" >> $GITHUB_STEP_SUMMARY | |
| cat /tmp/validation-output.txt >> $GITHUB_STEP_SUMMARY | |
| echo "\`\`\`" >> $GITHUB_STEP_SUMMARY | |
| else | |
| echo "validation=failed" >> $GITHUB_OUTPUT | |
| echo "❌ Registry validation failed!" >> $GITHUB_STEP_SUMMARY | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| echo "\`\`\`" >> $GITHUB_STEP_SUMMARY | |
| cat /tmp/validation-output.txt >> $GITHUB_STEP_SUMMARY | |
| echo "\`\`\`" >> $GITHUB_STEP_SUMMARY | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| echo "**Check the logs above for detailed error output**" >> $GITHUB_STEP_SUMMARY | |
| exit 1 | |
| fi | |
| - name: Commit registry updates (Internal PRs only) | |
| if: | | |
| github.event.inputs.skip_validation != 'true' && | |
| steps.fork_check.outputs.is_fork == 'false' && | |
| steps.auto_detect.outputs.new_components == 'true' && | |
| steps.validate_prompts.outputs.prompt_validation == 'passed' && | |
| steps.validate.outputs.validation == 'passed' | |
| run: | | |
| git config --local user.email "github-actions[bot]@users.noreply.github.com" | |
| git config --local user.name "github-actions[bot]" | |
| if ! git diff --quiet registry.json; then | |
| git add registry.json | |
| git commit -m "chore: auto-update registry with new components [skip ci]" | |
| # For manual runs, use the fetched branch name | |
| BRANCH_NAME="${{ github.event_name == 'workflow_dispatch' && steps.get_pr.outputs.head_ref || github.event.pull_request.head.ref }}" | |
| git push origin "$BRANCH_NAME" | |
| echo "## 🚀 Registry Updated" >> $GITHUB_STEP_SUMMARY | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| echo "Registry has been automatically updated with new components." >> $GITHUB_STEP_SUMMARY | |
| echo "Changes have been pushed to this PR branch." >> $GITHUB_STEP_SUMMARY | |
| else | |
| echo "## ℹ️ No Changes to Commit" >> $GITHUB_STEP_SUMMARY | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| echo "Registry is already up to date." >> $GITHUB_STEP_SUMMARY | |
| fi | |
| - name: Fork PR notice | |
| if: | | |
| github.event.inputs.skip_validation != 'true' && | |
| steps.fork_check.outputs.is_fork == 'true' && | |
| steps.auto_detect.outputs.new_components == 'true' && | |
| steps.validate_prompts.outputs.prompt_validation == 'passed' && | |
| steps.validate.outputs.validation == 'passed' | |
| uses: actions/github-script@v7 | |
| with: | |
| script: | | |
| github.rest.issues.createComment({ | |
| issue_number: context.issue.number, | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| body: `## 📝 Registry Update Needed | |
| Hi @${{ github.event.pull_request.user.login }}! 👋 | |
| New components were detected in your PR. Since this is a fork PR, I can't auto-commit the registry updates for security reasons. | |
| **Please run these commands locally:** | |
| \`\`\`bash | |
| ./scripts/registry/auto-detect-components.sh --auto-add | |
| git add registry.json | |
| git commit -m "chore: update registry" | |
| git push | |
| \`\`\` | |
| Once you push the updated registry, the checks will pass! ✅` | |
| }); | |
| - name: Fork PR summary | |
| if: steps.fork_check.outputs.is_fork == 'true' && github.event.inputs.skip_validation != 'true' | |
| run: | | |
| echo "## 🔀 Fork PR Detected" >> $GITHUB_STEP_SUMMARY | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| echo "This is an external contribution - thank you! 🎉" >> $GITHUB_STEP_SUMMARY | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| if [ "${{ steps.auto_detect.outputs.new_components }}" == "true" ]; then | |
| echo "⚠️ **Action Required:** New components detected" >> $GITHUB_STEP_SUMMARY | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| echo "A comment has been posted with instructions to update the registry." >> $GITHUB_STEP_SUMMARY | |
| else | |
| echo "✅ No registry updates needed" >> $GITHUB_STEP_SUMMARY | |
| fi | |
| - name: Post validation summary | |
| if: always() | |
| run: | | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| echo "---" >> $GITHUB_STEP_SUMMARY | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| PROMPT_VALID="${{ steps.validate_prompts.outputs.prompt_validation }}" | |
| CONTEXT_LINKS_VALID="${{ steps.validate_context_links.outputs.context_links }}" | |
| REGISTRY_VALID="${{ steps.validate.outputs.validation }}" | |
| if [ "$PROMPT_VALID" = "passed" ] && [ "$CONTEXT_LINKS_VALID" = "passed" ] && [ "$REGISTRY_VALID" = "passed" ]; then | |
| echo "### ✅ All Validations Passed" >> $GITHUB_STEP_SUMMARY | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| echo "- ✅ Prompt library structure is valid" >> $GITHUB_STEP_SUMMARY | |
| echo "- ✅ Context markdown links are valid" >> $GITHUB_STEP_SUMMARY | |
| echo "- ✅ Registry paths are valid" >> $GITHUB_STEP_SUMMARY | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| echo "This PR is ready for review!" >> $GITHUB_STEP_SUMMARY | |
| else | |
| echo "### ❌ Validation Failed" >> $GITHUB_STEP_SUMMARY | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| if [ "$PROMPT_VALID" != "passed" ]; then | |
| echo "- ❌ Prompt library validation failed" >> $GITHUB_STEP_SUMMARY | |
| else | |
| echo "- ✅ Prompt library validation passed" >> $GITHUB_STEP_SUMMARY | |
| fi | |
| if [ "$CONTEXT_LINKS_VALID" != "passed" ]; then | |
| echo "- ❌ Context markdown link validation failed" >> $GITHUB_STEP_SUMMARY | |
| else | |
| echo "- ✅ Context markdown link validation passed" >> $GITHUB_STEP_SUMMARY | |
| fi | |
| if [ "$REGISTRY_VALID" != "passed" ]; then | |
| echo "- ❌ Registry validation failed" >> $GITHUB_STEP_SUMMARY | |
| else | |
| echo "- ✅ Registry validation passed" >> $GITHUB_STEP_SUMMARY | |
| fi | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| echo "Please fix the issues above before merging." >> $GITHUB_STEP_SUMMARY | |
| fi | |
| - name: Fail if validation failed | |
| if: | | |
| (steps.validate_prompts.outputs.prompt_validation == 'failed' || steps.validate_context_links.outputs.context_links == 'failed' || steps.validate.outputs.validation == 'failed') && | |
| github.event.inputs.skip_validation != 'true' | |
| run: | | |
| echo "❌ Validation failed - blocking PR merge" | |
| echo "Maintainer can override by running workflow manually with 'skip_validation' enabled" | |
| exit 1 |