Skip to content

Commit

Permalink
Improve test speed (#445)
Browse files Browse the repository at this point in the history
  • Loading branch information
blink1073 authored Oct 16, 2022
1 parent 7977e0e commit 7cbb682
Show file tree
Hide file tree
Showing 8 changed files with 60 additions and 43 deletions.
7 changes: 5 additions & 2 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@ defaults:
run:
shell: bash -eux {0}

env:
PYTHONDONTWRITEBYTECODE: 1

jobs:
# Run "pre-commit run --all-files --hook-stage=manual"
pre-commit:
Expand Down Expand Up @@ -51,13 +54,13 @@ jobs:
- name: Run the tests with coverage on Ubuntu
if: ${{ matrix.os == 'ubuntu-latest' }}
run: |
hatch run cov:test
hatch run cov:test -n auto || hatch run test:test --lf
pip install codecov
codecov
- name: Run the tests on Windows and MacOS
if: ${{ matrix.os != 'ubuntu-latest' }}
run: hatch run test:test -s
run: hatch run test:test -s -n auto || hatch run test:test -s --lf

generate-changelog:
runs-on: ubuntu-20.04
Expand Down
30 changes: 14 additions & 16 deletions jupyter_releaser/lib.py
Original file line number Diff line number Diff line change
Expand Up @@ -248,7 +248,8 @@ def populate_release(

def delete_release(auth, release_url, dry_run=False):
"""Delete a draft GitHub release by url to the release page"""
match = re.match(util.RELEASE_HTML_PATTERN, release_url)
pattern = util.RELEASE_HTML_PATTERN % util.get_mock_github_url()
match = re.match(pattern, release_url)
match = match or re.match(util.RELEASE_API_PATTERN, release_url)
if not match:
raise ValueError(f"Release url is not valid: {release_url}")
Expand Down Expand Up @@ -409,21 +410,6 @@ def prep_git(ref, branch, repo, auth, username, url):
"""Set up git"""
repo = repo or util.get_repo()

try:
util.run("git config --global user.email")
has_git_config = True
except Exception:
has_git_config = False

if not has_git_config:
# Default to the GitHub Actions bot
# https://github.jparrowsec.cnmunity/t/github-actions-bot-email-address/17204/6
git_user_name = username or "41898282+github-actions[bot]"
util.run(
f'git config --global user.email "{git_user_name}@users.noreply.github.com"', echo=True
)
util.run(f'git config --global user.name "{git_user_name}"', echo=True)

# Set up the repository
checkout_dir = os.environ.get("RH_CHECKOUT_DIR", util.CHECKOUT_NAME)
checkout_exists = False
Expand Down Expand Up @@ -504,6 +490,18 @@ def prep_git(ref, branch, repo, auth, username, url):
elif util.PACKAGE_JSON.exists():
util.run("npm install")

try:
has_git_config = util.run("git config user.email").strip()
except Exception:
has_git_config = False

if not has_git_config:
# Default to the GitHub Actions bot
# https://github.jparrowsec.cnmunity/t/github-actions-bot-email-address/17204/6
git_user_name = username or "41898282+github-actions[bot]"
util.run(f'git config user.email "{git_user_name}@users.noreply.github.com"', echo=True)
util.run(f'git config user.name "{git_user_name}"', echo=True)

os.chdir(orig_dir)

return branch
Expand Down
12 changes: 7 additions & 5 deletions jupyter_releaser/mock_github.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
from fastapi.staticfiles import StaticFiles
from pydantic import BaseModel

from jupyter_releaser.util import MOCK_GITHUB_URL
from jupyter_releaser.util import get_mock_github_url

app = FastAPI()

Expand Down Expand Up @@ -131,9 +131,10 @@ async def create_a_release(owner: str, repo: str, request: Request) -> Release:
"""https://docs.github.com/en/rest/releases/releases#create-a-release"""
release_id = uuid.uuid4().int
data = await request.json()
url = f"{MOCK_GITHUB_URL}/repos/{owner}/{repo}/releases/{release_id}"
html_url = f"{MOCK_GITHUB_URL}/{owner}/{repo}/releases/tag/{data['tag_name']}"
upload_url = f"{MOCK_GITHUB_URL}/repos/{owner}/{repo}/releases/{release_id}/assets"
base_url = get_mock_github_url()
url = f"{base_url}/repos/{owner}/{repo}/releases/{release_id}"
html_url = f"{base_url}/{owner}/{repo}/releases/tag/{data['tag_name']}"
upload_url = f"{base_url}/repos/{owner}/{repo}/releases/{release_id}/assets"
fmt_str = r"%Y-%m-%dT%H:%M:%SZ"
created_at = datetime.datetime.utcnow().strftime(fmt_str)
model = Release(
Expand Down Expand Up @@ -164,14 +165,15 @@ async def update_a_release(owner: str, repo: str, release_id: int, request: Requ
@app.post("/repos/{owner}/{repo}/releases/{release_id}/assets")
async def upload_a_release_asset(owner: str, repo: str, release_id: int, request: Request) -> None:
"""https://docs.github.com/en/rest/releases/assets#upload-a-release-asset"""
base_url = get_mock_github_url()
model = releases[str(release_id)]
asset_id = uuid.uuid4().int
name = request.query_params["name"]
with open(f"{static_dir}/{asset_id}", "wb") as fid:
async for chunk in request.stream():
fid.write(chunk)
headers = request.headers
url = f"{MOCK_GITHUB_URL}/static/{asset_id}"
url = f"{base_url}/static/{asset_id}"
asset = Asset(
id=asset_id,
name=name,
Expand Down
2 changes: 1 addition & 1 deletion jupyter_releaser/python.py
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ def get_pypi_token(release_url, python_package):
pypi_token_map = os.environ.get("PYPI_TOKEN_MAP", "").replace(r"\n", "\n")
if pypi_token_map and release_url:
parts = (
release_url.replace(util.MOCK_GITHUB_URL + "/", "")
release_url.replace(util.get_mock_github_url() + "/", "")
.replace("https://github.com/", "")
.split("/")
)
Expand Down
16 changes: 9 additions & 7 deletions jupyter_releaser/tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,15 @@
from jupyter_releaser.util import ensure_mock_github, run


@fixture(autouse=True)
def github_port(worker_id):
# The worker id will be of the form "gw123" unless xdist is disabled,
# in which case it will be "master".
if worker_id == "master":
return
os.environ["MOCK_GITHUB_PORT"] = str(8000 + int(worker_id[2:]))


@fixture(autouse=True)
def mock_env(mocker):
"""Clear unwanted environment variables"""
Expand All @@ -29,13 +38,6 @@ def mock_env(mocker):
del env[key]

mocker.patch.dict(os.environ, env, clear=True)

try:
run("git config --global user.name")
except Exception:
run("git config --global user.name snuffy")
run("git config --global user.email [email protected]")

yield


Expand Down
5 changes: 3 additions & 2 deletions jupyter_releaser/tests/test_cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -94,18 +94,19 @@ def test_prep_git_full(py_package, tmp_path, mocker, runner):
os.mkdir(util.CHECKOUT_NAME)

runner(["prep-git"], env=env)

mock_run.assert_has_calls(
[
call("echo before-prep-git >> 'log.txt'"),
call("git config --global user.email"),
call("git init .jupyter_releaser_checkout"),
call("git remote add origin https://snuffy:[email protected]/baz/bar.git"),
call(f"{GIT_FETCH_CMD} --tags --force"),
call(f"{GIT_FETCH_CMD} +refs/pull/42:refs/pull/42"),
call(f"{GIT_FETCH_CMD} refs/pull/42"),
call("git checkout -B foo refs/pull/42"),
call("git symbolic-ref -q HEAD"),
call("git config user.email"),
call('git config user.email "[email protected]"', echo=True),
call('git config user.name "snuffy"', echo=True),
]
)

Expand Down
28 changes: 19 additions & 9 deletions jupyter_releaser/util.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
from io import BytesIO
from pathlib import Path
from subprocess import PIPE, CalledProcessError, check_output
from urllib.parse import urlparse

import requests
import toml
Expand All @@ -45,14 +46,13 @@
TBUMP_CMD = "pipx run tbump --non-interactive --only-patch"

CHECKOUT_NAME = ".jupyter_releaser_checkout"

MOCK_GITHUB_URL = "http://127.0.0.1:8000"
RELEASE_HTML_PATTERN = f"(?:https://github.com|{MOCK_GITHUB_URL})/(?P<owner>[^/]+)/(?P<repo>[^/]+)/releases/tag/(?P<tag>.*)"
RELEASE_HTML_PATTERN = (
"(?:https://github.com|%s)/(?P<owner>[^/]+)/(?P<repo>[^/]+)/releases/tag/(?P<tag>.*)"
)
RELEASE_API_PATTERN = (
"https://api.github.com/repos/(?P<owner>[^/]+)/(?P<repo>[^/]+)/releases/tags/(?P<tag>.*)"
)


SCHEMA = files("jupyter_releaser").joinpath("schema.json").read_text()
SCHEMA = json.loads(SCHEMA)

Expand Down Expand Up @@ -468,7 +468,8 @@ def read_config():

def parse_release_url(release_url):
"""Parse a release url into a regex match"""
match = re.match(RELEASE_HTML_PATTERN, release_url)
pattern = RELEASE_HTML_PATTERN % get_mock_github_url()
match = re.match(pattern, release_url)
match = match or re.match(RELEASE_API_PATTERN, release_url)
if not match:
raise ValueError(f"Release url is not valid: {release_url}")
Expand Down Expand Up @@ -686,13 +687,20 @@ def get_remote_name(dry_run):
return "test"


def get_mock_github_url():
port = os.environ.get("MOCK_GITHUB_PORT", "8000")
return f"http://127.0.0.1:{port}"


def ensure_mock_github():
"""Check for or start a mock github server."""
core.GH_HOST = MOCK_GITHUB_URL
core.GH_HOST = host = get_mock_github_url()
port = urlparse(host).port

log("Ensuring mock GitHub")
# First see if it is already running.
try:
requests.get(MOCK_GITHUB_URL)
requests.get(host)
return
except requests.ConnectionError:
pass
Expand All @@ -705,7 +713,9 @@ def ensure_mock_github():
except ImportError:
run(f"'{python}' -m pip install fastapi uvicorn")

proc = subprocess.Popen([python, "-m", "uvicorn", "jupyter_releaser.mock_github:app"])
proc = subprocess.Popen(
[python, "-m", "uvicorn", "jupyter_releaser.mock_github:app", "--port", str(port)]
)

try:
ret = proc.wait(1)
Expand All @@ -718,7 +728,7 @@ def ensure_mock_github():

while 1:
try:
requests.get(MOCK_GITHUB_URL)
requests.get(host)
break
except requests.ConnectionError:
pass
Expand Down
3 changes: 2 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ test = [
"pytest>=7.0",
"pytest-cov",
"pytest-mock",
"pytest-xdist[psutil]",
"uvicorn"
]

Expand Down Expand Up @@ -94,7 +95,7 @@ after-populate-release = "bash ./.github/scripts/bump_tag.sh"
post-version-spec = "dev"

[tool.pytest.ini_options]
addopts = "-raXs --durations 10 --color=yes --doctest-modules"
addopts = "-raXs --durations 10 --color=yes --doctest-modules -p no:pastebin -p no:nose"
testpaths = [
"jupyter_releaser/tests/"
]
Expand Down

0 comments on commit 7cbb682

Please sign in to comment.