name: Test Agents on: pull_request: branches: [ main, dev ] paths: - '.opencode/**' - 'evals/**' - '.github/workflows/test-agents.yml' push: branches: [ main ] workflow_dispatch: inputs: skip_tests: description: 'Skip tests (maintainer override)' required: false type: boolean default: false jobs: # Check if this is a PR merge commit (skip tests if so - they already ran on PR) check-trigger: name: Check Trigger Type runs-on: ubuntu-latest outputs: should_test: ${{ steps.check.outputs.should_test }} should_bump: ${{ steps.check.outputs.should_bump }} steps: - name: Determine if tests should run id: check run: | # For PRs, always run tests if [ "${{ github.event_name }}" == "pull_request" ]; then echo "should_test=true" >> $GITHUB_OUTPUT echo "should_bump=false" >> $GITHUB_OUTPUT echo "PR detected - will run tests" exit 0 fi # For workflow_dispatch, check skip_tests input if [ "${{ github.event_name }}" == "workflow_dispatch" ]; then if [ "${{ github.event.inputs.skip_tests }}" == "true" ]; then echo "should_test=false" >> $GITHUB_OUTPUT echo "should_bump=false" >> $GITHUB_OUTPUT echo "Manual trigger - tests skipped by maintainer" else echo "should_test=true" >> $GITHUB_OUTPUT echo "should_bump=false" >> $GITHUB_OUTPUT echo "Manual trigger - will run tests" fi exit 0 fi # For push events, check if it's a PR merge COMMIT_MSG="${{ github.event.head_commit.message }}" # PR merges have messages like "Merge pull request #123" or contain (#123) if echo "$COMMIT_MSG" | grep -qE "^Merge pull request #|^.*\(#[0-9]+\)$"; then echo "should_test=false" >> $GITHUB_OUTPUT echo "should_bump=true" >> $GITHUB_OUTPUT echo "PR merge detected - skipping tests, will bump version" # Skip version bump commits elif echo "$COMMIT_MSG" | grep -qE "^\[skip ci\]|chore: bump version"; then echo "should_test=false" >> $GITHUB_OUTPUT echo "should_bump=false" >> $GITHUB_OUTPUT echo "Version bump commit - skipping everything" else echo "should_test=true" >> $GITHUB_OUTPUT echo "should_bump=true" >> $GITHUB_OUTPUT echo "Direct push detected - will run tests and bump version" fi test-openagent: name: Test OpenAgent runs-on: ubuntu-latest needs: check-trigger if: needs.check-trigger.outputs.should_test == 'true' timeout-minutes: 15 steps: - name: Checkout code uses: actions/checkout@v4 - name: Setup Node.js uses: actions/setup-node@v4 with: node-version: '20' cache: 'npm' cache-dependency-path: 'evals/framework/package-lock.json' # Install the OpenCode CLI (from opencode.ai, NOT our install.sh) # Our install.sh only installs agents/commands/tools, not the CLI binary # The @opencode-ai/sdk spawns `opencode serve` internally, so CLI is required - name: Install OpenCode CLI run: | npm install -g opencode-ai which opencode opencode --version # Install our OpenAgents components (agents, commands, tools) - name: Install OpenAgents Components run: bash install.sh essential --install-dir .opencode - name: Install dependencies working-directory: evals/framework run: npm install - name: Build framework working-directory: evals/framework run: npm run build - name: Run OpenAgent smoke test run: npm run test:ci:openagent env: CI: true - name: Upload test results if: always() uses: actions/upload-artifact@v4 with: name: openagent-results path: evals/results/ retention-days: 30 test-opencoder: name: Test OpenCoder runs-on: ubuntu-latest needs: check-trigger if: needs.check-trigger.outputs.should_test == 'true' timeout-minutes: 15 steps: - name: Checkout code uses: actions/checkout@v4 - name: Setup Node.js uses: actions/setup-node@v4 with: node-version: '20' cache: 'npm' cache-dependency-path: 'evals/framework/package-lock.json' # Install the OpenCode CLI (from opencode.ai, NOT our install.sh) # Our install.sh only installs agents/commands/tools, not the CLI binary # The @opencode-ai/sdk spawns `opencode serve` internally, so CLI is required - name: Install OpenCode CLI run: | npm install -g opencode-ai which opencode opencode --version # Install our OpenAgents components (agents, commands, tools) - name: Install OpenAgents Components run: bash install.sh essential --install-dir .opencode - name: Install dependencies working-directory: evals/framework run: npm install - name: Build framework working-directory: evals/framework run: npm run build - name: Run OpenCoder smoke test run: npm run test:ci:opencoder env: CI: true - name: Upload test results if: always() uses: actions/upload-artifact@v4 with: name: opencoder-results path: evals/results/ retention-days: 30 report-results: name: Report Test Results runs-on: ubuntu-latest needs: [check-trigger, test-openagent, test-opencoder] if: always() && needs.check-trigger.outputs.should_test == 'true' steps: - name: Download OpenAgent results uses: actions/download-artifact@v4 with: name: openagent-results path: results/openagent continue-on-error: true - name: Download OpenCoder results uses: actions/download-artifact@v4 with: name: opencoder-results path: results/opencoder continue-on-error: true - name: Display results summary run: | echo "## Test Results Summary" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY if [ -f results/openagent/latest.json ]; then echo "### OpenAgent" >> $GITHUB_STEP_SUMMARY cat results/openagent/latest.json | jq -r '"- Passed: \(.passed)\n- Failed: \(.failed)\n- Total: \(.total)"' >> $GITHUB_STEP_SUMMARY fi if [ -f results/opencoder/latest.json ]; then echo "" >> $GITHUB_STEP_SUMMARY echo "### OpenCoder" >> $GITHUB_STEP_SUMMARY cat results/opencoder/latest.json | jq -r '"- Passed: \(.passed)\n- Failed: \(.failed)\n- Total: \(.total)"' >> $GITHUB_STEP_SUMMARY fi auto-version-bump: name: Auto Version Bump runs-on: ubuntu-latest needs: [check-trigger, test-openagent, test-opencoder] # Run version bump if: # 1. Tests ran and passed, OR # 2. This is a PR merge (tests already passed on PR) if: | github.event_name == 'push' && github.ref == 'refs/heads/main' && needs.check-trigger.outputs.should_bump == 'true' && (needs.check-trigger.outputs.should_test == 'false' || (needs.test-openagent.result == 'success' && needs.test-opencoder.result == 'success')) permissions: contents: write steps: - name: Checkout code uses: actions/checkout@v4 with: fetch-depth: 0 token: ${{ secrets.GITHUB_TOKEN }} - name: Setup Node.js uses: actions/setup-node@v4 with: node-version: '20' - name: Configure Git run: | git config user.name "github-actions[bot]" git config user.email "github-actions[bot]@users.noreply.github.com" - name: Determine version bump type id: bump-type run: | # Get the last commit message COMMIT_MSG=$(git log -1 --pretty=%B) # Determine bump type from commit message if echo "$COMMIT_MSG" | grep -qiE "^(feat|feature)\(.*\)!:|^BREAKING CHANGE:|^[a-z]+!:"; then echo "type=major" >> $GITHUB_OUTPUT echo "Detected BREAKING CHANGE - bumping major version" elif echo "$COMMIT_MSG" | grep -qiE "^(feat|feature)(\(.*\))?:"; then echo "type=minor" >> $GITHUB_OUTPUT echo "Detected feature - bumping minor version" elif echo "$COMMIT_MSG" | grep -qiE "^(fix|bugfix)(\(.*\))?:"; then echo "type=patch" >> $GITHUB_OUTPUT echo "Detected fix - bumping patch version" elif echo "$COMMIT_MSG" | grep -qiE "^\[alpha\]"; then echo "type=alpha" >> $GITHUB_OUTPUT echo "Detected [alpha] tag - bumping alpha version" elif echo "$COMMIT_MSG" | grep -qiE "^\[beta\]"; then echo "type=beta" >> $GITHUB_OUTPUT echo "Detected [beta] tag - bumping beta version" elif echo "$COMMIT_MSG" | grep -qiE "^\[rc\]"; then echo "type=rc" >> $GITHUB_OUTPUT echo "Detected [rc] tag - bumping rc version" else echo "type=patch" >> $GITHUB_OUTPUT echo "No specific type detected - defaulting to patch version bump" fi - name: Bump version run: | BUMP_TYPE="${{ steps.bump-type.outputs.type }}" # Get current version CURRENT_VERSION=$(cat VERSION) echo "Current version: $CURRENT_VERSION" # Bump version in package.json npm run version:bump:$BUMP_TYPE # Get new version NEW_VERSION=$(cat VERSION) echo "New version: $NEW_VERSION" # Update CHANGELOG.md DATE=$(date +%Y-%m-%d) COMMIT_MSG=$(git log -1 --pretty=%B) # Create changelog entry cat > /tmp/changelog_entry.md << EOF ## [$NEW_VERSION] - $DATE ### Changes - $COMMIT_MSG EOF # Prepend to CHANGELOG.md (after the header) if [ -f CHANGELOG.md ]; then # Insert after the first occurrence of "## [" awk '/^## \[/ && !found {print; system("cat /tmp/changelog_entry.md"); found=1; next} 1' CHANGELOG.md > /tmp/changelog_new.md mv /tmp/changelog_new.md CHANGELOG.md fi - name: Commit version bump run: | NEW_VERSION=$(cat VERSION) git add VERSION package.json CHANGELOG.md git commit -m "chore: bump version to v$NEW_VERSION [skip ci]" git tag "v$NEW_VERSION" - name: Push changes run: | git push origin main --tags env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - name: Create GitHub Release run: | NEW_VERSION=$(cat VERSION) # Extract changelog entry for this version RELEASE_NOTES=$(awk '/^## \['"$NEW_VERSION"'\]/{flag=1; next} /^## \[/{flag=0} flag' CHANGELOG.md) # If no specific notes found, use commit message if [ -z "$RELEASE_NOTES" ]; then RELEASE_NOTES="Release v$NEW_VERSION" fi # Create the release gh release create "v$NEW_VERSION" \ --title "v$NEW_VERSION" \ --notes "$RELEASE_NOTES" \ --latest env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}