diff --git a/.github/renovate.json5 b/.github/renovate.json5 index 9cfae95e..0809b600 100644 --- a/.github/renovate.json5 +++ b/.github/renovate.json5 @@ -38,7 +38,8 @@ { matchManagers: ["poetry", "pip_requirements"], matchDepTypes: ["python"], - enabled: false, + allowedVersions: "<=3.13", + enabled: true, }, { description: "Auto merge non-major updates", diff --git a/.github/workflows/rigging_pr_description.yaml b/.github/workflows/rigging_pr_description.yaml new file mode 100644 index 00000000..0053bfe5 --- /dev/null +++ b/.github/workflows/rigging_pr_description.yaml @@ -0,0 +1,54 @@ +--- +name: Update PR Description with Rigging +on: + pull_request: + types: [opened] + +jobs: + update-description: + name: Update PR Description with Rigging + runs-on: ubuntu-latest + permissions: + pull-requests: write + contents: read + + steps: + - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 + with: + fetch-depth: 0 # full history for proper diffing + + - name: Set up Python + uses: actions/setup-python@83679a892e2d95755f2dac6acb0bfd1e9ac5d548 # v6.1.0 + with: + python-version: "3.14" + + - name: Install uv + run: | + python -m pip install --upgrade pip + pip install uv + + - name: Generate PR Description + id: description + env: + OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }} + run: | + DESCRIPTION="$(uv run --no-project .hooks/generate_pr_description.py --base-ref "origin/${{ github.base_ref }}" --exclude "./*.lock")" + { + echo "description<> "$GITHUB_OUTPUT" + + - name: Update PR Description + uses: nefrob/pr-description@4dcc9f3ad5ec06b2a197c5f8f93db5e69d2fdca7 # v1.2.0 + with: + token: ${{ secrets.GITHUB_TOKEN }} + content: | + + --- + + ## Generated Summary: + + ${{ steps.description.outputs.description }} + + This summary was generated with โค๏ธ by [rigging](https://rigging.dreadnode.io/) diff --git a/.github/workflows/template-sync.yaml b/.github/workflows/template-sync.yaml index 3d86ac85..a19992f6 100644 --- a/.github/workflows/template-sync.yaml +++ b/.github/workflows/template-sync.yaml @@ -1,34 +1,58 @@ --- -name: Template Sync +name: Template Sync Dispatcher on: - repository_dispatch: + workflow_run: + workflows: ["Pre-Commit"] types: - - template-sync + - completed + branches: + - main # checkov:skip=CKV_GHA_7: "Workflow dispatch inputs are required for manual debugging and configuration" workflow_dispatch: - inputs: - dryRun: - description: Dry Run - default: "false" - required: false - logLevel: - description: Log Level - default: "debug" - required: false permissions: - contents: write - pull-requests: write - -concurrency: - group: ${{ github.workflow }}-${{ github.ref }} - cancel-in-progress: true + contents: read jobs: - template-sync: - name: Template Sync + check-changes: + runs-on: ubuntu-latest + if: ${{ github.event.workflow_run.conclusion == 'success' }} + outputs: + should_dispatch: ${{ steps.filter.outputs.templates }} + steps: + - name: Checkout triggering commit + uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 + with: + ref: ${{ github.event.workflow_run.head_sha || github.ref }} + + - name: Check if template files changed + uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3 + id: filter + with: + filters: | + templates: + - '.github/**' + - '.hooks/**' + - '.pre-commit-config.yaml' + - '.mdlrc' + - '.editorconfig' + - 'Taskfile.yaml' + - '.task/**' + + dispatch-to-targets: + needs: check-changes runs-on: ubuntu-latest + if: needs.check-changes.outputs.should_dispatch == 'true' + strategy: + matrix: + repo: + - ares + - platform + - sast-agent + - dreadnode-server + - dreadnode-sdk + - rigging steps: - name: Generate Token uses: actions/create-github-app-token@29824e69f54612133e76f7eaac726eef6c875baf # v2.2.1 @@ -38,30 +62,12 @@ jobs: private-key: "${{ secrets.BOT_APP_PRIVATE_KEY }}" owner: "${{ github.repository_owner }}" - - name: Checkout - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 - with: - token: "${{ steps.app-token.outputs.token }}" - - - name: Template Sync - uses: AndreasAugustin/actions-template-sync@v2 - with: - source_gh_token: ${{ steps.app-token.outputs.token }} - target_gh_token: ${{ steps.app-token.outputs.token }} - git_user_name: github-actions[bot] - git_user_email: github-actions[bot]@users.noreply.github.com - pr_title: "chore: sync infrastructure files with template" - pr_labels: sync,template - pr_body: | - ๐Ÿค– A new version of the python template files is available. - - This PR was automatically created to sync the following: - - GitHub Actions workflows - - Pre-commit hooks and configs - - Task definitions - - Editor configs and linter rules - - Please review the changes carefully before merging. - source_repo_path: dreadnode/python-template - steps: "prechecks,pull,commit,push,pr" - upstream_branch: main + - name: Dispatch to ${{ matrix.repo }} + run: | + gh api repos/dreadnode/${{ matrix.repo }}/dispatches \ + -X POST \ + -H "Accept: application/vnd.github+json" \ + -f event_type="template-sync" \ + -f client_payload[ref]="${{ github.event.workflow_run.head_sha }}" + env: + GH_TOKEN: ${{ steps.app-token.outputs.token }} diff --git a/.github/workflows/tests.yaml b/.github/workflows/tests.yaml index 0ff24b80..531d3a33 100644 --- a/.github/workflows/tests.yaml +++ b/.github/workflows/tests.yaml @@ -30,7 +30,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - python-version: ["3.10", "3.11", "3.12", "3.13"] + python-version: ["3.9", "3.10", "3.11"] steps: - name: Set up git repository @@ -45,7 +45,7 @@ jobs: - name: Install dependencies run: | python -m pip install --upgrade pip - pip install pytest pytest-cov pytest-asyncio ruff + pip install pytest pytest-cov ruff pip install -e . - name: Lint with ruff diff --git a/.gitignore b/.gitignore index 6450c881..dd1ebc30 100644 --- a/.gitignore +++ b/.gitignore @@ -1,11 +1,5 @@ # Testing code notebooks/ -test-alerts/ - -# Project-specific ignores -TODO -.tool-versions -/reports/ # Custom parquet storage *.parquet diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 57a1db34..87df4062 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -31,7 +31,7 @@ repos: rev: v2.4.1 hooks: - id: codespell - entry: codespell -q 3 -f --skip=".git,.github,README.md" --ignore-words-list="astroid,braket" + entry: codespell -q 3 -f --skip=".git,.github,README.md" --ignore-words-list="astroid" - repo: https://github.com/RodrigoGonzalez/check-mkdocs rev: v1.2.0 diff --git a/CHANGELOG.md b/CHANGELOG.md index 113aae28..76c4bff9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,14 +10,16 @@ and this project adheres to ### Added -- Initial release of Ares autonomous SOC investigation agent -- MITRE ATT&CK Navigator question engine -- Pyramid of Pain Climber question engine -- Integration with Grafana, Loki, and Prometheus -- Four-stage investigation workflow (Triage, Causation, Lateral Movement, - Synthesis) -- Markdown report generation -- Parallel query execution -- Dreadnode Agent SDK integration +- Modern Python project template with batteries included +- pyproject.toml configuration +- Testing setup with pytest +- Code quality tools (Black, Ruff, mypy) +- Pre-commit hooks configuration +- GitHub Actions workflows +- Documentation template with MkDocs +- Security policy template +- CODEOWNERS template +- Taskfile for common commands +- VSCode workspace configuration -[Unreleased]: https://github.com/dreadnode/ares/compare/v0.0.0...HEAD +[Unreleased]: https://github.com/dreadnode/python-template/compare/v0.0.0...HEAD diff --git a/docs/contributing.md b/docs/contributing.md index 922f7cdf..d4dc9cc8 100644 --- a/docs/contributing.md +++ b/docs/contributing.md @@ -8,8 +8,8 @@ This guide will help you get started with contributing effectively. 1. Fork the repository and clone your fork: ```bash - gh repo clone dreadnode/ares - cd ares + gh repo clone dreadnode/python-template + cd python-template ``` 1. Set up your development environment with your preferred package manager: @@ -58,7 +58,8 @@ task types # Type checking with mypy task test # Run tests with pytest ``` -The pre-commit hooks will automatically run most checks when you commit changes. +The pre-commit hooks will automatically run most checks when you commit +changes. ### Documentation diff --git a/docs/index.md b/docs/index.md index abae72f4..7a1f17cd 100644 --- a/docs/index.md +++ b/docs/index.md @@ -1,82 +1,52 @@ -# Ares Documentation +# Python Project Template Documentation -Welcome to the Ares documentation. -Ares is an autonomous security operations agent with dual capabilities: -**Blue Team** (SOC investigation) and **Red Team** (penetration testing). +Welcome to the Python Project Template documentation. +A modern Python project scaffold with batteries included. ## Quick Links - [Project README](../README.md) -- [Taskfile Usage Guide](taskfile_usage.md) -- [Grafana MCP Integration](grafana_mcp_usage.md) -- [Prompt Templates](prompt_templates.md) - [Contributing Guide](contributing.md) - [Security Policy](../SECURITY.md) +- [Changelog](../CHANGELOG.md) +- [Project Setup Guide](topics/project-from-template.md) ## Overview -Ares provides autonomous security operations through two specialized agents: +This template provides a complete Python project structure with modern +development tools and best practices pre-configured. +It's designed to help you start new Python projects quickly with quality +tooling already in place. -**Blue Team Agent** - Transforms security alerts into actionable threat -intelligence through question-driven investigations. Uses MITRE ATT&CK -framework and Pyramid of Pain methodology. +## Key Features -**Red Team Agent** - Autonomous penetration testing for Active Directory -environments. Systematically enumerates, harvests credentials, and attempts -domain admin access. - -Built with the [Dreadnode Agent SDK](https://github.com/dreadnode/agent-sdk). - -## Key Capabilities - -### Blue Team (SOC Investigation) - -- Autonomous Grafana alert investigation -- MITRE ATT&CK technique mapping -- Pyramid of Pain-based analysis elevation -- Multi-stage investigation workflow (Triage, Causation, Lateral, Synthesis) -- Integration with Grafana, Loki, and Prometheus via MCP -- Comprehensive markdown reporting - -### Red Team (Penetration Testing) - -- Active Directory enumeration (hosts, users, shares) -- Credential harvesting (secretsdump, kerberoasting, AS-REP roasting) -- Password hash cracking (hashcat, John the Ripper) -- BloodHound integration for ACL abuse paths -- ADCS exploitation (ESC1-15 vulnerabilities) -- Golden ticket generation -- Delegation attacks (RBCD, unconstrained, constrained) +- ๐Ÿ“ Modern `pyproject.toml` configuration +- ๐Ÿงช Testing setup with pytest +- ๐Ÿ” Code quality tools (Black, Ruff, mypy) +- ๐Ÿ”„ GitHub Actions workflows +- ๐Ÿ“š Documentation with MkDocs +- ๐Ÿ”’ Security policy and Semgrep analysis ## Getting Started -See the [README](../README.md) for installation instructions and usage -examples. +See the [README](../README.md) for quick start instructions, or check out the +detailed [Project Setup Guide](topics/project-from-template.md) for step-by-step +instructions on using this template. ## Repository Layout ```text -ares/ -โ”œโ”€โ”€ src/ares/ # Main package -โ”‚ โ”œโ”€โ”€ agents/ # Agent orchestrators -โ”‚ โ”‚ โ”œโ”€โ”€ blue/ # SOC investigation agent -โ”‚ โ”‚ โ””โ”€โ”€ red/ # Penetration testing agent -โ”‚ โ”œโ”€โ”€ core/ # Core models and engines -โ”‚ โ”‚ โ””โ”€โ”€ factories/ # Agent factories -โ”‚ โ”œโ”€โ”€ integrations/ # External integrations (MITRE) -โ”‚ โ”œโ”€โ”€ reports/ # Report generators -โ”‚ โ””โ”€โ”€ tools/ # Agent toolsets -โ”‚ โ”œโ”€โ”€ blue/ # Blue team tools -โ”‚ โ”œโ”€โ”€ red/ # Red team tools -โ”‚ โ””โ”€โ”€ shared/ # Shared tools (MITRE) -โ”œโ”€โ”€ templates/ # Jinja2 prompt templates -โ”‚ โ”œโ”€โ”€ agent/ # Blue team agent templates -โ”‚ โ”œโ”€โ”€ engines/ # Question engine templates -โ”‚ โ”œโ”€โ”€ redteam/ # Red team agent templates -โ”‚ โ””โ”€โ”€ reports/ # Report templates -โ”œโ”€โ”€ tests/ # Test suite -โ”œโ”€โ”€ docs/ # Documentation -โ””โ”€โ”€ reports/ # Generated reports +python-template/ +โ”œโ”€โ”€ CODEOWNERS # Repository access control +โ”œโ”€โ”€ LICENSE # Apache License 2.0 +โ”œโ”€โ”€ README.md # Project overview +โ”œโ”€โ”€ SECURITY.md # Security policy +โ”œโ”€โ”€ Taskfile.yaml # Task automation +โ”œโ”€โ”€ docs/ # Documentation +โ”œโ”€โ”€ examples/ # Usage examples +โ”œโ”€โ”€ pyproject.toml # Python project config +โ”œโ”€โ”€ requirements.txt # Dependencies +โ””โ”€โ”€ tests/ # Test suite ``` ## Development diff --git a/docs/topics/.gitkeep b/docs/topics/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/docs/topics/project-from-template.md b/docs/topics/project-from-template.md new file mode 100644 index 00000000..1468694d --- /dev/null +++ b/docs/topics/project-from-template.md @@ -0,0 +1,200 @@ +# Setting Up a New Project from python-template + +This guide walks through creating a new project using our Python template +repository. + +## Initial Repository Setup + +1. Create new repository from template: + + - Go to the python-template repository + - Click "Use this template" + - Repository name: Your project name (e.g., `siqcalc`) + - Add description (e.g., "THE BEST Calculator example") + - Click "Create repository" + +1. Clone your new repository: + + ```bash + gh repo clone dreadnode/your-project-name + cd your-project-name + ``` + +## Project Configuration + +1. Remove template files: + + ```bash + # Remove example files + rm -rf src/* tests/* + ``` + +1. Update `pyproject.toml`: + + - Set your project name, version, and description + - Update author information + - Configure dependencies as needed + +1. Create your project structure: + + ```bash + # Create source files + mkdir -p src/your_project_name + touch src/your_project_name/__init__.py + + # Create test directory + mkdir -p tests + ``` + +## Development Environment Setup + +1. Create and activate virtual environment: + + ```bash + python -m venv .venv + source .venv/bin/activate # On macOS/Linux + # or + .venv\Scripts\activate # On Windows + ``` + +1. Install dependencies: + + ```bash + # Upgrade pip + python -m pip install --upgrade pip + + # Install core development tools + pip install poetry pytest pytest-cov ruff + + # Install project in editable mode + pip install -e . + ``` + +1. Update lock and initialize Poetry: + + ```bash + poetry lock + poetry install + ``` + +## Github Actions Configuration + +1. Add your `OPENAI_API_KEY` to the repo's Action Secrets for + [AI PR decorating][ai-pr-decorating] + +1. Ensure the `@dreadnode/team` team have `write` access to the repository, as + per the `CODEOWNERS` [definition][codeowners] + +[ai-pr-decorating]: https://github.com/dreadnode/python-template/blob/b2e90f5905ae8c4793ffe5e646577754dc6b4fe6/.github/workflows/rigging_pr_description.yaml#L33-L34 +[codeowners]: https://github.com/dreadnode/python-template/blob/b2e90f5905ae8c4793ffe5e646577754dc6b4fe6/CODEOWNERS#L1 + +1. Update repository general settings (optional), recommended: + + - [Suggestions to update pull request branches][pr-branches] + - Enable [auto-merge capabilities][auto-merge] + - [Automatic branch deletion][branch-deletion] + - Enable [signed commits][signed-commits] + - Remove features such as [Wikis][wikis] and [Projects][projects] that + aren't necessary (rule of least requirements) + +1. Setup [branch protection rules][branch-protection] (optional, but strongly + recommended for public repositories) + +[pr-branches]: https://docs.github.com/en/repositories/configuring-branches-and-merges-in-your-repository/configuring-pull-request-merges/managing-suggestions-to-update-pull-request-branches +[auto-merge]: https://docs.github.com/en/repositories/configuring-branches-and-merges-in-your-repository/configuring-pull-request-merges/managing-auto-merge-for-pull-requests-in-your-repository +[branch-deletion]: https://docs.github.com/en/repositories/configuring-branches-and-merges-in-your-repository/configuring-pull-request-merges/managing-the-automatic-deletion-of-branches +[signed-commits]: https://docs.github.com/en/authentication/managing-commit-signature-verification/signing-commits +[wikis]: https://docs.github.com/en/communities/documenting-your-project-with-wikis +[projects]: https://docs.github.com/en/issues/planning-and-tracking-with-projects/learning-about-projects/about-projects +[branch-protection]: https://docs.github.com/en/repositories/configuring-branches-and-merges-in-your-repository/managing-protected-branches/managing-a-branch-protection-rule + +1. Require a pull request before merging + + - Require at least 1 approval + - Dismiss stale pull request approvals when new commits are pushed + +1. Require status checks to pass before merging + + - Require branches to be up to date before merging + - Required checks: `test`, `lint`, `format` + +1. Include administrators in these restrictions +1. Allow force pushes: Disable (protect history) + +## Quality Checks + +Run these commands to verify your setup: + +```bash +# Format code +ruff format . + +# Run linting +ruff check . + +# Run tests with coverage +pytest --cov=src --cov-report=term-missing +``` + +## Documentation + +1. Create basic documentation: + + ```bash + mkdir -p docs + touch docs/index.md + ``` + +1. Build documentation locally: + + ```bash + poetry run mkdocs serve + ``` + + View at http://127.0.0.1:8000 + +## Common Issues + +1. **Poetry Installation Conflicts**: If you encounter dependency conflicts + while installing Poetry: + + ```bash + # Alternative installation method + curl -sSL https://install.python-poetry.org | python3 - + ``` + + Add to PATH if needed: + + ```bash + export PATH="$HOME/.local/bin:$PATH" + ``` + +1. **Import Errors**: If you see import errors in tests: + + - Verify your project structure matches the expected layout + - Ensure you've installed the project in editable mode + (`pip install -e .`) + +1. **Linting Errors**: For Ruff formatting issues: + + ```bash + # Auto-fix formatting + ruff format . + + # Auto-fix linting issues where possible + ruff check . --fix + ``` + +## Next Steps + +1. Start adding your project code to `src/` +1. Write tests in `tests/` +1. Update documentation in `docs/` +1. Configure CI/CD in `.github/workflows/` + +## Reference + +- [Python Template Documentation](link-to-template-docs) +- [Poetry Documentation](https://python-poetry.org/docs/) +- [Ruff Documentation](https://beta.ruff.rs/docs/) +- [pytest Documentation](https://docs.pytest.org/) diff --git a/poetry.lock b/poetry.lock index f2139b21..1179fa4d 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1888,13 +1888,13 @@ pyyaml = ">=5.1" [[package]] name = "mkdocs-material" -version = "9.7.0" +version = "9.7.1" description = "Documentation that simply works" optional = false python-versions = ">=3.8" files = [ - {file = "mkdocs_material-9.7.0-py3-none-any.whl", hash = "sha256:da2866ea53601125ff5baa8aa06404c6e07af3c5ce3d5de95e3b52b80b442887"}, - {file = "mkdocs_material-9.7.0.tar.gz", hash = "sha256:602b359844e906ee402b7ed9640340cf8a474420d02d8891451733b6b02314ec"}, + {file = "mkdocs_material-9.7.1-py3-none-any.whl", hash = "sha256:3f6100937d7d731f87f1e3e3b021c97f7239666b9ba1151ab476cabb96c60d5c"}, + {file = "mkdocs_material-9.7.1.tar.gz", hash = "sha256:89601b8f2c3e6c6ee0a918cc3566cb201d40bf37c3cd3c2067e26fadb8cce2b8"}, ] [package.dependencies] @@ -1910,7 +1910,7 @@ paginate = ">=0.5" pillow = {version = ">=10.2,<12.0", optional = true, markers = "extra == \"imaging\""} pygments = ">=2.16" pymdown-extensions = ">=10.2" -requests = ">=2.26" +requests = ">=2.30" [package.extras] git = ["mkdocs-git-committers-plugin-2 (>=1.1,<3)", "mkdocs-git-revision-date-localized-plugin (>=1.2.4,<2.0)"] @@ -1944,17 +1944,17 @@ mkdocs = ">=1.2" [[package]] name = "mkdocstrings" -version = "1.0.0" +version = "0.30.1" description = "Automatic documentation from sources, for MkDocs." optional = false -python-versions = ">=3.10" +python-versions = ">=3.9" files = [ - {file = "mkdocstrings-1.0.0-py3-none-any.whl", hash = "sha256:4c50eb960bff6e05dfc631f6bc00dfabffbcb29c5ff25f676d64daae05ed82fa"}, - {file = "mkdocstrings-1.0.0.tar.gz", hash = "sha256:351a006dbb27aefce241ade110d3cd040c1145b7a3eb5fd5ac23f03ed67f401a"}, + {file = "mkdocstrings-0.30.1-py3-none-any.whl", hash = "sha256:41bd71f284ca4d44a668816193e4025c950b002252081e387433656ae9a70a82"}, + {file = "mkdocstrings-0.30.1.tar.gz", hash = "sha256:84a007aae9b707fb0aebfc9da23db4b26fc9ab562eb56e335e9ec480cb19744f"}, ] [package.dependencies] -Jinja2 = ">=3.1" +Jinja2 = ">=2.11.1" Markdown = ">=3.6" MarkupSafe = ">=1.1" mkdocs = ">=1.6" @@ -2763,13 +2763,13 @@ windows-terminal = ["colorama (>=0.4.6)"] [[package]] name = "pymdown-extensions" -version = "10.19" +version = "10.20" description = "Extension pack for Python Markdown." optional = false python-versions = ">=3.9" files = [ - {file = "pymdown_extensions-10.19-py3-none-any.whl", hash = "sha256:dc5f249fc3a1b6d8a6de4634ba8336b88d0942cee75e92b18ac79eaf3503bf7c"}, - {file = "pymdown_extensions-10.19.tar.gz", hash = "sha256:01bb917ea231f9ce14456fa9092cdb95ac3e5bd32202a3ee61dbd5ad2dd9ef9b"}, + {file = "pymdown_extensions-10.20-py3-none-any.whl", hash = "sha256:ea9e62add865da80a271d00bfa1c0fa085b20d133fb3fc97afdc88e682f60b2f"}, + {file = "pymdown_extensions-10.20.tar.gz", hash = "sha256:5c73566ab0cf38c6ba084cb7c5ea64a119ae0500cce754ccb682761dfea13a52"}, ] [package.dependencies] @@ -3809,4 +3809,4 @@ type = ["pytest-mypy"] [metadata] lock-version = "2.0" python-versions = ">=3.14,<3.15" -content-hash = "989d26ad1a23dd892b951b4e32796df771da21a14b170c109948d455315307ff" +content-hash = "0f6353a1040dc2a10b686eb0d648e8d4b1a2e600218885083020ea673bc6cb98" diff --git a/pyproject.toml b/pyproject.toml index 2db34b49..4650fd1b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,133 +1,93 @@ [project] -name = "ares" +name = "python-template" version = "0.1.0" -description = "Autonomous SOC Investigation Agent" -authors = [{ name = "Dreadnode", email = "hello@dreadnode.io" }] -readme = "README.md" -license = { file = "LICENSE" } -requires-python = ">=3.10,<3.14" -classifiers = [ - "Programming Language :: Python :: 3", - "Programming Language :: Python :: 3.10", - "Programming Language :: Python :: 3.11", - "Programming Language :: Python :: 3.12", - "Programming Language :: Python :: 3.13", - "License :: OSI Approved :: Apache Software License", - "Operating System :: OS Independent", -] - +description = "A Python project template" +requires-python = ">=3.9" dependencies = [ - "dreadnode>=1.17.0", - "cyclopts>=4.2.0", - "loguru>=0.7.3", - "httpx>=0.28.0,<1.0.0", -] - -[project.optional-dependencies] -docs = [ "mkdocs>=1.6.1", "mkdocs-material>=9.6.1", "mkdocs-section-index>=0.3.8", - "mkdocstrings>=1.0.0", - "mkdocstrings-python>=2.0.0", - "pymdown-extensions>=10.8.1", - "pygments>=2.18.0", + "tomli>=2.0.1", ] -[dependency-groups] +[project.optional-dependencies] dev = [ - "mypy>=1.8.0,<2.0.0", - "ruff>=0.11.6,<1.0.0", - "pre-commit>=4.0.0,<5.0.0", - "pytest>=8.3.3", - "pytest-asyncio>=0.24.0", + "pre-commit>=4.1.0", + "pytest>=8.0.0", "pytest-cov>=4.1.0", - "types-requests>=2.32.0.20250306", - "tomli>=2.0.0; python_version < '3.11'", - "jinja2>=3.0.0", + "pytest-randomly>=3.15.0", + "tomli>=2.0.1", ] -[project.scripts] -ares = "ares.__main__:run" - -[tool.poetry.plugins."pipx.run"] -ares = 'ares.__main__:run' - -[project.urls] -Homepage = "https://github.com/dreadnode/ares" -Repository = "https://github.com/dreadnode/ares" -Documentation = "https://docs.dreadnode.io" - -# Build - [build-system] -requires = ["hatchling"] -build-backend = "hatchling.build" +requires = ["setuptools>=42", "wheel"] +build-backend = "setuptools.build_meta" -[tool.hatch.build.targets.wheel] -packages = ["src/ares"] - -[tool.hatch.build.targets.sdist] -include = ["/src", "/tests", "/docs", "/README.md", "/LICENSE"] +[tool.bandit] +exclude_dirs = ["tests"] +skips = ["B101"] -# Dev +[tool.poetry] +name = "python-template" +version = "0.1.0" +description = "A Python project template" +authors = ["Your Name "] + +[tool.poetry.dependencies] +python = ">=3.14,<3.15" + +[tool.poetry.group.docs.dependencies] +mkdocs = "^1.6.1" +mkdocs-material = { extras = ["imaging"], version = "^9.5.20" } +mkdocstrings = "^0.30.0" +mkdocstrings-python = "^2.0.0" +mkdocs-section-index = "^0.3.9" +pymdown-extensions = "^10.8.1" +pygments = "^2.18.0" + +[tool.poetry.group.dev.dependencies] +pre-commit = "^4.1.0" +pytest = "^9.0.0" +pytest-cov = "^7.0.0" +pytest-randomly = "^4.0.0" +tomli = "^2.0.1" +rigging = "^3.0.0" + +[tool.poetry.scripts] +# Define CLI entry points here, e.g.: +# mycommand = "my_project.module:function" [tool.pytest.ini_options] -asyncio_mode = "auto" testpaths = ["tests"] python_files = ["test_*.py"] -addopts = ["--strict-markers", "--cov=ares", "--cov-report=term-missing"] +addopts = ["--strict-markers", "--cov=scripts", "--cov-report=term-missing"] pythonpath = ["."] markers = [ "slow: marks tests as slow (deselect with '-m \"not slow\"')", "integration: marks tests as integration tests", ] -[tool.mypy] -strict = true -python_version = "3.10" -exclude = ["tests", ".hooks", "scripts"] - -[[tool.mypy.overrides]] -module = ["ares.*"] -disable_error_code = [ - "unused-ignore", - "import-untyped", - "import-not-found", - "type-arg", - "no-untyped-def", - "no-untyped-call", - "no-any-return", - "attr-defined", - "call-arg", - "list-item", - "misc", - "valid-type", - "untyped-decorator", -] - -[tool.pyright] -typeCheckingMode = "off" # we prefer mypy and don't want to deal with small differences +[tool.ruff] +line-length = 100 +target-version = "py39" +include = ["*.py", "**/pyproject.toml", "*.ipynb"] +extend-include = [".hooks/*.py"] -[tool.ty.environment] -python-version = "3.10" +[tool.ruff.format] +quote-style = "double" +indent-style = "space" +skip-magic-trailing-comma = false -[tool.ty.src] -exclude = [".hooks", "tests"] +[tool.ruff.lint] +select = ["E", "F", "I", "N"] +ignore = [] -[tool.bandit] -exclude_dirs = ["tests"] -skips = [ - "B101", # assert_used - "B603", # subprocess_without_shell_equals_true (intentional for pentesting tools) - "B404", # import_subprocess (required for pentesting) - "B110", # try_except_pass (acceptable in cleanup code) - "B107", # hardcoded_password_default (false positives on empty string defaults) -] +[tool.ruff.lint.isort] +known-first-party = ["src"] [tool.coverage.run] branch = true -source = ["src"] +source = ["scripts"] [tool.coverage.report] exclude_lines = [ @@ -138,83 +98,14 @@ exclude_lines = [ "if __name__ == .__main__.:", ] -[tool.ruff] -target-version = "py310" -line-length = 100 -extend-exclude = [ - "*.ipynb", # jupyter notebooks -] - -[tool.ruff.lint] -select = ["ALL"] -ignore = [ - "E501", # line too long (we make best effort) - "TRY003", # long messages in exception classes - "EM", # picky message construction for exceptions - "C90", # mccabe complexity - "A002", # shadowing built-in - "D", # docstrings - "ANN", # annotations (handled by mypy) - "PLR0913", # too many arguments - "ERA001", # commented out code - "FIX002", # contains todo, consider fixing - "COM812", # disabled for formatting - "ISC001", # disabled for formatting - "PLC0415", # import should be at the top of the file - "TD003", # missing issue link on todos - "PLR2004", # magic values - too many false positives - "S603", # subprocess call without shell=True (intentional for airgap CLI tools) - "S607", # partial executable path (intentional for kubectl/zarf) - "PERF401", # use list comprehension - many false positives when code is clearer as is - "TRY300", # consider moving to else block - often less readable - "BLE001", # blind exception catching - acceptable in top-level handlers - "PLR0915", # too many statements - acceptable for main functions - "G004", # f-strings in logging - we use loguru, not stdlib logging - "TRY400", # logging.exception vs logging.error - we use loguru - "PLR0911", # too many return statements - acceptable for tool methods - "ARG001", # unused function argument - tools API requires specific signatures - "ARG002", # unused method argument - tools API requires specific signatures - "PLW0603", # global statement - acceptable for module-level caching - "SLF001", # private member access - intentional for internal APIs - "SIM105", # contextlib.suppress - style preference - "S110", # try-except-pass - acceptable in cleanup code - "PTH108", # os.unlink vs Path.unlink - compatibility - "PTH110", # os.path.exists vs Path.exists - compatibility - "PTH123", # open() vs Path.open() - style preference - "RUF005", # list concatenation - style preference - "FBT001", # boolean positional argument - acceptable for tool methods - "FBT002", # boolean default positional argument - acceptable for tool methods -] +[tool.readme] +github_org = "dreadnode" +logo_url = "https://d1lppblt9t2x15.cloudfront.net/logos/5714928f3cdc09503751580cffbe8d02.png" +tagline = "with batteries included ๐Ÿ”‹" +emoji = "๐Ÿ" -[tool.ruff.format] -skip-magic-trailing-comma = false +[tool.hatch.build.targets.wheel] +packages = ["src"] -[tool.ruff.lint.extend-per-file-ignores] -".hooks/**/*.py" = [ - "ARG001", # temporary for rigging decorators - "T201", # printing is fine for hooks - "BLE001", # blind exception catching is fine for hooks - "TRY301", # abstract raise is fine for hooks -] -"tests/**/*.py" = [ - "INP001", # namespace not required for pytest - "SLF001", # allow access to private members - "PLR2004", # magic values - "S1", # security issues in tests are not relevant - "PERF", # performance issues in tests are not relevant - "T201", # printing is fine for tests - "DTZ003", # datetime without tz is fine for tests - "PLR0915", # too many statements is fine for tests - "PTH123", # open() vs Path.open() is fine for tests - "PTH109", # os.getcwd() vs Path.cwd() is fine for tests -] -"scripts/**/*.py" = [ - "T201", # printing is fine for scripts - "S602", # subprocess shell=True is fine for scripts (we have # nosec) - "PTH123", # open() vs Path.open() is fine for scripts - "RUF059", # unused unpacked variables is fine -] -"examples/**/*.py" = [ - "T201", # printing is fine for examples - "DTZ003", # datetime without tz is fine for examples -] +[tool.hatch.build.targets.sdist] +packages = ["src"]