Repository: python/mypy
Pull request: Migrate tests from Travis.ci to Github Action
### Description

Switch from Travis CI 

Closes https://github.com/python/mypy/issues/11062.


Problem statement:
Did Travis die?
I noticed Travis wasn't running on my PR. Travis' website still exists, but it looks like it hasn't run a build for us, on PR or master, in 18 days. Anyone know what's up? Pretty bad to have CI silently disappear.

Hints from issue discussion:
This happened to python/typing too and we just moved CI fully to GH Actions. I'm afraid we'll have to do the same here.
I can maybe take a look at this in the next week or so.
This issue is quite important thus I'll open a draft PR today. I might only add one or two tests at first and it would be great if anyone can make further contribution.

Commit message: Delete .travis.yml

Patch to review:
diff --git a/.github/workflows/build_wheels.yml b/.github/workflows/build_wheels.yml
new file mode 100644
index 000000000000..7880848c4bd7
--- /dev/null
+++ b/.github/workflows/build_wheels.yml
@@ -0,0 +1,25 @@
+name: Build wheels
+
+on:
+  push:
+    branches: [master]
+    tags: ['*']
+    paths-ignore:
+    - 'docs/**'
+    - '**/*.rst'
+    - '**/*.md'
+    - .gitignore
+    - .travis.yml
+    - CREDITS
+    - LICENSE
+
+jobs:
+  build-wheels:
+    runs-on: ubuntu-latest
+    steps:
+      - uses: actions/checkout@v2
+      - uses: actions/setup-python@v2
+        with:
+          python-version: '3.7'
+      - name: Trigger script
+        run: ./misc/trigger_wheel_build.sh
diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml
new file mode 100644
index 000000000000..f314257790a7
--- /dev/null
+++ b/.github/workflows/docs.yml
@@ -0,0 +1,30 @@
+name: Check documentation build
+
+on:
+  push:
+    branches: [master]
+    tags: ['*']
+  pull_request:
+    paths:
+    - 'docs/**'
+    - '**/*.rst'
+    - '**/*.md'
+    - CREDITS
+    - LICENSE
+
+jobs:
+  docs:
+    runs-on: ubuntu-latest
+    env:
+      TOXENV: docs
+    steps:
+      - uses: actions/checkout@v2
+      - uses: actions/setup-python@v2
+        with:
+          python-version: '3.7'
+      - name: Install tox
+        run: pip install --upgrade 'setuptools!=50' 'virtualenv<16.7.11' tox==3.20.1
+      - name: Setup tox environment
+        run: tox -e ${{ env.TOXENV }} --notest
+      - name: Test
+        run: tox -e ${{ env.TOXENV }} --skip-pkg-install
diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
index eca1e3b67956..5583db0ea104 100644
--- a/.github/workflows/test.yml
+++ b/.github/workflows/test.yml
@@ -1,4 +1,4 @@
-name: main
+name: Run tests
 
 on:
   push:
@@ -15,12 +15,16 @@ on:
     - LICENSE
 
 jobs:
-  build:
+  main:
     runs-on: ${{ matrix.os }}
     strategy:
       fail-fast: false
       matrix:
-        name: [windows-py37-32, windows-py37-64]
+        name: [windows-py37-32, windows-py37-64,
+               ubuntu-py37, ubuntu-py38,
+               ubuntu-py36-mypyc, ubuntu-py39-mypyc,
+               macos-py36, ubuntu-py-36-debug-build,
+               type-checking, code-style]
         include:
         - name: windows-py37-32
           python: '3.7'
@@ -32,6 +36,55 @@ jobs:
           arch: x64
           os: windows-latest
           toxenv: py37
+        - name: ubuntu-py37
+          python: '3.7'
+          arch: x64
+          os: ubuntu-latest
+          toxenv: py
+          tox_extra_args: "-n 2"
+        - name: ubuntu-py38
+          python: '3.8'
+          arch: x64
+          os: ubuntu-latest
+          toxenv: py
+          tox_extra_args: "-n 2"
+        - name: ubuntu-py36-mypyc
+          python: '3.6'
+          arch: x64
+          os: ubuntu-latest
+          toxenv: py
+          tox_extra_args: "-n 2"
+          test_mypyc: true
+        - name: ubuntu-py39-mypyc
+          python: '3.9'
+          arch: x64
+          os: ubuntu-latest
+          toxenv: py
+          tox_extra_args: "-n 2"
+          test_mypyc: true
+        - name: macos-py36
+          python: '3.6'
+          arch: x64
+          os: macos-latest
+          toxenv: py
+          tox_extra_args: "-n 2 mypyc/test/test_run.py mypyc/test/test_external.py"
+        - name: ubuntu-py-36-debug-build
+          python: '3.6.8'
+          arch: x64
+          os: ubuntu-latest
+          toxenv: py36
+          tox_extra_args: "-n 2 mypyc/test/test_run.py mypyc/test/test_external.py"
+          debug_build: true
+        - name: type-checking
+          python: '3.7'
+          arch: x64
+          os: ubuntu-latest
+          toxenv: type
+        - name: code-style
+          python: '3.7'
+          arch: x64
+          os: ubuntu-latest
+          toxenv: lint
 
     steps:
     - uses: actions/checkout@v2
@@ -39,9 +92,42 @@ jobs:
       with:
         python-version: ${{ matrix.python }}
         architecture: ${{ matrix.arch }}
-    - name: install tox
+    - name: Debug build
+      if: ${{ matrix.debug_build }}
+      run: |
+        PYTHONVERSION=${{ matrix.python }}
+        PYTHONDIR=~/python-debug/python-$PYTHONVERSION
+        VENV=$PYTHONDIR/env
+        ./misc/build-debug-python.sh $PYTHONVERSION $PYTHONDIR $VENV
+        source $VENV/bin/activate
+    - name: Install tox
       run: pip install --upgrade 'setuptools!=50' 'virtualenv<16.7.11' tox==3.20.1
-    - name: setup tox environment
+    - name: Compiled with mypyc
+      if: ${{ matrix.test_mypyc }}
+      run: |
+        pip install -r test-requirements.txt
+        CC=clang MYPYC_OPT_LEVEL=0 python3 setup.py --use-mypyc build_ext --inplace
+    - name: Setup tox environment
       run: tox -e ${{ matrix.toxenv }} --notest
-    - name: test
-      run: tox -e ${{ matrix.toxenv }} --skip-pkg-install
+    - name: Test
+      run: tox -e ${{ matrix.toxenv }} --skip-pkg-install -- ${{ matrix.tox_extra_args }}
+
+  python-nightly:
+    runs-on: ubuntu-latest
+    steps:
+    - uses: actions/checkout@v2
+    - uses: actions/setup-python@v2
+      with:
+        python-version: '3.10-dev'
+    - name: Install tox
+      run: |
+        pip install -U pip==21.2.3 setuptools
+        pip install --upgrade 'setuptools!=50' virtualenv==20.4.7 tox==3.20.1
+    - name: Setup tox environment
+      run: tox -e py --notest
+    - name: Test
+      run: tox -e py --skip-pkg-install -- "-n 2"
+      continue-on-error: true
+    - name: Mark as a success
+      run: exit 0
+
diff --git a/.travis.yml b/.travis.yml
deleted file mode 100644
index d7dbcce5ab91..000000000000
--- a/.travis.yml
+++ /dev/null
@@ -1,121 +0,0 @@
-# in the python/mypy repo, we only CI the master, release branches, tags and PRs
-if: tag IS present OR type = pull_request OR ((branch = master OR branch =~ release-*) AND type = push) OR repo != python/mypy
-
-language: python
-# cache package wheels (1 cache per python version)
-cache: pip
-# also cache the directories where we set up our custom pythons in some builds
-cache:
-  directories:
-    - $HOME/python-debug
-    # I ran into some issues with this but will investigate again later.
-    # - $HOME/.pyenv/versions
-    - $HOME/Library/Caches/pip
-
-# newer python versions are available only on xenial (while some older only on trusty) Ubuntu distribution
-dist: xenial
-
-env:
-  TOXENV=py
-  EXTRA_ARGS="-n 2"
-  TEST_MYPYC=0
-  PYTHON_DEBUG_BUILD=0
-
-jobs:
-  fast_finish: true
-  include:
-  - name: "run test suite with python 3.6 (compiled with mypyc)"
-    python: 3.6    # 3.6.3  pip  9.0.1
-    env:
-    - TOXENV=py
-    - EXTRA_ARGS="-n 2"
-    - TEST_MYPYC=1
-  - name: "run test suite with python 3.7"
-    python: 3.7
-  - name: "run test suite with python 3.8"
-    python: 3.8
-  - name: "run test suite with python 3.9 (compiled with mypyc)"
-    python: 3.9
-    env:
-    - TOXENV=py
-    - EXTRA_ARGS="-n 2"
-    - TEST_MYPYC=1
-  - name: "run test suite with python nightly"
-    python: nightly
-  - name: "run mypyc runtime tests with python 3.6 debug build"
-    language: generic
-    env:
-      - TOXENV=py36
-      - PYTHONVERSION=3.6.8
-      - PYTHON_DEBUG_BUILD=1
-      - EXTRA_ARGS="-n 2 mypyc/test/test_run.py mypyc/test/test_external.py"
-  - name: "run mypyc runtime tests with python 3.6 on OS X"
-    os: osx
-    osx_image: xcode8.3
-    language: generic
-    env:
-      - PYTHONVERSION=3.6.3
-      - EXTRA_ARGS="-n 2 mypyc/test/test_run.py mypyc/test/test_external.py"
-  - name: "type check our own code"
-    python: 3.7
-    env:
-    - TOXENV=type
-    - EXTRA_ARGS=
-  - name: "check code style with flake8"
-    python: 3.7
-    env:
-    - TOXENV=lint
-    - EXTRA_ARGS=
-  - name: "trigger a build of wheels"
-    python: 3.7
-    script: if [[ ($TRAVIS_BRANCH = "master" || $TRAVIS_BRANCH =~ release-*) && $TRAVIS_PULL_REQUEST = "false" ]]; then ./misc/trigger_wheel_build.sh; fi
-  - name: "check documentation build"
-    python: 3.7
-    env:
-    - TOXENV=docs
-  # Disabled because of some pip bug? See #6716
-  # - name: "check dev environment builds"
-  #   python: 3.7
-  #   env:
-  #   - TOXENV=dev
-  #   - EXTRA_ARGS=
-  allow_failures:
-  - python: nightly
-
-install:
-# pip 21.0 no longer works on Python 3.5
-- pip install -U pip==20.3.4 setuptools
-- pip install -U 'virtualenv<16.7.11'
-- pip install -U tox==3.20.1
-- python2 -m pip install --user -U typing
-- tox --notest
-
-# This is a big hack and only works because the layout of our directories
-# means that tox picks up the mypy from the source directories instead of
-# the version it installed into a venv. This is also *why* we need to do this,
-# since if we arranged for tox to build with mypyc, pytest wouldn't use it.
-- if [[ $TEST_MYPYC == 1 ]]; then pip install -r test-requirements.txt; CC=clang MYPYC_OPT_LEVEL=0 python3 setup.py --use-mypyc build_ext --inplace; fi
-
-script:
-- tox --skip-pkg-install -- $EXTRA_ARGS
-
-# Getting our hands on a debug build or the right OS X build is
-# annoying, unfortunately.
-before_install: |
-  set -e
-  if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then
-    if [[ $PYTHON_DEBUG_BUILD == 1 ]]; then
-      PYTHONDIR=~/python-debug/python-$PYTHONVERSION
-      VENV=$PYTHONDIR/env
-      misc/build-debug-python.sh $PYTHONVERSION $PYTHONDIR $VENV
-      source $VENV/bin/activate
-    fi
-  elif [[ "$TRAVIS_OS_NAME" == "osx" ]]; then
-    # Attempt to install, skipping if version already exists.
-    pyenv install $PYTHONVERSION -s
-    # Regenerate shims
-    pyenv rehash
-    # Manually set pyenv variables per https://pythonhosted.org/CodeChat/.travis.yml.html
-    export PYENV_VERSION=$PYTHONVERSION
-    export PATH="/Users/travis/.pyenv/shims:${PATH}"
-  fi
diff --git a/mypy/checker.py b/mypy/checker.py
index 7ed4ba351347..ea8037a36b57 100644
--- a/mypy/checker.py
+++ b/mypy/checker.py
@@ -346,8 +346,10 @@ def check_second_pass(self,
                     # print("XXX in pass %d, class %s, function %s" %
                     #       (self.pass_num, type_name, node.fullname or node.name))
                     done.add(node)
-                    with self.tscope.class_scope(active_typeinfo) if active_typeinfo else nothing():
-                        with self.scope.push_class(active_typeinfo) if active_typeinfo else nothing():
+                    with self.tscope.class_scope(active_typeinfo) if active_typeinfo \
+                            else nothing():
+                        with self.scope.push_class(active_typeinfo) if active_typeinfo \
+                                else nothing():
                             self.check_partial(node)
             return True
 
diff --git a/mypy/meet.py b/mypy/meet.py
index 465b25dd7c0d..e21b0fcbab70 100644
--- a/mypy/meet.py
+++ b/mypy/meet.py
@@ -57,7 +57,7 @@ def narrow_declared_type(declared: Type, narrowed: Type) -> Type:
     if declared == narrowed:
         return declared
     # Ignore the error about using get_proper_type().
-    if isinstance(narrowed, TypeGuardType):  # type: ignore[misc]
+    if isinstance(narrowed, TypeGuardType):
         # A type guard forces the new type even if it doesn't overlap the old.
         return narrowed.type_guard
     elif isinstance(declared, UnionType):
@@ -162,7 +162,7 @@ def _is_overlapping_types(left: Type, right: Type) -> bool:
         assert False, "Unexpectedly encountered partial type"
 
     # Ignore the error about using get_proper_type().
-    if isinstance(left, TypeGuardType) or isinstance(right, TypeGuardType):  # type: ignore[misc]
+    if isinstance(left, TypeGuardType) or isinstance(right, TypeGuardType):
         # A type guard forces the new type even if it doesn't overlap the old.
         return True
 
diff --git a/mypy/server/deps.py b/mypy/server/deps.py
index 62f500442c8f..f17ca1f136ed 100644
--- a/mypy/server/deps.py
+++ b/mypy/server/deps.py
@@ -82,7 +82,6 @@ class 'mod.Cls'. This can also refer to an attribute inherited from a
 from typing import Dict, List, Set, Optional, Tuple
 from typing_extensions import DefaultDict
 
-from mypy.backports import nullcontext
 from mypy.checkmember import bind_self
 from mypy.nodes import (
     Node, Expression, MypyFile, FuncDef, ClassDef, AssignmentStmt, NameExpr, MemberExpr, Import,
@@ -240,8 +239,9 @@ def visit_class_def(self, o: ClassDef) -> None:
             self.is_class = old_is_class
 
     def visit_newtype_expr(self, o: NewTypeExpr) -> None:
-        with self.scope.class_scope(o.info) if o.info else nullcontext():
-            self.process_type_info(o.info)
+        if o.info:
+            with self.scope.class_scope(o.info):
+                self.process_type_info(o.info)
 
     def process_type_info(self, info: TypeInfo) -> None:
         target = self.scope.current_full_target()


Code review comments:
diff_hunk: @@ -0,0 +1,25 @@
+name: Build wheels
+
+on:
+  push:
+    branches: [master]
+    tags: ['*']
+    paths-ignore:
+    - 'docs/**'
+    - '**/*.rst'
+    - '**/*.md'
+    - .gitignore
+    - .travis.yml
path: .github/workflows/build_wheels.yml
text: @user1:
nit: can remove .travis.yml :-)

diff_hunk: @@ -0,0 +1,25 @@
+name: Build wheels
+
+on:
+  push:
+    branches: [master]
+    tags: ['*']
+    paths-ignore:
+    - 'docs/**'
+    - '**/*.rst'
+    - '**/*.md'
+    - .gitignore
+    - .travis.yml
+    - CREDITS
+    - LICENSE
+
+jobs:
+  build-wheels:
+    runs-on: ubuntu-latest
+    steps:
+      - uses: actions/checkout@v2
+      - uses: actions/setup-python@v2
+        with:
+          python-version: '3.7'
+      - name: Trigger script
+        run: ./misc/trigger_wheel_build.sh
path: .github/workflows/build_wheels.yml
text: @user1:
Does this work?
If not, do we know who has perms to make WHEEL_PUSH_TOKEN? https://github.com/python/mypy/blob/7b9aa4cfe2cb57fa3f90a917dcd02620986bee79/misc/trigger_wheel_build.sh#L6

@user2:
Can't imagine that it would work. I hopefully have the creds somewhere, let me look

@author:
This might be helpful? https://docs.github.com/en/actions/reference/encrypted-secrets

@user2:
Alright, I have added a token with the secret name `WHEELS_PUSH_TOKEN`