fyre-toolkit 0.1.13__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.
Files changed (54) hide show
  1. fyre_toolkit-0.1.13/.editorconfig +17 -0
  2. fyre_toolkit-0.1.13/.gitee/ISSUE_TEMPLATE.zh-CN.md +13 -0
  3. fyre_toolkit-0.1.13/.gitee/PULL_REQUEST_TEMPLATE.zh-CN.md +12 -0
  4. fyre_toolkit-0.1.13/.github/ISSUE_TEMPLATE/config.yaml +1 -0
  5. fyre_toolkit-0.1.13/.github/ISSUE_TEMPLATE/feature_request.yml +43 -0
  6. fyre_toolkit-0.1.13/.github/ISSUE_TEMPLATE/issue_report.yml +54 -0
  7. fyre_toolkit-0.1.13/.github/workflows/test.yml +131 -0
  8. fyre_toolkit-0.1.13/.gitignore +156 -0
  9. fyre_toolkit-0.1.13/.vscode/settings.json +7 -0
  10. fyre_toolkit-0.1.13/AGENTS.md +129 -0
  11. fyre_toolkit-0.1.13/Jenkinsfile +124 -0
  12. fyre_toolkit-0.1.13/LICENSE +201 -0
  13. fyre_toolkit-0.1.13/PKG-INFO +96 -0
  14. fyre_toolkit-0.1.13/README.en.md +105 -0
  15. fyre_toolkit-0.1.13/README.md +82 -0
  16. fyre_toolkit-0.1.13/deployment_manifest.txt +109 -0
  17. fyre_toolkit-0.1.13/examples/generate_result.py +35 -0
  18. fyre_toolkit-0.1.13/examples/sample_test_suite.yaml +37 -0
  19. fyre_toolkit-0.1.13/examples/test_example.py +163 -0
  20. fyre_toolkit-0.1.13/pyproject.toml +92 -0
  21. fyre_toolkit-0.1.13/resources/kd-test/db-oodbapi.result +16 -0
  22. fyre_toolkit-0.1.13/resources/kd-test/rtdbc-middate.result +11 -0
  23. fyre_toolkit-0.1.13/resources/kd-test/rtdbc-midmmi.result +9 -0
  24. fyre_toolkit-0.1.13/resources/kd-test/scada.result +11 -0
  25. fyre_toolkit-0.1.13/resources/kd-test/sjk-download.result +8 -0
  26. fyre_toolkit-0.1.13/resources/kd-test/sjk-metadata.result +8 -0
  27. fyre_toolkit-0.1.13/resources/kd-test/sjk-sync.result +8 -0
  28. fyre_toolkit-0.1.13/resources/kd-test/zx-xtgl.result +27 -0
  29. fyre_toolkit-0.1.13/resources/multiple_test_case_template.yaml +68 -0
  30. fyre_toolkit-0.1.13/resources/single_test_case_template.yaml +38 -0
  31. fyre_toolkit-0.1.13/resources/test_result.xml +25 -0
  32. fyre_toolkit-0.1.13/resources/test_result_formatted.xml +292 -0
  33. fyre_toolkit-0.1.13/resources/test_suite_schema.json +143 -0
  34. fyre_toolkit-0.1.13/resources/test_suite_template.json +87 -0
  35. fyre_toolkit-0.1.13/src/testkit/__init__.py +20 -0
  36. fyre_toolkit-0.1.13/src/testkit/aggregator.py +59 -0
  37. fyre_toolkit-0.1.13/src/testkit/generator.py +431 -0
  38. fyre_toolkit-0.1.13/src/testkit/parser.py +50 -0
  39. fyre_toolkit-0.1.13/src/testkit/schema.py +140 -0
  40. fyre_toolkit-0.1.13/src/testkit/utils.py +328 -0
  41. fyre_toolkit-0.1.13/src/testkit/validator.py +401 -0
  42. fyre_toolkit-0.1.13/tests/__init__.py +0 -0
  43. fyre_toolkit-0.1.13/tests/conftest.py +26 -0
  44. fyre_toolkit-0.1.13/tests/resources/invalid_case.yaml +4 -0
  45. fyre_toolkit-0.1.13/tests/resources/multiple_valid_cases.yaml +37 -0
  46. fyre_toolkit-0.1.13/tests/resources/valid_one_case.yaml +16 -0
  47. fyre_toolkit-0.1.13/tests/test_suite_from_yaml.py +121 -0
  48. fyre_toolkit-0.1.13/tests/test_testkit_aggregator.py +96 -0
  49. fyre_toolkit-0.1.13/tests/test_testkit_genereator.py +1069 -0
  50. fyre_toolkit-0.1.13/tests/test_testkit_module.py +145 -0
  51. fyre_toolkit-0.1.13/tests/test_testkit_parser.py +79 -0
  52. fyre_toolkit-0.1.13/tests/test_testkit_schema.py +177 -0
  53. fyre_toolkit-0.1.13/tests/test_testkit_utils.py +1124 -0
  54. fyre_toolkit-0.1.13/tests/test_testkit_validator.py +900 -0
@@ -0,0 +1,17 @@
1
+ root = true
2
+
3
+ [*]
4
+ end_of_line = lf
5
+ insert_final_newline = true
6
+
7
+ [*.py]
8
+ charset = utf-8
9
+ indent_style = space
10
+ indent_size = 4
11
+ continuation_indent_size = 4
12
+ spaces_around_operators = 1
13
+ max_line_length = 80
14
+
15
+ [Makefile]
16
+ indent_style = tab
17
+ tab_width = 2
@@ -0,0 +1,13 @@
1
+ #### 该问题是怎么引起的?
2
+
3
+
4
+
5
+ #### 重现步骤
6
+
7
+
8
+
9
+ #### 报错信息
10
+
11
+
12
+
13
+
@@ -0,0 +1,12 @@
1
+ #### 相关的Issue
2
+
3
+
4
+ #### 原因(目的、解决的问题等)
5
+
6
+
7
+ #### 描述(做了什么,变更了什么)
8
+
9
+
10
+ #### 测试用例(新增、改动、可能影响的功能)
11
+
12
+
@@ -0,0 +1 @@
1
+ blank_issues_enabled: true
@@ -0,0 +1,43 @@
1
+ name: 功能建议
2
+ description: 对本项目提出一个功能建议
3
+ title: "[Feature]: "
4
+ labels: ["feature"]
5
+ body:
6
+ - type: markdown
7
+ attributes:
8
+ value: |
9
+ 感谢提出功能建议,我们将仔细考虑!
10
+ - type: textarea
11
+ id: related-problem
12
+ attributes:
13
+ label: 你的功能建议是否和某个问题相关?
14
+ description: 清晰并简洁地描述问题是什么,例如,当我...时,我总是感到困扰。
15
+ validations:
16
+ required: false
17
+ - type: textarea
18
+ id: desired-solution
19
+ attributes:
20
+ label: 你希望看到什么解决方案?
21
+ description: 清晰并简洁地描述你希望发生的事情。
22
+ validations:
23
+ required: true
24
+ - type: textarea
25
+ id: alternatives
26
+ attributes:
27
+ label: 你考虑过哪些替代方案?
28
+ description: 清晰并简洁地描述你考虑过的任何替代解决方案或功能。
29
+ validations:
30
+ required: false
31
+ - type: textarea
32
+ id: additional-context
33
+ attributes:
34
+ label: 你有其他上下文或截图吗?
35
+ description: 在此处添加有关功能请求的任何其他上下文或截图。
36
+ validations:
37
+ required: false
38
+ - type: checkboxes
39
+ attributes:
40
+ label: 意向参与贡献
41
+ options:
42
+ - label: 我有意向参与具体功能的开发实现并将代码贡献回到本项目
43
+ required: false
@@ -0,0 +1,54 @@
1
+ name: 问题反馈
2
+ description: 当你在代码中发现了一个问题, 导致应用崩溃或抛出异常, 或者有一个组件存在问题, 或者某些地方看起来不对劲.
3
+ title: "[Bug]: "
4
+ labels: ["bug"]
5
+ body:
6
+ - type: markdown
7
+ attributes:
8
+ value: |
9
+ 感谢对项目的支持与关注。在提出问题之前,请确保你已查看相关开发或使用文档:
10
+ - https://...
11
+ - type: checkboxes
12
+ attributes:
13
+ label: 这个问题是否已经存在?
14
+ options:
15
+ - label: 我已经搜索过现有的问题
16
+ required: false
17
+ - type: textarea
18
+ attributes:
19
+ label: 如何复现
20
+ description: 请详细告诉我们如何复现你遇到的问题,如涉及代码,可提供一个最小代码示例,并使用反引号```附上它
21
+ placeholder: |
22
+ 1. ...
23
+ 2. ...
24
+ 3. ...
25
+ validations:
26
+ required: true
27
+ - type: textarea
28
+ attributes:
29
+ label: 预期结果
30
+ description: 请告诉我们你预期会发生什么。
31
+ validations:
32
+ required: true
33
+ - type: textarea
34
+ attributes:
35
+ label: 实际结果
36
+ description: 请告诉我们实际发生了什么。
37
+ validations:
38
+ required: true
39
+ - type: textarea
40
+ attributes:
41
+ label: 截图或视频
42
+ description: 如果可以的话,上传任何关于 bug 的截图。
43
+ value: |
44
+ [在这里上传图片]
45
+ - type: dropdown
46
+ id: version
47
+ attributes:
48
+ label: 版本
49
+ description: 你当前正在使用我们软件的哪个版本/分支?
50
+ options:
51
+ - 0.1 (默认)
52
+ - 0.2
53
+ validations:
54
+ required: true
@@ -0,0 +1,131 @@
1
+ # This workflow will install Python dependencies, run tests, lint and build with a variety of Python versions
2
+ # For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-python
3
+
4
+ name: pytest
5
+
6
+ on:
7
+ push:
8
+ branches: ["main"]
9
+ pull_request:
10
+ branches: ["feature-**"]
11
+
12
+ jobs:
13
+ build-artifacts:
14
+ runs-on: ubuntu-latest
15
+ strategy:
16
+ fail-fast: false
17
+ matrix:
18
+ python-version: ["3.11", "3.12", "3.13", "3.14"]
19
+
20
+ steps:
21
+ - uses: actions/checkout@v6
22
+ with:
23
+ persist-credentials: false
24
+ - name: Set up Python ${{ matrix.python-version }}
25
+ uses: actions/setup-python@v6
26
+ with:
27
+ python-version: ${{ matrix.python-version }}
28
+ - name: Install dependencies
29
+ run: |
30
+ python -m pip install --upgrade pip
31
+ python -m pip install uv flake8 pytest ruff
32
+ if [ -f pyproject.toml ]; then uv sync; fi
33
+ env:
34
+ CI: true
35
+ - name: Install pypa/build
36
+ run: |
37
+ python -m pip install build --user
38
+ - name: Lint with ruff
39
+ run: |
40
+ # stop the build if there are Python syntax errors or undefined names
41
+ # flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics
42
+ # exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide
43
+ # flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics
44
+ uv run ruff check
45
+ - name: Test with pytest
46
+ run: |
47
+ uv run pytest --disable-warnings --tb=short
48
+ - name: Build a binary wheel and a source tarball
49
+ run: python3 -m build
50
+ - name: Store the distribution packages
51
+ if: matrix.python-version == '3.12'
52
+ uses: actions/upload-artifact@v5
53
+ with:
54
+ name: python-package-distributions
55
+ path: dist/
56
+
57
+ bump-version:
58
+ # Use a condition to prevent infinite loops from the bot's own commits
59
+ if: "! contains(github.event.head_commit.message, 'Bump version')"
60
+ runs-on: ubuntu-latest
61
+ needs: build-artifacts
62
+ permissions:
63
+ contents: write
64
+
65
+ steps:
66
+ - name: Checkout code
67
+ uses: actions/checkout@v5
68
+ with:
69
+ fetch-depth: 0
70
+ token: ${{ secrets.BOT_TOKEN }}
71
+
72
+ - name: Set up Python
73
+ uses: actions/setup-python@v6
74
+ with:
75
+ python-version: "3.12"
76
+
77
+ - name: Install and link bump2version
78
+ run: |
79
+ # Install to the specific local directory the action expects
80
+ python -m pip install --user bump2version
81
+
82
+ # Ensure the directory exists and add to PATH
83
+ mkdir -p /home/runner/.local/bin
84
+ echo "/home/runner/.local/bin" >> $GITHUB_PATH
85
+
86
+ # Verify installation path
87
+ which bumpversion || echo "Warning: bumpversion not found in PATH"
88
+ which bump2version || echo "Warning: bump2version not found in PATH"
89
+
90
+ - name: Bump Version and Push
91
+ run: |
92
+ # 1. Configure Git identity
93
+ git config --global user.name "Automated Version Bump Bot"
94
+ git config --global user.email "actions@github.com"
95
+
96
+ # 2. Extract current version from file to avoid the "parse" error
97
+ # This finds the first x.y.z string in your file
98
+ CURRENT_VERSION=$(grep -oE "[0-9]+\.[0-9]+\.[0-9]+" src/testkit/__init__.py | head -1)
99
+
100
+ # 3. Execute bump2version directly
101
+ # This updates [src/testkit/__init__.py]
102
+ # and creates a git commit automatically
103
+ bump2version patch \
104
+ --current-version "$CURRENT_VERSION" \
105
+ --commit \
106
+ --message "Bump version: {current_version} -> {new_version} [skip ci]" \
107
+ src/testkit/__init__.py
108
+
109
+ # 4. Push the changes
110
+ git push origin main
111
+
112
+ publish-to-pypi:
113
+ name: >-
114
+ Publish Python 🐍 distribution 📦 to PyPI
115
+ if: startsWith(github.ref, 'refs/heads/main') && !contains(github.event.head_commit.message, 'Bump version')
116
+ needs: bump-version
117
+ runs-on: ubuntu-latest
118
+ environment:
119
+ name: pypi
120
+ url: https://pypi.org/p/fyre-toolkit/
121
+ permissions:
122
+ id-token: write
123
+
124
+ steps:
125
+ - name: Download all the dists
126
+ uses: actions/download-artifact@v6
127
+ with:
128
+ name: python-package-distributions
129
+ path: dist/
130
+ - name: Publish distribution 📦 to PyPI
131
+ uses: pypa/gh-action-pypi-publish@release/v1
@@ -0,0 +1,156 @@
1
+ # Byte-compiled / optimized / DLL files
2
+ __pycache__/
3
+ *.py[cod]
4
+ *$py.class
5
+
6
+ # C extensions
7
+ *.so
8
+
9
+ # Distribution / packaging
10
+ .Python
11
+ build/
12
+ develop-eggs/
13
+ dist/
14
+ downloads/
15
+ eggs/
16
+ .eggs/
17
+ lib/
18
+ lib64/
19
+ parts/
20
+ sdist/
21
+ var/
22
+ wheels/
23
+ share/python-wheels/
24
+ *.egg-info/
25
+ .installed.cfg
26
+ *.egg
27
+ MANIFEST
28
+ pkg_deps/
29
+ requirements.txt
30
+
31
+ # PyInstaller
32
+ # Usually these files are written by a python script from a template
33
+ # before PyInstaller builds the exe, so as to inject date/other infos into it.
34
+ *.manifest
35
+ *.spec
36
+
37
+ # Installer logs
38
+ pip-log.txt
39
+ pip-delete-this-directory.txt
40
+
41
+ # Unit test / coverage reports
42
+ htmlcov/
43
+ .tox/
44
+ .nox/
45
+ .coverage
46
+ .coverage.*
47
+ .cache
48
+ nosetests.xml
49
+ coverage.xml
50
+ *-results.xml
51
+ pytest_result.xml
52
+ *_report.html
53
+ *.cover
54
+ *.py,cover
55
+ .hypothesis/
56
+ .pytest_cache/
57
+ cover/
58
+
59
+ # Translations
60
+ *.mo
61
+ *.pot
62
+
63
+ # Django stuff:
64
+ *.log
65
+ local_settings.py
66
+ db.sqlite3
67
+ db.sqlite3-journal
68
+
69
+ # Flask stuff:
70
+ instance/
71
+ .webassets-cache
72
+
73
+ # Scrapy stuff:
74
+ .scrapy
75
+
76
+ # Sphinx documentation
77
+ docs/_build/
78
+
79
+ # PyBuilder
80
+ .pybuilder/
81
+ target/
82
+
83
+ # Jupyter Notebook
84
+ .ipynb_checkpoints
85
+
86
+ # IPython
87
+ profile_default/
88
+ ipython_config.py
89
+
90
+ # pyenv
91
+ # For a library or package, you might want to ignore these files since the code is
92
+ # intended to run in multiple environments; otherwise, check them in:
93
+ # .python-version
94
+
95
+ # pipenv
96
+ # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
97
+ # However, in case of collaboration, if having platform-specific dependencies or dependencies
98
+ # having no cross-platform support, pipenv may install dependencies that don't work, or not
99
+ # install all needed dependencies.
100
+ #Pipfile.lock
101
+
102
+ # PEP 582; used by e.g. github.com/David-OConnor/pyflow
103
+ __pypackages__/
104
+
105
+ # Celery stuff
106
+ celerybeat-schedule
107
+ celerybeat.pid
108
+
109
+ # SageMath parsed files
110
+ *.sage.py
111
+
112
+ # Environments
113
+ .env
114
+ .venv
115
+ env/
116
+ venv/
117
+ ENV/
118
+ env.bak/
119
+ venv.bak/
120
+
121
+ # Spyder project settings
122
+ .spyderproject
123
+ .spyproject
124
+
125
+ # Rope project settings
126
+ .ropeproject
127
+
128
+ # mkdocs documentation
129
+ /site
130
+
131
+ # mypy
132
+ .mypy_cache/
133
+ .dmypy.json
134
+ dmypy.json
135
+
136
+ # Pyre type checker
137
+ .pyre/
138
+
139
+ # pytype static type analyzer
140
+ .pytype/
141
+
142
+ # Cython debug symbols
143
+ cython_debug/
144
+
145
+ # UV
146
+ uv.lock
147
+ .ruff_cache/
148
+
149
+ # PyCharm
150
+ .idea/
151
+
152
+ # SonarQube
153
+ .scannerwork/
154
+
155
+ # Others
156
+ workspace-*/
@@ -0,0 +1,7 @@
1
+ {
2
+ "python.testing.pytestArgs": [
3
+ "tests"
4
+ ],
5
+ "python.testing.unittestEnabled": false,
6
+ "python.testing.pytestEnabled": true
7
+ }
@@ -0,0 +1,129 @@
1
+ # AGENTS.md — Fyre Toolkit
2
+
3
+ > Guidelines for agentic coding agents operating in this repository.
4
+
5
+ ## Project Overview
6
+
7
+ Python 3.12+ package (`fyre-toolkit`) that generates pytest test cases from YAML definitions using Pydantic schema validation. Built with `uv` + `hatchling`.
8
+
9
+ ## Build / Lint / Test Commands
10
+
11
+ ### Dependency Management
12
+ ```bash
13
+ uv sync # Install all deps (including dev)
14
+ uv lock --no-cache # Re-lock dependencies
15
+ ```
16
+
17
+ ### Linting
18
+ ```bash
19
+ uv run ruff check # Lint src/ (excludes tests/)
20
+ uv run ruff check --fix # Auto-fix linting issues
21
+ ```
22
+
23
+ ### Type Checking
24
+ ```bash
25
+ uv run mypy src/ # Strict type checking
26
+ ```
27
+
28
+ ### Testing
29
+ ```bash
30
+ uv run pytest # Run all tests (with coverage)
31
+ uv run pytest -k "keyword" # Run tests matching keyword
32
+ uv run pytest tests/test_testkit_parser.py # Single file
33
+ uv run pytest tests/test_testkit_parser.py::TestLoadYamlFile # Single class
34
+ uv run pytest tests/test_testkit_parser.py::TestLoadYamlFile::test_load_valid_file # Single test
35
+ uv run pytest -v # Verbose output
36
+ uv run pytest --no-cov # Run without coverage (faster)
37
+ ```
38
+
39
+ ### Coverage
40
+ ```bash
41
+ uv run pytest --cov=src --cov-report=term # Terminal report
42
+ uv run pytest --cov=src --cov-report=html # HTML report in htmlcov/
43
+ ```
44
+
45
+ ### Building
46
+ ```bash
47
+ uv build --wheel # Build wheel distribution
48
+ uv run twine upload ... # Publish to PyPI
49
+ ```
50
+
51
+ ### CI Pipeline (Jenkinsfile)
52
+ - **PR branches**: `pytest --cov=src` + `diff-cover --fail-under=80`
53
+ - **Main branch**: `pytest --cov=src --cov-fail-under=80` + SonarQube scan
54
+
55
+ ## Code Style
56
+
57
+ ### Imports
58
+ - Standard library → third-party → local, separated by blank lines (isort ordering via ruff `I`)
59
+ - Use `from pathlib import Path` instead of `os.path`
60
+ - Use `collections.abc` for type hints (`Callable`, `Iterator`)
61
+
62
+ ### Formatting
63
+ - 4-space indentation, UTF-8 encoding
64
+ - Max line length: 80 characters (ruff ignores E501 but .editorconfig enforces 80)
65
+ - LF line endings, trailing newline required
66
+ - Use `uv run ruff check --fix` before committing
67
+
68
+ ### Type Hints
69
+ - **mypy strict mode** is enforced — no `Any`, no suppressed errors
70
+ - All function parameters and return types must be annotated
71
+ - Use `collections.abc` types: `Callable[[str, str], str]`, `Iterator[str]`
72
+ - Pydantic v2 models for data structures (`model_dump()`, not `.dict()`)
73
+
74
+ ### Naming Conventions
75
+ - Modules: `snake_case` (e.g., `generator.py`, `testkit_utils.py`)
76
+ - Classes: `PascalCase` (e.g., `TestCase`, `TestSuite`, `TestLoadYamlFile`)
77
+ - Functions/variables: `snake_case` (e.g., `sanitize_identifier`, `test_suite`)
78
+ - Constants: `UPPER_SNAKE_CASE` (e.g., `PYTEST_MODULE_HEADER`)
79
+ - Private helpers: leading underscore (e.g., `_load_yaml_file`, `_check_package`)
80
+ - Test classes: `Test` + CamelCase (e.g., `TestLoadYamlFile`)
81
+ - Test methods: `test_` + snake_case (e.g., `test_load_valid_file`)
82
+
83
+ ### Docstrings
84
+ - Google-style with triple-quoted strings
85
+ - Include: brief description, Args, Returns, Raises, Example sections
86
+ - Doctest examples encouraged for pure functions
87
+
88
+ ### Error Handling
89
+ - Raise specific exceptions: `TypeError`, `ValueError`, `FileNotFoundError`, `RuntimeError`
90
+ - Use descriptive error messages with context (e.g., f-strings with file paths)
91
+ - Chain exceptions with `from e` when re-raising (except where ruff allows `B904`)
92
+ - Use `pytest.raises` for testing expected exceptions
93
+ - Log exceptions with `logging.exception()` before re-raising in library code
94
+
95
+ ### Testing Patterns
96
+ - Use pytest fixtures in `conftest.py` for shared test data
97
+ - Class-based tests for grouping related test methods
98
+ - Use `unittest.mock.patch` for mocking external dependencies
99
+ - Use `tmp_path` fixture for temporary file testing
100
+ - Integration tests alongside unit tests (see `test_integration_*`)
101
+ - Test resources (YAML files) go in `tests/resources/`
102
+
103
+ ### Pydantic Models
104
+ - Use Pydantic v2 (`model_dump()`, not `.dict()`)
105
+ - Models defined in `testkit/schema.py` — do not duplicate
106
+ - Validation errors surface as `pydantic.ValidationError`
107
+
108
+ ## Project Structure
109
+ ```
110
+ src/testkit/ # Main package
111
+ __init__.py # Public API exports, __version__
112
+ schema.py # Pydantic models (TestCase, TestSuite, etc.)
113
+ parser.py # YAML loading and validation
114
+ generator.py # Pytest code generation
115
+ aggregator.py # Component aggregation
116
+ utils.py # Utility functions
117
+ tests/ # Test suite
118
+ conftest.py # Shared pytest fixtures
119
+ resources/ # Test data (YAML files)
120
+ test_testkit_*.py # Test modules (one per source module)
121
+ examples/ # Usage examples
122
+ ```
123
+
124
+ ## Key Constraints
125
+ - **Never suppress type errors** (`as any`, `# type: ignore`, `@ts-ignore`)
126
+ - **Never commit** unless explicitly requested
127
+ - **Match existing patterns** — this codebase is disciplined; follow its style
128
+ - **Fix minimally** — do not refactor while fixing bugs
129
+ - **Run `ruff check`** on changed files before declaring work complete
@@ -0,0 +1,124 @@
1
+ pipeline {
2
+ agent { label 'python' }
3
+ environment {
4
+ PATH="${env.HOME}/.local/bin:${env.PATH}"
5
+ SONAR_HOST_URL="http://192.168.119.2:9000"
6
+ SONAR_PROJECT_KEY="fyre_toolkit"
7
+ SONAR_TOKEN=credentials('sonar')
8
+ UV_PUBLISH_URL="http://192.168.119.2:8082/repository/pypi-internal/"
9
+ UV_PUBLISH_USERNAME="devs"
10
+ UV_PUBLISH_PASSWORD=credentials("uv")
11
+ }
12
+ options {
13
+ skipStagesAfterUnstable()
14
+ }
15
+ stages {
16
+ stage ('Setup') {
17
+ steps {
18
+ script {
19
+ sh '''
20
+ printenv
21
+ uv lock --no-cache
22
+ uv sync --no-cache --no-editable
23
+ '''
24
+ }
25
+ }
26
+ }
27
+ stage ('Lint') {
28
+ steps {
29
+ sh 'uv run ruff check'
30
+ }
31
+ }
32
+ stage ('Build') {
33
+ steps {
34
+ sh 'uv build --wheel'
35
+
36
+ }
37
+ }
38
+ stage ('Feature Branch Test') {
39
+ when { branch 'PR-*' }
40
+ steps {
41
+ sh '''
42
+ uv run pytest \
43
+ --cov=src \
44
+ --junitxml=pytest_result.xml
45
+ '''
46
+ sh '''
47
+ uv run diff-cover \
48
+ --format html:diff_report.html ./coverage.xml \
49
+ --compare-branch origin/main \
50
+ --ignore-unstaged \
51
+ --ignore-staged \
52
+ --fail-under=80
53
+ '''
54
+ }
55
+ }
56
+ stage ('Main Branch Test') {
57
+ when { branch 'main' }
58
+ steps {
59
+ sh '''
60
+ uv run pytest \
61
+ --cov=src \
62
+ --cov-fail-under=80 \
63
+ --junitxml=pytest_result.xml
64
+ '''
65
+ sh '''
66
+ uv run diff-cover \
67
+ --format html:diff_report.html ./coverage.xml \
68
+ --compare-branch HEAD^ \
69
+ --ignore-unstaged \
70
+ --ignore-staged \
71
+ --fail-under=50
72
+ '''
73
+ }
74
+ }
75
+ stage ('Quality Gate') {
76
+ when { anyOf { branch 'main'; branch 'release-*' } }
77
+ steps {
78
+ withEnv(["SONAR_TOKEN=${SONAR_TOKEN}"]) {
79
+ sh '''
80
+ $SONAR_SCANNER_HOME/bin/sonar-scanner \
81
+ -Dsonar.projectKey=${SONAR_PROJECT_KEY} \
82
+ -Dsonar.sources=src \
83
+ -Dsonar.exclusions=tests/** \
84
+ -Dsonar.python.coverage.reportPaths=./coverage.xml \
85
+ -Dsonar.host.url=${SONAR_HOST_URL} \
86
+ -Dsonar.login=${SONAR_TOKEN}
87
+ '''
88
+
89
+ // timeout(time: 1, unit: 'HOURS') {
90
+ // waitForQualityGate abortPipeline: true
91
+ // }
92
+ }
93
+ }
94
+ }
95
+ stage ('Install') {
96
+ when { anyOf { branch 'main'; branch 'release-*' } }
97
+ steps {
98
+ sh 'uv pip install --upgrade dist/fyre_toolkit-0.1.0-py3-none-any.whl'
99
+ sh 'uv run python -c "from testkit import __version__; print(__version__)"'
100
+ sh 'uv pip uninstall fyre-toolkit'
101
+ }
102
+ }
103
+ stage ('Publish') {
104
+ when { anyOf { branch 'main'; branch 'release-*' } }
105
+ steps {
106
+ echo 'Start Publish...'
107
+ // sh 'uv publish --username ${UV_PUBLISH_USERNAME} --password ${UV_PUBLISH_PASSWORD} --publish-url ${UV_PUBLISH_URL}'
108
+ }
109
+ }
110
+ }
111
+ post {
112
+ always {
113
+ archiveArtifacts artifacts: '**/coverage.xml, **/diff_report.html, dist/fyre_toolkit-0.1.0-py3-none-any.whl', allowEmptyArchive: true
114
+ echo "Pipeline completed."
115
+ }
116
+ success {
117
+ echo "Pipeline succeeded."
118
+ }
119
+ failure {
120
+ echo "Pipeline failed. Check logs or SonarQube for details."
121
+ }
122
+ }
123
+ }
124
+