diff --git a/.github/workflows/test.bridge.yml b/.github/workflows/test.bridge.yml index 9e56b07..60d0400 100644 --- a/.github/workflows/test.bridge.yml +++ b/.github/workflows/test.bridge.yml @@ -24,6 +24,12 @@ jobs: with: fetch-depth: 0 + - name: Configure Git + run: | + git config --global user.name "github-actions[bot]" + git config --global user.email "github-actions[bot]@users.noreply.github.com" + git config --global --add safe.directory /github/workspace + - name: Set up Python uses: actions/setup-python@v5 with: @@ -129,100 +135,100 @@ jobs: # Basic YAML validation using Python python -c " -import yaml -import sys -try: - with open('$action_yml', 'r') as f: - content = f.read() - - # Skip header comments for YAML parsing - yaml_content = '\n'.join(line for line in content.split('\n') if not line.strip().startswith('#')) - config = yaml.safe_load(yaml_content) - - # Check required GitHub Action fields - required_fields = ['name', 'runs'] - missing = [field for field in required_fields if field not in config] - - if missing: - print(f'❌ Missing required fields in $action_name: {missing}') - sys.exit(1) - - # Check runs configuration - if 'using' not in config['runs']: - print(f'❌ Missing runs.using in $action_name') - sys.exit(1) - - print(f'✅ $action_name is valid GitHub Action') - -except Exception as e: - print(f'❌ Error validating $action_name: {e}') - sys.exit(1) -" - fi - done - - - name: Upload Test Results - if: always() - uses: actions/upload-artifact@v4 - with: - name: bridge-test-results - path: | - .bridge/test-results.json - .bridge/validation-report.txt - retention-days: 30 - - - name: Comment Test Results - if: github.event_name == 'pull_request' - uses: actions/github-script@v7 - with: - script: | - const fs = require('fs'); - - let comment = '## 🔗 Bridge Test Results\n\n'; - - try { - // Read test results if available - if (fs.existsSync('.bridge/test-results.json')) { - const results = JSON.parse(fs.readFileSync('.bridge/test-results.json', 'utf8')); - const summary = results.summary; - - comment += `### Test Summary\n`; - comment += `- **Total Tests**: ${summary.total}\n`; - comment += `- **Passed**: ${summary.passed} ✅\n`; - comment += `- **Failed**: ${summary.failed} ${summary.failed > 0 ? '❌' : ''}\n`; - comment += `- **Skipped**: ${summary.skipped} ⏭️\n`; + import yaml + import sys + try: + with open('$action_yml', 'r') as f: + content = f.read() + + # Skip header comments for YAML parsing + yaml_content = '\n'.join(line for line in content.split('\n') if not line.strip().startswith('#')) + config = yaml.safe_load(yaml_content) + + # Check required GitHub Action fields + required_fields = ['name', 'runs'] + missing = [field for field in required_fields if field not in config] + + if missing: + print(f'❌ Missing required fields in $action_name: {missing}') + sys.exit(1) + + # Check runs configuration + if 'using' not in config['runs']: + print(f'❌ Missing runs.using in $action_name') + sys.exit(1) + + print(f'✅ $action_name is valid GitHub Action') + + except Exception as e: + print(f'❌ Error validating $action_name: {e}') + sys.exit(1) + " + fi + done - const successRate = summary.total > 0 ? (summary.passed / summary.total * 100).toFixed(1) : 0; - comment += `- **Success Rate**: ${successRate}%\n\n`; + - name: Upload Test Results + if: always() + uses: actions/upload-artifact@v4 + with: + name: bridge-test-results + path: | + .bridge/test-results.json + .bridge/validation-report.txt + retention-days: 30 - if (summary.failed > 0) { - comment += `### Failed Tests\n`; - const failedTests = results.tests.filter(t => t.status === 'failed'); - failedTests.forEach(test => { - comment += `- ❌ **${test.name}**: ${test.message}\n`; - }); - comment += '\n'; - } - } else { - comment += 'Test results file not found.\n\n'; - } - } catch (error) { - comment += `Error reading test results: ${error.message}\n\n`; - } - - comment += `### Architecture Status\n`; - comment += `- FCM Definitions: \`axioms/\`\n`; - comment += `- Generated Actions: \`actions/core/\`\n`; - comment += `- Bridge Infrastructure: \`.bridge/\`\n\n`; - comment += `For detailed results, check the workflow artifacts.`; - - // Post comment - github.rest.issues.createComment({ - issue_number: context.issue.number, - owner: context.repo.owner, - repo: context.repo.repo, - body: comment - }); + - name: Comment Test Results + if: github.event_name == 'pull_request' + uses: actions/github-script@v7 + with: + script: | + const fs = require('fs'); + + let comment = '## 🔗 Bridge Test Results\n\n'; + + try { + // Read test results if available + if (fs.existsSync('.bridge/test-results.json')) { + const results = JSON.parse(fs.readFileSync('.bridge/test-results.json', 'utf8')); + const summary = results.summary; + + comment += `### Test Summary\n`; + comment += `- **Total Tests**: ${summary.total}\n`; + comment += `- **Passed**: ${summary.passed} ✅\n`; + comment += `- **Failed**: ${summary.failed} ${summary.failed > 0 ? '❌' : ''}\n`; + comment += `- **Skipped**: ${summary.skipped} ⏭️\n`; + + const successRate = summary.total > 0 ? (summary.passed / summary.total * 100).toFixed(1) : 0; + comment += `- **Success Rate**: ${successRate}%\n\n`; + + if (summary.failed > 0) { + comment += `### Failed Tests\n`; + const failedTests = results.tests.filter(t => t.status === 'failed'); + failedTests.forEach(test => { + comment += `- ❌ **${test.name}**: ${test.message}\n`; + }); + comment += '\n'; + } + } else { + comment += 'Test results file not found.\n\n'; + } + } catch (error) { + comment += `Error reading test results: ${error.message}\n\n`; + } + + comment += `### Architecture Status\n`; + comment += `- FCM Definitions: \`axioms/\`\n`; + comment += `- Generated Actions: \`actions/core/\`\n`; + comment += `- Bridge Infrastructure: \`.bridge/\`\n\n`; + comment += `For detailed results, check the workflow artifacts.`; + + // Post comment + github.rest.issues.createComment({ + issue_number: context.issue.number, + owner: context.repo.owner, + repo: context.repo.repo, + body: comment + }); action-tests: name: Test Generated Actions @@ -233,14 +239,16 @@ except Exception as e: - name: Checkout Repository uses: actions/checkout@v4 + - name: Configure Git + run: | + git config --global user.name "github-actions[bot]" + git config --global user.email "github-actions[bot]@users.noreply.github.com" + git config --global --add safe.directory /github/workspace + - name: Test Tag Operations Action run: | echo "=== Testing Tag Operations Action ===" - # Set up git for testing - git config user.name "Test User" - git config user.email "test@example.com" - # Test the generated tag-operations action if it exists if [ -d "actions/core/tag-operations" ]; then echo "Found generated tag-operations action" @@ -272,43 +280,43 @@ except Exception as e: # Use Python to parse and validate the action interface python -c " -import yaml -import sys + import yaml + import sys -try: - with open('$action_dir/action.yml', 'r') as f: - content = f.read() - - # Skip header comments - yaml_content = '\n'.join(line for line in content.split('\n') if not line.strip().startswith('#')) - config = yaml.safe_load(yaml_content) - - # Validate inputs - inputs = config.get('inputs', {}) - if not inputs: - print(f'⚠️ $action_name has no inputs') - else: - for input_name, input_config in inputs.items(): - if 'description' not in input_config: - print(f'❌ $action_name input {input_name} missing description') - sys.exit(1) - if 'required' not in input_config: - print(f'❌ $action_name input {input_name} missing required field') - sys.exit(1) - print(f'✅ $action_name has {len(inputs)} valid inputs') - - # Validate outputs - outputs = config.get('outputs', {}) - if outputs: - for output_name, output_config in outputs.items(): - if 'description' not in output_config: - print(f'❌ $action_name output {output_name} missing description') - sys.exit(1) - print(f'✅ $action_name has {len(outputs)} valid outputs') - -except Exception as e: - print(f'❌ Error validating $action_name interface: {e}') - sys.exit(1) -" - fi - done \ No newline at end of file + try: + with open('$action_dir/action.yml', 'r') as f: + content = f.read() + + # Skip header comments + yaml_content = '\n'.join(line for line in content.split('\n') if not line.strip().startswith('#')) + config = yaml.safe_load(yaml_content) + + # Validate inputs + inputs = config.get('inputs', {}) + if not inputs: + print(f'⚠️ $action_name has no inputs') + else: + for input_name, input_config in inputs.items(): + if 'description' not in input_config: + print(f'❌ $action_name input {input_name} missing description') + sys.exit(1) + if 'required' not in input_config: + print(f'❌ $action_name input {input_name} missing required field') + sys.exit(1) + print(f'✅ $action_name has {len(inputs)} valid inputs') + + # Validate outputs + outputs = config.get('outputs', {}) + if outputs: + for output_name, output_config in outputs.items(): + if 'description' not in output_config: + print(f'❌ $action_name output {output_name} missing description') + sys.exit(1) + print(f'✅ $action_name has {len(outputs)} valid outputs') + + except Exception as e: + print(f'❌ Error validating $action_name interface: {e}') + sys.exit(1) + " + fi + done \ No newline at end of file