diff --git a/.editorconfig b/.editorconfig index 31447bf17..a182e3b56 100644 --- a/.editorconfig +++ b/.editorconfig @@ -7,6 +7,7 @@ charset = utf-8 trim_trailing_whitespace = true insert_final_newline = true end_of_line = lf +quote_type = single [Makefile] indent_style = tab diff --git a/.github/workflows/_checks.yaml b/.github/workflows/_checks.yaml index b6fec131d..9fb709aff 100644 --- a/.github/workflows/_checks.yaml +++ b/.github/workflows/_checks.yaml @@ -15,6 +15,9 @@ on: permissions: contents: read +env: + NODE_VERSION: 24 + jobs: actions_lint_check: name: Actions lint check @@ -46,6 +49,86 @@ jobs: with: python_versions: '["3.11", "3.12", "3.13", "3.14"]' + markdown_lint_check: + name: Markdown lint check + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@v7 + + - name: Set up Node + uses: actions/setup-node@v6 + with: + node-version: ${{ env.NODE_VERSION }} + + - name: Install pnpm and website dependencies + uses: apify/actions/pnpm-install@v1.2.0 + with: + working-directory: website + + - name: Lint Markdown + run: pnpm lint:md + working-directory: website + + website_lint_check: + name: Website lint check + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@v7 + + - name: Set up Node + uses: actions/setup-node@v6 + with: + node-version: ${{ env.NODE_VERSION }} + + - name: Install pnpm and website dependencies + uses: apify/actions/pnpm-install@v1.2.0 + with: + working-directory: website + + - name: Lint website code + run: pnpm lint:code + working-directory: website + + - name: Check website formatting + run: pnpm format:check + working-directory: website + + image_lint_check: + name: Image lint check + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@v7 + with: + fetch-depth: 0 + + # Doc images must be committed as optimized `.webp`. This fails when a PR adds raster + # images in another format so they get converted via `pnpm opt:images` first. + - name: Get changed unoptimized images + id: changed-files + uses: tj-actions/changed-files@v47 + with: + files: | + docs/**/*.{png,jpg,jpeg,gif,bmp,tif,tiff,avif} + website/static/**/*.{png,jpg,jpeg,gif,bmp,tif,tiff,avif} + separator: "\n" + + - name: Fail on unoptimized images + if: steps.changed-files.outputs.any_changed == 'true' + env: + UNOPTIMIZED_IMAGE_FILES: ${{ steps.changed-files.outputs.all_changed_files }} + run: | + echo "Unoptimized images detected! Convert each one to WebP, e.g.:" + echo "" + while IFS= read -r file_path; do + echo " (cd website && pnpm opt:images \"../$file_path\")" + done <<< "$UNOPTIMIZED_IMAGE_FILES" + echo "" + echo "Then reference the resulting .webp files in your Markdown." + exit 1 + unit_tests: name: Unit tests if: inputs.run_tests diff --git a/.github/workflows/manual_release_docs.yaml b/.github/workflows/manual_release_docs.yaml index f2a4d8f40..badaaaec6 100644 --- a/.github/workflows/manual_release_docs.yaml +++ b/.github/workflows/manual_release_docs.yaml @@ -23,7 +23,7 @@ permissions: contents: read env: - NODE_VERSION: 22 + NODE_VERSION: 24 PYTHON_VERSION: 3.14 jobs: diff --git a/.github/workflows/manual_version_docs.yaml b/.github/workflows/manual_version_docs.yaml index c5843c3d4..32b3b5c4a 100644 --- a/.github/workflows/manual_version_docs.yaml +++ b/.github/workflows/manual_version_docs.yaml @@ -27,7 +27,7 @@ permissions: contents: read env: - NODE_VERSION: "22" + NODE_VERSION: "24" PYTHON_VERSION: "3.14" jobs: diff --git a/.markdownlint.yaml b/.markdownlint.yaml index 01c2c62fa..0c492ccd2 100644 --- a/.markdownlint.yaml +++ b/.markdownlint.yaml @@ -1,5 +1,30 @@ +# markdownlint config for the docs and top-level Markdown files. +# Run via `pnpm lint:md` / `pnpm lint:md:fix` from the `website/` directory. default: true -line-length: - line_length: 150 -ul-style: dash + +# Prose is written one sentence per line, so line length is not enforced. +line-length: false + +ul-style: + style: dash + +# Nested unordered lists use 4-space indentation. +ul-indent: + indent: 4 + +# Docs are MDX and embed JSX components. no-inline-html: false + +# MDX pages set their title via front matter, so multiple/duplicate H1s are fine. +single-title: false +no-duplicate-heading: + siblings_only: true + +# Anchor links into other pages can't be validated locally. +link-fragments: false + +no-bare-urls: false +no-trailing-punctuation: + punctuation: ".,;:。,;:" +no-multiple-blanks: + maximum: 2 diff --git a/.rules.md b/.rules.md index 91ac6d6af..a6834c021 100644 --- a/.rules.md +++ b/.rules.md @@ -52,12 +52,12 @@ uv run poe e2e-tests - Unused imports are allowed in `__init__.py` files (re-exports) - **Pre-commit hooks**: lint check + type check run automatically on commit - **Commits**: [Conventional Commits](https://www.conventionalcommits.org/) format. Choose the type based on *what* changed, not just *why*: - - `feat:` / `fix:` / `perf:` / `refactor:` / `style:` — **source code only**; these trigger a release and appear in the changelog - - `test:` — test additions or changes (no release triggered) - - `docs:` — documentation changes; also triggers a doc release on master - - `ci:` — CI/workflow changes - - `chore:` — dependency bumps, tooling, and other housekeeping - - `build:` — build system changes + - `feat:` / `fix:` / `perf:` / `refactor:` / `style:` — **source code only**; these trigger a release and appear in the changelog + - `test:` — test additions or changes (no release triggered) + - `docs:` — documentation changes; also triggers a doc release on master + - `ci:` — CI/workflow changes + - `chore:` — dependency bumps, tooling, and other housekeeping + - `build:` — build system changes ## Architecture diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index cbcaa8b21..8651363d7 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -118,6 +118,22 @@ To run the documentation locally (requires Node.js): uv run poe run-docs ``` +### Linting the docs and website + +Markdown content (this guide, `README.md`, and the `docs/` folder) is checked with +[markdownlint](https://github.com/DavidAnson/markdownlint). The Docusaurus website code is linted +with [oxlint](https://oxc.rs/) and formatted with [oxfmt](https://oxc.rs/). All of them run in CI. +To run them locally (requires Node.js 22.12 or newer and pnpm), from the `website/` directory: + +```sh +pnpm lint # lint Markdown and website code +pnpm lint:fix # auto-fix both +pnpm format # format the website code +``` + +Doc images are committed as optimized `.webp`. To convert a new image, run +`pnpm opt:images ` from the `website/` directory. + ## Commits We use [Conventional Commits](https://www.conventionalcommits.org/) format for commit messages. This convention is used to automatically determine version bumps during the release process. @@ -149,25 +165,22 @@ Publishing new versions to [PyPI](https://pypi.org/project/apify) is automated t 1. **Do not do this unless absolutely necessary.** In all conceivable scenarios, you should use the `release` workflow instead. 2. **Make sure you know what you're doing.** +3. Update the version number by modifying the `version` field under `project` in `pyproject.toml`: -3. Update the version number: - -- Modify the `version` field under `project` in `pyproject.toml`. - -```toml -[project] -name = "apify" -version = "x.z.y" -``` + ```toml + [project] + name = "apify" + version = "x.z.y" + ``` 4. Build the package: -```sh -uv run poe build -``` + ```sh + uv run poe build + ``` 5. Upload to PyPI: -```sh -uv publish --token YOUR_API_TOKEN -``` + ```sh + uv publish --token YOUR_API_TOKEN + ``` diff --git a/README.md b/README.md index 56f78840e..b9c9ea55e 100644 --- a/README.md +++ b/README.md @@ -195,7 +195,7 @@ async def main() -> None: The full SDK documentation lives at **[docs.apify.com/sdk/python](https://docs.apify.com/sdk/python)**. For the Apify platform itself, see the [Apify documentation](https://docs.apify.com/). | Section | What you'll find | -|---|---| +| --- | --- | | [Overview](https://docs.apify.com/sdk/python/docs/overview) | What the SDK is, what Actors are, and how the pieces fit together. | | [Quick start](https://docs.apify.com/sdk/python/docs/quick-start) | Create, run, and deploy your first Python Actor. | | [Concepts](https://docs.apify.com/sdk/python/docs/concepts/actor-lifecycle) | Actor lifecycle, input, storages, events, proxy management, interacting with other Actors, webhooks, accessing the Apify API, logging, configuration, and pay-per-event. | diff --git a/docs/02_concepts/09_logging.mdx b/docs/02_concepts/09_logging.mdx index cc0b519f1..a953a3b05 100644 --- a/docs/02_concepts/09_logging.mdx +++ b/docs/02_concepts/09_logging.mdx @@ -53,7 +53,6 @@ You can use the `extra` argument for all log levels, it's not specific to the wa Result: -