mirror of
https://github.com/trycua/computer.git
synced 2026-01-06 05:20:02 -06:00
269 lines
11 KiB
YAML
269 lines
11 KiB
YAML
name: Reusable Package Publish Workflow
|
|
|
|
on:
|
|
workflow_call:
|
|
inputs:
|
|
package_name:
|
|
description: 'Name of the package (e.g. pylume, computer, agent)'
|
|
required: true
|
|
type: string
|
|
package_dir:
|
|
description: 'Directory containing the package relative to workspace root (e.g. libs/pylume)'
|
|
required: true
|
|
type: string
|
|
version:
|
|
description: 'Version to publish'
|
|
required: true
|
|
type: string
|
|
is_lume_package:
|
|
description: 'Whether this package includes the lume binary'
|
|
required: false
|
|
type: boolean
|
|
default: false
|
|
base_package_name:
|
|
description: 'PyPI package name (e.g. pylume, cua-agent)'
|
|
required: true
|
|
type: string
|
|
secrets:
|
|
PYPI_TOKEN:
|
|
required: true
|
|
outputs:
|
|
version:
|
|
description: "The version that was published"
|
|
value: ${{ jobs.build-and-publish.outputs.version }}
|
|
|
|
jobs:
|
|
build-and-publish:
|
|
runs-on: macos-latest
|
|
permissions:
|
|
contents: write # This permission is needed for creating releases
|
|
outputs:
|
|
version: ${{ steps.set-version.outputs.version }}
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
with:
|
|
fetch-depth: 0 # Full history for release creation
|
|
|
|
- name: Set up Python
|
|
uses: actions/setup-python@v4
|
|
with:
|
|
python-version: '3.10'
|
|
|
|
- name: Create root pdm.lock file
|
|
run: |
|
|
# Create an empty pdm.lock file in the root
|
|
touch pdm.lock
|
|
|
|
- name: Install PDM
|
|
uses: pdm-project/setup-pdm@v3
|
|
with:
|
|
python-version: '3.10'
|
|
cache: true
|
|
|
|
- name: Set version
|
|
id: set-version
|
|
run: |
|
|
echo "VERSION=${{ inputs.version }}" >> $GITHUB_ENV
|
|
echo "version=${{ inputs.version }}" >> $GITHUB_OUTPUT
|
|
|
|
- name: Initialize PDM in package directory
|
|
run: |
|
|
# Make sure we're working with a properly initialized PDM project
|
|
cd ${{ inputs.package_dir }}
|
|
|
|
# Create pdm.lock if it doesn't exist
|
|
if [ ! -f "pdm.lock" ]; then
|
|
echo "No pdm.lock found, initializing PDM project..."
|
|
pdm lock
|
|
fi
|
|
|
|
- name: Set version in package
|
|
run: |
|
|
cd ${{ inputs.package_dir }}
|
|
# Replace pdm bump with direct edit of pyproject.toml
|
|
if [[ "$OSTYPE" == "darwin"* ]]; then
|
|
# macOS version of sed needs an empty string for -i
|
|
sed -i '' "s/version = \".*\"/version = \"$VERSION\"/" pyproject.toml
|
|
else
|
|
# Linux version
|
|
sed -i "s/version = \".*\"/version = \"$VERSION\"/" pyproject.toml
|
|
fi
|
|
# Verify version was updated
|
|
echo "Updated version in pyproject.toml:"
|
|
grep "version =" pyproject.toml
|
|
|
|
# Conditional step for lume binary download (only for pylume package)
|
|
- name: Download and setup lume binary
|
|
if: inputs.is_lume_package
|
|
run: |
|
|
# Install required packages
|
|
pip install requests
|
|
|
|
# Create a simple Python script for better error handling
|
|
cat > get_lume_version.py << 'EOF'
|
|
import requests, re, json, sys
|
|
try:
|
|
response = requests.get('https://api.github.com/repos/trycua/lume/releases/latest')
|
|
sys.stderr.write(f"API Status Code: {response.status_code}\n")
|
|
sys.stderr.write(f"API Response: {response.text}\n")
|
|
data = json.loads(response.text)
|
|
if 'tag_name' not in data:
|
|
sys.stderr.write(f"Warning: tag_name not found in API response. Keys: {list(data.keys())}\n")
|
|
print('0.1.9')
|
|
else:
|
|
tag_name = data['tag_name']
|
|
match = re.match(r'v(\d+\.\d+\.\d+)', tag_name)
|
|
if match:
|
|
print(match.group(1))
|
|
else:
|
|
sys.stderr.write("Error: Could not parse version from tag\n")
|
|
print('0.1.9')
|
|
except Exception as e:
|
|
sys.stderr.write(f"Error fetching release info: {str(e)}\n")
|
|
print('0.1.9')
|
|
EOF
|
|
|
|
# Execute the script to get the version
|
|
LUME_VERSION=$(python get_lume_version.py)
|
|
echo "Using lume version: $LUME_VERSION"
|
|
|
|
# Create a temporary directory for extraction
|
|
mkdir -p temp_lume
|
|
|
|
# Download the lume release (silently)
|
|
echo "Downloading lume version v${LUME_VERSION}..."
|
|
curl -sL "https://github.com/trycua/lume/releases/download/v${LUME_VERSION}/lume.tar.gz" -o temp_lume/lume.tar.gz
|
|
|
|
# Extract the tar file (ignore ownership and suppress warnings)
|
|
cd temp_lume && tar --no-same-owner -xzf lume.tar.gz
|
|
|
|
# Make the binary executable
|
|
chmod +x lume
|
|
|
|
# Copy the lume binary to the correct location in the pylume package
|
|
mkdir -p "${GITHUB_WORKSPACE}/${{ inputs.package_dir }}/pylume"
|
|
cp lume "${GITHUB_WORKSPACE}/${{ inputs.package_dir }}/pylume/lume"
|
|
|
|
# Verify the binary exists and is executable
|
|
test -x "${GITHUB_WORKSPACE}/${{ inputs.package_dir }}/pylume/lume" || { echo "lume binary not found or not executable"; exit 1; }
|
|
|
|
# Cleanup
|
|
cd "${GITHUB_WORKSPACE}" && rm -rf temp_lume
|
|
|
|
# Save the lume version for reference
|
|
echo "LUME_VERSION=${LUME_VERSION}" >> $GITHUB_ENV
|
|
|
|
- name: Build and publish
|
|
env:
|
|
PYPI_TOKEN: ${{ secrets.PYPI_TOKEN }}
|
|
run: |
|
|
cd ${{ inputs.package_dir }}
|
|
# Build with PDM
|
|
pdm build
|
|
|
|
# For pylume package, verify the binary is in the wheel
|
|
if [ "${{ inputs.is_lume_package }}" = "true" ]; then
|
|
python -m pip install wheel
|
|
wheel unpack dist/*.whl --dest temp_wheel
|
|
echo "Listing contents of wheel directory:"
|
|
find temp_wheel -type f
|
|
test -f temp_wheel/pylume-*/pylume/lume || { echo "lume binary not found in wheel"; exit 1; }
|
|
rm -rf temp_wheel
|
|
echo "Publishing ${{ inputs.base_package_name }} ${VERSION} with lume ${LUME_VERSION}"
|
|
else
|
|
echo "Publishing ${{ inputs.base_package_name }} ${VERSION}"
|
|
fi
|
|
|
|
# Install and use twine directly instead of PDM publish
|
|
echo "Installing twine for direct publishing..."
|
|
pip install twine
|
|
|
|
echo "Publishing to PyPI using twine..."
|
|
TWINE_USERNAME="__token__" TWINE_PASSWORD="$PYPI_TOKEN" python -m twine upload dist/*
|
|
|
|
# Save the wheel file path for the release
|
|
WHEEL_FILE=$(ls dist/*.whl | head -1)
|
|
echo "WHEEL_FILE=${WHEEL_FILE}" >> $GITHUB_ENV
|
|
|
|
- name: Prepare Simple Release Notes
|
|
if: startsWith(github.ref, 'refs/tags/')
|
|
run: |
|
|
# Create release notes based on package type
|
|
echo "# ${{ inputs.base_package_name }} v${VERSION}" > release_notes.md
|
|
echo "" >> release_notes.md
|
|
|
|
if [ "${{ inputs.package_name }}" = "pylume" ]; then
|
|
echo "## Python SDK for lume - run macOS and Linux VMs on Apple Silicon" >> release_notes.md
|
|
echo "" >> release_notes.md
|
|
echo "This package provides Python bindings for the lume virtualization tool." >> release_notes.md
|
|
echo "" >> release_notes.md
|
|
echo "## Dependencies" >> release_notes.md
|
|
echo "* lume binary: v${LUME_VERSION}" >> release_notes.md
|
|
elif [ "${{ inputs.package_name }}" = "computer" ]; then
|
|
echo "## Computer control library for the Computer Universal Automation (CUA) project" >> release_notes.md
|
|
echo "" >> release_notes.md
|
|
echo "## Dependencies" >> release_notes.md
|
|
echo "* pylume: ${PYLUME_VERSION:-latest}" >> release_notes.md
|
|
elif [ "${{ inputs.package_name }}" = "agent" ]; then
|
|
echo "## Dependencies" >> release_notes.md
|
|
echo "* cua-computer: ${COMPUTER_VERSION:-latest}" >> release_notes.md
|
|
echo "* cua-som: ${SOM_VERSION:-latest}" >> release_notes.md
|
|
echo "" >> release_notes.md
|
|
echo "## Installation Options" >> release_notes.md
|
|
echo "" >> release_notes.md
|
|
echo "### Basic installation with Anthropic" >> release_notes.md
|
|
echo '```bash' >> release_notes.md
|
|
echo "pip install cua-agent[anthropic]==${VERSION}" >> release_notes.md
|
|
echo '```' >> release_notes.md
|
|
echo "" >> release_notes.md
|
|
echo "### With SOM (recommended)" >> release_notes.md
|
|
echo '```bash' >> release_notes.md
|
|
echo "pip install cua-agent[som]==${VERSION}" >> release_notes.md
|
|
echo '```' >> release_notes.md
|
|
echo "" >> release_notes.md
|
|
echo "### All features" >> release_notes.md
|
|
echo '```bash' >> release_notes.md
|
|
echo "pip install cua-agent[all]==${VERSION}" >> release_notes.md
|
|
echo '```' >> release_notes.md
|
|
elif [ "${{ inputs.package_name }}" = "som" ]; then
|
|
echo "## Computer Vision and OCR library for detecting and analyzing UI elements" >> release_notes.md
|
|
echo "" >> release_notes.md
|
|
echo "This package provides enhanced UI understanding capabilities through computer vision and OCR." >> release_notes.md
|
|
elif [ "${{ inputs.package_name }}" = "computer-server" ]; then
|
|
echo "## Computer Server for the Computer Universal Automation (CUA) project" >> release_notes.md
|
|
echo "" >> release_notes.md
|
|
echo "A FastAPI-based server implementation for computer control." >> release_notes.md
|
|
echo "" >> release_notes.md
|
|
echo "## Dependencies" >> release_notes.md
|
|
echo "* cua-computer: ${COMPUTER_VERSION:-latest}" >> release_notes.md
|
|
echo "" >> release_notes.md
|
|
echo "## Usage" >> release_notes.md
|
|
echo '```bash' >> release_notes.md
|
|
echo "# Run the server" >> release_notes.md
|
|
echo "cua-computer-server" >> release_notes.md
|
|
echo '```' >> release_notes.md
|
|
fi
|
|
|
|
# Add installation section if not agent (which has its own installation section)
|
|
if [ "${{ inputs.package_name }}" != "agent" ]; then
|
|
echo "" >> release_notes.md
|
|
echo "## Installation" >> release_notes.md
|
|
echo '```bash' >> release_notes.md
|
|
echo "pip install ${{ inputs.base_package_name }}==${VERSION}" >> release_notes.md
|
|
echo '```' >> release_notes.md
|
|
fi
|
|
|
|
echo "Release notes created:"
|
|
cat release_notes.md
|
|
|
|
- name: Create GitHub Release
|
|
uses: softprops/action-gh-release@v1
|
|
if: startsWith(github.ref, 'refs/tags/')
|
|
with:
|
|
name: "${{ inputs.base_package_name }} v${{ env.VERSION }}"
|
|
body_path: release_notes.md
|
|
files: ${{ inputs.package_dir }}/${{ env.WHEEL_FILE }}
|
|
draft: false
|
|
prerelease: false
|
|
env:
|
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} |