Skip to content

Release v4.10.0

Release v4.10.0 #5433

Workflow file for this run

---
name: Lint
"on":
workflow_call:
push:
branches:
- main
pull_request:
concurrency:
# Group workflow jobs so new commits cancels in-progress execution triggered by previous commits.
# Source: https://mail.python.org/archives/list/[email protected]/thread/PCBCQMJF64JGRBOX7E2EE4YLKHT4DI55/
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.sha }}
cancel-in-progress: true
jobs:
project-metadata:
name: Project metadata
runs-on: ubuntu-24.04
outputs:
python_files: ${{ steps.project-metadata.outputs.python_files }}
is_python_project: ${{ steps.project-metadata.outputs.is_python_project }}
mypy_params: ${{ steps.project-metadata.outputs.mypy_params }}
steps:
- uses: actions/[email protected]
with:
# Checkout pull request HEAD commit to ignore actions/checkout's merge commit. Fallback to push SHA.
ref: ${{ github.event.pull_request.head.sha || github.sha }}
# We're going to browse all new commits.
fetch-depth: 0
- name: Install uv
run: |
python -m pip install -r https://raw.githubusercontent.com/kdeldycke/workflows/main/requirements/uv.txt
- name: Run gha-utils metadata
id: project-metadata
env:
GITHUB_CONTEXT: ${{ toJSON(github) }}
run: >
uvx
--with-requirements https://raw.githubusercontent.com/kdeldycke/workflows/main/requirements/gha-utils.txt
--
gha-utils --verbosity DEBUG metadata --overwrite "$GITHUB_OUTPUT"
mypy-lint:
needs:
- project-metadata
# Skip linting on prepare-release branch as it points to a tagged URL that does not exist yet.
if: github.head_ref != 'prepare-release' && needs.project-metadata.outputs.python_files
runs-on: ubuntu-24.04
steps:
- uses: actions/[email protected]
- name: Install uv
run: |
python -m pip install -r https://raw.githubusercontent.com/kdeldycke/workflows/main/requirements/uv.txt
- name: Install Mypy
run: |
uv --no-progress venv --python 3.13
uv --no-progress pip install \
--requirement https://raw.githubusercontent.com/kdeldycke/workflows/main/requirements/mypy.txt
- name: Install package
# Use --inexact so that uv doesn't try to remove the mypy package installed above.
run: |
uv --no-progress sync --frozen --all-extras --inexact
- name: Run Mypy
# --color-output - Force colorized output as in CI, Mypy defaults to no color in CI.
run: >
uv --no-progress run --frozen -- mypy --color-output ${{ needs.project-metadata.outputs.mypy_params }}
${{ needs.project-metadata.outputs.python_files }}
lint-yaml:
# Skip linting on prepare-release branch as it points to a tagged URL that does not exist yet.
if: github.head_ref != 'prepare-release'
runs-on: ubuntu-24.04
steps:
- uses: actions/[email protected]
- name: Install uv
run: |
python -m pip install -r https://raw.githubusercontent.com/kdeldycke/workflows/main/requirements/uv.txt
- name: Install yamllint
run: >
uv tool install --with-requirements
https://raw.githubusercontent.com/kdeldycke/workflows/main/requirements/yamllint.txt yamllint
- name: Run yamllint
run: |
yamllint --strict --config-data "{rules: {line-length: {max: 120}}}" --format github .
lint-zsh:
runs-on: ubuntu-24.04
steps:
- uses: actions/[email protected]
- name: Install Zsh
run: |
sudo apt update
sudo apt install --yes zsh
- name: Lint
run: |
find . -iname "*.sh" -exec zsh --no-exec "{}" \;
lint-github-action:
runs-on: ubuntu-24.04
steps:
- uses: actions/[email protected]
- name: Install actionlint
id: install_actionlint
run: |
bash <(curl https://raw.githubusercontent.com/rhysd/actionlint/main/scripts/download-actionlint.bash)
- name: Install shellcheck
run: |
sudo apt update
sudo apt install --yes shellcheck
- name: Install problem matcher
# Source: https://github.com/rhysd/actionlint/blob/main/docs/usage.md#problem-matchers
run: >
curl -fsSL --output ./.github/labeller-file-based.yaml
https://raw.githubusercontent.com/rhysd/actionlint/main/.github/actionlint-matcher.json
- name: Register problem matcher
run: |
echo "::add-matcher::.github/labeller-file-based.yaml"
- name: Run actionlint
# XXX actionlint triggers this error:
# Error: .github/workflows/release.yaml:198:27:
# property "workflow_update_github_pat" is not defined in object type {actions_runner_debug: string;
# actions_step_debug: string; github_token: string; pypi_token: string} [expression]
# See: https://github.com/rhysd/actionlint/issues/148
run: >
${{ steps.install_actionlint.outputs.executable }}
-color
-ignore 'property "workflow_update_github_pat" is not defined in .+'
broken-links:
# Skip checks on prepare-release branch as it contains commits in changelog and documentation that points to a tag
# that does not exist yet, rendering URLs artificially broken. Also skips the merge commit of the prepare-release
# branch, as if the URLs are good, the tag is created asynchronously by release.yaml:git-tag job. And as a
# precautionary measure, just skip any event that contains a post-release bump commit.
if: >
github.head_ref != 'prepare-release'
&& github.ref != 'refs/heads/prepare-release'
&& (! contains(github.event.commits.*.message, '[changelog] Post-release version bump'))
runs-on: ubuntu-24.04
# XXX We need to manually manage the life-cycle of issues created in this job because the create-issue-from-file
# action blindly creates issues ad-nauseam. See: https://github.com/peter-evans/create-issue-from-file/issues/298 .
# This was also discussed at: https://github.com/lycheeverse/lychee-action/issues/74#issuecomment-1587089689
steps:
- uses: actions/[email protected]
- uses: lycheeverse/[email protected]
id: lychee_run
with:
# XXX Skip HN because of rate-limiting.
# See: https://github.com/lycheeverse/lychee/issues/989#issuecomment-1587208730
# https://github.com/lycheeverse/lychee/pull/1147
args: >
--exclude ycombinator.com
--base .
--verbose
--no-progress
'./**/*.md' './**/*.html' './**/*.rst'
- name: List open issues
id: open_issues
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: >
echo "issues=$(
gh issue list
--state open
--author 'github-actions[bot]'
--json number,title,createdAt )" >> "$GITHUB_OUTPUT"
- name: Print open issues
run: |
echo '${{ steps.open_issues.outputs.issues }}'
jq -aR <<< echo '${{ steps.open_issues.outputs.issues }}'
- name: Filter issues
id: issue_groups
shell: python
run: |
import json
import os
from operator import itemgetter
from pathlib import Path
exit_code = """${{ steps.lychee_run.outputs.exit_code }}"""
print(f"Lychee exit code: {exit_code!r}")
broken_links_found = bool(int(exit_code))
if broken_links_found:
print("Broken links found: create a new issue or update the existing one.")
else:
print("No broken link found: close all open issues.")
open_issues = json.loads("""${{ steps.open_issues.outputs.issues }}""")
issue_to_update: int | None = None
issues_to_close: set[int] = set()
for issue in sorted(open_issues, key=itemgetter("createdAt"), reverse=True):
print(f"Processing {issue!r} ...")
if issue["title"] != "Broken links":
print(f"{issue!r} is not a broken links issue, skip it.")
continue
if broken_links_found and not issue_to_update:
print(f"{issue!r} is the most recent open issue.")
issue_to_update = issue["number"]
else:
print(f"{issue!r} is an old open issue we have to close.")
issues_to_close.add(issue["number"])
output = f"broken_links_found={str(broken_links_found).lower()}\n"
output += f"issue_to_update={issue_to_update}\n"
output += f"issues_to_close={' '.join(issues_to_close)}\n"
env_file = Path(os.getenv("GITHUB_OUTPUT"))
env_file.write_text(output)
- name: Print issue groups
run: |
echo "Broken links found: ${{ steps.issue_groups.outputs.broken_links_found }}"
echo "Issue to update: ${{ steps.issue_groups.outputs.issue_to_update }}"
echo "Issues to close: ${{ steps.issue_groups.outputs.issues_to_close }}"
- name: Close old issues
if: steps.issue_groups.outputs.issues_to_close
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
NUMBER_LIST="${{ steps.issue_groups.outputs.issues_to_close }}"
for number in $NUMBER_LIST; do
gh issue close "$number" --comment "Superseded by #${{ steps.issue_groups.outputs.issue_to_update }}.";
done
- name: Get label
if: fromJSON(steps.issue_groups.outputs.broken_links_found)
id: get_label
run: >
echo "label=${{ startsWith(github.event.repository.name, 'awesome-')
&& '🩹 fix link' || '📚 documentation' }}" >> "$GITHUB_OUTPUT"
- name: Create or update issue
if: fromJSON(steps.issue_groups.outputs.broken_links_found)
uses: peter-evans/[email protected]
with:
title: "Broken links"
issue-number: ${{ steps.issue_groups.outputs.issue_to_update }}
content-filepath: ./lychee/out.md
labels: ${{ steps.get_label.outputs.label }}
lint-awesome:
name: Lint Awesome list
if: >
startsWith(github.event.repository.name, 'awesome-')
&& github.event.repository.name != 'awesome-template'
runs-on: ubuntu-24.04
steps:
- uses: actions/[email protected]
with:
# Fetch all history to please linter's age checks.
fetch-depth: 0
- run: |
npx awesome-lint --version
npx awesome-lint
check-secrets:
runs-on: ubuntu-24.04
steps:
- uses: actions/[email protected]
with:
fetch-depth: 0
- uses: gitleaks/[email protected]
with:
config-path: .github/gitleaks.toml
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}