Merge pull request #19105 from gnossen/twine_check_artifacts

Produce Python Wheels with a Valid long_description field
diff --git a/src/python/grpcio/README.rst b/src/python/grpcio/README.rst
index 44d516e..07c9434 100644
--- a/src/python/grpcio/README.rst
+++ b/src/python/grpcio/README.rst
@@ -16,8 +16,8 @@
 
 gRPC Python is available for Linux, macOS, and Windows.
 
-From PyPI
-~~~~~~~~~
+Installing From PyPI
+~~~~~~~~~~~~~~~~~~~~
 
 If you are installing locally...
 
@@ -45,8 +45,8 @@
 to retrieve the proper wheel from PyPI. Be sure to upgrade to the latest
 version!
 
-From Source
-~~~~~~~~~~~
+Installing From Source
+~~~~~~~~~~~~~~~~~~~~~~
 
 Building from source requires that you have the Python headers (usually a
 package named :code:`python-dev`).
diff --git a/tools/distrib/python/grpcio_tools/README.rst b/tools/distrib/python/grpcio_tools/README.rst
index cc974ed..2fe7935 100644
--- a/tools/distrib/python/grpcio_tools/README.rst
+++ b/tools/distrib/python/grpcio_tools/README.rst
@@ -17,8 +17,8 @@
 The gRPC Python tools package is available for Linux, Mac OS X, and Windows
 running Python 2.7.
 
-From PyPI
-~~~~~~~~~
+Installing From PyPI
+~~~~~~~~~~~~~~~~~~~~
 
 If you are installing locally...
 
@@ -50,8 +50,8 @@
 distribution if gRPC Python's system coverage with wheels does not happen to
 include your system.
 
-From Source
-~~~~~~~~~~~
+Installing From Source
+~~~~~~~~~~~~~~~~~~~~~~
 
 Building from source requires that you have the Python headers (usually a
 package named :code:`python-dev`) and Cython installed. It further requires a
diff --git a/tools/run_tests/artifacts/build_artifact_python.bat b/tools/run_tests/artifacts/build_artifact_python.bat
index 795e80d..c946cd9 100644
--- a/tools/run_tests/artifacts/build_artifact_python.bat
+++ b/tools/run_tests/artifacts/build_artifact_python.bat
@@ -46,6 +46,10 @@
 python setup.py bdist_wheel || goto :error
 popd
 
+@rem Ensure the generate artifacts are valid.
+python -m pip install twine
+python -m twine check dist\* tools\distrib\python\grpcio_tools\dist\* || goto :error
+
 xcopy /Y /I /S dist\* %ARTIFACT_DIR% || goto :error
 xcopy /Y /I /S tools\distrib\python\grpcio_tools\dist\* %ARTIFACT_DIR% || goto :error
 
diff --git a/tools/run_tests/artifacts/build_artifact_python.sh b/tools/run_tests/artifacts/build_artifact_python.sh
index e451ced..c5e380f 100755
--- a/tools/run_tests/artifacts/build_artifact_python.sh
+++ b/tools/run_tests/artifacts/build_artifact_python.sh
@@ -130,5 +130,11 @@
   cp -r src/python/grpcio_status/dist/* "$ARTIFACT_DIR"
 fi
 
+# Ensure the generated artifacts are valid.
+"${PYTHON}" -m virtualenv venv || { "${PYTHON}" -m pip install virtualenv && "${PYTHON}" -m virtualenv venv; }
+venv/bin/python -m pip install twine
+venv/bin/python -m twine check dist/* tools/distrib/python/grpcio_tools/dist/*
+rm -rf venv/
+
 cp -r dist/* "$ARTIFACT_DIR"
 cp -r tools/distrib/python/grpcio_tools/dist/* "$ARTIFACT_DIR"