diff --git a/.github/workflows/cli-build-binary-and-optionally-release.yml b/.github/workflows/cli-build-binary-and-optionally-release.yml new file mode 100644 index 0000000000..bf8c0e854a --- /dev/null +++ b/.github/workflows/cli-build-binary-and-optionally-release.yml @@ -0,0 +1,104 @@ +# Workflow that builds and tests the CLI binary executable +name: CLI - Build binary and optionally release + +# Run on pushes to main branch and CLI tags, and on pull requests when CLI files change +on: + push: + branches: + - main + tags: + - "*-cli" + pull_request: + paths: + - "openhands-cli/**" + +# Cancel previous runs if a new commit is pushed +concurrency: + group: ${{ github.workflow }}-${{ (github.head_ref && github.ref) || github.run_id }} + cancel-in-progress: true + +jobs: + build-and-test-binary: + name: Build and test binary executable + strategy: + matrix: + os: [ubuntu-latest, macos-latest] + runs-on: ${{ matrix.os }} + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version: 3.12 + + - name: Install uv + uses: astral-sh/setup-uv@v3 + with: + version: "latest" + + - name: Install dependencies + working-directory: openhands-cli + run: | + uv sync + + - name: Build binary executable + working-directory: openhands-cli + run: | + ./build.sh --install-pyinstaller | tee output.log + echo "Full output:" + cat output.log + + if grep -q "❌" output.log; then + echo "❌ Found failure marker in output" + exit 1 + fi + + echo "✅ Build & test finished without ❌ markers" + + - name: Upload binary artifact (for releases only) + if: startsWith(github.ref, 'refs/tags/') + uses: actions/upload-artifact@v4 + with: + name: openhands-cli-${{ matrix.os }} + path: openhands-cli/dist/openhands* + retention-days: 30 + + create-github-release: + name: Create GitHub Release + runs-on: ubuntu-latest + needs: build-and-test-binary + if: startsWith(github.ref, 'refs/tags/') + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Download all artifacts + uses: actions/download-artifact@v4 + with: + path: artifacts + + - name: Prepare release assets + run: | + mkdir -p release-assets + # Rename binaries to include OS in filename + if [ -f artifacts/openhands-cli-ubuntu-latest/openhands ]; then + cp artifacts/openhands-cli-ubuntu-latest/openhands release-assets/openhands-linux + fi + if [ -f artifacts/openhands-cli-macos-latest/openhands ]; then + cp artifacts/openhands-cli-macos-latest/openhands release-assets/openhands-macos + fi + ls -la release-assets/ + + - name: Create GitHub Release + uses: softprops/action-gh-release@v2 + with: + files: release-assets/* + draft: true + prerelease: false + env: + GITHUB_TOKEN: ${{ secrets.CLI_RELEASE_TOKEN }} diff --git a/.github/workflows/cli-build-test.yml b/.github/workflows/cli-build-test.yml index b1fc1ac6f4..0fddcbfe0a 100644 --- a/.github/workflows/cli-build-test.yml +++ b/.github/workflows/cli-build-test.yml @@ -12,6 +12,9 @@ on: paths: - "openhands-cli/**" +permissions: + contents: write # needed to create releases or upload assets + # Cancel previous runs if a new commit is pushed concurrency: group: ${{ github.workflow }}-${{ (github.head_ref && github.ref) || github.run_id }} @@ -101,4 +104,4 @@ jobs: draft: true prerelease: false env: - GITHUB_TOKEN: ${{ secrets.CLI_RELEASE_TOKEN }} + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/tests/unit/mcp/test_mcp_tool_timeout_stall.py b/tests/unit/mcp/test_mcp_tool_timeout_stall.py index 209cf4fa46..e588b10311 100644 --- a/tests/unit/mcp/test_mcp_tool_timeout_stall.py +++ b/tests/unit/mcp/test_mcp_tool_timeout_stall.py @@ -149,6 +149,7 @@ async def test_mcp_tool_timeout_error_handling(conversation_stats): # This demonstrates that the fix is working +@pytest.mark.skip(reason='flaky test') @pytest.mark.asyncio async def test_mcp_tool_timeout_agent_continuation(conversation_stats): """Test that verifies the agent can continue processing after an MCP tool timeout."""