From 76b2765dbe50490d8c9973cd59d1c1bfdfab494a Mon Sep 17 00:00:00 2001 From: Alexander Dokuchaev Date: Tue, 27 Feb 2024 02:10:54 +0200 Subject: [PATCH] init --- .github/workflows/validation.yml | 20 +++++++++++--------- README.md | 23 +++++++++++++++++------ action.yaml | 27 +++++++++++++++++++++++++++ md_dead_link_check/config.py | 3 ++- md_dead_link_check/link_checker.py | 18 ++++++++++++++---- 5 files changed, 71 insertions(+), 20 deletions(-) create mode 100644 action.yaml diff --git a/.github/workflows/validation.yml b/.github/workflows/validation.yml index 68746ed..804a4bc 100644 --- a/.github/workflows/validation.yml +++ b/.github/workflows/validation.yml @@ -2,7 +2,8 @@ name: Validation on: push: - branches: [main] + branches: + - '*' pull_request: types: - opened @@ -14,32 +15,33 @@ jobs: runs-on: ubuntu-22.04 steps: - uses: actions/checkout@v4 - - uses: actions/setup-python@v4 with: python-version: "3.10" - - name: Install pre-commit run: pip install pre-commit==3.2.2 - - name: Run pre-commit run: pre-commit run -a pytest: + runs-on: ubuntu-22.04 strategy: matrix: python-version: ["3.8", "3.9", "3.10", "3.11", "3.12"] - runs-on: ubuntu-22.04 - steps: - uses: actions/checkout@v4 - - uses: actions/setup-python@v4 with: python-version: ${{ matrix.python-version }} - - name: Install package run: pip install .[dev] - - name: Pytest run: pytest tests -rfs -vv + + md-dead-link-check: + runs-on: ubuntu-22.04 + steps: + - uses: actions/checkout@v4 + - uses: AlexanderDokuchaev/md-dead-link-check@gha + with: + config: pyproject.toml1 diff --git a/README.md b/README.md index 47de274..15f35b7 100644 --- a/README.md +++ b/README.md @@ -22,11 +22,15 @@ File: tests/test_md_files/fail.md:13 • Link: a.md#fail • Error: Not found fr ## Usage -### From pip +### Github action -```bash -pip install md-dead-link-check -md-dead-link-check +```yaml +jobs: + md-dead-link-check: + runs-on: ubuntu-22.04 + steps: + - uses: actions/checkout@v4 + - uses: AlexanderDokuchaev/md-dead-link-check@main ``` ### Pre-commit hook @@ -35,12 +39,19 @@ Adding to your .pre-commit-config.yaml ```yaml - repo: https://github.com/AlexanderDokuchaev/md-dead-link-check - rev: v0.1.0 + rev: main hooks: - id: md-dead-link-check ``` -### From github repo +### Install rom pip + +```bash +pip install md-dead-link-check +md-dead-link-check +``` + +### Install github repo ```bash git clone https://github.com/AlexanderDokuchaev/md-dead-link-check diff --git a/action.yaml b/action.yaml new file mode 100644 index 0000000..e079db5 --- /dev/null +++ b/action.yaml @@ -0,0 +1,27 @@ +name: 'Markdown dead link checker GitHub Action' +description: 'A GitHub Action to help you keep your Markdown files free of broken links!' +branding: + icon: 'external-link' + color: 'blue' + +inputs: + config: + description: 'Config toml file' + required: false + default: 'pyproject.toml' + +runs: + using: 'composite' + steps: + - name: Install Python + uses: actions/setup-python@v4 + with: + python-version: '3.10' + + - name: Install md-dead-link-check + run: pip install md-dead-link-check==0.1 + shell: bash + + - name: Fetch the number's square + run: md-dead-link-check --config=${{ inputs.config }} + shell: bash diff --git a/md_dead_link_check/config.py b/md_dead_link_check/config.py index 6a1d0ee..b167099 100644 --- a/md_dead_link_check/config.py +++ b/md_dead_link_check/config.py @@ -31,6 +31,7 @@ def get_config(root_dir: Path, config_path: Optional[Path]) -> Config: setattr(config, key, value) else: raise ConnectionError( - f"Unexpected config key `{key}` in pyproject.toml. Available keys: [{', '.join(config.__annotations__)}]" + f"Unexpected config key `{key}` in {config_path.name}. " + f"Available keys: [{', '.join(config.__annotations__)}]" ) return config diff --git a/md_dead_link_check/link_checker.py b/md_dead_link_check/link_checker.py index 74d5996..2c46fad 100644 --- a/md_dead_link_check/link_checker.py +++ b/md_dead_link_check/link_checker.py @@ -31,6 +31,9 @@ def __lt__(self, other: StatusInfo) -> bool: def get_proxies(env: Mapping[str, Any]) -> Dict[str, Optional[str]]: + """ + Find proxies in environment. + """ return { "http": env.get("http_proxy", env.get("HTTP_PROXY")), "https": env.get("https_proxy", env.get("HTTPS_PROXY")), @@ -38,6 +41,9 @@ def get_proxies(env: Mapping[str, Any]) -> Dict[str, Optional[str]]: def select_proxy(url: str, proxies: Dict[str, Optional[str]]) -> Optional[str]: + """ + Select proxy setting by type by suffix of url. + """ if url.startswith("https://"): proxy = proxies.get("https") else: @@ -48,6 +54,11 @@ def select_proxy(url: str, proxies: Dict[str, Optional[str]]) -> Optional[str]: async def process_link( link_info: LinkInfo, session: ClientSession, proxies: Dict[str, Optional[str]], timeout: int ) -> StatusInfo: + """ + Asynchronously processes a link to check its status and gather information. + Timeout is not interpolated as error, because timeout often occur due to temporary server issues and + retrying the request might be more appropriate than treating it as an immediate failure. + """ try: proxy = select_proxy(link_info.link, proxies) headers = {"User-Agent": "Mozilla/5.0"} @@ -72,7 +83,7 @@ async def async_check_links(links: list[LinkInfo], config: Config) -> List[Statu proxies = get_proxies(os.environ) async with ClientSession() as session: ret = await asyncio.gather(*[process_link(li, session, proxies, config.timeout) for li in links]) - return sorted(ret) + return ret def check_web_links(md_data: Dict[str, MarkdownInfo], config: Config, files: List[str]) -> List[StatusInfo]: @@ -125,7 +136,6 @@ def check_path_links(md_data: Dict[str, MarkdownInfo], root_dir: Path, config: C if res_path.as_posix() not in md_data: if not abs_path.exists(): - # check not md file ret.append(StatusInfo(md_link, "Path does not exist")) continue @@ -133,7 +143,7 @@ def check_path_links(md_data: Dict[str, MarkdownInfo], root_dir: Path, config: C ret.append(StatusInfo(md_link, "Not found fragment")) continue ret.append(StatusInfo(md_link, None)) - return sorted(ret) + return ret def check_all_links( @@ -143,4 +153,4 @@ def check_all_links( if config.check_web_links: status_list.extend(check_web_links(md_data, config, files)) status_list.extend(check_path_links(md_data, root_dir, config)) - return status_list + return sorted(status_list)