name: Link Checker on: push: branches: [ edge ] pull_request: branches: [ edge ] schedule: - cron: '30 12 1 * *' workflow_dispatch: permissions: contents: read concurrency: group: link-checker-${{ github.ref }} cancel-in-progress: false jobs: linkChecker: name: linkChecker runs-on: ubuntu-26.04 steps: - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: persist-credentials: false fetch-depth: 0 # Check local links across the repository first to catch broken links in # files that are not part of the PR's changed files. - name: Check local links (offline run) if: github.event_name == 'pull_request' uses: lycheeverse/lychee-action@e7477775783ea5526144ba13e8db5eec57747ce8 # v2.9.0 with: fail: true failIfEmpty: false args: > --offline . - name: Get changed files if: github.event_name == 'pull_request' env: BASE_SHA: ${{ github.event.pull_request.base.sha }} HEAD_SHA: ${{ github.event.pull_request.head.sha }} run: | git diff --name-only --diff-filter=ACMR \ "$BASE_SHA" \ "$HEAD_SHA" \ > changed-files.txt # Lychee does not apply `extensions` from the config to files passed via `--files-from`. # Filter the changed files so only allowed file types are checked. python3 <<'PY' import pathlib import tomllib with open("lychee.toml", "rb") as fp: config = tomllib.load(fp) extensions = {e.lstrip(".").lower() for e in config["extensions"]} files = pathlib.Path("changed-files.txt").read_text().splitlines() files = [ f for f in files if ( pathlib.PurePath(f).suffix.lstrip(".").lower() in extensions or ( not pathlib.PurePath(f).suffix and pathlib.PurePath(f).name.startswith(".") and pathlib.PurePath(f).name.lstrip(".").lower() in extensions ) or ( not pathlib.PurePath(f).suffix and not pathlib.PurePath(f).name.startswith(".") and config.get("default_extension") in extensions ) ) ] pathlib.Path("changed-files.txt").write_text( "\n".join(files) + ("\n" if files else "") ) PY - name: Restore lychee cache id: restore-cache uses: actions/cache/restore@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0 with: path: .lycheecache key: cache-lychee-${{ github.sha }} restore-keys: cache-lychee- - name: Run lychee uses: lycheeverse/lychee-action@e7477775783ea5526144ba13e8db5eec57747ce8 # v2.9.0 with: # PAT with read-only permissions used to avoid GitHub rate limits (allows 5,000 requests per hour) # Won't be available to forks in pull requests due to restrictions, so falls back to default # GITHUB_TOKEN with 1,000 requests per hour instead. token: ${{ secrets.LYCHEE_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} fail: true failIfEmpty: false # Avoid failing in PRs with no links in changed files (`true` is the default) # Config is loaded from lychee.toml args: > ${{ github.event_name == 'pull_request' && '--files-from changed-files.txt' || '.' }} - name: Save lychee cache uses: actions/cache/save@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0 if: always() with: path: .lycheecache key: ${{ steps.restore-cache.outputs.cache-primary-key }}