mcpField
M
migrate-to-uv

migrate-to-uv

github.com/keboola开发17188 次安装1 天前更新
代码仓库

关于 migrate-to-uv

此技能指导开发者将 Keboola 组件从 pip 和 requirements.txt 迁移到 uv 与 pyproject.toml,适用于基于 Docker 的组件维护。内容涵盖依赖、Ruff、Docker、CI 和模板对齐步骤。

主要功能

  1. 01将依赖迁移至 uv 和 pyproject.toml
  2. 02配置 Ruff 检查与格式化
  3. 03更新多阶段 Docker 构建
  4. 04替换 GitHub Actions 工作流
  5. 05检查与组件模板的对齐情况

适用场景

  1. 01现代化 Keboola 组件的 Python 打包方式
  2. 02在组件构建中加入检查与测试阶段
  3. 03随依赖更新部署工作流

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/keboola/ai-kit --skill migrate-to-uv

安装后在 Claude Code 中输入/migrate-to-uv确认已加载。

附带文件references/examples.mdreferences/troubleshooting.md

详细介绍

迁移到 uv 构建系统

将一个 Keboola 组件(基于 Docker,通过 ECR 部署)从 requirements.txt + pip 迁移到 pyproject.toml + uv,并使用 ruff 进行代码检查。

请使用你可用的工具自行执行所有步骤。不要委派给或调用任何其他 Agent(component-builder、develop-component 或类似 Agent)——第 6 阶段的 component-developer:component-defaults 除外。

必须完成以下所有步骤。不要跳过任何步骤——如果文件不存在,请直接继续,不要提示。


步骤 0:读取当前状态

cat requirements.txt
grep "FROM python:" Dockerfile
cat .github/workflows/push.yml

提交 1:migrate to pyproject.toml 📦

创建 pyproject.toml

创建一个包含元数据和 ruff 配置的最简 pyproject.toml,但暂不添加依赖项——接下来会用 uv add 添加:

  • 始终使用 requires-python = "~=3.13.0" 和 target-version = "py313"
  • 暂时将 dependencies = [] 留空

然后使用 uv 从 requirements.txt 填充依赖项:

# Add all main deps at once
uv add -r requirements.txt

# Move test-only deps to the dev group (common ones: pytest, mock, freezegun, responses)
# For each test dep found in requirements.txt:
uv remove <test-dep>
uv add --group dev <test-dep>

uv add 会自动将固定版本转换为 >= 范围,并就地更新 uv.lock——无需手动转换。

删除文件
rm -f requirements.txt
rm -f .flake8 flake8.cfg
rm -f scripts/build_n_run.ps1 scripts/run.bat scripts/run_kbc_tests.ps1
rm -f scripts/update_dev_portal_properties.sh
rm -rf docs/imgs/
rm -f component_config/configuration_description.md component_config/stack_parameters.json

(如果文件不存在,rm -f 会静默执行,不会报错或中断。)

填充 component_config/ URL(如果这些文件当前为空)
component_config/documentationUrl.md  → https://github.com/keboola/REPO/blob/master/README.md
component_config/licenseUrl.md        → https://github.com/keboola/REPO/blob/master/LICENSE.md
component_config/sourceCodeUrl.md     → https://github.com/keboola/REPO
更新 .gitignore

如果尚未包含以下行,则添加:

*.egg-info/
.venv/
.DS_Store
/data

将裸写的 data/ 替换为 /data。移除重复的 .vscode/ 条目。

提交
git add -u                                          # stages all deletions
git add pyproject.toml uv.lock .gitignore component_config/
git commit -m "migrate to pyproject.toml 📦"

提交 2:uv 💜

更新 Dockerfile

使用多阶段构建模式。 base 阶段由 test 和 production 共用,这样可保持生产镜像精简(不含开发依赖和测试文件)。

FROM python:3.13-slim AS base
COPY --from=ghcr.io/astral-sh/uv:latest /uv /uvx /bin/

# apt-get installs MUST come before uv sync
# RUN apt-get update && apt-get install -y <packages>  ← keep if already present

WORKDIR /code/
COPY pyproject.toml uv.lock ./
ENV UV_PROJECT_ENVIRONMENT="/usr/local/"
RUN uv sync --no-dev --frozen

COPY src/ src/
COPY scripts/ scripts/
COPY deploy.sh .

FROM base AS test
RUN uv sync --all-groups --frozen
COPY tests/ tests/
RUN uv run ruff check src/ tests/
CMD ["uv", "run", "pytest", "tests/", "-v"]

FROM base AS production
CMD ["python", "-u", "/code/src/component.py"]

说明:

  • base 只安装生产依赖(--no-dev);test 在此基础上添加开发依赖
  • Ruff 检查在 test 阶段的镜像构建时运行——尽早发现失败
  • 使用 ENV KEY="value" 语法(不要使用旧式 ENV KEY value)
  • 任何位置都不得使用 pip install
  • 所有 apt-get 代码块都必须放在 RUN uv sync 之前
更新 scripts/build_n_test.sh
#!/bin/sh
set -e

ruff check
python -m pytest tests/ --tb=short -q
更新 tests/__init__.py

替换旧的 os.path 写法:

import sys
from pathlib import Path
sys.path.append(str(Path(__file__).resolve().parent.parent / "src"))
更新 .github/workflows/push.yml

标准的 push.yml 使用与多阶段 Dockerfile 匹配的多作业流水线。不要逐个修补步骤,而应将整个文件替换为标准模板(来自第 6 阶段 / component-defaults),并且只更新此组件的 env: 代码块:

env:
  KBC_DEVELOPERPORTAL_APP: "vendor.component-id"   # full component ID from Developer Portal
  KBC_DEVELOPERPORTAL_VENDOR: "vendor"              # your vendor name
  DOCKERHUB_USER: ${{ secrets.DOCKERHUB_USER }}
  KBC_DEVELOPERPORTAL_USERNAME: ${{ vars.KBC_DEVELOPERPORTAL_USERNAME }}
  DOCKERHUB_TOKEN: ${{ secrets.DOCKERHUB_TOKEN }}
  KBC_DEVELOPERPORTAL_PASSWORD: ${{ secrets.KBC_DEVELOPERPORTAL_PASSWORD }}
  KBC_TEST_PROJECT_CONFIGS: ""
  KBC_STORAGE_TOKEN: ${{ secrets.KBC_STORAGE_TOKEN }}

新流水线结构(保持标准模板中的原样):

  • push_event_info — 检测分支/标签,输出 is_deploy_ready(要求为默认分支 + 语义化标签)
  • build-test — 构建 --target test 阶段,并上传为 *-test.tar 工件
  • tests — 下载测试工件并运行容器(默认 CMD = pytest;ruff 已在构建时运行)
  • tests-kbc — 如果已设置 KBC_TEST_PROJECT_CONFIGS 和令牌,则运行 KBC 集成测试
  • build-production — 在所有测试通过后构建 --target production 阶段,并上传为 *.tar 工件
  • push — 加载生产工件并推送到 ECR
  • deploy — 仅当 is_deploy_ready == true 时,在 Developer Portal 中设置标签
  • update_developer_portal_properties — 运行 scripts/developer_portal/update_properties.sh
生成 / 验证锁文件

uv add 已在提交 1 期间更新了 uv.lock。运行以下命令,确保文件完全一致:

uv sync --all-groups
提交
git add Dockerfile scripts/ tests/ .github/workflows/
git commit -m "uv 💜"

提交 3:ruff linting baseline 🎨

ruff format .
ruff check --fix .

如果有文件更改,则提交:

git add src/ tests/
git commit -m "ruff linting baseline 🎨"

阶段 6:Cookiecutter 对齐检查

使用 Task 工具加载规范模板文件:

  • subagent_type:component-developer:component-defaults
  • prompt:"Return the canonical Keboola component template files."

然后将以下各项与返回的规范版本进行比较:

组件文件规范版本
Dockerfile来自 component-defaults
.github/workflows/push.yml来自 component-defaults
scripts/build_n_test.sh来自 component-defaults
docker-compose.yml来自 component-defaults
.pre-commit-config.yaml来自 component-defaults

修复结构差异。保留组件专属的添加项(自定义 apt 包、SSL 证书等)。 根据规范版本创建缺失文件(旧组件通常缺少 .pre-commit-config.yaml)。

git add Dockerfile scripts/ .github/workflows/ docker-compose.yml .pre-commit-config.yaml
git commit -m "align with cookiecutter template 🍪"

验证

# Build and run tests (ruff runs at build time inside the test stage)
docker build --target test -t test-component .
docker run test-component

# Optionally verify the production image builds cleanly
docker build --target production -t prod-component .

常见模式

依赖项转换:

requirements.txt          pyproject.toml
keboola.component==1.4.4  "keboola-component>=1.4.4"
mock                      "mock>=5.2.0"  (in dev group)

Ruff 配置(pyupgrade 始终使用 "UP"):

[tool.ruff]
line-length = 120
target-version = "py313"

[tool.ruff.lint]
extend-select = ["I", "UP"]

评论

支持 Markdown