feat: add Ruff workflow generation and uv support - #499
Conversation
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 39205d24f4
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| install_cmd = "uv pip install --system" if use_uv else "pip install" | ||
| return self._cube("black", python_version, [f"{install_cmd} black", f"black {options} {src}"]) |
There was a problem hiding this comment.
Bootstrap uv before running SourceCraft jobs
When use_uv=True on SourceCraft, every affected cube runs uv pip install inside a plain docker.io/library/python:* image, but unlike the GitLab path no preceding command installs uv. Since those images do not provide the uv executable, generated lint and test jobs fail immediately with uv: command not found; prepend a bootstrap step to each cube before invoking uv.
Useful? React with 👍 / 👎.
| "include_pep8": ["lint", "Lint", "pep8_check"], | ||
| "include_autopep8": ["autopep8"], | ||
| "include_fix_pep8": ["fix_pep8_command", "fix-pep8"], | ||
| "include_ruff": ["ruff", "ruff-lint", "ruff-format"], |
There was a problem hiding this comment.
Filter existing Ruff jobs in the legacy workflow plan
When the legacy scheduler is used with include_ruff=True and repository inspection finds an existing ruff, ruff-lint, or ruff-format job, this mapping computes job_exists, but build_actual_plan() does not include include_ruff in any branch that applies and not job_exists; it falls through and keeps the flag enabled. Consequently GitHub generation can overwrite an existing ruff.yml or add a duplicate Ruff workflow instead of honoring the existing-job suppression used for the other job types.
Useful? React with 👍 / 👎.
| if use_uv: | ||
| uv_setup_step = ' - name: "Set up uv"\n uses: astral-sh/setup-uv@v7\n' | ||
| install_command = "uv pip install --system -r requirements.txt && uv pip install --system pytest pytest-cov" |
There was a problem hiding this comment.
Preserve custom dependency commands when uv is enabled
When a caller supplies a custom dependencies_command to generate_unit_test() and also enables use_uv, this branch silently discards that command and assumes the repository has requirements.txt. For example, a project passing uv pip install --system -e . because it has only pyproject.toml receives a workflow that fails on the nonexistent requirements file; the uv path should retain an explicitly supplied installation command or provide a separate uv-specific override.
Useful? React with 👍 / 👎.
| include_fix_pep8: bool = Field(default=False, description="Include fix-pep8 command workflow.") | ||
| include_pypi: bool = Field(default=False, description="Include PyPI publish workflow.") | ||
| include_ruff: bool = Field(default=False, description="Include Ruff linter and formatter workflow.") | ||
| use_uv: bool = Field(default=False, description="Use uv instead of pip for dependency installation in workflows.") |
There was a problem hiding this comment.
Apply use_uv to PyPI publishing workflows
When include_pypi=True, use_poetry=False, and use_uv=True, all three backends still generate their existing bare pip install step for build and publishing dependencies because none of the generate_pypi_publish() calls receive or honor this setting. This contradicts the new flag's workflow-wide dependency-install behavior and prevents users from obtaining an all-uv workflow; propagate the setting into the publishing generators and emit the corresponding setup/bootstrap step.
Useful? React with 👍 / 👎.
| if settings.include_ruff: | ||
| lint_cubes.append(self.generate_ruff(python_version=latest, use_uv=settings.use_uv)) |
There was a problem hiding this comment.
Merge Ruff into existing SourceCraft lint workflows
When a SourceCraft repository already has a workflows.lint definition but no Ruff cube, this newly created cube is placed in a replacement workflows_section["lint"]; the later merge deliberately retains the existing key without merging its cubes, so the Ruff request is silently discarded while include_ruff is marked done and generation reports success. Merge the Ruff cube into the existing lint workflow, or otherwise report that it was not added.
Useful? React with 👍 / 👎.
DRMPN
left a comment
There was a problem hiding this comment.
Hi Arifuzzaman Joy,
Thank you for your contribution to the project!
Could you please address the changes described in the comments.
Additionally, could you add tests to verify the indentation of the generated YAML configs after the placeholders are populated?
Finally, please consider the Codex review comments as well.
| !!! warning "Ruff + Black conflict" | ||
| Enabling both `--include-ruff` and `--include-black` generates CI jobs that may produce conflicting formatting results, since Ruff's formatter and Black apply different style rules. Prefer one formatter per project. |
There was a problem hiding this comment.
Could we format this line as "Note: ..." not as "!!! warning".
| stage: fix | ||
| script: | ||
| - pip install autopep8 | ||
| {uv_bootstrap} - {install_command} autopep8 |
There was a problem hiding this comment.
- The inline {uv_bootstrap} is a syntax breaker.
| python-version: {python_version} | ||
| - name: "Install dependencies" | ||
| run: "pip install {tool}" | ||
| {uv_setup_step} - name: "Install dependencies" |
There was a problem hiding this comment.
- The {uv_setup_step} placement is fragile.
| {uv_setup_step} - name: "Install dependencies" | ||
| run: "{install_command}" | ||
| - name: "Run tests" | ||
| run: "{test_command} --cov=." | ||
| {codecov_step} No newline at end of file | ||
| run: "{test_command} --cov=." | ||
| {codecov_step} |
There was a problem hiding this comment.
- The {uv_setup_step} placement is fragile.
| {uv_setup_step} - name: "Install dependencies" | |
| run: "{install_command}" | |
| - name: "Run tests" | |
| run: "{test_command} --cov=." | |
| {codecov_step} | |
| \ No newline at end of file | |
| run: "{test_command} --cov=." | |
| {codecov_step} | |
| {uv_setup_step} | |
| - name: "Install dependencies" | |
| run: "{install_command}" | |
| - name: "Run tests" | |
| run: "{test_command} --cov=." | |
| {codecov_step} |
| {uv_bootstrap} - {install_command} black | ||
| - black {src} {black_options} |
There was a problem hiding this comment.
- The inline {uv_bootstrap} is a syntax breaker, please change others accordingly.
| {uv_bootstrap} - {install_command} black | |
| - black {src} {black_options} | |
| {uv_bootstrap} | |
| - {install_command} black | |
| - black {src} {black_options} |
| stage: lint | ||
| script: | ||
| - pip install {tool} | ||
| {uv_bootstrap} - {install_command} {tool} |
There was a problem hiding this comment.
- The inline {uv_bootstrap} is a syntax breaker.
| image: python:${{PYTHON_VERSION}} | ||
| before_script: | ||
| - pip install -r requirements.txt pytest | ||
| {uv_bootstrap} - {install_command} -r requirements.txt pytest |
There was a problem hiding this comment.
- The inline {uv_bootstrap} is a syntax breaker
| str: Path to the generated file. | ||
| """ | ||
| if use_uv: | ||
| uv_setup_step = ' - name: "Set up uv"\n uses: astral-sh/setup-uv@v7\n' |
| tool_command = f"{tool} {args}" if args else tool | ||
|
|
||
| if use_uv: | ||
| uv_setup_step = ' - name: "Set up uv"\n uses: astral-sh/setup-uv@v7\n' |
| that installs uv itself (empty when use_uv is False). | ||
| """ | ||
| if use_uv: | ||
| return "uv pip install --system", " - pip install uv\n" |
|
Thanks for the review! I just pushed an update to address all the comments:
|
Two related additions to workflow generation: a Ruff job and a
use_uvflag.Ruff (
--include-ruff) generates a lint + format-check job across all threebackends — GitHub via
astral-sh/ruff-action, GitLab and SourceCraft via aplain pip install. Ruff has become the default choice for new Python projects,
so it seemed worth offering alongside flake8/pylint.
uv (
--use-uv) swaps pip for uv in the generated dependency-install steps.GitHub gets an
astral-sh/setup-uv@v7step; GitLab and SourceCraft bootstrap uvinside the script since their runners are plain
python:images. Usesuv pip install --systemthroughout, since none of these run inside a venv.Ruff's formatter and Black will fight if both are enabled, so
generate_selected_jobslogs a warning and the docs table notes it.Pinned to floating major tags (
@v7,@v3) to match the existingactions/checkout@v4convention rather than pinning exact patches.Config, CLI args, and the scheduler docs table are all updated. Seven new tests
covering Ruff generation and the uv paths on each backend.
Two unrelated bugs turned up while testing this — the
${{ }}collapse ingenerate_unit_testand the{branches_section}indentation in the GitLabunit_test.ymltemplate. Both predate this branch, so I've left them alone andwill file them separately.