diff --git a/.github/workflows/conventional_commit_pr.yml b/.github/workflows/conventional_commit_pr.yml new file mode 100644 index 0000000..a4c59ce --- /dev/null +++ b/.github/workflows/conventional_commit_pr.yml @@ -0,0 +1,17 @@ +name: Conventional commit PR + +on: [pull_request] + +jobs: + cog_check_job: + runs-on: ubuntu-latest + name: check conventional commit compliance + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + # pick the pr HEAD instead of the merge commit + ref: ${{ github.event.pull_request.head.sha }} + + - name: Conventional commit check + uses: cocogitto/cocogitto-action@v3 diff --git a/.github/workflows/conventional_commit_pr_title.yml b/.github/workflows/conventional_commit_pr_title.yml new file mode 100644 index 0000000..b06f470 --- /dev/null +++ b/.github/workflows/conventional_commit_pr_title.yml @@ -0,0 +1,21 @@ +name: "Lint PR" + +on: + pull_request_target: + types: + - opened + - edited + - synchronize + - reopened + +permissions: + pull-requests: read + +jobs: + main: + name: Validate PR title + runs-on: ubuntu-latest + steps: + - uses: amannn/action-semantic-pull-request@v5 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/pre_commit.yml b/.github/workflows/pre_commit.yml new file mode 100644 index 0000000..524f04f --- /dev/null +++ b/.github/workflows/pre_commit.yml @@ -0,0 +1,14 @@ +name: pre-commit + +on: + pull_request: + push: + branches: [main] + +jobs: + pre-commit: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - uses: actions/setup-python@v3 + - uses: pre-commit/action@v3.0.1 diff --git a/.github/workflows/pytests.yml b/.github/workflows/pytests.yml new file mode 100644 index 0000000..5bae75a --- /dev/null +++ b/.github/workflows/pytests.yml @@ -0,0 +1,40 @@ +name: Pytests + +on: + pull_request: + push: + +permissions: + contents: write + checks: write + pull-requests: write + +jobs: + pytest: + runs-on: ubuntu-latest + + strategy: + fail-fast: true + matrix: + python-version: ["3.12"] + + steps: + - uses: actions/checkout@v4 + + - name: Install uv + uses: astral-sh/setup-uv@v4 + with: + enable-cache: true + python-version: ${{ matrix.python-version }} + + - name: Install all dependencies + run: uv sync --frozen --all-extras --all-groups + + - name: Build goose image + run: | + uv tool install --with-editable . . + cubbi image build goose + + - name: Tests + run: | + uv run --frozen -m pytest -v diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..4471f6a --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,127 @@ +name: Release + +on: + workflow_dispatch: + inputs: + release_force: + # see https://python-semantic-release.readthedocs.io/en/latest/github-action.html#command-line-options + description: | + Force release be one of: [major | minor | patch] + Leave empty for auto-detect based on commit messages. + type: choice + options: + - "" # auto - no force + - major # force major + - minor # force minor + - patch # force patch + default: "" + required: false + prerelease_token: + description: 'The "prerelease identifier" to use as a prefix for the "prerelease" part of a semver. Like the rc in `1.2.0-rc.8`.' + type: choice + options: + - rc + - beta + - alpha + default: rc + required: false + prerelease: + description: "Is a pre-release" + type: boolean + default: false + required: false + +concurrency: + group: deploy + cancel-in-progress: false # prevent hickups with semantic-release + +env: + PYTHON_VERSION_DEFAULT: "3.12" + +jobs: + release: + runs-on: ubuntu-latest + concurrency: release + + permissions: + id-token: write + contents: write + + steps: + # Note: we need to checkout the repository at the workflow sha in case during the workflow + # the branch was updated. To keep PSR working with the configured release branches, + # we force a checkout of the desired release branch but at the workflow sha HEAD. + - name: Setup | Checkout Repository at workflow sha + uses: actions/checkout@v4 + with: + fetch-depth: 0 + ref: ${{ github.sha }} + ssh-key: ${{ secrets.DEPLOY_KEY }} + + - name: Setup | Force correct release branch on workflow sha + run: | + git checkout -B ${{ github.ref_name }} ${{ github.sha }} + + - name: Install uv + uses: astral-sh/setup-uv@v4 + with: + enable-cache: true + python-version: ${{ env.PYTHON_VERSION_DEFAULT }} + + - name: Install all dependencies + run: uv sync --frozen --all-extras --all-groups + + # 2 steps to prevent uv.lock out of sync + # CF https://github.com/python-semantic-release/python-semantic-release/issues/1125 + - name: Action | Semantic Version Release (stamp only) + uses: python-semantic-release/python-semantic-release@v9.12.0 + with: + github_token: ${{ secrets.GITHUB_TOKEN }} + git_committer_name: "github-actions" + git_committer_email: "actions@users.noreply.github.com" + force: ${{ github.event.inputs.release_force }} + prerelease: ${{ github.event.inputs.prerelease }} + prerelease_token: ${{ github.event.inputs.prerelease_token }} + ssh_public_signing_key: ${{ secrets.DEPLOY_KEY_PUB }} + ssh_private_signing_key: ${{ secrets.DEPLOY_KEY }} + push: false + commit: false + tag: false + changelog: false + + - name: Push and tags + run: | + uv lock + git add uv.lock + + - name: Action | Semantic Version Release (fully to create release) + id: release + uses: python-semantic-release/python-semantic-release@v9.12.0 + with: + github_token: ${{ secrets.GITHUB_TOKEN }} + git_committer_name: "github-actions" + git_committer_email: "actions@users.noreply.github.com" + force: ${{ github.event.inputs.release_force }} + prerelease: ${{ github.event.inputs.prerelease }} + prerelease_token: ${{ github.event.inputs.prerelease_token }} + ssh_public_signing_key: ${{ secrets.DEPLOY_KEY_PUB }} + ssh_private_signing_key: ${{ secrets.DEPLOY_KEY }} + push: false + + - name: Push and tags + run: | + git push --set-upstream --follow-tags origin ${{ github.ref_name }} + + - name: Build package + run: uv build + + - name: Publish | Upload package to PyPI + uses: pypa/gh-action-pypi-publish@release/v1 + if: steps.release.outputs.released == 'true' + + - name: Publish | Upload to GitHub Release Assets + uses: python-semantic-release/publish-action@v9.8.9 + if: steps.release.outputs.released == 'true' + with: + github_token: ${{ secrets.GITHUB_TOKEN }} + tag: ${{ steps.release.outputs.tag }} diff --git a/README.md b/README.md index 691e8aa..8a1256f 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,16 @@ +
+ # Cubbi - Container Tool -Cubbi is a command-line tool for managing ephemeral -containers that run AI tools and development environments. It works with both -local Docker and a dedicated remote web service that manages containers in a -Docker-in-Docker (DinD) environment. Cubbi also supports connecting to MCP (Model Control Protocol) servers to extend AI tools with additional capabilities. +Cubbi is a command-line tool for managing ephemeral containers that run AI tools and development environments. It works with both local Docker and a dedicated remote web service that manages containers in a Docker-in-Docker (DinD) environment. Cubbi also supports connecting to MCP (Model Control Protocol) servers to extend AI tools with additional capabilities. -## Quick Reference +![PyPI - Version](https://img.shields.io/pypi/v/cubbi) +![PyPI - Python Version](https://img.shields.io/pypi/pyversions/cubbi) +[![Tests](https://github.com/monadical-sas/cubbi/actions/workflows/pytests.yml/badge.svg?branch=main&event=push)](https://github.com/monadical-sas/cubbi/actions/workflows/pytests.yml) + +
+ +## 🚀 Quick Reference - `cubbi session create` - Create a new session - `cubbix` - Shortcut for `cubbi session create` @@ -13,11 +18,11 @@ Docker-in-Docker (DinD) environment. Cubbi also supports connecting to MCP (Mode - `cubbix /path/to/dir` - Mount a specific directory - `cubbix https://github.com/user/repo` - Clone a repository -## Requirements +## 📋 Requirements - [uv](https://docs.astral.sh/uv/) -## Installation +## 📥 Installation ```bash # Clone the repository @@ -38,7 +43,7 @@ Important: compile your first image cubbi image build goose ``` -## Basic Usage +## 📚 Basic Usage ```bash # Show help message (displays available commands) @@ -98,7 +103,7 @@ cubbix . --run "apt-get update && apt-get install -y my-package" cubbix --ssh ``` -## Image Management +## 🖼️ Image Management Cubbi includes an image management system that allows you to build, manage, and use Docker images for different AI tools: @@ -143,7 +148,7 @@ uvx mypy . uvx ruff format . ``` -## Configuration +## ⚙️ Configuration Cubbi supports user-specific configuration via a YAML file located at `~/.config/cubbi/config.yaml`. This allows you to set default values and configure service credentials. @@ -270,7 +275,7 @@ Service credentials like API keys configured in `~/.config/cubbi/config.yaml` ar | `openrouter.api_key` | `OPENROUTER_API_KEY` | | `google.api_key` | `GOOGLE_API_KEY` | -## MCP Server Management +## 🌐 MCP Server Management MCP (Model Control Protocol) servers provide tool-calling capabilities to AI models, enhancing their ability to interact with external services, databases, and systems. Cubbi supports multiple types of MCP servers: