ruff-sync 0.1.4.dev0__tar.gz → 0.1.5.dev1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {ruff_sync-0.1.4.dev0 → ruff_sync-0.1.5.dev1}/.agents/TESTING.md +2 -2
- ruff_sync-0.1.5.dev1/.agents/skills/dirty-equals/SKILL.md +37 -0
- ruff_sync-0.1.5.dev1/.agents/skills/dirty-equals/references/common-matchers.md +51 -0
- ruff_sync-0.1.5.dev1/.agents/skills/dirty-equals/references/toml-matching.md +54 -0
- ruff_sync-0.1.5.dev1/.agents/skills/dirty-equals/trigger_eval.json +30 -0
- ruff_sync-0.1.5.dev1/.agents/skills/mike/SKILL.md +64 -0
- ruff_sync-0.1.5.dev1/.agents/skills/mike/references/commands.md +78 -0
- {ruff_sync-0.1.4.dev0 → ruff_sync-0.1.5.dev1}/.agents/skills/ruff-sync-usage/SKILL.md +1 -1
- ruff_sync-0.1.5.dev1/.agents/skills/ruff-sync-usage/references/ci-integration.md +213 -0
- {ruff_sync-0.1.4.dev0 → ruff_sync-0.1.5.dev1}/.github/workflows/ci.yaml +61 -0
- {ruff_sync-0.1.4.dev0 → ruff_sync-0.1.5.dev1}/.pre-commit-config.yaml +2 -2
- {ruff_sync-0.1.4.dev0 → ruff_sync-0.1.5.dev1}/AGENTS.md +31 -7
- {ruff_sync-0.1.4.dev0 → ruff_sync-0.1.5.dev1}/CONTRIBUTING.md +1 -0
- {ruff_sync-0.1.4.dev0 → ruff_sync-0.1.5.dev1}/PKG-INFO +1 -1
- ruff_sync-0.1.5.dev1/docs/ci-integration.md +170 -0
- {ruff_sync-0.1.4.dev0 → ruff_sync-0.1.5.dev1}/docs/gen_ref_pages.py +1 -1
- {ruff_sync-0.1.4.dev0 → ruff_sync-0.1.5.dev1}/mkdocs.yml +8 -0
- {ruff_sync-0.1.4.dev0 → ruff_sync-0.1.5.dev1}/pyproject.toml +5 -1
- {ruff_sync-0.1.4.dev0 → ruff_sync-0.1.5.dev1}/src/ruff_sync/__init__.py +4 -0
- {ruff_sync-0.1.4.dev0 → ruff_sync-0.1.5.dev1}/src/ruff_sync/cli.py +172 -82
- {ruff_sync-0.1.4.dev0 → ruff_sync-0.1.5.dev1}/src/ruff_sync/constants.py +67 -4
- {ruff_sync-0.1.4.dev0 → ruff_sync-0.1.5.dev1}/src/ruff_sync/core.py +133 -34
- {ruff_sync-0.1.4.dev0 → ruff_sync-0.1.5.dev1}/src/ruff_sync/formatters.py +245 -1
- {ruff_sync-0.1.4.dev0 → ruff_sync-0.1.5.dev1}/tasks.py +3 -3
- {ruff_sync-0.1.4.dev0 → ruff_sync-0.1.5.dev1}/tests/test_basic.py +22 -32
- {ruff_sync-0.1.4.dev0 → ruff_sync-0.1.5.dev1}/tests/test_check.py +208 -2
- ruff_sync-0.1.5.dev1/tests/test_ci_integration.py +34 -0
- ruff_sync-0.1.5.dev1/tests/test_ci_validation.py +226 -0
- {ruff_sync-0.1.4.dev0 → ruff_sync-0.1.5.dev1}/tests/test_config_validation.py +33 -0
- {ruff_sync-0.1.4.dev0 → ruff_sync-0.1.5.dev1}/tests/test_e2e.py +81 -2
- {ruff_sync-0.1.4.dev0 → ruff_sync-0.1.5.dev1}/tests/test_formatters.py +98 -3
- {ruff_sync-0.1.4.dev0 → ruff_sync-0.1.5.dev1}/tests/test_serialization.py +21 -38
- {ruff_sync-0.1.4.dev0 → ruff_sync-0.1.5.dev1}/uv.lock +116 -56
- ruff_sync-0.1.4.dev0/.agents/skills/ruff-sync-usage/references/ci-integration.md +0 -134
- ruff_sync-0.1.4.dev0/docs/ci-integration.md +0 -103
- {ruff_sync-0.1.4.dev0 → ruff_sync-0.1.5.dev1}/.agents/formatters-architecture.md +0 -0
- {ruff_sync-0.1.4.dev0 → ruff_sync-0.1.5.dev1}/.agents/gitlab-reports.md +0 -0
- {ruff_sync-0.1.4.dev0 → ruff_sync-0.1.5.dev1}/.agents/issue-102-context.md +0 -0
- {ruff_sync-0.1.4.dev0 → ruff_sync-0.1.5.dev1}/.agents/skills/gh-issues/SKILL.md +0 -0
- {ruff_sync-0.1.4.dev0 → ruff_sync-0.1.5.dev1}/.agents/skills/mkdocs-generation/SKILL.md +0 -0
- {ruff_sync-0.1.4.dev0 → ruff_sync-0.1.5.dev1}/.agents/skills/mkdocs-generation/examples.md +0 -0
- {ruff_sync-0.1.4.dev0 → ruff_sync-0.1.5.dev1}/.agents/skills/mkdocs-generation/templates/api-reference.md +0 -0
- {ruff_sync-0.1.4.dev0 → ruff_sync-0.1.5.dev1}/.agents/skills/mkdocs-generation/templates/getting-started.md +0 -0
- {ruff_sync-0.1.4.dev0 → ruff_sync-0.1.5.dev1}/.agents/skills/mkdocs-generation/templates/index.md +0 -0
- {ruff_sync-0.1.4.dev0 → ruff_sync-0.1.5.dev1}/.agents/skills/mkdocs-generation/templates/mkdocs.yml +0 -0
- {ruff_sync-0.1.4.dev0 → ruff_sync-0.1.5.dev1}/.agents/skills/release-notes-generation/SKILL.md +0 -0
- {ruff_sync-0.1.4.dev0 → ruff_sync-0.1.5.dev1}/.agents/skills/ruff-sync-usage/references/configuration.md +0 -0
- {ruff_sync-0.1.4.dev0 → ruff_sync-0.1.5.dev1}/.agents/skills/ruff-sync-usage/references/troubleshooting.md +0 -0
- {ruff_sync-0.1.4.dev0 → ruff_sync-0.1.5.dev1}/.agents/workflows/add-test-case.md +0 -0
- {ruff_sync-0.1.4.dev0 → ruff_sync-0.1.5.dev1}/.git-blame-ignore-revs +0 -0
- {ruff_sync-0.1.4.dev0 → ruff_sync-0.1.5.dev1}/.github/dependabot.yml +0 -0
- {ruff_sync-0.1.4.dev0 → ruff_sync-0.1.5.dev1}/.github/workflows/complexity.yaml +0 -0
- {ruff_sync-0.1.4.dev0 → ruff_sync-0.1.5.dev1}/.github/workflows/docs.yaml +0 -0
- {ruff_sync-0.1.4.dev0 → ruff_sync-0.1.5.dev1}/.gitignore +0 -0
- {ruff_sync-0.1.4.dev0 → ruff_sync-0.1.5.dev1}/.pre-commit-hooks.yaml +0 -0
- {ruff_sync-0.1.4.dev0 → ruff_sync-0.1.5.dev1}/LICENSE.md +0 -0
- {ruff_sync-0.1.4.dev0 → ruff_sync-0.1.5.dev1}/README.md +0 -0
- {ruff_sync-0.1.4.dev0 → ruff_sync-0.1.5.dev1}/codecov.yml +0 -0
- {ruff_sync-0.1.4.dev0 → ruff_sync-0.1.5.dev1}/configs/data-science-engineering/ruff.toml +0 -0
- {ruff_sync-0.1.4.dev0 → ruff_sync-0.1.5.dev1}/configs/fastapi/ruff.toml +0 -0
- {ruff_sync-0.1.4.dev0 → ruff_sync-0.1.5.dev1}/configs/kitchen-sink/ruff.toml +0 -0
- {ruff_sync-0.1.4.dev0 → ruff_sync-0.1.5.dev1}/docs/agent-skill.md +0 -0
- {ruff_sync-0.1.4.dev0 → ruff_sync-0.1.5.dev1}/docs/assets/favicon.png +0 -0
- {ruff_sync-0.1.4.dev0 → ruff_sync-0.1.5.dev1}/docs/assets/github-pr-annotation.png +0 -0
- {ruff_sync-0.1.4.dev0 → ruff_sync-0.1.5.dev1}/docs/assets/logo.png +0 -0
- {ruff_sync-0.1.4.dev0 → ruff_sync-0.1.5.dev1}/docs/assets/ruff_sync_banner.png +0 -0
- {ruff_sync-0.1.4.dev0 → ruff_sync-0.1.5.dev1}/docs/best-practices.md +0 -0
- {ruff_sync-0.1.4.dev0 → ruff_sync-0.1.5.dev1}/docs/configuration.md +0 -0
- {ruff_sync-0.1.4.dev0 → ruff_sync-0.1.5.dev1}/docs/contributing.md +0 -0
- {ruff_sync-0.1.4.dev0 → ruff_sync-0.1.5.dev1}/docs/examples/advanced-config.toml +0 -0
- {ruff_sync-0.1.4.dev0 → ruff_sync-0.1.5.dev1}/docs/examples/basic-config.toml +0 -0
- {ruff_sync-0.1.4.dev0 → ruff_sync-0.1.5.dev1}/docs/index.md +0 -0
- {ruff_sync-0.1.4.dev0 → ruff_sync-0.1.5.dev1}/docs/installation.md +0 -0
- {ruff_sync-0.1.4.dev0 → ruff_sync-0.1.5.dev1}/docs/pre-commit.md +0 -0
- {ruff_sync-0.1.4.dev0 → ruff_sync-0.1.5.dev1}/docs/pre-defined-configs.md +0 -0
- {ruff_sync-0.1.4.dev0 → ruff_sync-0.1.5.dev1}/docs/troubleshooting.md +0 -0
- {ruff_sync-0.1.4.dev0 → ruff_sync-0.1.5.dev1}/docs/url-resolution.md +0 -0
- {ruff_sync-0.1.4.dev0 → ruff_sync-0.1.5.dev1}/docs/usage.md +0 -0
- {ruff_sync-0.1.4.dev0 → ruff_sync-0.1.5.dev1}/scripts/check_dogfood.sh +0 -0
- {ruff_sync-0.1.4.dev0 → ruff_sync-0.1.5.dev1}/scripts/gitclone_dogfood.sh +0 -0
- {ruff_sync-0.1.4.dev0 → ruff_sync-0.1.5.dev1}/scripts/pull_dogfood.sh +0 -0
- {ruff_sync-0.1.4.dev0 → ruff_sync-0.1.5.dev1}/skills-lock.json +0 -0
- {ruff_sync-0.1.4.dev0 → ruff_sync-0.1.5.dev1}/src/ruff_sync/__main__.py +0 -0
- {ruff_sync-0.1.4.dev0 → ruff_sync-0.1.5.dev1}/src/ruff_sync/pre_commit.py +0 -0
- {ruff_sync-0.1.4.dev0 → ruff_sync-0.1.5.dev1}/tests/__init__.py +0 -0
- {ruff_sync-0.1.4.dev0 → ruff_sync-0.1.5.dev1}/tests/conftest.py +0 -0
- {ruff_sync-0.1.4.dev0 → ruff_sync-0.1.5.dev1}/tests/lifecycle_tomls/multi_upstream_final.toml +0 -0
- {ruff_sync-0.1.4.dev0 → ruff_sync-0.1.5.dev1}/tests/lifecycle_tomls/multi_upstream_initial.toml +0 -0
- {ruff_sync-0.1.4.dev0 → ruff_sync-0.1.5.dev1}/tests/lifecycle_tomls/multi_upstream_up1.toml +0 -0
- {ruff_sync-0.1.4.dev0 → ruff_sync-0.1.5.dev1}/tests/lifecycle_tomls/multi_upstream_up2.toml +0 -0
- {ruff_sync-0.1.4.dev0 → ruff_sync-0.1.5.dev1}/tests/lifecycle_tomls/no_changes_final.toml +0 -0
- {ruff_sync-0.1.4.dev0 → ruff_sync-0.1.5.dev1}/tests/lifecycle_tomls/no_changes_initial.toml +0 -0
- {ruff_sync-0.1.4.dev0 → ruff_sync-0.1.5.dev1}/tests/lifecycle_tomls/no_changes_upstream.toml +0 -0
- {ruff_sync-0.1.4.dev0 → ruff_sync-0.1.5.dev1}/tests/lifecycle_tomls/no_dotted_keys_final.toml +0 -0
- {ruff_sync-0.1.4.dev0 → ruff_sync-0.1.5.dev1}/tests/lifecycle_tomls/no_dotted_keys_initial.toml +0 -0
- {ruff_sync-0.1.4.dev0 → ruff_sync-0.1.5.dev1}/tests/lifecycle_tomls/no_dotted_keys_upstream.toml +0 -0
- {ruff_sync-0.1.4.dev0 → ruff_sync-0.1.5.dev1}/tests/lifecycle_tomls/no_ruff_cfg_final.toml +0 -0
- {ruff_sync-0.1.4.dev0 → ruff_sync-0.1.5.dev1}/tests/lifecycle_tomls/no_ruff_cfg_initial.toml +0 -0
- {ruff_sync-0.1.4.dev0 → ruff_sync-0.1.5.dev1}/tests/lifecycle_tomls/no_ruff_cfg_upstream.toml +0 -0
- {ruff_sync-0.1.4.dev0 → ruff_sync-0.1.5.dev1}/tests/lifecycle_tomls/readme_excludes_final.toml +0 -0
- {ruff_sync-0.1.4.dev0 → ruff_sync-0.1.5.dev1}/tests/lifecycle_tomls/readme_excludes_initial.toml +0 -0
- {ruff_sync-0.1.4.dev0 → ruff_sync-0.1.5.dev1}/tests/lifecycle_tomls/readme_excludes_upstream.toml +0 -0
- {ruff_sync-0.1.4.dev0 → ruff_sync-0.1.5.dev1}/tests/lifecycle_tomls/standard_final.toml +0 -0
- {ruff_sync-0.1.4.dev0 → ruff_sync-0.1.5.dev1}/tests/lifecycle_tomls/standard_initial.toml +0 -0
- {ruff_sync-0.1.4.dev0 → ruff_sync-0.1.5.dev1}/tests/lifecycle_tomls/standard_upstream.toml +0 -0
- {ruff_sync-0.1.4.dev0 → ruff_sync-0.1.5.dev1}/tests/ruff.toml +0 -0
- {ruff_sync-0.1.4.dev0 → ruff_sync-0.1.5.dev1}/tests/test_constants.py +0 -0
- {ruff_sync-0.1.4.dev0 → ruff_sync-0.1.5.dev1}/tests/test_corner_cases.py +0 -0
- {ruff_sync-0.1.4.dev0 → ruff_sync-0.1.5.dev1}/tests/test_deprecation.py +0 -0
- {ruff_sync-0.1.4.dev0 → ruff_sync-0.1.5.dev1}/tests/test_git_fetch.py +0 -0
- {ruff_sync-0.1.4.dev0 → ruff_sync-0.1.5.dev1}/tests/test_pre_commit.py +0 -0
- {ruff_sync-0.1.4.dev0 → ruff_sync-0.1.5.dev1}/tests/test_project.py +0 -0
- {ruff_sync-0.1.4.dev0 → ruff_sync-0.1.5.dev1}/tests/test_scaffold.py +0 -0
- {ruff_sync-0.1.4.dev0 → ruff_sync-0.1.5.dev1}/tests/test_toml_operations.py +0 -0
- {ruff_sync-0.1.4.dev0 → ruff_sync-0.1.5.dev1}/tests/test_url_handling.py +0 -0
- {ruff_sync-0.1.4.dev0 → ruff_sync-0.1.5.dev1}/tests/test_whitespace.py +0 -0
- {ruff_sync-0.1.4.dev0 → ruff_sync-0.1.5.dev1}/tests/w_ruff_sync_cfg/pyproject.toml +0 -0
- {ruff_sync-0.1.4.dev0 → ruff_sync-0.1.5.dev1}/tests/wo_ruff_cfg/pyproject.toml +0 -0
- {ruff_sync-0.1.4.dev0 → ruff_sync-0.1.5.dev1}/tests/wo_ruff_sync_cfg/pyproject.toml +0 -0
|
@@ -8,7 +8,7 @@ This document defines the mandatory testing standards and patterns for the `ruff
|
|
|
8
8
|
- **No Side Effects**: Tests must be isolated and not touch the actual filesystem or make real network calls.
|
|
9
9
|
- **Semantic + Structural Assertions**: When testing TOML merges, always verify **both**:
|
|
10
10
|
1. **Structural/Whitespace**: The file "looks" correct (comments and spacing are preserved).
|
|
11
|
-
2. **Semantic**: The actual data in the merged result matches the expected values.
|
|
11
|
+
2. **Semantic**: The actual data in the merged result matches the expected values. Use the [dirty-equals](skills/dirty-equals/SKILL.md) Agent Skill for declarative, concise assertions.
|
|
12
12
|
- **DRY with Fixtures and Parameterization**: Avoid code duplication. Use fixtures for common setups and `@pytest.mark.parametrize` for matrix testing.
|
|
13
13
|
|
|
14
14
|
## 2. Tooling and Environment
|
|
@@ -130,6 +130,6 @@ def test_my_edge_case():
|
|
|
130
130
|
|
|
131
131
|
## 6. Code Coverage
|
|
132
132
|
|
|
133
|
-
We target **high coverage** for `ruff_sync
|
|
133
|
+
We target **high coverage** for `src/ruff_sync/`.
|
|
134
134
|
- Run coverage locally: `uv run coverage run -m pytest -vv && uv run coverage report`
|
|
135
135
|
- New features MUST include unit tests in `tests/test_basic.py` or specialized files like `tests/test_whitespace.py` if they involve formatting logic.
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: dirty-equals
|
|
3
|
+
description: Use this skill when you need to write declarative, readable, and maintainable assertions in Python tests. It is particularly effective for matching complex data structures, validating merged TOML configurations, and performing fuzzy matching on URLs, file paths, or object types. Use this when the user asks to "assert," "check," "verify," or "match" data in a test, even if they don't explicitly mention "dirty-equals."
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# `dirty-equals` Skill
|
|
7
|
+
|
|
8
|
+
This skill provides patterns and best practices for writing declarative assertions in the `ruff-sync` project using the `dirty-equals` library.
|
|
9
|
+
|
|
10
|
+
## Overview
|
|
11
|
+
|
|
12
|
+
Instead of asserting on every field manually, compare against a "dirty" object that matches the expected structure and types.
|
|
13
|
+
|
|
14
|
+
```python
|
|
15
|
+
from dirty_equals import IsInt, IsPartialDict, IsStr
|
|
16
|
+
|
|
17
|
+
def test_config_logic():
|
|
18
|
+
result = {"status": "active", "version": 1, "extra": "data"}
|
|
19
|
+
# Declarative assertion
|
|
20
|
+
assert result == IsPartialDict({
|
|
21
|
+
"status": IsStr(regex="act.*"),
|
|
22
|
+
"version": IsInt(gt=0),
|
|
23
|
+
})
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
## Detailed reference
|
|
27
|
+
|
|
28
|
+
Check these references for project-specific usage and common matchers:
|
|
29
|
+
|
|
30
|
+
- **[Common Matchers](references/common-matchers.md)**: Standard `dirty-equals` matchers like `IsPartialDict`, `IsInstance`, and more.
|
|
31
|
+
- **[Specialized Matching](references/toml-matching.md)**: Handling `tomlkit.unwrap()` and `Arguments._asdict()`.
|
|
32
|
+
|
|
33
|
+
## Best Practices
|
|
34
|
+
|
|
35
|
+
- **Import Style**: Always use the `from dirty_equals import ...` style at the **module level** of your test files.
|
|
36
|
+
- **Semantic Matching**: Use `dirty-equals` for the semantic part of your test assertions, while using string comparisons or `respx` for structural/whitespace checks where appropriate.
|
|
37
|
+
- **Type Safety**: Prefer `IsInstance(httpx.URL)` or `IsInstance(pathlib.Path)` over custom regex for well-known types in the project.
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
# Common `dirty-equals` Matchers
|
|
2
|
+
|
|
3
|
+
This guide covers the most frequently used `dirty-equals` matchers in the `ruff-sync` project. Standard practice is to import these using the `from` syntax at the module level in test files.
|
|
4
|
+
|
|
5
|
+
## Structural Matching
|
|
6
|
+
|
|
7
|
+
- **`IsPartialDict`**: Matches a subset of a dictionary. Essential for verifying specific fields in a larger configuration.
|
|
8
|
+
- **`IsDict`**: Matches an entire dictionary exactly (while still allowing fuzzy values).
|
|
9
|
+
- **`IsList`**: Matches a list, allowing fuzzy matching for elements.
|
|
10
|
+
|
|
11
|
+
## Type and Instance Matching
|
|
12
|
+
|
|
13
|
+
- **`IsInstance(type)`**: Matches an object of a specific class. Used for objects like `httpx.URL` or `pathlib.Path`.
|
|
14
|
+
- **`IsStr()`**: Matches any string. Can also specify regex or prefix/suffix.
|
|
15
|
+
- **`IsInt()`**: Matches any integer.
|
|
16
|
+
|
|
17
|
+
## Examples
|
|
18
|
+
|
|
19
|
+
### Using `IsPartialDict` and `IsInstance`
|
|
20
|
+
|
|
21
|
+
```python
|
|
22
|
+
from dirty_equals import IsInstance, IsPartialDict
|
|
23
|
+
import httpx
|
|
24
|
+
import pathlib
|
|
25
|
+
|
|
26
|
+
# Match a partial dict with mixed types
|
|
27
|
+
assert response_data == IsPartialDict({
|
|
28
|
+
"url": IsInstance(httpx.URL),
|
|
29
|
+
"status": "success",
|
|
30
|
+
"retries": 0,
|
|
31
|
+
})
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
### String and Path Matching
|
|
35
|
+
|
|
36
|
+
```python
|
|
37
|
+
from dirty_equals import IsInstance, IsStr
|
|
38
|
+
import pathlib
|
|
39
|
+
|
|
40
|
+
# Match a path instance
|
|
41
|
+
assert result_path == IsInstance(pathlib.Path)
|
|
42
|
+
|
|
43
|
+
# Match a string with a specific prefix
|
|
44
|
+
assert error_message == IsStr(regex="^ERROR:.*")
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
## Logic Matchers
|
|
48
|
+
|
|
49
|
+
- **`~` (Negation)**: Match values that are *not* the given value (e.g., `assert x == ~IsNone`).
|
|
50
|
+
- **`&` (AND)**: Combine matchers (e.g., `IsInt & IsPositive`).
|
|
51
|
+
- **`|` (OR)**: Combine alternatives.
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
# Specialized Matching for `ruff-sync`
|
|
2
|
+
|
|
3
|
+
This reference covers project-specific data structures where `dirty-equals` matchers require particular preparation for reliable results.
|
|
4
|
+
|
|
5
|
+
## TOML Matching (`tomlkit`)
|
|
6
|
+
|
|
7
|
+
`tomlkit` returns proxy objects (containers and items). To reliably match these with `dirty-equals`, always use `.unwrap()` on the parsed document or table to convert it to plain Python types.
|
|
8
|
+
|
|
9
|
+
### Correct Pattern
|
|
10
|
+
|
|
11
|
+
```python
|
|
12
|
+
from dirty_equals import IsPartialDict
|
|
13
|
+
import tomlkit
|
|
14
|
+
|
|
15
|
+
# Parse some TOML
|
|
16
|
+
doc = tomlkit.parse('[tool.ruff]\nline-length = 80')
|
|
17
|
+
|
|
18
|
+
# Match the tool.ruff section
|
|
19
|
+
ruff_config = doc["tool"]["ruff"]
|
|
20
|
+
|
|
21
|
+
# Must use .unwrap()
|
|
22
|
+
assert ruff_config.unwrap() == IsPartialDict({"line-length": 80})
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
### Potential Gotcha
|
|
26
|
+
Direct matching of `tomlkit` proxy objects without `.unwrap()` can fail because `dirty-equals` may see the proxy's internal attributes rather than its data.
|
|
27
|
+
|
|
28
|
+
## CLI `Arguments` matching
|
|
29
|
+
|
|
30
|
+
Our CLI arguments are defined as a `NamedTuple`. To match specific fields without validating the entire object, convert it to a dictionary using `._asdict()`.
|
|
31
|
+
|
|
32
|
+
### Correct Pattern
|
|
33
|
+
|
|
34
|
+
```python
|
|
35
|
+
from dirty_equals import IsInstance, IsPartialDict
|
|
36
|
+
import httpx
|
|
37
|
+
import pathlib
|
|
38
|
+
import ruff_sync_cli
|
|
39
|
+
|
|
40
|
+
# Sample Arguments instance
|
|
41
|
+
args = ruff_sync_cli.Arguments(
|
|
42
|
+
command="pull",
|
|
43
|
+
upstream=(httpx.URL("https://example.com"),),
|
|
44
|
+
to=pathlib.Path("."),
|
|
45
|
+
# ... other defaults ...
|
|
46
|
+
)
|
|
47
|
+
|
|
48
|
+
# Convert to dict and match specific fields
|
|
49
|
+
assert args._asdict() == IsPartialDict({
|
|
50
|
+
"command": "pull",
|
|
51
|
+
"upstream": (IsInstance(httpx.URL),),
|
|
52
|
+
"to": IsInstance(pathlib.Path),
|
|
53
|
+
})
|
|
54
|
+
```
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
[
|
|
2
|
+
{
|
|
3
|
+
"query": "I need to check if the tool.ruff section was merged correctly",
|
|
4
|
+
"should_trigger": true
|
|
5
|
+
},
|
|
6
|
+
{
|
|
7
|
+
"query": "add a unit test that verifies the output",
|
|
8
|
+
"should_trigger": true
|
|
9
|
+
},
|
|
10
|
+
{
|
|
11
|
+
"query": "where should I use dirty-equals",
|
|
12
|
+
"should_trigger": true
|
|
13
|
+
},
|
|
14
|
+
{
|
|
15
|
+
"query": "verify that this URL is from github.com",
|
|
16
|
+
"should_trigger": true
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
"query": "assert that the dictionary matches this schema",
|
|
20
|
+
"should_trigger": true
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
"query": "fix this syntax error in the CLI",
|
|
24
|
+
"should_trigger": false
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
"query": "run the tests with coverage",
|
|
28
|
+
"should_trigger": false
|
|
29
|
+
}
|
|
30
|
+
]
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: mike
|
|
3
|
+
description: Use this skill to manage multiple versions of documentation for MkDocs-powered sites. Deploy new versions, update aliases (like 'latest' or 'stable'), set the default version for the site root, and manage versioned subdirectories in the deployment branch. Use this whenever the user wants to publish, version, or alias documentation, even if they don't explicitly mention "mike". Also use this when the user wants to troubleshoot or debug versioned documentation.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# mike: MkDocs Versioning
|
|
7
|
+
|
|
8
|
+
`mike` is used in this project to manage a versioned documentation site, allowing side-by-side availability of `dev` (main branch) and stable release docs (e.g., `0.1.4`).
|
|
9
|
+
|
|
10
|
+
## Prerequisites
|
|
11
|
+
|
|
12
|
+
`mike` is included in the `docs` dependency group.
|
|
13
|
+
```bash
|
|
14
|
+
# Sync documentation dependencies
|
|
15
|
+
uv sync --group docs
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## Project Strategy
|
|
19
|
+
|
|
20
|
+
This project follows a specific versioning strategy:
|
|
21
|
+
1. **`dev`**: Represents the current `main` branch.
|
|
22
|
+
2. **Stable Releases**: Versioned documentation (e.g., `0.1.4`) created upon release.
|
|
23
|
+
3. **`stable`**: An alias always pointing to the most recent non-dev release.
|
|
24
|
+
|
|
25
|
+
## Core Workflows
|
|
26
|
+
|
|
27
|
+
### 1. Deploying Development Docs
|
|
28
|
+
Run this from the `main` branch to update the `dev` version:
|
|
29
|
+
```bash
|
|
30
|
+
mike deploy dev --push --update-aliases
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
### 2. Deploying a Stable Release
|
|
34
|
+
When a new version is released (e.g., `0.1.4`), deploy it and update the `stable` alias:
|
|
35
|
+
```bash
|
|
36
|
+
# Deploy the specific version and update 'stable'
|
|
37
|
+
mike deploy 0.1.4 stable --push --update-aliases
|
|
38
|
+
|
|
39
|
+
# Set 'stable' as the default version for the site root
|
|
40
|
+
mike set-default --push stable
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## Reference Commands
|
|
44
|
+
|
|
45
|
+
| Action | Command |
|
|
46
|
+
| :--- | :--- |
|
|
47
|
+
| **Deploy** | `mike deploy <version> [alias]` |
|
|
48
|
+
| **List** | `mike list` |
|
|
49
|
+
| **Set Default** | `mike set-default <version>` |
|
|
50
|
+
| **Alias** | `mike alias <version> <alias>` |
|
|
51
|
+
| **Delete** | `mike delete <identifier>` |
|
|
52
|
+
|
|
53
|
+
## CI/CD Integration
|
|
54
|
+
|
|
55
|
+
The deployment logic is automated in [.github/workflows/ci.yaml](.github/workflows/ci.yaml). It automatically:
|
|
56
|
+
- Extracts the version from `pyproject.toml`.
|
|
57
|
+
- Deploys to `dev` if the version contains `.dev`.
|
|
58
|
+
- Deploys to `<version>` and updates `stable` for official releases.
|
|
59
|
+
|
|
60
|
+
> [!IMPORTANT]
|
|
61
|
+
> **Do NOT** use `mike install-gh-pages`. It is deprecated and removed in the version used by this project. `mike deploy` handles branch initialization automatically.
|
|
62
|
+
|
|
63
|
+
> [!TIP]
|
|
64
|
+
> Use `mike serve` locally to preview the version switcher before pushing changes.
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
# Reference: mike CLI commands
|
|
2
|
+
|
|
3
|
+
Detailed parameter and core command reference for `mike`.
|
|
4
|
+
|
|
5
|
+
## `deploy`
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
mike deploy [options] <version> [alias]...
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
Build the documentation for the specified version and commit it to the deployment branch.
|
|
12
|
+
|
|
13
|
+
- `<version>`: The version name to deploy (e.g., `1.0`, `v1.2.3`).
|
|
14
|
+
- `[alias]`: Optional aliases to point to this version (e.g., `latest`, `stable`).
|
|
15
|
+
|
|
16
|
+
**Common options:**
|
|
17
|
+
- `-p, --push`: Push the branch to the remote repository.
|
|
18
|
+
- `-b, --branch NAME`: Deployment branch (default: `gh-pages`).
|
|
19
|
+
- `-m, --message MESSAGE`: Custom commit message.
|
|
20
|
+
- `-u, --update-aliases`: Update existing aliases if they already point to a different version.
|
|
21
|
+
- `--alias-type {symlink,redirect,copy}`: Method for creating aliases.
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
## `alias`
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
mike alias [options] <version> <alias>...
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
Create or update aliases for a version without rebuilding the documentation.
|
|
32
|
+
|
|
33
|
+
---
|
|
34
|
+
|
|
35
|
+
## `set-default`
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
mike set-default [options] <version>
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
Set the default version for the documentation site's root redirect.
|
|
42
|
+
|
|
43
|
+
---
|
|
44
|
+
|
|
45
|
+
## `list`
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
mike list [options]
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
List all versions and aliases deployed to the deployment branch.
|
|
52
|
+
|
|
53
|
+
---
|
|
54
|
+
|
|
55
|
+
## `delete`
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
mike delete [options] <identifier>...
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
Delete one or more versions or aliases.
|
|
62
|
+
|
|
63
|
+
- `<identifier>`: Version or alias name.
|
|
64
|
+
|
|
65
|
+
**Options:**
|
|
66
|
+
- `--all`: Delete all versions/aliases.
|
|
67
|
+
|
|
68
|
+
---
|
|
69
|
+
|
|
70
|
+
## `serve`
|
|
71
|
+
|
|
72
|
+
```bash
|
|
73
|
+
mike serve [options]
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
Locally serve the documentation from the deployment branch. This is for testing the built versioned site.
|
|
77
|
+
|
|
78
|
+
- `-a, --addr ADDR`: Address to bind to (default: `localhost:8000`).
|
|
@@ -117,7 +117,7 @@ ruff-sync git@github.com:my-org/standards.git # SSH (shallow clone)
|
|
|
117
117
|
|
|
118
118
|
| Flag | Meaning |
|
|
119
119
|
|------|---------|
|
|
120
|
-
| `--output-format` | `text` (default), `json`, `github` (
|
|
120
|
+
| `--output-format` | `text` (default), `json`, `github`, `gitlab`, `sarif` (auto-detected in CI) |
|
|
121
121
|
| `--semantic` | Ignore whitespace/comments in `check` |
|
|
122
122
|
| `--pre-commit` | Sync `.pre-commit-config.yaml` hook version |
|
|
123
123
|
| `--save` | Persist CLI args to `pyproject.toml` |
|
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
# CI Integration Recipes
|
|
2
|
+
|
|
3
|
+
## GitHub Actions
|
|
4
|
+
|
|
5
|
+
### Basic Drift Check
|
|
6
|
+
|
|
7
|
+
Add this step to any existing workflow (e.g., `.github/workflows/ci.yaml`):
|
|
8
|
+
|
|
9
|
+
```yaml
|
|
10
|
+
- name: Check Ruff config is in sync
|
|
11
|
+
run: ruff-sync check --semantic --output-format github
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
`--semantic` ignores cosmetic differences (comments, whitespace) — only real value or rule changes cause failure.
|
|
15
|
+
`--output-format github` creates inline PR annotations for errors and warnings.
|
|
16
|
+
|
|
17
|
+
### Full Workflow Example
|
|
18
|
+
|
|
19
|
+
Uses [`astral-sh/setup-uv`](https://github.com/astral-sh/setup-uv) — the official action that installs uv, adds it to PATH, and handles caching. No separate `setup-python` step needed.
|
|
20
|
+
|
|
21
|
+
```yaml
|
|
22
|
+
name: Ruff sync check
|
|
23
|
+
|
|
24
|
+
on:
|
|
25
|
+
push:
|
|
26
|
+
branches: [main]
|
|
27
|
+
pull_request:
|
|
28
|
+
|
|
29
|
+
jobs:
|
|
30
|
+
ruff-sync-check:
|
|
31
|
+
runs-on: ubuntu-latest
|
|
32
|
+
steps:
|
|
33
|
+
- uses: actions/checkout@v4
|
|
34
|
+
|
|
35
|
+
- name: Install uv
|
|
36
|
+
uses: astral-sh/setup-uv@v6
|
|
37
|
+
with:
|
|
38
|
+
version: "0.10.x" # pin to a minor range; Dependabot can keep this current
|
|
39
|
+
|
|
40
|
+
- name: Install ruff-sync
|
|
41
|
+
run: uv tool install ruff-sync
|
|
42
|
+
|
|
43
|
+
- name: Check Ruff config is in sync with upstream
|
|
44
|
+
run: ruff-sync check --semantic --output-format github
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
### With Pre-commit Sync Check
|
|
48
|
+
|
|
49
|
+
To also verify the pre-commit hook version, add the `--pre-commit` flag:
|
|
50
|
+
|
|
51
|
+
```yaml
|
|
52
|
+
- name: Check Ruff config and pre-commit hook
|
|
53
|
+
run: ruff-sync check --semantic --pre-commit --output-format github
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
(Note: For better consistency, you can instead set `pre-commit-version-sync = true` in your `pyproject.toml` — then `ruff-sync check --semantic` will automatically include this check.)
|
|
57
|
+
|
|
58
|
+
### SARIF Upload (GitHub Advanced Security)
|
|
59
|
+
|
|
60
|
+
For repositories with GitHub Advanced Security enabled, upload SARIF results to track drift findings in the **Security tab** and get per-key inline PR annotations that persist across runs:
|
|
61
|
+
|
|
62
|
+
```yaml
|
|
63
|
+
- name: Check Ruff config (SARIF)
|
|
64
|
+
run: ruff-sync check --output-format sarif > ruff-sync.sarif || true
|
|
65
|
+
|
|
66
|
+
- name: Upload SARIF results
|
|
67
|
+
uses: github/codeql-action/upload-sarif@v3
|
|
68
|
+
with:
|
|
69
|
+
sarif_file: ruff-sync.sarif
|
|
70
|
+
category: ruff-sync
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
The `|| true` ensures the upload step always runs even when `ruff-sync` exits 1 (drift detected). Without it, GitHub Actions would skip the upload step on failure.
|
|
74
|
+
|
|
75
|
+
> **Why SARIF over `--output-format github`?**
|
|
76
|
+
> The `github` format creates ephemeral workflow annotations that disappear once the check re-runs. SARIF findings are persisted in the Security tab, tracked as "introduced" and "resolved" across branches, and each drifted TOML key (`lint.select`, `target-version`, etc.) is a separate finding with a stable fingerprint — making it easy to trend configuration health over time.
|
|
77
|
+
|
|
78
|
+
---
|
|
79
|
+
|
|
80
|
+
## GitLab CI
|
|
81
|
+
|
|
82
|
+
Use the official [`ghcr.io/astral-sh/uv`](https://docs.astral.sh/uv/guides/integration/gitlab/) image — uv is already on the `PATH`, no install step needed.
|
|
83
|
+
|
|
84
|
+
```yaml
|
|
85
|
+
variables:
|
|
86
|
+
UV_VERSION: "0.10"
|
|
87
|
+
PYTHON_VERSION: "3.12"
|
|
88
|
+
BASE_LAYER: alpine
|
|
89
|
+
UV_LINK_MODE: copy # required: GitLab mounts build dir separately
|
|
90
|
+
|
|
91
|
+
ruff-sync-check:
|
|
92
|
+
stage: lint
|
|
93
|
+
image: ghcr.io/astral-sh/uv:$UV_VERSION-python$PYTHON_VERSION-$BASE_LAYER
|
|
94
|
+
script:
|
|
95
|
+
- uvx ruff-sync check --semantic --output-format gitlab > gl-code-quality-report.json
|
|
96
|
+
artifacts:
|
|
97
|
+
when: always
|
|
98
|
+
reports:
|
|
99
|
+
codequality: gl-code-quality-report.json
|
|
100
|
+
paths:
|
|
101
|
+
- gl-code-quality-report.json
|
|
102
|
+
expire_in: 1 week
|
|
103
|
+
rules:
|
|
104
|
+
- if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
|
|
105
|
+
- if: '$CI_COMMIT_BRANCH == "main"'
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
### GitLab SAST Report / SARIF (Ultimate tier)
|
|
109
|
+
|
|
110
|
+
Use `--output-format sarif` to feed the GitLab [Security & Compliance dashboard](https://docs.gitlab.com/user/application_security/) via the `sast` artifact report type:
|
|
111
|
+
|
|
112
|
+
```yaml
|
|
113
|
+
variables:
|
|
114
|
+
UV_VERSION: "0.10"
|
|
115
|
+
PYTHON_VERSION: "3.12"
|
|
116
|
+
BASE_LAYER: alpine
|
|
117
|
+
UV_LINK_MODE: copy # required: GitLab mounts build dir separately
|
|
118
|
+
|
|
119
|
+
ruff-sync-sarif:
|
|
120
|
+
stage: lint
|
|
121
|
+
image: ghcr.io/astral-sh/uv:$UV_VERSION-python$PYTHON_VERSION-$BASE_LAYER
|
|
122
|
+
script:
|
|
123
|
+
- uvx ruff-sync check --output-format sarif > ruff-sync.sarif
|
|
124
|
+
artifacts:
|
|
125
|
+
when: always # Upload even when ruff-sync exits 1 (drift detected)
|
|
126
|
+
reports:
|
|
127
|
+
sast: ruff-sync.sarif
|
|
128
|
+
paths:
|
|
129
|
+
- ruff-sync.sarif
|
|
130
|
+
expire_in: 1 week
|
|
131
|
+
rules:
|
|
132
|
+
- if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
> **Why SARIF over `--output-format gitlab` (codequality)?**
|
|
136
|
+
>
|
|
137
|
+
> | Concern | `codequality` | `sarif` |
|
|
138
|
+
> |---------|--------------|--------|
|
|
139
|
+
> | GitLab tier | Free (MR widget), Ultimate (inline diff) | Ultimate (Security dashboard) |
|
|
140
|
+
> | GitHub support | ❌ | ✅ via `upload-sarif` |
|
|
141
|
+
> | Per-key findings | ❌ one issue per file | ✅ one finding per drifted TOML key |
|
|
142
|
+
> | Finding persistence | MR widget only | Security tab, tracked across branches |
|
|
143
|
+
> | Portability | GitLab only | GitHub, GitLab, SonarQube, IDE extensions |
|
|
144
|
+
>
|
|
145
|
+
> **Rule of thumb**: use `codequality` for lightweight GitLab-native linting feedback; use `sarif` when you need cross-platform compatibility or want findings tracked in a security/code-scanning dashboard.
|
|
146
|
+
|
|
147
|
+
---
|
|
148
|
+
|
|
149
|
+
## Pre-commit Hook
|
|
150
|
+
|
|
151
|
+
Run `ruff-sync check` as a pre-commit hook to catch drift before every commit:
|
|
152
|
+
|
|
153
|
+
```yaml
|
|
154
|
+
# .pre-commit-config.yaml
|
|
155
|
+
- repo: https://github.com/Kilo59/ruff-sync
|
|
156
|
+
rev: v0.1.3 # pin to a release tag
|
|
157
|
+
hooks:
|
|
158
|
+
- id: ruff-sync-check
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
The hook runs `ruff-sync check --semantic` automatically. Update `rev` to the latest ruff-sync version.
|
|
162
|
+
|
|
163
|
+
---
|
|
164
|
+
|
|
165
|
+
## Makefile
|
|
166
|
+
|
|
167
|
+
```makefile
|
|
168
|
+
.PHONY: sync-check sync
|
|
169
|
+
|
|
170
|
+
sync-check:
|
|
171
|
+
ruff-sync check --semantic
|
|
172
|
+
|
|
173
|
+
sync:
|
|
174
|
+
ruff-sync
|
|
175
|
+
git diff pyproject.toml
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
---
|
|
179
|
+
|
|
180
|
+
## Deciding: `--semantic` vs. Full String Check
|
|
181
|
+
|
|
182
|
+
| Mode | Fails on | Use when |
|
|
183
|
+
|------|---------|---------|
|
|
184
|
+
| `ruff-sync check --semantic` | Value/rule differences only | CI — avoids false positives from local comment edits |
|
|
185
|
+
| `ruff-sync check` | Any string difference (comments, whitespace, values) | Enforcing exact config file consistency |
|
|
186
|
+
|
|
187
|
+
Recommendation: **use `--semantic` in CI** and save the full-string check for auditing purposes.
|
|
188
|
+
|
|
189
|
+
---
|
|
190
|
+
|
|
191
|
+
## Dogfooding (Self-Check)
|
|
192
|
+
|
|
193
|
+
If `ruff-sync` is configured in the project's own `pyproject.toml` (the standard case), just run:
|
|
194
|
+
|
|
195
|
+
```bash
|
|
196
|
+
ruff-sync check
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
No URL argument needed — it reads `upstream` from `[tool.ruff-sync]`.
|
|
200
|
+
|
|
201
|
+
---
|
|
202
|
+
|
|
203
|
+
## Exit Codes
|
|
204
|
+
|
|
205
|
+
| Code | Meaning |
|
|
206
|
+
|------|----------|
|
|
207
|
+
| **0** | In sync — no drift detected |
|
|
208
|
+
| **1** | Config drift — `[tool.ruff]` values differ from upstream |
|
|
209
|
+
| **2** | CLI usage error — invalid arguments (reserved by argparse) |
|
|
210
|
+
| **3** | Pre-commit hook drift — use `--pre-commit` flag to enable this check |
|
|
211
|
+
| **4** | Upstream unreachable — HTTP error or network failure |
|
|
212
|
+
|
|
213
|
+
All non-zero codes cause a CI step to fail, which is the desired behaviour. To diagnose which failure occurred, check the exit code with `echo $?` after the `ruff-sync check` call.
|
|
@@ -134,6 +134,67 @@ jobs:
|
|
|
134
134
|
echo "Verifying that --semantic check fails for kitchen-sink config (expected failure)..."
|
|
135
135
|
! ruff-sync check --semantic https://github.com/Kilo59/ruff-sync --path configs/kitchen-sink
|
|
136
136
|
|
|
137
|
+
publish-docs:
|
|
138
|
+
name: Publish Documentation
|
|
139
|
+
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
|
|
140
|
+
needs: [pre-publish]
|
|
141
|
+
runs-on: ubuntu-latest
|
|
142
|
+
permissions:
|
|
143
|
+
contents: write
|
|
144
|
+
steps:
|
|
145
|
+
- name: Checkout
|
|
146
|
+
uses: actions/checkout@v4
|
|
147
|
+
with:
|
|
148
|
+
fetch-depth: 0
|
|
149
|
+
|
|
150
|
+
- name: Install uv
|
|
151
|
+
uses: astral-sh/setup-uv@v5
|
|
152
|
+
|
|
153
|
+
- name: Set up Python
|
|
154
|
+
run: uv python install 3.10
|
|
155
|
+
|
|
156
|
+
- name: Install dependencies
|
|
157
|
+
run: uv sync --group docs --frozen
|
|
158
|
+
|
|
159
|
+
- name: Deploy documentation
|
|
160
|
+
run: |
|
|
161
|
+
# Configure git
|
|
162
|
+
git config user.name "github-actions[bot]"
|
|
163
|
+
git config user.email "github-actions[bot]@users.noreply.github.com"
|
|
164
|
+
|
|
165
|
+
# mike deploy handles gh-pages initialization automatically
|
|
166
|
+
|
|
167
|
+
# Extract version from pyproject.toml in a TOML-aware way using already installed dependencies
|
|
168
|
+
VERSION=$(uv run python - << 'PY'
|
|
169
|
+
import pathlib
|
|
170
|
+
import tomlkit
|
|
171
|
+
|
|
172
|
+
pyproject = pathlib.Path("pyproject.toml")
|
|
173
|
+
data = tomlkit.parse(pyproject.read_text(encoding="utf-8"))
|
|
174
|
+
|
|
175
|
+
# Support both top-level `version` and `[project]` table `version`
|
|
176
|
+
version = (
|
|
177
|
+
data.get("project", {}).get("version")
|
|
178
|
+
or data.get("version")
|
|
179
|
+
)
|
|
180
|
+
if not version:
|
|
181
|
+
raise SystemExit("Version not found in pyproject.toml")
|
|
182
|
+
print(version)
|
|
183
|
+
PY
|
|
184
|
+
)
|
|
185
|
+
echo "Current Version: $VERSION"
|
|
186
|
+
|
|
187
|
+
if [[ "$VERSION" == *".dev"* ]]; then
|
|
188
|
+
echo "Deploying DEV documentation only..."
|
|
189
|
+
uv run mike deploy --push --update-aliases dev
|
|
190
|
+
else
|
|
191
|
+
echo "Deploying STABLE documentation..."
|
|
192
|
+
uv run mike deploy --push --update-aliases $VERSION stable
|
|
193
|
+
uv run mike set-default --push stable
|
|
194
|
+
# Also update dev to match stable on a full release
|
|
195
|
+
uv run mike deploy --push --update-aliases dev
|
|
196
|
+
fi
|
|
197
|
+
|
|
137
198
|
publish:
|
|
138
199
|
name: Build and publish to PyPI
|
|
139
200
|
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
|
|
@@ -16,7 +16,7 @@ repos:
|
|
|
16
16
|
- id: no-commit-to-branch
|
|
17
17
|
args: [--branch, develop, --branch, main]
|
|
18
18
|
- repo: https://github.com/astral-sh/ruff-pre-commit
|
|
19
|
-
rev: "v0.15.
|
|
19
|
+
rev: "v0.15.9"
|
|
20
20
|
hooks:
|
|
21
21
|
- id: ruff-check
|
|
22
22
|
args: ["--fix"]
|
|
@@ -28,7 +28,7 @@ repos:
|
|
|
28
28
|
types_or: [yaml, json]
|
|
29
29
|
exclude: .agents/skills/mkdocs-generation/templates/mkdocs.yml
|
|
30
30
|
- repo: https://github.com/rhysd/actionlint
|
|
31
|
-
rev: v1.7.
|
|
31
|
+
rev: v1.7.12
|
|
32
32
|
hooks:
|
|
33
33
|
- id: actionlint
|
|
34
34
|
exclude: .github/workflows/complexity.yaml
|