1044 Commits

Author SHA1 Message Date
Jens
3958d4c907 feat: add preserve-local-settings toggle for download (#1091)
## ℹ️ Description

When re-downloading an ad that is already saved locally (via `--ads=all`
or numeric IDs), the ad YAML is atomically replaced. The download only
scrapes fields from the live page, so all **local-only settings** are
reset to defaults or zero:

| Field | What happens |
|---|---|
| `auto_price_reduction` | Reset to `AdDefaults` value (or `null`) |
| `republication_interval` | Reset to `AdDefaults` value (or `null`) |
| `repost_count` | Reset to `0` — bot forgets how many times it
published |
| `price_reduction_count` | Reset to `0` — bot forgets auto-reduction
progress |

The `new` selector avoids this by skipping already-saved ads, but `all`
and numeric IDs do not.

- Link to the related issue(s): N/A

## 📋 Changes Summary

- Add `download.preserve_local_settings` config option (default: `true`)
- Add `--preserve-local-settings` CLI flag with help text (English +
German)
- In `download_ad()`, when re-downloading an existing ad with the toggle
enabled, preserve four local-only fields from the existing YAML:
`auto_price_reduction`, `republication_interval`, `repost_count`,
`price_reduction_count`
- Uses validate-then-commit pattern: candidate values are staged on a
model copy, validated, then committed only on success
- Added test verifying local fields survive re-download
- Regenerated schemas and config defaults
- Updated German translations for new log messages

### ⚙️ Type of Change
- [x] 🐞 Bug fix
- [x]  New feature
- [ ] 💥 Breaking change

##  Checklist
- [x] I have reviewed my changes to ensure they meet the project's
standards.
- [x] I have tested my changes and ensured that all tests pass (`pdm run
test`).
- [x] I have formatted the code (`pdm run format`).
- [x] I have verified that linting passes (`pdm run lint`).
- [x] I have updated documentation where necessary.

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **New Features**
* Added `--preserve-local-settings` CLI flag to retain local ad settings
during re-downloads (including auto price reduction, republication
interval, and repost count).
* Settings now preserved by default; re-downloading existing ads
maintains local configurations instead of resetting to defaults.

* **Documentation**
* Updated configuration guide with details on the new
`preserve_local_settings` option.

* **Tests**
* Added unit tests for CLI flag parsing and preservation logic during ad
re-downloads.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-06-07 11:46:07 +02:00
Jens
faedfad23c refactor: extract CLI bootstrap (#1089)
## ℹ️ Description
This pull request extracts CLI parsing and runtime bootstrap into
dedicated modules while keeping the existing command behavior intact.

- Link to the related issue(s): Issue #
- Describe the motivation and context for this change.

## 📋 Changes Summary

- Moved CLI parsing/help logic into `src/kleinanzeigen_bot/cli.py`.
- Moved workspace resolution, config loading, browser config
application, and file logging setup into
`src/kleinanzeigen_bot/runtime_config.py`.
- Kept `python -m kleinanzeigen_bot` behavior unchanged via
`src/kleinanzeigen_bot/__main__.py`.
- Preserved frozen build startup by importing `runtime_config`
statically.
- Added focused tests for CLI parsing and runtime bootstrap behavior.
- Updated contributor docs and translation entries for the moved
user-facing messages.

### ⚙️ Type of Change
Select the type(s) of change(s) included in this pull request:
- [x] 🐞 Bug fix (non-breaking change which fixes an issue)
- [ ]  New feature (adds new functionality without breaking existing
usage)
- [ ] 💥 Breaking change (changes that might break existing user setups,
scripts, or configurations)

##  Checklist
Before requesting a review, confirm the following:
- [x] I have reviewed my changes to ensure they meet the project's
standards.
- [x] I have tested my changes and ensured that all tests pass (`pdm run
test`).
- [x] I have formatted the code (`pdm run format`).
- [x] I have verified that linting passes (`pdm run lint`).
- [x] I have updated documentation where necessary.

By submitting this pull request, I confirm that you can use, modify,
copy, and redistribute this contribution, under the terms of your
choice.


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **Documentation**
  * Clarified bootstrap docs to state the app’s CLI-driven entry point.

* **New Features**
* Localized CLI with improved argument parsing, help text and banner
control.
* Runtime bootstrapping: default-config creation, env-var credential
placeholders, category loading, workspace-aware browser profile
handling, and optional file logging.

* **Refactor**
* Centralized startup into the CLI/runtime layer; package entrypoint now
delegates to the CLI.

* **Tests**
* Added/updated unit and smoke tests covering CLI, runtime config,
workspace behavior and create-config.

* **Chores**
* Updated project script wrappers to print tool headers before running
linters.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-06-07 07:05:53 +02:00
Jens
b98ae58f77 refactor: clean up package-root price imports (#1088)
## Description

Clean up the remaining package-root price-reduction drift before the
next CLI/config extraction step.

- Related issue(s): None.
- Motivation: make price-reduction preview logging a normal module-level
API and stop exporting unused price calculation helpers from the package
root.

## Changes Summary

- Removed unused package-root re-exports for `calculate_auto_price` and
`calculate_auto_price_with_trace`.
- Renamed `_log_auto_price_reduction_preview` to
`log_auto_price_reduction_preview` and exported the public name from
`price_reduction`.
- Updated verify preview calls to access the logger through the
`price_reduction` module alias.
- Updated the German translation key for the renamed preview logger.

### Type of Change

- [x] Bug fix (non-breaking change which fixes an issue)
- [ ] New feature (adds new functionality without breaking existing
usage)
- [ ] Breaking change (changes that might break existing user setups,
scripts, or configurations)

Internal refactor only; none of the listed change types apply.

## Checklist

- [x] I have reviewed my changes to ensure they meet the project's
standards.
- [x] I have tested my changes and ensured that all tests pass (`pdm run
test`).
- [x] I have formatted the code (`pdm run format`).
- [x] I have verified that linting passes (`pdm run lint`).
- [x] I have updated documentation where necessary.


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **Bug Fixes**
* Auto-price reduction preview logging now consistently displays for
both ad publishing and update decisions.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-06-06 07:05:18 +02:00
kleinanzeigen-bot-tu[bot]
5d322a73ca chore: ✔ Update ruff 0.15.15 -> 0.15.16 (#1086) 2026-06-05 21:04:24 +02:00
Jens
55808363ec refactor: remove root compatibility facade (#1087)
## ℹ️ Description

Refactors the package root so kleinanzeigen_bot.__init__ no longer
preserves compatibility re-exports for internal helpers. This keeps the
supported project contract focused on CLI behavior rather than
accidental Python import paths.

- Link to the related issue(s): N/A
- Motivation: reduce __init__.py facade bloat as part of the monolith
breakdown while preserving user-facing CLI/config/browser behavior.

## 📋 Changes Summary

- Remove root-level compatibility re-exports and underscore aliases for
extracted helper modules.
- Update internal references and tests to use concrete modules for price
reduction, path renaming, diagnostics, XDG paths, and related helpers.
- Document in AGENTS.md that this project is a CLI application and
package-root imports are not a supported compatibility contract.
- No dependency, configuration, schema, or generated-artifact changes.

### ⚙️ Type of Change
Select the type(s) of change(s) included in this pull request:
- [ ] 🐞 Bug fix (non-breaking change which fixes an issue)
- [ ]  New feature (adds new functionality without breaking existing
usage)
- [x] 💥 Breaking change (changes that might break existing user setups,
scripts, or configurations)

Breaking-change note: this intentionally removes unsupported
package-root Python imports for internal helpers. CLI commands, config
behavior, generated YAML behavior, runtime messages, and browser
workflows remain stable.

##  Checklist
Before requesting a review, confirm the following:
- [x] I have reviewed my changes to ensure they meet the project's
standards.
- [x] I have tested my changes and ensured that all tests pass (pdm run
test).
- [x] I have formatted the code (pdm run format).
- [x] I have verified that linting passes (pdm run lint).
- [x] I have updated documentation where necessary.

By submitting this pull request, I confirm that you can use, modify,
copy, and redistribute this contribution, under the terms of your
choice.

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **Chores**
* Reorganized internal module imports and aliases to separate public API
from internal helpers.

* **Documentation**
* Added a “Project Contract” section defining guarantees for user-facing
behavior (CLI, config/defaults, generated outputs, persisted changes,
messages, automation) and clarifying non-goals for internal
compatibility.

* **Tests**
* Updated unit tests to align with the new module structure and import
paths.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-06-05 17:59:59 +02:00
Jens
98985e447f refactor: extract delete and download state helpers (#1085)
## ℹ️ Description

- Link to the related issue(s): Issue #
- Extract browser-free delete and download state decisions from
`kleinanzeigen_bot.__init__` into focused modules.
- This keeps `KleinanzeigenBot` responsible for browser and workflow
orchestration while making the state helpers directly unit-testable.

## 📋 Changes Summary

- Added `kleinanzeigen_bot.ad_state` for relative ad paths and
after-delete state cleanup.
- Added `kleinanzeigen_bot.download_selection` for numeric selector
matching and download active/ownership resolution.
- Updated `KleinanzeigenBot` to call the extracted helpers directly and
removed the class-level download state resolver wrapper.
- Added explicit `__all__` declarations for the new domain modules and
removed leftover local path renaming wrapper methods from
`KleinanzeigenBot`.
- Added focused unit tests for the extracted helpers and reduced
duplicate resolver/delete-state coverage in `test_init.py`.

### ⚙️ Type of Change
Select the type(s) of change(s) included in this pull request:
- [ ] 🐞 Bug fix (non-breaking change which fixes an issue)
- [x]  New feature (adds new functionality without breaking existing
usage)
- [ ] 💥 Breaking change (changes that might break existing user setups,
scripts, or configurations)


##  Checklist
Before requesting a review, confirm the following:
- [x] I have reviewed my changes to ensure they meet the project's
standards.
- [x] I have tested my changes and ensured that all tests pass (`pdm run
test`).
- [x] I have formatted the code (`pdm run format`).
- [x] I have verified that linting passes (`pdm run lint`).
- [x] I have updated documentation where necessary.

By submitting this pull request, I confirm that you can use, modify,
copy, and redistribute this contribution, under the terms of your
choice.


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **Refactor**
* Reorganized internal code structure by consolidating ad state
management, download selection logic, and path renaming utilities into
dedicated modules for improved code organization and maintainability.

* **Tests**
* Added comprehensive unit tests covering ad state handling, download
selection behavior, and path renaming functionality to enhance code
reliability.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-06-05 16:30:59 +02:00
Jens
cf1f45fdc1 fix: rename nodriver hook logs (#1084)
## ℹ️ Description
Update the post-install hook output to use the renamed `fix_nodriver`
prefix instead of the old `fix_nodriver_encoding` string.

## 📋 Changes Summary
- Renamed the emitted log/prefix text in `scripts/fix_nodriver.py`.
- Kept the hook behavior unchanged.

### ⚙️ Type of Change
- [x] 🐞 Bug fix (non-breaking change which fixes an issue)
- [ ]  New feature (adds new functionality without breaking existing
usage)
- [ ] 💥 Breaking change (changes that might break existing user setups,
scripts, or configurations)

##  Checklist
- [x] I have reviewed my changes to ensure they meet the project's
standards.
- [ ] I have tested my changes and ensured that all tests pass (`pdm run
test`).
- [ ] I have formatted the code (`pdm run format`).
- [ ] I have verified that linting passes (`pdm run lint`).
- [x] I have updated documentation where necessary.

By submitting this pull request, I confirm that you can use, modify,
copy, and redistribute this contribution, under the terms of your
choice.


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **Chores**
* Standardized error and diagnostic messages during post-installation
setup for improved consistency and clarity.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-06-05 13:30:55 +02:00
Jens
9ba817ab6e docs: update agent playbook (#1083)
## ℹ️ Description

- Link to the related issue(s): None.
- Updates the local agent playbook so future contributors and AI agents
follow the current repository structure and PR conventions.

## 📋 Changes Summary

- Document that browser-independent domain logic belongs in top-level
src/kleinanzeigen_bot/*.py modules, while utils/ is reserved for generic
infrastructure helpers.
- Broaden generated-artifact guidance to include schema-affecting
validators and create-config output.
- Clarify that branch names should use conventional type prefixes
matching semantic PR titles.
- Tighten PR publishing guidance to avoid placeholder sections,
incomplete checklist decisions, and non-semantic titles.
- Dependencies/configuration: none.

### ⚙️ Type of Change
Select the type(s) of change(s) included in this pull request:
- [ ] 🐞 Bug fix (non-breaking change which fixes an issue)
- [ ]  New feature (adds new functionality without breaking existing
usage)
- [ ] 💥 Breaking change (changes that might break existing user setups,
scripts, or configurations)
- [x] Documentation-only change (no runtime behavior change)

##  Checklist
Before requesting a review, confirm the following:
- [x] I have reviewed my changes to ensure they meet the project's
standards.
- [ ] I have tested my changes and ensured that all tests pass (pdm run
test). Not run; documentation-only change.
- [ ] I have formatted the code (pdm run format). Not run;
documentation-only change.
- [ ] I have verified that linting passes (pdm run lint). Not run;
documentation-only change.
- [x] I have updated documentation where necessary.

By submitting this pull request, I confirm that you can use, modify,
copy, and redistribute this contribution, under the terms of your
choice.

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **Documentation**
* Updated contribution guidelines with enhanced repository structure
rules for code organization.
* Expanded guidance on regenerating artifacts for configuration and
schema changes.
  * Added branch naming conventions and PR expectations for submissions.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-06-05 12:18:21 +02:00
Jens
effc6ed5db fix: redact contact zipcode from logs (#1082)
## ℹ️ Description
Fixes CodeQL alert 132 (`py/clear-text-logging-sensitive-data`) by
avoiding clear-text logging of the configured contact ZIP code when the
contact ZIP field cannot be filled.

- Link to the related issue(s): Code scanning alert 132
- The warning log now keeps the timeout/error context without writing
the user-provided ZIP code to logs.

## 📋 Changes Summary

- Redacted `contact.zipcode` from the contact ZIP-code failure warning.
- Updated the German translation entry for the changed log message.

### ⚙️ Type of Change
Select the type(s) of change(s) included in this pull request:
- [x] 🐞 Bug fix (non-breaking change which fixes an issue)
- [ ]  New feature (adds new functionality without breaking existing
usage)
- [ ] 💥 Breaking change (changes that might break existing user setups,
scripts, or configurations)

##  Checklist
Before requesting a review, confirm the following:
- [x] I have reviewed my changes to ensure they meet the project's
standards.
- [x] I have tested my changes and ensured that all tests pass (`pdm run
test`).
- [x] I have formatted the code (`pdm run format`).
- [x] I have verified that linting passes (`pdm run lint`).
- [x] I have updated documentation where necessary.

Validation performed:

- `pdm run format`
- `pdm run lint`
- `pdm run pytest tests/unit/test_translations.py -q`
- `pdm run test` -> 1176 passed, 4 skipped

By submitting this pull request, I confirm that you can use, modify,
copy, and redistribute this contribution, under the terms of your
choice.


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **Documentation**
  * Reformatted testing guidance section
  
* **Chores**
  * Updated error logging in contact field handling

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-06-05 12:07:43 +02:00
Jens
bff8ae7be4 fix: align Docker tags with release channels (#1081)
## Description

- Link to the related issue(s): Issue #1077
- Align Docker image tags with the existing GitHub release channels so
`main` publishes preview images and `release` publishes stable latest
images.

## Changes Summary

- Publish per-arch Docker images as `preview-amd64` / `preview-arm64`
from `main`.
- Publish per-arch Docker images as `latest-amd64` / `latest-arm64` from
`release`.
- Stitch the matching multi-arch channel manifest as `:preview` or
`:latest`.
- Document `:latest` as the stable Docker image tag and mention
`:preview` in the README.

### Type of Change

- [x] Bug fix (non-breaking change which fixes an issue)
- [ ] New feature (adds new functionality without breaking existing
usage)
- [ ] Breaking change (changes that might break existing user setups,
scripts, or configurations)

## Validation

- [x] `pdm run format`
- [x] `pdm run lint`
- [x] `pdm run test` (`1176 passed, 4 skipped`)

## Checklist

- [x] I have reviewed my changes to ensure they meet the project's
standards.
- [x] I have tested my changes and ensured that all tests pass (`pdm run
test`).
- [x] I have formatted the code (`pdm run format`).
- [x] I have verified that linting passes (`pdm run lint`).
- [x] I have updated documentation where necessary.

By submitting this pull request, I confirm that you can use, modify,
copy, and redistribute this contribution, under the terms of your
choice.


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **New Features**
  * Docker preview channel is now available for testing

* **Documentation**
* Updated Docker installation instructions with image references and
guidance on using the preview channel

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-06-05 10:46:45 +02:00
Jens
82020fb3dc ci: publish multi-arch docker manifest (#1080)
## ℹ️ Description

- Link to the related issue(s): Issue #1077
- Fixes GHCR `:latest` publishing so the amd64 and arm64 Docker matrix
jobs no longer race by pushing the same single-arch tag.

## 📋 Changes Summary

- Publish architecture-specific Docker image tags from the Ubuntu matrix
jobs (`:latest-amd64` / `:latest-arm64`).
- Add a dependent `publish-docker-manifest` job that stitches those
per-arch tags into a multi-arch `:latest` manifest using Docker Buildx.
- Add workflow-level concurrency so `main` publishing runs are
serialized while non-main runs cancel older attempts.
- Add `actionlint-py` as a PDM-managed dev dependency and include
`actionlint` in `pdm run lint`.
- Fix existing workflow shellcheck findings reported by `actionlint`.

### ⚙️ Type of Change
- [x] 🐞 Bug fix (non-breaking change which fixes an issue)
- [ ]  New feature (adds new functionality without breaking existing
usage)
- [ ] 💥 Breaking change (changes that might break existing user setups,
scripts, or configurations)

##  Checklist
- [x] I have reviewed my changes to ensure they meet the project's
standards.
- [x] I have tested my changes and ensured that all tests pass (`pdm run
test`).
- [x] I have formatted the code (`pdm run format`).
- [x] I have verified that linting passes (`pdm run lint`).
- [ ] I have updated documentation where necessary. — N/A, CI-only
behavior and dev dependency wiring.

By submitting this pull request, I confirm that you can use, modify,
copy, and redistribute this contribution, under the terms of your
choice.

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **Chores**
* Optimized CI/CD workflow serialization and concurrent run handling for
improved build efficiency.
* Enhanced Docker publishing to support multi-architecture image
manifest generation.
* Added GitHub Actions workflow validation to the development tooling
pipeline.
* Updated development dependencies and extended linting script coverage.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-06-05 10:15:14 +02:00
kleinanzeigen-bot-tu[bot]
a29d349fb3 chore: Update Python dependencies (#1074)
✔ Update filelock 3.29.0 -> 3.29.1 successful
  ✔ Update idna 3.17 -> 3.18 successful
  ✔ Update typer 0.26.5 -> 0.26.7 successful
  ✔ Update cyclonedx-python-lib 11.7.0 -> 11.8.0 successful

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-06-05 07:25:51 +02:00
Jens
e81671a24c refactor: extract ad_content and ad_form_helpers domain modules (#1076)
## ℹ️ Description

Extract ad description composition and browser-independent form helpers
from the ~3500-line `__init__.py` into dedicated domain modules.

- **`ad_description.py`**: `get_ad_description()` — prefix/suffix affix
composition, `@` → `(at)` replacement, length validation
- **`ad_form_helpers.py`**: `normalize_condition`, `xpath_literal`,
`get_marker_value`/`get_marker_value_from_attrs`, and related constants
(`WANTED_SHIPPING_LABELS`, `SPECIAL_ATTRIBUTE_TOKEN_RE`,
`CONDITION_GERMAN_TO_API`)
- `__init__.py` imports the extracted helpers for existing call sites
and preserves compatibility re-exports where needed
- Condition dialog probing prefers canonical API values before legacy
German fallbacks to avoid avoidable `quick_dom` timeouts
- No browser/nodriver types imported into the helper modules
- Test coverage migrated to per-module suites: `test_ad_description.py`
and `test_ad_form_helpers.py`
- Command/config tests use temporary paths so unit tests do not create
log files in the repository root

## 📋 Changes Summary

- New: `src/kleinanzeigen_bot/ad_description.py`
- New: `src/kleinanzeigen_bot/ad_form_helpers.py`
- New: `tests/unit/test_ad_description.py`
- New: `tests/unit/test_ad_form_helpers.py`
- Modified: `src/kleinanzeigen_bot/__init__.py` — removed extracted
helper logic and the redundant description wrapper
- Modified: `tests/unit/test_init.py` — removed old description-wrapper
coverage and kept command tests isolated with `tmp_path`

### ⚙️ Type of Change
- [x]  Enhancement (refactoring, no behavior change)

##  Checklist
- [x] I have reviewed my changes to ensure they meet the project's
standards.
- [x] I have tested my changes and ensured that all tests pass (`pdm run
test`).
- [x] I have formatted the code (`pdm run format`).
- [x] I have verified that linting passes (`pdm run lint`).
- [x] I have updated documentation where necessary.

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **New Features**
* Ad descriptions support configurable prefix/suffix affixes and replace
"@" with "(at)" when affixes are applied; final description length is
validated.

* **Refactor**
* Form- and description-related logic consolidated into shared helpers
for more consistent condition normalization, shipping label selection,
hidden-image marker handling, and XPath-safe quoting.

* **Tests**
* New unit tests cover description composition/validation, condition
normalization, marker extraction, XPath quoting, token validation, and
related wiring.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-06-05 07:25:25 +02:00
dependabot[bot]
925ac016e4 ci(deps): bump the all-actions group with 2 updates (#1075)
Bumps the all-actions group with 2 updates:
[actions/checkout](https://github.com/actions/checkout) and
[github/codeql-action](https://github.com/github/codeql-action).

Updates `actions/checkout` from 6.0.2 to 6.0.3
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/actions/checkout/releases">actions/checkout's
releases</a>.</em></p>
<blockquote>
<h2>v6.0.3</h2>
<h2>What's Changed</h2>
<ul>
<li>Update changelog by <a
href="https://github.com/ericsciple"><code>@​ericsciple</code></a> in <a
href="https://redirect.github.com/actions/checkout/pull/2357">actions/checkout#2357</a></li>
<li>fix: expand merge commit SHA regex and add SHA-256 test cases by <a
href="https://github.com/yaananth"><code>@​yaananth</code></a> in <a
href="https://redirect.github.com/actions/checkout/pull/2414">actions/checkout#2414</a></li>
<li>Fix checkout init for SHA-256 repositories by <a
href="https://github.com/yaananth"><code>@​yaananth</code></a> in <a
href="https://redirect.github.com/actions/checkout/pull/2439">actions/checkout#2439</a></li>
<li>Update changelog for v6.0.3 by <a
href="https://github.com/yaananth"><code>@​yaananth</code></a> in <a
href="https://redirect.github.com/actions/checkout/pull/2446">actions/checkout#2446</a></li>
</ul>
<h2>New Contributors</h2>
<ul>
<li><a href="https://github.com/yaananth"><code>@​yaananth</code></a>
made their first contribution in <a
href="https://redirect.github.com/actions/checkout/pull/2414">actions/checkout#2414</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/actions/checkout/compare/v6...v6.0.3">https://github.com/actions/checkout/compare/v6...v6.0.3</a></p>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="df4cb1c069"><code>df4cb1c</code></a>
Update changelog for v6.0.3 (<a
href="https://redirect.github.com/actions/checkout/issues/2446">#2446</a>)</li>
<li><a
href="1cce3390c2"><code>1cce339</code></a>
Fix checkout init for SHA-256 repositories (<a
href="https://redirect.github.com/actions/checkout/issues/2439">#2439</a>)</li>
<li><a
href="900f2210b1"><code>900f221</code></a>
fix: expand merge commit SHA regex and add SHA-256 test cases (<a
href="https://redirect.github.com/actions/checkout/issues/2414">#2414</a>)</li>
<li><a
href="0c366fd6a8"><code>0c366fd</code></a>
Update changelog (<a
href="https://redirect.github.com/actions/checkout/issues/2357">#2357</a>)</li>
<li>See full diff in <a
href="https://github.com/actions/checkout/compare/v6.0.2...v6.0.3">compare
view</a></li>
</ul>
</details>
<br />

Updates `github/codeql-action` from 4.36.0 to 4.36.1
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/github/codeql-action/releases">github/codeql-action's
releases</a>.</em></p>
<blockquote>
<h2>v4.36.1</h2>
<p>No user facing changes.</p>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/github/codeql-action/blob/main/CHANGELOG.md">github/codeql-action's
changelog</a>.</em></p>
<blockquote>
<h1>CodeQL Action Changelog</h1>
<p>See the <a
href="https://github.com/github/codeql-action/releases">releases
page</a> for the relevant changes to the CodeQL CLI and language
packs.</p>
<h2>[UNRELEASED]</h2>
<p>No user facing changes.</p>
<h2>4.36.1 - 02 Jun 2026</h2>
<p>No user facing changes.</p>
<h2>4.36.0 - 22 May 2026</h2>
<ul>
<li><em>Breaking change</em>: Bump the minimum required CodeQL bundle
version to 2.19.4. <a
href="https://redirect.github.com/github/codeql-action/pull/3894">#3894</a></li>
<li>Add support for SHA-256 Git object IDs. <a
href="https://redirect.github.com/github/codeql-action/pull/3893">#3893</a></li>
<li>Update default CodeQL bundle version to <a
href="https://github.com/github/codeql-action/releases/tag/codeql-bundle-v2.25.5">2.25.5</a>.
<a
href="https://redirect.github.com/github/codeql-action/pull/3926">#3926</a></li>
</ul>
<h2>4.35.5 - 15 May 2026</h2>
<ul>
<li>We have improved how the JavaScript bundles for the CodeQL Action
are generated to avoid duplication across bundles and reduce the size of
the repository by around 70%. This should have no effect on the runtime
behaviour of the CodeQL Action. <a
href="https://redirect.github.com/github/codeql-action/pull/3899">#3899</a></li>
<li>For performance and accuracy reasons, <a
href="https://redirect.github.com/github/roadmap/issues/1158">improved
incremental analysis</a> will now only be enabled on a pull request when
diff-informed analysis is also enabled for that run. If diff-informed
analysis is unavailable (for example, because the PR diff ranges could
not be computed), the action will fall back to a full analysis. <a
href="https://redirect.github.com/github/codeql-action/pull/3791">#3791</a></li>
<li>If multiple inputs are provided for the GitHub-internal
<code>analysis-kinds</code> input, only <code>code-scanning</code> will
be enabled. The <code>analysis-kinds</code> input is experimental, for
GitHub-internal use only, and may change without notice at any time. <a
href="https://redirect.github.com/github/codeql-action/pull/3892">#3892</a></li>
<li>Added an experimental change which, when running a Code Scanning
analysis for a PR with <a
href="https://redirect.github.com/github/roadmap/issues/1158">improved
incremental analysis</a> enabled, prefers CodeQL CLI versions that have
a cached overlay-base database for the configured languages. This speeds
up analysis for a repository when there is not yet a cached overlay-base
database for the latest CLI version. We expect to roll this change out
to everyone in May. <a
href="https://redirect.github.com/github/codeql-action/pull/3880">#3880</a></li>
</ul>
<h2>4.35.4 - 07 May 2026</h2>
<ul>
<li>Update default CodeQL bundle version to <a
href="https://github.com/github/codeql-action/releases/tag/codeql-bundle-v2.25.4">2.25.4</a>.
<a
href="https://redirect.github.com/github/codeql-action/pull/3881">#3881</a></li>
</ul>
<h2>4.35.3 - 01 May 2026</h2>
<ul>
<li><em>Upcoming breaking change</em>: Add a deprecation warning for
customers using CodeQL version 2.19.3 and earlier. These versions of
CodeQL were discontinued on 9 April 2026 alongside GitHub Enterprise
Server 3.15, and will be unsupported by the next minor release of the
CodeQL Action. <a
href="https://redirect.github.com/github/codeql-action/pull/3837">#3837</a></li>
<li>Configurations for private registries that use Cloudsmith or GCP
OIDC are now accepted. <a
href="https://redirect.github.com/github/codeql-action/pull/3850">#3850</a></li>
<li>Best-effort connection tests for private registries now use
<code>GET</code> requests instead of <code>HEAD</code> for better
compatibility with various registry implementations. For NuGet feeds,
the test is now always performed against the service index. <a
href="https://redirect.github.com/github/codeql-action/pull/3853">#3853</a></li>
<li>Fixed a bug where two diagnostics produced within the same
millisecond could overwrite each other on disk, causing one of them to
be lost. <a
href="https://redirect.github.com/github/codeql-action/pull/3852">#3852</a></li>
<li>Update default CodeQL bundle version to <a
href="https://github.com/github/codeql-action/releases/tag/codeql-bundle-v2.25.3">2.25.3</a>.
<a
href="https://redirect.github.com/github/codeql-action/pull/3865">#3865</a></li>
</ul>
<h2>4.35.2 - 15 Apr 2026</h2>
<ul>
<li>The undocumented TRAP cache cleanup feature that could be enabled
using the <code>CODEQL_ACTION_CLEANUP_TRAP_CACHES</code> environment
variable is deprecated and will be removed in May 2026. If you are
affected by this, we recommend disabling TRAP caching by passing the
<code>trap-caching: false</code> input to the <code>init</code> Action.
<a
href="https://redirect.github.com/github/codeql-action/pull/3795">#3795</a></li>
<li>The Git version 2.36.0 requirement for improved incremental analysis
now only applies to repositories that contain submodules. <a
href="https://redirect.github.com/github/codeql-action/pull/3789">#3789</a></li>
<li>Python analysis on GHES no longer extracts the standard library,
relying instead on models of the standard library. This should result in
significantly faster extraction and analysis times, while the effect on
alerts should be minimal. <a
href="https://redirect.github.com/github/codeql-action/pull/3794">#3794</a></li>
<li>Fixed a bug in the validation of OIDC configurations for private
registries that was added in CodeQL Action 4.33.0 / 3.33.0. <a
href="https://redirect.github.com/github/codeql-action/pull/3807">#3807</a></li>
<li>Update default CodeQL bundle version to <a
href="https://github.com/github/codeql-action/releases/tag/codeql-bundle-v2.25.2">2.25.2</a>.
<a
href="https://redirect.github.com/github/codeql-action/pull/3823">#3823</a></li>
</ul>
<h2>4.35.1 - 27 Mar 2026</h2>
<ul>
<li>Fix incorrect minimum required Git version for <a
href="https://redirect.github.com/github/roadmap/issues/1158">improved
incremental analysis</a>: it should have been 2.36.0, not 2.11.0. <a
href="https://redirect.github.com/github/codeql-action/pull/3781">#3781</a></li>
</ul>
<h2>4.35.0 - 27 Mar 2026</h2>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="87557b9c84"><code>87557b9</code></a>
Merge pull request <a
href="https://redirect.github.com/github/codeql-action/issues/3940">#3940</a>
from github/update-v4.36.1-2a1689ed4</li>
<li><a
href="9431011964"><code>9431011</code></a>
Update changelog for v4.36.1</li>
<li><a
href="2a1689ed43"><code>2a1689e</code></a>
Merge pull request <a
href="https://redirect.github.com/github/codeql-action/issues/3939">#3939</a>
from github/henrymercer/skip-overlay-revert-when-exp...</li>
<li><a
href="524532393a"><code>5245323</code></a>
Disable missing diff-ranges fallback when overlay enabled manually</li>
<li><a
href="d1eb1207b4"><code>d1eb120</code></a>
Merge pull request <a
href="https://redirect.github.com/github/codeql-action/issues/3933">#3933</a>
from github/update-supported-enterprise-server-versions</li>
<li><a
href="115001ba8d"><code>115001b</code></a>
Merge pull request <a
href="https://redirect.github.com/github/codeql-action/issues/3934">#3934</a>
from github/dependabot/npm_and_yarn/npm-minor-86fb5c...</li>
<li><a
href="cef2e7a910"><code>cef2e7a</code></a>
Merge pull request <a
href="https://redirect.github.com/github/codeql-action/issues/3925">#3925</a>
from github/dependabot/github_actions/dot-github/wor...</li>
<li><a
href="5e6adf70ed"><code>5e6adf7</code></a>
Merge pull request <a
href="https://redirect.github.com/github/codeql-action/issues/3936">#3936</a>
from github/dependabot/npm_and_yarn/tmp-0.2.7</li>
<li><a
href="ad170e6c4e"><code>ad170e6</code></a>
Merge branch 'main' into
dependabot/github_actions/dot-github/workflows/actio...</li>
<li><a
href="6a37b3a57a"><code>6a37b3a</code></a>
Rebuild</li>
<li>Additional commits viewable in <a
href="7211b7c807...87557b9c84">compare
view</a></li>
</ul>
</details>
<br />


Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore <dependency name> major version` will close this
group update PR and stop Dependabot creating any more for the specific
dependency's major version (unless you unignore this specific
dependency's major version or upgrade to it yourself)
- `@dependabot ignore <dependency name> minor version` will close this
group update PR and stop Dependabot creating any more for the specific
dependency's minor version (unless you unignore this specific
dependency's minor version or upgrade to it yourself)
- `@dependabot ignore <dependency name>` will close this group update PR
and stop Dependabot creating any more for the specific dependency
(unless you unignore this specific dependency or upgrade to it yourself)
- `@dependabot unignore <dependency name>` will remove all of the ignore
conditions of the specified dependency
- `@dependabot unignore <dependency name> <ignore condition>` will
remove the ignore condition of the specified dependency and ignore
conditions


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-06-03 22:58:42 +02:00
kleinanzeigen-bot-tu[bot]
70f9208302 chore: Update Python dependencies (#1072)
✔ Update pip 26.1.1 -> 26.1.2 successful
  ✔ Update typer 0.26.4 -> 0.26.5 successful

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-06-02 09:02:26 +02:00
Jens
debc517c8a chore: rename fix_nodriver_encoding.py to fix_nodriver.py (#1073)
## ℹ️ Description

The script `fix_nodriver_encoding.py` now applies multiple patches
(encoding fix, flat-mode session retry on `-32601`). The old name was
misleading.

### ⚙️ Type of Change
- [x] 🏗️ Chore / maintenance

##  Checklist
- [x] I have reviewed my changes to ensure they meet the project's
standards.
- [x] I have tested my changes and ensured that all tests pass (`pdm run
test`).
- [x] I have formatted the code (`pdm run format`).
- [x] I have verified that linting passes (`pdm run lint`).
- [x] I have updated documentation where necessary.

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **Chores**
  * Updated build configuration for improved setup process.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-06-02 09:01:52 +02:00
Jens
36f5fc18c1 build: migrate nodriver to upstream 0.50.3 with post-install compat fixes (#1071) 2026-06-01 22:42:58 +02:00
Jens
2b5cccf9c6 refactor: extract local path renaming primitives and orchestrator into domain module (#1069)
## ℹ️ Description

Extract local path renaming logic from `kleinanzeigen_bot/__init__.py`
into a pure domain module `kleinanzeigen_bot/local_path_renaming.py`.

The new module has explicit `__all__`, public operation names, and zero
dependency on `KleinanzeigenBot`. Bot methods are reduced to thin
wrapper adapters that derive config values from `self.config`.

## 📋 Changes Summary

- **New:** `src/kleinanzeigen_bot/local_path_renaming.py` — types,
template-slot replacement, path-rename helpers, file/folder/image
orchestrator functions
- **Modified:** `src/kleinanzeigen_bot/__init__.py` — bot methods
reduced to thin wrappers; coordinator (~30 lines → 6 line adapter)
- **Modified:** `src/kleinanzeigen_bot/resources/translations.de.yaml` —
moved translations for renamed functions
- **New:** `tests/unit/test_local_path_renaming.py` — 22 focused tests
importing directly from the module (no bot construction)
- **Modified:** `tests/unit/test_init.py` — removed moved tests; kept
compat alias verification

### ⚙️ Type of Change
- [x]  Refactor (non-breaking internal restructuring)

##  Checklist
- [x] I have reviewed my changes to ensure they meet the project's
standards.
- [x] I have tested my changes and ensured that all tests pass (`pdm run
test`).
- [x] I have formatted the code (`pdm run format`).
- [x] I have verified that linting passes (`pdm run lint`).
- [x] I have updated documentation where necessary.

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **Refactor**
* Moved local path renaming into a dedicated component; bot now
delegates renames via thin wrappers and re-exports renaming outcomes.
* Added template-based ID matching and safer rename behavior for ad
files, ad folders, and referenced images (avoids overwrites, handles
symlink/collision cases).

* **Tests**
* Expanded unit tests for template matching, collision/symlink handling,
image-reference updates, per-image skip rules, and end-to-end rename
scenarios; init tests adjusted.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-06-01 14:22:09 +02:00
Jens
cd74770e74 ci: use non-interactive apt-get with progress suppression flags (#1070)
## ℹ️ Description
Suppress verbose apt-get progress/color output in CI by making apt-get
invocations explicitly non-interactive with progress suppression flags.

- Link to the related issue(s): Issue #
- Motivation: `apt-get` in non-interactive CI environments produces
noisy progress/color output that clutters logs (see linked run). Using
`DEBIAN_FRONTEND=noninteractive` and the `-o` flags for Progress-Fancy
and Color cleans this up.

## 📋 Changes Summary

- Added `DEBIAN_FRONTEND=noninteractive` env var to `build` and
`publish-release` jobs
- Added `-o Dpkg::Progress-Fancy=0 -o Dpkg::Use-Pty=0 -o
Acquire::Progress-Fancy=0 -o APT::Color=0` flags to all `apt-get
install` commands (chromium, xvfb, binutils, clamav)
- Added `-o Acquire::Progress-Fancy=0 -o APT::Color=0` flags to `apt-get
update` (ClamAV step)
- Added `--no-install-recommends` to the ClamAV install (was missing
previously)

### ⚙️ Type of Change
Select the type(s) of change(s) included in this pull request:
- [x] 🐞 Bug fix (non-breaking change which fixes an issue)
- [ ]  New feature (adds new functionality without breaking existing
usage)
- [ ] 💥 Breaking change (changes that might break existing user setups,
scripts, or configurations)


##  Checklist
Before requesting a review, confirm the following:
- [x] I have reviewed my changes to ensure they meet the project's
standards.
- [x] I have tested my changes and ensured that all tests pass (`pdm run
test`).
- [x] I have formatted the code (`pdm run format`).
- [x] I have verified that linting passes (`pdm run lint`).
- [x] I have updated documentation where necessary.

By submitting this pull request, I confirm that you can use, modify,
copy, and redistribute this contribution, under the terms of your
choice.
2026-06-01 12:50:35 +02:00
Jens
418d9859bc fix(update): include ads with pending auto price reductions in --ads changed (#1067)
## ℹ️ Description

`pdm run app update` (default `--ads changed`) loads 0 ads even when
`verify` shows pending price reductions. Root cause:
`__check_ad_changed()` only compares `content_hash`, but auto price
reduction is time-driven.

- Link to the related issue(s): Issue #1064

## 📋 Changes Summary

- **`price_reduction.py`**: Added `is_auto_price_reduction_due(ad_cfg,
ad_file_relative) -> bool` — evaluates price reduction in MODIFY mode
and returns true when a visible reduction cycle is due
- **`__init__.py` — `load_ads()`**: The `"changed"` selector now also
checks `is_auto_price_reduction_due()` **only during `update` command**
via `self.command` guard — publish is unaffected
- **`translations.de.yaml`**: Added German translation under
`price_reduction.py:is_auto_price_reduction_due`
- **Tests**: 8 new unit tests for `is_auto_price_reduction_due()` (5
mocked + 3 real eligibility with timing) in `test_price_reduction.py`; 3
integration tests in `test_init.py` including regression test for
publish mode exclusion

### ⚙️ Type of Change

- [x] 🐞 Bug fix (non-breaking change which fixes an issue)

##  Checklist

- [x] I have reviewed my changes to ensure they meet the project's
standards.
- [x] I have tested my changes and ensured that all tests pass (`pdm run
test`).
- [x] I have formatted the code (`pdm run format`).
- [x] I have verified that linting passes (`pdm run lint`).
- [x] I have updated documentation where necessary.

Closes #1064

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

## Release Notes

* **New Features**
* Automatic price reductions are now considered when identifying changed
ads during updates. Ads with pending price reductions are included in
the "changed" selection for update operations, regardless of content
modifications.

* **Tests**
* Added comprehensive test coverage for automatic price reduction
due-state detection and update behavior validation.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-05-31 15:13:19 +02:00
Jens
717b493b30 fix(publish): dismiss 'Effektiver verkaufen' upsell dialog after submit click (#1066)
## ℹ️ Description

PostListingForm v2 shows an upsell dialog ("Effektiver verkaufen" — Sell
more effectively) after clicking the submit button on the edit page,
blocking the actual form POST. The bot's confirmation URL polling timed
out because the page never navigated to the confirmation URL, causing
`PublishSubmissionUncertainError` to be raised.

## 📋 Changes Summary

- After clicking the submit button, probe for an open dialog containing
"Effektiver verkaufen"
- If detected, dismiss it by clicking "Ohne Hochschieben weiter" (the
decline/continue-without-upsell button)
- Wait 500ms for the dialog close animation before proceeding with the
normal post-submit flow
- Added German translation for the new log message

### ⚙️ Type of Change
- [x] 🐞 Bug fix (non-breaking change which fixes an issue)

##  Checklist
- [x] I have reviewed my changes to ensure they meet the project's
standards.
- [x] I have tested my changes and ensured that all tests pass (`pdm run
test`).
- [x] I have formatted the code (`pdm run format`).
- [x] I have verified that linting passes (`pdm run lint`).
- [x] I have updated documentation where necessary.

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **Bug Fixes**
* Resolved an issue where promotional dialogs could block the listing
submission process, ensuring smooth and uninterrupted completion of ad
postings.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-05-31 14:08:54 +02:00
kleinanzeigen-bot-tu[bot]
aa8f4a4b54 chore: Update Python dependencies (#1065)
✔ Update typer 0.26.3 -> 0.26.4 successful
  ✔ Update nodejs-wheel-binaries 24.15.0 -> 24.16.0 successful

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-05-31 14:01:39 +02:00
Jens
3faab5cfbd refactor: move AdUpdateStrategy to ad_model and extract price_reduction module (#1063)
## ℹ️ Description

Part of an effort to reduce `__init__.py` from ~4,245 lines by
extracting related logic into standalone modules.

This PR moves `AdUpdateStrategy` to the model layer and extracts all
price reduction functions into a new `price_reduction.py` module.
Root-package re-exports are preserved for full backward compatibility.
Includes a bug fix for null-pointer crashes when an Ad has no
`auto_price_reduction` configuration.

## 📋 Changes Summary

- Add `AdUpdateStrategy` enum to
`src/kleinanzeigen_bot/model/ad_model.py`
- Create `src/kleinanzeigen_bot/price_reduction.py` (526 lines):
`PriceReductionDecision`, `evaluate_auto_price_reduction`,
`apply_auto_price_reduction`, helper functions
- Remove moved code from `__init__.py` (4,245 → 3,778 lines, -467)
- Add re-export imports in `__init__.py` to preserve root-package public
API
- Update `translations.de.yaml` to reflect new module locations
- Add `test_root_re_exports_resolve_correctly` to verify
backward-compatible imports
- 🐞 Fix: add null guard in `evaluate_auto_price_reduction` when
`auto_price_reduction` is `None` on the Ad config (pre-existing bug)
- 🐞 Fix: add null guard in `publish_ad` MODIFY branch before accessing
`ad_cfg.auto_price_reduction.enabled` (pre-existing bug)
- Add regression tests for both `evaluate_auto_price_reduction` and
`apply_auto_price_reduction` with `auto_price_reduction=None`

### ⚙️ Type of Change
- [x] 🐞 Bug fix (non-breaking change which fixes an issue)
- [ ]  New feature (adds new functionality without breaking existing
usage)
- [ ] 💥 Breaking change (changes that might break existing user setups,
scripts, or configurations)

##  Checklist
- [x] I have reviewed my changes to ensure they meet the project's
standards.
- [x] I have tested my changes and ensured that all tests pass (`pdm run
test`).
- [x] I have formatted the code (`pdm run format`).
- [x] I have verified that linting passes (`pdm run lint`).
- [x] I have updated documentation where necessary.

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **New Features**
* Added automatic multi-cycle price-reduction capability to evaluate and
apply ad price adjustments.

* **Bug Fixes**
* Publish flow now safely handles missing auto-price-reduction settings
to prevent update errors.

* **Refactor**
* Price-reduction and ad update strategy logic reorganized into clearer,
focused components while preserving public behavior.

* **Tests**
* Added/updated unit tests for price-reduction behavior,
null-configuration handling, and public API surface.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-05-31 13:22:22 +02:00
Jens
c872621f28 feat: add opt-in local path renaming after ad republish (#1056)
## ℹ️ Description

Closes: Discussion
[#839](https://github.com/Second-Hand-Friends/kleinanzeigen-bot/discussions/839)

When an ad is re-published on Kleinanzeigen, it receives a new ad ID —
but local files and folders still carry the old ID in their names (e.g.
`ad_5195800653_Title/ad_5195800653.yaml`). Over time, file names become
stale and locating ads in the filesystem becomes confusing.

This PR adds an opt-in, conservative path renaming feature that runs
after a successful publish/republish. By default nothing changes
(`OFF`). Users can enable `TEMPLATE_MATCH` mode, which renames only
paths whose names match the structure of their configured download
naming templates — preserving user-edited titles and never touching
manually-named or unrelated files.

## Design decisions

- **Opt-in and backwards-compatible**: default `OFF`; no existing setups
are affected.
- **Config lives under `publishing`** (not `download`): the trigger is a
successful publish with a changed ad ID.
- **Template-derived matching, not full re-render**: `{title}` is
matched as wildcard (preserving user edits and truncation), while only
the numeric ID in the `{id}` slot is replaced. This avoids brittleness
from title changes or truncation drift, and handles the case where a
prior republish already left a stale ID in the path.
- **Uses existing download templates**: `download.folder_name_template`
and `download.ad_file_name_template` serve as provenance hints. Changing
those templates automatically changes which paths qualify for renaming —
no separate renaming config needed.
- **Conservative scope**: only the loaded ad file, its parent folder,
and its referenced images are touched.

## How it works (per ad, after successful publish)

1. **Referenced image files are renamed first**, and the YAML `images`
list is updated with new paths — *before* `content_hash` is recomputed
and the YAML is saved. This ensures the saved file references
actually-existing files and the hash matches.
2. **The ad YAML and containing folder are renamed after saving**, since
the saved file itself may move.
3. **If saving fails, image renames are rolled back** to avoid leaving
the filesystem in an inconsistent state.

## Safety guardrails

| Guardrail | Behavior |
|---|---|
| Name mismatch | Skip — the helper only matches names whose structure
conforms to the configured download templates |
| Target exists (file or symlink) | Skip — never overwrite; log a
warning |
| Absolute image paths | Skip — cannot be safely remapped after a folder
rename |
| Paths outside the ad folder (`../`) | Skip — avoid touching
external/shared files |
| Idempotent (`old_id == new_id`) | Skip — no rename needed |
| Mode `OFF` (default) | Entire feature is a no-op |
| Save failure after image renames | Image renames are rolled back
before re-raising |

## 📋 Changes Summary

### Configuration
- **New**: `publishing.local_path_renaming.mode` (`"OFF"` |
`"TEMPLATE_MATCH"`, default `"OFF"`)
- Description documents the interaction with
`download.folder_name_template` / `download.ad_file_name_template`

### Core logic (`src/kleinanzeigen_bot/__init__.py`)
- `RenameStatus` enum and `RenamePathResult` / `ImageRenameResult` /
`LocalPathRenameResult` dataclasses — structured result types instead of
booleans/tuples
- `_replace_template_id_slot()` — slot-aware regex matcher; replaces
only the `{id}` value, preserves everything else
- `_rename_path_if_target_is_free()` — rename with collision/symlink
safety
- `_rename_local_ad_file_and_folder_after_id_change()` — renames YAML
file and parent folder
- `_rename_referenced_local_image_files_after_id_change()` — renames
image files referenced in `ad_cfg_orig["images"]`, returns updated image
refs without mutating the config dict
- `_log_local_path_rename_result()` — structured summary logging with
translated labels

### Generated artifacts
- `docs/config.default.yaml` — new `publishing.local_path_renaming.mode:
OFF` section
- `schemas/config.schema.json` — updated

### Translations
- German translations added for all new log messages and dynamic labels

### Tests
- Unit tests covering: config validation, template matching (multiple
templates), disabled-by-default, image path updates, unreferenced images
ignored, collision handling, absolute/external paths skipped, broken
symlink collision, save-failure rollback, cross-platform path separators

## ⚙️ Type of Change
- [x]  New feature (adds new functionality without breaking existing
usage)

##  Checklist
- [x] I have reviewed my changes to ensure they meet the project's
standards.
- [x] I have tested my changes and ensured that all tests pass (`pdm run
test` → 1119 passed, 4 skipped).
- [x] I have formatted the code (`pdm run format`).
- [x] I have verified that linting passes (`pdm run lint`).
- [x] I have updated documentation where necessary (generated
artifacts).

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **New Features**
* Template-driven local renaming of ad YAML, containing folder, and
referenced relative images when an ad ID changes; only the {id} portion
is updated, collisions or unsafe targets are skipped, and a
human-readable summary is logged.

* **Configuration**
* New publishing.local_path_renaming option with OFF (default) and
TEMPLATE_MATCH modes to enable template-based renaming.

* **Bug Fixes**
* Image renames are rolled back if saving fails; publish flow ordering
adjusted to ensure consistent local renames.

* **Tests**
* Added unit tests for template matching, id-slot substitution,
image-path updates, collision/symlink safety, and scope rules.

<!-- review_stack_entry_start -->

[![Review Change
Stack](https://storage.googleapis.com/coderabbit_public_assets/review-stack-in-coderabbit-ui.svg)](https://app.coderabbit.ai/change-stack/Second-Hand-Friends/kleinanzeigen-bot/pull/1056?utm_source=github_walkthrough&utm_medium=github&utm_campaign=change_stack)

<!-- review_stack_entry_end -->

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-05-30 22:20:30 +02:00
kleinanzeigen-bot-tu[bot]
0a6ad5a953 chore: Update Python dependencies (#1062)
✔ Update idna 3.16 -> 3.17 successful
  ✔ Update typer 0.26.2 -> 0.26.3 successful
  ✔ Update ruff 0.15.14 -> 0.15.15 successful

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-05-30 22:05:00 +02:00
Jens
ed3b73c3fb feat: resolve login credentials from environment variables (#1061)
## ℹ️ Description

Adds support for `${KLEINANZEIGEN_BOT_USERNAME}` and
`${KLEINANZEIGEN_BOT_PASSWORD}` environment variable substitution in
`login.username` and `login.password` config values. Also supports
`${VAR:-default}` fallback syntax.

This allows users to commit `config.yaml` to VCS without exposing
credentials.

Closes #1060.

## 📋 Changes Summary

- New `_resolve_login_credentials()` static method on `KleinanzeigenBot`
— resolves `${VAR}` and `${VAR:-default}` patterns from `os.environ` for
`login.username` and `login.password` only
- Called in `load_config()` after YAML loading, before Pydantic
validation — `LoginConfig` model remains unchanged (`Field(...,
min_length=1)`)
- Module-level `_LOGIN_ENV_PATTERN` regex for the `${VAR}` /
`${VAR:-default}` pattern
- Guard against non-dict YAML input (passes through to Pydantic for
clean validation errors)
- Updated `README.md` and `docs/CONFIGURATION.md` with env var examples
- Removed obsolete "Config file not found" translation (no longer
raised)
- 9 new unit tests in `TestResolveLoginCredentials` covering resolution,
fallback, error cases, edge cases, and `load_config` integration

### ⚙️ Type of Change
- [x]  New feature (adds new functionality without breaking existing
usage)

##  Checklist
- [x] I have reviewed my changes to ensure they meet the project's
standards.
- [x] I have tested my changes and ensured that all tests pass (`pdm run
test`).
- [x] I have formatted the code (`pdm run format`).
- [x] I have verified that linting passes (`pdm run lint`).
- [x] I have updated documentation where necessary.

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **New Features**
* Login credentials support environment variable substitution using
${VARIABLE} with optional fallbacks (${VARIABLE:-default}); plaintext
values remain supported.

* **Documentation**
* Configuration docs updated with YAML and shell examples (exporting
variables) and an explicit security note advising against committing
plaintext credentials.

<!-- review_stack_entry_start -->

[![Review Change
Stack](https://storage.googleapis.com/coderabbit_public_assets/review-stack-in-coderabbit-ui.svg)](https://app.coderabbit.ai/change-stack/Second-Hand-Friends/kleinanzeigen-bot/pull/1061?utm_source=github_walkthrough&utm_medium=github&utm_campaign=change_stack)

<!-- review_stack_entry_end -->
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-05-29 13:41:40 +02:00
kleinanzeigen-bot-tu[bot]
726d62c3a8 chore: Update Python dependencies (#1058)
✔ Update pytest-asyncio 1.3.0 -> 1.4.0 successful
  ✔ Update platformdirs 4.9.6 -> 4.10.0 successful
  ✔ Update typer 0.25.1 -> 0.26.2 successful
  ✔ Update coverage 7.14.0 -> 7.14.1 successful

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-05-29 11:24:19 +02:00
Torsten Liermann
45b4361b37 fix(publish): accept readonly <input> for ad-city (zip-derived value) (#1059) 2026-05-28 22:27:32 +02:00
dependabot[bot]
ed93d18210 ci(deps): bump github/codeql-action from 4.35.5 to 4.36.0 in the all-actions group (#1057) 2026-05-26 22:58:50 +02:00
Jens
bd60a317c5 refactor: centralize condition normalization (#1055)
## ℹ️ Description
* Centralize `condition_s` normalization before dialog-specific
handling.

- Link to the related issue(s): Fix #1023
- Describe the motivation and context for this change.

## 📋 Changes Summary

- Added a shared `_normalize_condition()` helper and reused it in both
condition code paths.
- Preserved legacy warning behavior and canonical-first radio probing
with legacy fallback.
- Removed a redundant snapshot-style unit test and updated lint
configuration for existing PLW0717 noise.

### ⚙️ Type of Change
Select the type(s) of change(s) included in this pull request:
- [x] 🐞 Bug fix (non-breaking change which fixes an issue)
- [ ]  New feature (adds new functionality without breaking existing
usage)
- [ ] 💥 Breaking change (changes that might break existing user setups,
scripts, or configurations)

##  Checklist
Before requesting a review, confirm the following:
- [x] I have reviewed my changes to ensure they meet the project's
standards.
- [x] I have tested my changes and ensured that all tests pass (`pdm run
test`).
- [x] I have formatted the code (`pdm run format`).
- [x] I have verified that linting passes (`pdm run lint`).
- [x] I have updated documentation where necessary.

By submitting this pull request, I confirm that you can use, modify,
copy, and redistribute this contribution, under the terms of your
choice.

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

## Release Notes

* **Refactor**
* Normalized item condition handling and added deprecation warnings for
legacy condition formats; fallbacks now prefer canonical condition
codes.

* **Bug Fixes**
* Probe/lookup timeouts during condition handling now propagate instead
of being silently skipped.

* **Tests**
* Removed an outdated condition-dialog test and added tests verifying
missing-control warning behavior and timeout propagation.

* **Chores**
  * Updated linting configuration.

<!-- review_stack_entry_start -->

[![Review Change
Stack](https://storage.googleapis.com/coderabbit_public_assets/review-stack-in-coderabbit-ui.svg)](https://app.coderabbit.ai/change-stack/Second-Hand-Friends/kleinanzeigen-bot/pull/1055?utm_source=github_walkthrough&utm_medium=github&utm_campaign=change_stack)

<!-- review_stack_entry_end -->
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-05-24 18:13:18 +02:00
kleinanzeigen-bot-tu[bot]
4b864c345d chore: ✔ Update basedpyright 1.39.5 -> 1.39.6 (#1053)
✔ Update basedpyright 1.39.5 -> 1.39.6 successful

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-05-24 15:21:22 +02:00
Jens
0ea0fd5f0c fix: harden pickup shipping probe (#1054)
## ℹ️ Description
Fixes issue #1003 by distinguishing genuine pickup-only categories from
partially rendered shipping sections.

- Link to the related issue(s): Fix #1003
- Describe the motivation and context for this change.
  - Avoid silently treating a partially loaded page as PICKUP-only.

## 📋 Changes Summary
- Probe `#ad-shipping-enabled-no` first.
- If missing, probe `#ad-shipping-enabled` and only short-circuit when
both are absent.
- Raise a diagnostic `TimeoutError` when the fieldset exists but the
pickup radio is missing.
- Update unit tests and the German translation string.

### ⚙️ Type of Change
- [x] 🐞 Bug fix (non-breaking change which fixes an issue)
- [ ]  New feature (adds new functionality without breaking existing
usage)
- [ ] 💥 Breaking change (changes that might break existing user setups,
scripts, or configurations)

##  Checklist
- [x] I have reviewed my changes to ensure they meet the project's
standards.
- [x] I have tested my changes and ensured that all tests pass (`pdm run
test`).
- [x] I have formatted the code (`pdm run format`).
- [ ] I have verified that linting passes (`pdm run lint`).
- [x] I have updated documentation where necessary.

Note: `pdm run lint` currently reports existing `PLW0717` violations in
this checkout, so CI lint is expected to fail until that separate
cleanup is done.

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **Bug Fixes**
* Improved error handling for PICKUP shipping selection. The bot now
clearly distinguishes between page loading issues and categories without
shipping options, providing better error messages when the page may not
be fully loaded.

<!-- review_stack_entry_start -->

[![Review Change
Stack](https://storage.googleapis.com/coderabbit_public_assets/review-stack-in-coderabbit-ui.svg)](https://app.coderabbit.ai/change-stack/Second-Hand-Friends/kleinanzeigen-bot/pull/1054?utm_source=github_walkthrough&utm_medium=github&utm_campaign=change_stack)

<!-- review_stack_entry_end -->

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-05-24 14:47:33 +02:00
kleinanzeigen-bot-tu[bot]
d9a4d22f2d chore: Update Python dependencies (#1052)
✔ Update idna 3.15 -> 3.16 successful
  ✔ Update pytest-rerunfailures 16.2 -> 16.3 successful
  ✔ Update more-itertools 11.0.2 -> 11.1.0 successful
  ✔ Update click 8.4.0 -> 8.4.1 successful
  ✔ Update wrapt 2.1.2 -> 2.2.1 successful
  ✔ Update ruff 0.15.13 -> 0.15.14 successful

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-05-23 21:51:07 +02:00
kleinanzeigen-bot-tu[bot]
4c2161546c chore: ✔ Update certifi 2026.4.22 -> 2026.5.20 (#1051)
✔ Update certifi 2026.4.22 -> 2026.5.20 successful

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-05-20 22:00:22 +02:00
dependabot[bot]
6d7a55fa20 ci(deps): bump the all-actions group with 4 updates (#1050) 2026-05-19 22:15:22 +02:00
kleinanzeigen-bot-tu[bot]
1f57b0ce5d chore: Update Python dependencies (#1049) 2026-05-18 16:08:32 +02:00
Jens
2a7f091d45 fix: compare preview release notes against latest (#1048)
## ℹ️ Description
*Ensure preview releases generate changelog notes against the last
stable latest release instead of the previous preview release.*

- Link to the related issue(s): N/A
- Describe the motivation and context for this change.

## 📋 Changes Summary

- Adjust release note generation in the publish workflow.
- Preview releases now set `previous_tag_name=latest` when calling
GitHub release notes generation.
- Verified with a local `gh api` dry-run that preview notes include
concrete changelog entries.

### ⚙️ Type of Change
Select the type(s) of change(s) included in this pull request:
- [x] 🐞 Bug fix (non-breaking change which fixes an issue)
- [ ]  New feature (adds new functionality without breaking existing
usage)
- [ ] 💥 Breaking change (changes that might break existing user setups,
scripts, or configurations)

##  Checklist
Before requesting a review, confirm the following:
- [x] I have reviewed my changes to ensure they meet the project's
standards.
- [x] I have tested my changes and ensured that all tests pass (`pdm run
test`).
- [x] I have formatted the code (`pdm run format`).
- [x] I have verified that linting passes (`pdm run lint`).
- [x] I have updated documentation where necessary.

Dry-run verification:
- `gh api .../releases/generate-notes` with `previous_tag_name=latest`
returned concrete preview changelog entries.

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **Chores**
* Improved release notes generation to correctly reference the
appropriate previous release version based on release type (latest vs.
preview).

<!-- review_stack_entry_start -->

[![Review Change
Stack](https://storage.googleapis.com/coderabbit_public_assets/review-stack-in-coderabbit-ui.svg)](https://app.coderabbit.ai/change-stack/Second-Hand-Friends/kleinanzeigen-bot/pull/1048?utm_source=github_walkthrough&utm_medium=github&utm_campaign=change_stack)

<!-- review_stack_entry_end -->

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-05-16 21:51:22 +02:00
kleinanzeigen-bot-tu[bot]
f9e3bf0ddf chore: ✔ Update jaraco-functools 4.4.0 -> 4.5.0 (#1047)
✔ Update jaraco-functools 4.4.0 -> 4.5.0 successful

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-05-16 13:36:07 +02:00
kleinanzeigen-bot-tu[bot]
f5d8814966 chore: Update Python dependencies (#1046)
✔ Update requests 2.34.1 -> 2.34.2 successful
  ✔ Update ast-serialize 0.3.0 -> 0.4.0 successful
  ✔ Update ruff 0.15.12 -> 0.15.13 successful

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-05-15 14:22:01 +02:00
kleinanzeigen-bot-tu[bot]
cf243ce4e8 chore: ✔ Update requests 2.34.0 -> 2.34.1 (#1045) 2026-05-15 11:52:26 +02:00
kleinanzeigen-bot-tu[bot]
641eb40fb1 chore: Update Python dependencies (#1043)
✔ Update pytest-rerunfailures 16.1 -> 16.2 successful
  ✔ Update idna 3.14 -> 3.15 successful
  ✔ Update types-requests 2.33.0.20260508 -> 2.33.0.20260513 successful

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-05-13 14:37:35 +02:00
Jens
0f2581171b fix: streamline download selector handling (#1042)
## ℹ️ Description
- Link to the related issue(s): N/A
- Reduce long-wait DOM lookups in the download flow while keeping
optional selectors handled safely.

## 📋 Changes Summary
- Use probe-style lookups for optional download-flow elements and keep
the gallery selector on the probe path.
- Centralize the creation-date selector constant and update the
corresponding extraction test.
- Refresh unit coverage for the updated download extraction behavior.

### ⚙️ Type of Change
- [x] 🐞 Bug fix (non-breaking change which fixes an issue)
- [ ]  New feature (adds new functionality without breaking existing
usage)
- [ ] 💥 Breaking change (changes that might break existing user setups,
scripts, or configurations)

##  Checklist
- [x] I have reviewed my changes to ensure they meet the project's
standards.
- [x] I have tested my changes and ensured that all tests pass (`pdm run
test`).
- [x] I have formatted the code (`pdm run format`).
- [x] I have verified that linting passes (`pdm run lint`).
- [x] I have updated documentation where necessary.

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

## Release Notes

* **Bug Fixes**
* Increased reliability of ad metadata extraction, including creation
dates and contact details.
* Enhanced error handling and messaging when ad images are unavailable.
  * Streamlined ad navigation popup handling.

* **Tests**
  * Added test coverage for creation date extraction validation.
  * Updated tests to verify improved ad data extraction robustness.

<!-- review_stack_entry_start -->

[![Review Change
Stack](https://storage.googleapis.com/coderabbit_public_assets/review-stack-in-coderabbit-ui.svg)](https://app.coderabbit.ai/change-stack/Second-Hand-Friends/kleinanzeigen-bot/pull/1042)

<!-- review_stack_entry_end -->

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-05-13 10:50:42 +02:00
kleinanzeigen-bot-tu[bot]
59d5d594ff chore: ✔ Update requests 2.33.1 -> 2.34.0 (#1041)
✔ Update requests 2.33.1 -> 2.34.0 successful

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-05-12 21:37:25 +02:00
dependabot[bot]
8490d9c6ab ci(deps): bump github/codeql-action from 4.35.3 to 4.35.4 in the all-actions group (#1039) 2026-05-12 06:57:00 +02:00
Jens
1b1c939162 fix: warn and continue when optional publish controls are missing (#1038)
## ℹ️ Description
This change makes publishing tolerant of optional Kleinanzeigen controls
that are not rendered for some categories.

- Link to the related issue(s): #1034
- Motivation and context: categories can omit controls like
`condition_s` or the `sell_directly` toggle entirely, and the bot
currently treats that as a hard publish failure. That forces users to
remove otherwise valid config values just to post an ad. This update
keeps real interaction failures strict, but skips only the
missing-control case so valid ads can still be published.

## 📋 Changes Summary
- Warn and continue when `condition_s` is not rendered for a category.
- Warn and continue when `sell_directly` is requested but
`ad-buy-now-true` is unavailable.
- Add German translations and regression tests for both paths.

### ⚙️ Type of Change
Select the type(s) of change(s) included in this pull request:
- [x] 🐞 Bug fix (non-breaking change which fixes an issue)
- [ ]  New feature (adds new functionality without breaking existing
usage)
- [ ] 💥 Breaking change (changes that might break existing user setups,
scripts, or configurations)

##  Checklist
Before requesting a review, confirm the following:
- [x] I have reviewed my changes to ensure they meet the project's
standards.
- [x] I have tested my changes and ensured that all tests pass (`pdm run
test`).
- [x] I have formatted the code (`pdm run format`).
- [x] I have verified that linting passes (`pdm run lint`).
- [ ] I have updated documentation where necessary.

Closes #1034

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **Bug Fixes**
* Publishing now skips unavailable buy-now/direct-buy controls and logs
a warning instead of failing; genuine timeouts still propagate.
* Special attribute (condition) fields that are missing are logged and
skipped so publishing can continue.

* **Tests**
* Updated/added tests covering missing attribute controls, buy-now
warning behavior and timeout propagation, and consolidated
price-reduction persistence checks.

[![Review Change
Stack](https://storage.googleapis.com/coderabbit_public_assets/review-stack-in-coderabbit-ui.svg)](https://app.coderabbit.ai/change-stack/Second-Hand-Friends/kleinanzeigen-bot/pull/1038)
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-05-11 23:11:59 +02:00
Jens
bbbf1d0f2b chore: pin nodriver to GitHub fork (#1035)
## ℹ️ Description
*Replace the PyPI-pinned nodriver dependency with a GitHub-only fork
pinned to a commit SHA.*

- Link to the related issue(s): #1033
- Motivation:
  - Upstream has no update for issue.
  - Upstream still has UTF-8 issues.
- There is no practical way to coordinate changes upstream because of
the non-contributor policy (no issues/PRs from non-contributors).
- Fixing UTF-8 handling and keeping CDP mappings current is easy in a
custom fork.
- We can switch back to upstream once it ships an update that addresses
these issues.
- Tracking of this temporary change is done in #1036  

## 📋 Changes Summary

- Updated the nodriver dependency in `pyproject.toml` to a GitHub direct
reference pinned to commit `c465695769a0e99d9154b90e61c521d593732789`.
- Regenerated `pdm.lock` for the new VCS dependency.
- Updated a nodriver source comment to point at the fork repository.

### ⚙️ Type of Change
Select the type(s) of change(s) included in this pull request:
- [x] 🐞 Bug fix (non-breaking change which fixes an issue)
- [ ]  New feature (adds new functionality without breaking existing
usage)
- [ ] 💥 Breaking change (changes that might break existing user setups,
scripts, or configurations)

##  Checklist
Before requesting a review, confirm the following:
- [x] I have reviewed my changes to ensure they meet the project's
standards.
- [x] I have tested my changes and ensured that all tests pass (`pdm run
test`).
- [x] I have formatted the code (`pdm run format`).
- [x] I have verified that linting passes (`pdm run lint`).
- [x] I have updated documentation where necessary.

By submitting this pull request, I confirm that you can use, modify,
copy, and redistribute this contribution, under the terms of your
choice.

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **Chores**
* Updated browser automation dependency to use a specific fork version
for improved web scraping compatibility.

[![Review Change
Stack](https://storage.googleapis.com/coderabbit_public_assets/review-stack-in-coderabbit-ui.svg)](https://app.coderabbit.ai/change-stack/Second-Hand-Friends/kleinanzeigen-bot/pull/1035)

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-05-11 21:35:04 +02:00
kleinanzeigen-bot-tu[bot]
d252fa5d92 chore: Update Python dependencies (#1037)
✔ Update idna 3.13 -> 3.14 successful
  ✔ Update librt 0.10.0 -> 0.11.0 successful
  ✔ Update coverage 7.13.5 -> 7.14.0 successful
  ✔ Update basedpyright 1.39.3 -> 1.39.4 successful

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-05-11 21:02:28 +02:00
kleinanzeigen-bot-tu[bot]
6ac8c88013 chore: Update Python dependencies (#1032) 2026-05-08 19:45:07 +02:00
kleinanzeigen-bot-tu[bot]
0569e36f73 chore: Update Python dependencies (#1031) 2026-05-08 06:33:56 +02:00
kleinanzeigen-bot-tu[bot]
6493992eb1 chore: Update Python dependencies (#1030) 2026-05-05 15:12:04 +02:00