Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 36 additions & 0 deletions .github/workflows/actionlint.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
name: Lint GitHub Actions workflows

on:
workflow_dispatch:
push:
branches:
- main
paths:
- ".github/workflows/**"
pull_request:
paths:
- ".github/workflows/**"

permissions:
contents: read

concurrency:
group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}
cancel-in-progress: true

jobs:
actionlint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- name: Run actionlint
# This is the recommended way to run actionlint in CI:
# https://github.com/rhysd/actionlint/blob/main/docs/usage.md#use-actionlint-on-github-actions.
# The actionlint pre-commit hook would be an alternative,
# but it causes our pre-commit CI jobs to time out.
# The Docker image includes ShellCheck and Pyflakes.
uses: docker://rhysd/actionlint:1.7.12@sha256:b1934ee5f1c509618f2508e6eb47ee0d3520686341fec936f3b79331f9315667
with:
args: -color -verbose
11 changes: 8 additions & 3 deletions .github/workflows/daily.yml
Original file line number Diff line number Diff line change
Expand Up @@ -86,19 +86,24 @@ jobs:
run: |
PACKAGES=$(python tests/get_stubtest_system_requirements.py)

# System package names contain no whitespace or glob characters, so word splitting is intentional.
# shellcheck disable=SC2086
if [ "${{ runner.os }}" = "Linux" ]; then
if [ -n "$PACKAGES" ]; then
printf "Installing APT packages:\n $(echo $PACKAGES | sed 's/ /\n /g')\n"
printf 'Installing APT packages:\n'
printf ' %s\n' $PACKAGES
sudo apt-get update -q && sudo apt-get install -qy $PACKAGES
fi
else
if [ "${{ runner.os }}" = "macOS" ] && [ -n "$PACKAGES" ]; then
printf "Installing Homebrew packages:\n $(echo $PACKAGES | sed 's/ /\n /g')\n"
printf 'Installing Homebrew packages:\n'
printf ' %s\n' $PACKAGES
brew install -q $PACKAGES
fi

if [ "${{ runner.os }}" = "Windows" ] && [ -n "$PACKAGES" ]; then
printf "Installing Chocolatey packages:\n $(echo $PACKAGES | sed 's/ /\n /g')\n"
printf 'Installing Chocolatey packages:\n'
printf ' %s\n' $PACKAGES
choco install -y $PACKAGES
fi
fi
Expand Down
6 changes: 3 additions & 3 deletions .github/workflows/mypy_primer.yml
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ jobs:
cd typeshed_to_test
MYPY_VERSION=$(grep mypy== requirements-tests.txt | cut -d = -f 3)
echo "new commit"
git rev-list --format=%s --max-count=1 $GITHUB_SHA
git rev-list --format=%s --max-count=1 "$GITHUB_SHA"
git checkout -b upstream_main origin/main
echo "base commit"
git rev-list --format=%s --max-count=1 upstream_main
Expand All @@ -50,9 +50,9 @@ jobs:
# fail action if exit code isn't zero or one
(
mypy_primer \
--new v${MYPY_VERSION} --old v${MYPY_VERSION} \
--new "v${MYPY_VERSION}" --old "v${MYPY_VERSION}" \
--custom-typeshed-repo typeshed_to_test \
--new-typeshed $GITHUB_SHA --old-typeshed upstream_main \
--new-typeshed "$GITHUB_SHA" --old-typeshed upstream_main \
--num-shards 6 --shard-index ${{ matrix.shard-index }} \
--debug \
--output concise \
Expand Down
19 changes: 13 additions & 6 deletions .github/workflows/stubtest_third_party.yml
Original file line number Diff line number Diff line change
Expand Up @@ -56,30 +56,35 @@ jobs:
# Use the daily.yml workflow to run stubtest on all third party stubs.
function find_stubs {
git diff --name-only "origin/${GITHUB_BASE_REF}" HEAD | \
egrep ^stubs/ | cut -d "/" -f 2 | sort -u | \
(while read stub; do [ -d "stubs/$stub" ] && echo -n "$stub " || true; done)
grep -E ^stubs/ | cut -d "/" -f 2 | sort -u | \
(while IFS= read -r stub; do [ -d "stubs/$stub" ] && echo -n "$stub " || true; done)
}
STUBS=$(find_stubs || echo '')
echo "Changed stubs: $STUBS"
echo "STUBS=$STUBS" >> $GITHUB_ENV
echo "STUBS=$STUBS" >> "$GITHUB_ENV"
- name: Install required system packages
shell: bash
run: |
# System package and stub directory names contain no whitespace or glob characters; split both lists into arguments.
# shellcheck disable=SC2086
if [ -n "$STUBS" ]; then
PACKAGES=$(python tests/get_stubtest_system_requirements.py $STUBS)
if [ "${{ runner.os }}" = "Linux" ]; then
if [ -n "$PACKAGES" ]; then
printf "Installing APT packages:\n $(echo $PACKAGES | sed 's/ /\n /g')\n"
printf 'Installing APT packages:\n'
printf ' %s\n' $PACKAGES
sudo apt-get update -q && sudo apt-get install -qy $PACKAGES
fi
else
if [ "${{ runner.os }}" = "macOS" ] && [ -n "$PACKAGES" ]; then
printf "Installing Homebrew packages:\n $(echo $PACKAGES | sed 's/ /\n /g')\n"
printf 'Installing Homebrew packages:\n'
printf ' %s\n' $PACKAGES
brew install -q $PACKAGES
fi

if [ "${{ runner.os }}" = "Windows" ] && [ -n "$PACKAGES" ]; then
printf "Installing Chocolatey packages:\n $(echo $PACKAGES | sed 's/ /\n /g')\n"
printf 'Installing Chocolatey packages:\n'
printf ' %s\n' $PACKAGES
choco install -y $PACKAGES
fi
fi
Expand All @@ -96,6 +101,8 @@ jobs:
PYTHON_EXECUTABLE="python"
fi

# Stub directory names contain no whitespace or glob characters, so word splitting is intentional.
# shellcheck disable=SC2086
$PYTHON_EXECUTABLE tests/stubtest_third_party.py --ci-platforms-only $STUBS
else
echo "Nothing to test"
Expand Down
33 changes: 26 additions & 7 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -63,8 +63,11 @@ jobs:
- name: Install required APT packages
run: |
PACKAGES=$(python tests/get_stubtest_system_requirements.py)
# System package names contain no whitespace or glob characters, so word splitting is intentional.
# shellcheck disable=SC2086
if [ -n "$PACKAGES" ]; then
printf "Installing APT packages:\n $(echo $PACKAGES | sed 's/ /\n /g')\n"
printf 'Installing APT packages:\n'
printf ' %s\n' $PACKAGES
sudo apt-get update -q && sudo apt-get install -qy $PACKAGES
fi
- name: Run mypy_test.py
Expand Down Expand Up @@ -117,7 +120,11 @@ jobs:
run: |
PACKAGES=$(python tests/get_external_stub_requirements.py)
if [ -n "$PACKAGES" ]; then
uv pip install --python-version ${{ matrix.python-version }} $PACKAGES
PACKAGE_ARGS=()
while IFS= read -r package; do
PACKAGE_ARGS+=("$package")
done <<< "$PACKAGES"
uv pip install --python-version ${{ matrix.python-version }} "${PACKAGE_ARGS[@]}"
fi
# Published stub packages can shadow the checked-in stubs when ty
# resolves their relative imports.
Comment on lines 120 to 130

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@srittau -- codex reckons that the shellcheck diagnostic here (and for other places where we use get_external_stub_requirements.py in our workflows) was not a false positive, and I think codex/shellcheck have a point here. Here's codex's reasoning:

get_external_stub_requirements.py returns complete requirement specifiers, not just package names. A valid requirement can contain whitespace, such as example>=1; python_version < "3.14", or characters with special meaning to shell globbing, such as the brackets in example[extra]. Expanding $PACKAGES without quotes would split the first example into multiple arguments and could interpret the second as a filename pattern. Quoting "$PACKAGES" as a whole would not solve this: it would pass the entire list of requirements as one argument.

Those steps therefore still read the helper's output into an array, one requirement per line, and pass "${PACKAGE_ARGS[@]}" to uv. This preserves each requirement as exactly one argument. It protects the requirement syntax the helper supports; it isn't a claim that one of our current requirements is already causing an installation failure.

Expand Down Expand Up @@ -152,7 +159,11 @@ jobs:
run: |
PACKAGES=$(python tests/get_external_stub_requirements.py)
if [ -n "$PACKAGES" ]; then
uv pip install --python-version ${{ matrix.python-version }} $PACKAGES
PACKAGE_ARGS=()
while IFS= read -r package; do
PACKAGE_ARGS+=("$package")
done <<< "$PACKAGES"
uv pip install --python-version ${{ matrix.python-version }} "${PACKAGE_ARGS[@]}"
fi
# Published stub packages can shadow the checked-in stubs when pyrefly
# resolves their relative imports.
Expand Down Expand Up @@ -186,8 +197,11 @@ jobs:
- name: Install required APT packages
run: |
PACKAGES=$(python tests/get_stubtest_system_requirements.py)
# System package names contain no whitespace or glob characters, so word splitting is intentional.
# shellcheck disable=SC2086
if [ -n "$PACKAGES" ]; then
printf "Installing APT packages:\n $(echo $PACKAGES | sed 's/ /\n /g')\n"
printf 'Installing APT packages:\n'
printf ' %s\n' $PACKAGES
sudo apt-get update -q && sudo apt-get install -qy $PACKAGES
fi
- name: Create an isolated venv for testing
Expand All @@ -196,11 +210,16 @@ jobs:
run: |
PACKAGES=$(python tests/get_external_stub_requirements.py)
if [ -n "$PACKAGES" ]; then
printf "Installing python packages:\n $(echo $PACKAGES | sed 's/ /\n /g')\n"
uv pip install --python-version ${{ matrix.python-version }} $PACKAGES
PACKAGE_ARGS=()
while IFS= read -r package; do
PACKAGE_ARGS+=("$package")
done <<< "$PACKAGES"
printf 'Installing python packages:\n'
printf ' %s\n' "${PACKAGE_ARGS[@]}"
uv pip install --python-version ${{ matrix.python-version }} "${PACKAGE_ARGS[@]}"
fi
- name: Activate the isolated venv for the rest of the job
run: echo "$PWD/.venv/bin" >> $GITHUB_PATH
run: echo "$PWD/.venv/bin" >> "$GITHUB_PATH"
- name: List 3rd-party stub dependencies installed
run: uv pip freeze
- name: Run pyright with basic settings on all the stubs
Expand Down
Loading