diff --git a/.github/workflows/lint-infra.yml b/.github/workflows/lint-infra.yml new file mode 100644 index 0000000..b2c8a19 --- /dev/null +++ b/.github/workflows/lint-infra.yml @@ -0,0 +1,40 @@ +name: lint-infra + +on: + push: + pull_request: + +jobs: + shellcheck: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 + with: + persist-credentials: false + + - name: Run shellcheck + run: | + find . -name "*.sh" \ + -not -path "./hashcat-utils/*" \ + -not -path "./princeprocessor/*" \ + -not -path "./omen/*" \ + -not -path "./PACK/*" \ + -not -path "./build/*" \ + -not -path "./dist/*" \ + -not -path "./.venv/*" \ + -print0 | xargs -0 shellcheck + + actionlint: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 + with: + persist-credentials: false + + - name: Install actionlint + run: | + curl -sL https://github.com/rhysd/actionlint/releases/latest/download/actionlint_1.7.7_linux_amd64.tar.gz | tar xz + sudo mv actionlint /usr/local/bin/ + + - name: Run actionlint + run: actionlint diff --git a/.github/workflows/pytest-py310.yml b/.github/workflows/pytest-py310.yml deleted file mode 100644 index 7e9815d..0000000 --- a/.github/workflows/pytest-py310.yml +++ /dev/null @@ -1,34 +0,0 @@ -name: pytest-py310 - -on: - push: - pull_request: - -jobs: - pytest: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - - uses: actions/setup-python@v5 - with: - python-version: "3.10" - - - name: Install system dependencies - run: sudo apt-get update && sudo apt-get install -y p7zip-full transmission-cli - - - name: Install uv - run: python -m pip install --upgrade pip uv==0.9.28 - - - name: Install project dependencies - run: | - uv venv .venv - uv pip install --python .venv/bin/python ".[dev]" - - - name: Run tests - env: - HATE_CRACK_RUN_E2E: "0" - HATE_CRACK_RUN_DOCKER_TESTS: "0" - HATE_CRACK_RUN_LIVE_TESTS: "0" - HATE_CRACK_SKIP_INIT: "1" - run: .venv/bin/python -m pytest diff --git a/.github/workflows/pytest-py311.yml b/.github/workflows/pytest-py311.yml deleted file mode 100644 index ecd11e5..0000000 --- a/.github/workflows/pytest-py311.yml +++ /dev/null @@ -1,34 +0,0 @@ -name: pytest-py311 - -on: - push: - pull_request: - -jobs: - pytest: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - - uses: actions/setup-python@v5 - with: - python-version: "3.11" - - - name: Install system dependencies - run: sudo apt-get update && sudo apt-get install -y p7zip-full transmission-cli - - - name: Install uv - run: python -m pip install --upgrade pip uv==0.9.28 - - - name: Install project dependencies - run: | - uv venv .venv - uv pip install --python .venv/bin/python ".[dev]" - - - name: Run tests - env: - HATE_CRACK_RUN_E2E: "0" - HATE_CRACK_RUN_DOCKER_TESTS: "0" - HATE_CRACK_RUN_LIVE_TESTS: "0" - HATE_CRACK_SKIP_INIT: "1" - run: .venv/bin/python -m pytest diff --git a/.github/workflows/pytest-py312.yml b/.github/workflows/pytest-py312.yml deleted file mode 100644 index 7a7a530..0000000 --- a/.github/workflows/pytest-py312.yml +++ /dev/null @@ -1,34 +0,0 @@ -name: pytest-py312 - -on: - push: - pull_request: - -jobs: - pytest: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - - uses: actions/setup-python@v5 - with: - python-version: "3.12" - - - name: Install system dependencies - run: sudo apt-get update && sudo apt-get install -y p7zip-full transmission-cli - - - name: Install uv - run: python -m pip install --upgrade pip uv==0.9.28 - - - name: Install project dependencies - run: | - uv venv .venv - uv pip install --python .venv/bin/python ".[dev]" - - - name: Run tests - env: - HATE_CRACK_RUN_E2E: "0" - HATE_CRACK_RUN_DOCKER_TESTS: "0" - HATE_CRACK_RUN_LIVE_TESTS: "0" - HATE_CRACK_SKIP_INIT: "1" - run: .venv/bin/python -m pytest diff --git a/.github/workflows/pytest-py313.yml b/.github/workflows/pytest-py313.yml deleted file mode 100644 index 9ebf712..0000000 --- a/.github/workflows/pytest-py313.yml +++ /dev/null @@ -1,34 +0,0 @@ -name: pytest-py313 - -on: - push: - pull_request: - -jobs: - pytest: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - - uses: actions/setup-python@v5 - with: - python-version: "3.13" - - - name: Install system dependencies - run: sudo apt-get update && sudo apt-get install -y p7zip-full transmission-cli - - - name: Install uv - run: python -m pip install --upgrade pip uv==0.9.28 - - - name: Install project dependencies - run: | - uv venv .venv - uv pip install --python .venv/bin/python ".[dev]" - - - name: Run tests - env: - HATE_CRACK_RUN_E2E: "0" - HATE_CRACK_RUN_DOCKER_TESTS: "0" - HATE_CRACK_RUN_LIVE_TESTS: "0" - HATE_CRACK_SKIP_INIT: "1" - run: .venv/bin/python -m pytest diff --git a/.github/workflows/pytest-py314.yml b/.github/workflows/pytest-py314.yml deleted file mode 100644 index e75d1b8..0000000 --- a/.github/workflows/pytest-py314.yml +++ /dev/null @@ -1,34 +0,0 @@ -name: pytest-py314 - -on: - push: - pull_request: - -jobs: - pytest: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - - uses: actions/setup-python@v5 - with: - python-version: "3.14" - - - name: Install system dependencies - run: sudo apt-get update && sudo apt-get install -y p7zip-full transmission-cli - - - name: Install uv - run: python -m pip install --upgrade pip uv==0.9.28 - - - name: Install project dependencies - run: | - uv venv .venv - uv pip install --python .venv/bin/python ".[dev]" - - - name: Run tests - env: - HATE_CRACK_RUN_E2E: "0" - HATE_CRACK_RUN_DOCKER_TESTS: "0" - HATE_CRACK_RUN_LIVE_TESTS: "0" - HATE_CRACK_SKIP_INIT: "1" - run: .venv/bin/python -m pytest diff --git a/.github/workflows/pytest-py39.yml b/.github/workflows/pytest-py39.yml deleted file mode 100644 index bae0100..0000000 --- a/.github/workflows/pytest-py39.yml +++ /dev/null @@ -1,34 +0,0 @@ -name: pytest-py39 - -on: - push: - pull_request: - -jobs: - pytest: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - - uses: actions/setup-python@v5 - with: - python-version: "3.9" - - - name: Install system dependencies - run: sudo apt-get update && sudo apt-get install -y p7zip-full transmission-cli - - - name: Install uv - run: python -m pip install --upgrade pip uv==0.9.28 - - - name: Install project dependencies - run: | - uv venv .venv - uv pip install --python .venv/bin/python ".[dev]" - - - name: Run tests - env: - HATE_CRACK_RUN_E2E: "0" - HATE_CRACK_RUN_DOCKER_TESTS: "0" - HATE_CRACK_RUN_LIVE_TESTS: "0" - HATE_CRACK_SKIP_INIT: "1" - run: .venv/bin/python -m pytest diff --git a/.github/workflows/pytest.yml b/.github/workflows/pytest.yml index 4abfa2f..6a1fd23 100644 --- a/.github/workflows/pytest.yml +++ b/.github/workflows/pytest.yml @@ -11,9 +11,11 @@ jobs: matrix: python-version: ["3.9", "3.10", "3.11", "3.12", "3.13", "3.14"] steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 + with: + persist-credentials: false - - uses: actions/setup-python@v5 + - uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5 with: python-version: ${{ matrix.python-version }} diff --git a/.github/workflows/ruff.yml b/.github/workflows/ruff.yml index 6230128..4720358 100644 --- a/.github/workflows/ruff.yml +++ b/.github/workflows/ruff.yml @@ -8,9 +8,11 @@ jobs: ruff: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 + with: + persist-credentials: false - - uses: actions/setup-python@v5 + - uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5 with: python-version: "3.13" diff --git a/.github/workflows/mypy.yml b/.github/workflows/ty.yml similarity index 54% rename from .github/workflows/mypy.yml rename to .github/workflows/ty.yml index d8a5739..7322bc6 100644 --- a/.github/workflows/mypy.yml +++ b/.github/workflows/ty.yml @@ -1,16 +1,18 @@ -name: mypy +name: ty on: push: pull_request: jobs: - mypy: + ty: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 + with: + persist-credentials: false - - uses: actions/setup-python@v5 + - uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5 with: python-version: "3.13" @@ -22,5 +24,5 @@ jobs: uv venv .venv uv pip install --python .venv/bin/python ".[dev]" - - name: Run mypy - run: .venv/bin/mypy --exclude HashcatRosetta --exclude hashcat-utils --ignore-missing-imports hate_crack + - name: Run ty + run: .venv/bin/ty check hate_crack diff --git a/.github/workflows/version-bump.yml b/.github/workflows/version-bump.yml index 9877853..d26fbc2 100644 --- a/.github/workflows/version-bump.yml +++ b/.github/workflows/version-bump.yml @@ -13,15 +13,17 @@ jobs: if: github.event.pull_request.merged == true runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 with: fetch-depth: 0 + persist-credentials: false - name: Determine version bump type id: bump-type + env: + BRANCH: ${{ github.head_ref }} + TITLE: ${{ github.event.pull_request.title }} run: | - BRANCH="${{ github.head_ref }}" - TITLE="${{ github.event.pull_request.title }}" # Feature branches (feat/) bump minor, everything else bumps patch if echo "$BRANCH" | grep -qiE '^feat/'; then echo "type=minor" >> "$GITHUB_OUTPUT" diff --git a/Makefile b/Makefile index d848ced..b44fff8 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,5 @@ .DEFAULT_GOAL := submodules -.PHONY: install reinstall update dev-install dev-reinstall clean hashcat-utils submodules submodules-pre vendor-assets clean-vendor test coverage lint check ruff mypy +.PHONY: install reinstall update dev-install dev-reinstall clean hashcat-utils submodules submodules-pre vendor-assets clean-vendor test coverage lint check ruff ty hashcat-utils: submodules $(MAKE) -C hashcat-utils @@ -92,10 +92,10 @@ coverage: ruff: uv run ruff check hate_crack -mypy: - uv run mypy hate_crack +ty: + uv run ty check hate_crack -lint: ruff mypy +lint: ruff ty @echo "✓ All linting checks passed" check: lint diff --git a/README.md b/README.md index a939beb..f410697 100644 --- a/README.md +++ b/README.md @@ -12,17 +12,10 @@ **Code Quality & Testing:** [![ruff](https://github.com/trustedsec/hate_crack/actions/workflows/ruff.yml/badge.svg)](https://github.com/trustedsec/hate_crack/actions/workflows/ruff.yml) -[![mypy](https://github.com/trustedsec/hate_crack/actions/workflows/mypy.yml/badge.svg)](https://github.com/trustedsec/hate_crack/actions/workflows/mypy.yml) +[![ty](https://github.com/trustedsec/hate_crack/actions/workflows/ty.yml/badge.svg)](https://github.com/trustedsec/hate_crack/actions/workflows/ty.yml) [![pytest](https://github.com/trustedsec/hate_crack/actions/workflows/pytest.yml/badge.svg)](https://github.com/trustedsec/hate_crack/actions/workflows/pytest.yml) -**Python Version Testing:** - -[![py39](https://github.com/trustedsec/hate_crack/actions/workflows/pytest-py39.yml/badge.svg)](https://github.com/trustedsec/hate_crack/actions/workflows/pytest-py39.yml) -[![py310](https://github.com/trustedsec/hate_crack/actions/workflows/pytest-py310.yml/badge.svg)](https://github.com/trustedsec/hate_crack/actions/workflows/pytest-py310.yml) -[![py311](https://github.com/trustedsec/hate_crack/actions/workflows/pytest-py311.yml/badge.svg)](https://github.com/trustedsec/hate_crack/actions/workflows/pytest-py311.yml) -[![py312](https://github.com/trustedsec/hate_crack/actions/workflows/pytest-py312.yml/badge.svg)](https://github.com/trustedsec/hate_crack/actions/workflows/pytest-py312.yml) -[![py313](https://github.com/trustedsec/hate_crack/actions/workflows/pytest-py313.yml/badge.svg)](https://github.com/trustedsec/hate_crack/actions/workflows/pytest-py313.yml) -[![py314](https://github.com/trustedsec/hate_crack/actions/workflows/pytest-py314.yml/badge.svg)](https://github.com/trustedsec/hate_crack/actions/workflows/pytest-py314.yml) +The pytest workflow tests across Python 3.9-3.14 via a matrix build. ## Installation @@ -237,7 +230,7 @@ make test ### Setting Up the Development Environment -Install the project with optional dev dependencies (includes type stubs, linters, and testing tools): +Install the project with optional dev dependencies (includes linters and testing tools): ```bash make dev-install @@ -254,10 +247,10 @@ The project uses GitHub Actions to automatically run quality checks on every pus - ❌ **FAIL**: Code has style violations or quality issues - Run locally: `make ruff` -2. **Type Checking (Mypy)** - Static type analysis +2. **Type Checking (ty)** - Static type analysis - ✅ **PASS**: No type errors detected - ❌ **FAIL**: Type mismatches or missing annotations found - - Run locally: `make mypy` + - Run locally: `make ty` 3. **Testing (Multi-Version)** - Tests across Python 3.9 through 3.14 - ✅ **PASS**: All tests pass on all supported Python versions @@ -284,14 +277,14 @@ Auto-fix issues: .venv/bin/ruff check --fix hate_crack ``` -**Mypy (type checking):** +**ty (type checking):** ```bash -.venv/bin/mypy hate_crack +.venv/bin/ty check hate_crack ``` **Run all checks together:** ```bash -.venv/bin/ruff check hate_crack && .venv/bin/mypy hate_crack && echo "✓ All checks passed" +.venv/bin/ruff check hate_crack && .venv/bin/ty check hate_crack && echo "✓ All checks passed" ``` ### Running Tests @@ -305,23 +298,17 @@ With coverage: .venv/bin/pytest --cov=hate_crack ``` -### Pre-commit Hook (Optional) +### Git Hooks (prek) -Create `.git/hooks/pre-push` to automatically run checks before pushing: +Git hooks are managed by [prek](https://github.com/nicholasgasior/prek). Install hooks with: ```bash -#!/bin/bash -set -e -.venv/bin/ruff check hate_crack -.venv/bin/mypy --exclude HashcatRosetta --exclude hashcat-utils --ignore-missing-imports hate_crack -HATE_CRACK_SKIP_INIT=1 HATE_CRACK_RUN_E2E=0 HATE_CRACK_RUN_DOCKER_TESTS=0 HATE_CRACK_RUN_LIVE_TESTS=0 .venv/bin/python -m pytest -echo "✓ Local checks passed!" +prek install ``` -Make it executable: -```bash -chmod +x .git/hooks/pre-push -``` +This installs hooks defined in `prek.toml`: +- **pre-push**: ruff check, ty check, pytest +- **post-commit**: documentation audit ### Optional Dependencies @@ -341,13 +328,10 @@ PassGPT (option 17) will be hidden from the menu if ML dependencies are not inst ### Dev Dependencies The optional `[dev]` group includes: -- **mypy** - Static type checker +- **ty** - Static type checker - **ruff** - Fast Python linter and formatter - **pytest** - Testing framework - **pytest-cov** - Coverage reporting -- **types-requests** - Type stubs for requests library -- **types-beautifulsoup4** - Type stubs for BeautifulSoup -- **types-openpyxl** - Type stubs for openpyxl library ------------------------------------------------------------------- Common options: diff --git a/prek.toml b/prek.toml new file mode 100644 index 0000000..ef73ef5 --- /dev/null +++ b/prek.toml @@ -0,0 +1,11 @@ +[hooks.pre-push] +commands = [ + "uv run ruff check hate_crack", + "uv run ty check hate_crack", + "HATE_CRACK_SKIP_INIT=1 uv run pytest -q", +] + +[hooks.post-commit] +commands = [ + "bash .claude/audit-docs.sh HEAD", +] diff --git a/pyproject.toml b/pyproject.toml index c0f0fa0..1766ef6 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -26,13 +26,10 @@ ml = [ "accelerate>=1.1.0", ] dev = [ - "mypy>=1.8.0", - "ruff>=0.3.0", - "pytest>=7.0.0", - "pytest-cov>=4.0.0", - "types-requests>=2.31.0", - "types-beautifulsoup4>=4.12.0", - "types-openpyxl>=3.0.0", + "ty==0.0.17", + "ruff==0.15.1", + "pytest==9.0.2", + "pytest-cov==7.0.0", ] [tool.setuptools.packages.find] @@ -62,26 +59,29 @@ exclude = [ "rules", ] -[tool.mypy] +[tool.ty.src] exclude = [ - "^build/", - "^dist/", - "^PACK/", - "^wordlists/", - "^HashcatRosetta/", - "^hashcat-utils/", - "^hate_crack/hashcat-utils/", - "^hate_crack/omen/", - "^hate_crack/princeprocessor/", + "build/", + "dist/", + "PACK/", + "wordlists/", + "HashcatRosetta/", + "hashcat-utils/", + "hate_crack/hashcat-utils/", + "hate_crack/omen/", + "hate_crack/princeprocessor/", ] -ignore_missing_imports = true + +[tool.ty.rules] +# Module-level globals in main.py are assigned at runtime +unresolved-reference = "warn" +# Optional deps (torch, transformers, hashcat_rosetta) not always installed +unresolved-import = "warn" +# BeautifulSoup union types and module-level globals +unresolved-attribute = "warn" +invalid-argument-type = "warn" [tool.pytest.ini_options] testpaths = [ "tests", ] - -[dependency-groups] -dev = [ - "types-requests>=2.32.4.20260107", -] diff --git a/wordlists/kill_transmission.sh b/wordlists/kill_transmission.sh new file mode 100755 index 0000000..0128efc --- /dev/null +++ b/wordlists/kill_transmission.sh @@ -0,0 +1,27 @@ +#!/bin/bash +# +set -euo pipefail + +TORRENT_DIR="${TR_TORRENT_DIR:-}" +TORRENT_NAME="${TR_TORRENT_NAME:-}" + +if [ -z "$TORRENT_DIR" ] || [ -z "$TORRENT_NAME" ]; then + exit 0 +fi + +TORRENT_PATH="${TORRENT_DIR}/${TORRENT_NAME}" + +SEVENZ_BIN=$(command -v 7z || command -v 7za || true) +if [ -n "$SEVENZ_BIN" ]; then + if [ -f "$TORRENT_PATH" ] && [[ "$TORRENT_PATH" == *.7z ]]; then + "$SEVENZ_BIN" x -sdel "$TORRENT_PATH" -o"$TORRENT_DIR" + elif [ -d "$TORRENT_PATH" ]; then + find "$TORRENT_PATH" -maxdepth 2 -type f -name "*.7z" -print0 | while IFS= read -r -d '' zfile; do + "$SEVENZ_BIN" e -sdel "$zfile" + done + fi +fi + +if [ -n "$PPID" ]; then + kill "$PPID" +fi