mirror of
https://github.com/tahoe-lafs/tahoe-lafs.git
synced 2024-12-19 04:57:54 +00:00
Merge pull request #1327 from exarkun/4057.circleci-windows-unittests
Run the unit test suite on Windows on CircleCI Fixes: ticket:4057
This commit is contained in:
commit
c2b4cebcdd
@ -24,6 +24,11 @@ version: 2.1
|
||||
dockerhub-context-template: &DOCKERHUB_CONTEXT
|
||||
context: "dockerhub-auth"
|
||||
|
||||
# Required environment for using the coveralls tool to upload partial coverage
|
||||
# reports and then finish the process.
|
||||
coveralls-environment: &COVERALLS_ENVIRONMENT
|
||||
COVERALLS_REPO_TOKEN: "JPf16rLB7T2yjgATIxFzTsEgMdN1UNq6o"
|
||||
|
||||
# Next is a Docker executor template that gets the credentials from the
|
||||
# environment and supplies them to the executor.
|
||||
dockerhub-auth-template: &DOCKERHUB_AUTH
|
||||
@ -112,6 +117,21 @@ workflows:
|
||||
- "another-locale":
|
||||
{}
|
||||
|
||||
- "windows-server-2022":
|
||||
name: "Windows Server 2022, CPython <<matrix.pythonVersion>>"
|
||||
matrix:
|
||||
parameters:
|
||||
# Run the job for a number of CPython versions. These are the
|
||||
# two versions installed on the version of the Windows VM image
|
||||
# we specify (in the executor). This is handy since it means we
|
||||
# don't have to do any Python installation work. We pin the
|
||||
# Windows VM image so these shouldn't shuffle around beneath us
|
||||
# but if we want to update that image or get different versions
|
||||
# of Python, we probably have to do something here.
|
||||
pythonVersion:
|
||||
- "3.9"
|
||||
- "3.11"
|
||||
|
||||
- "integration":
|
||||
# Run even the slow integration tests here. We need the `--` to
|
||||
# sneak past tox and get to pytest.
|
||||
@ -126,6 +146,15 @@ workflows:
|
||||
- "docs":
|
||||
{}
|
||||
|
||||
- "finish-coverage-report":
|
||||
requires:
|
||||
# Referencing the job by "alias" (as CircleCI calls the mapping
|
||||
# key) instead of the value of its "name" property causes us to
|
||||
# require every instance of the job from its matrix expansion. So
|
||||
# this requirement is enough to require every Windows Server 2022
|
||||
# job.
|
||||
- "windows-server-2022"
|
||||
|
||||
images:
|
||||
<<: *IMAGES
|
||||
|
||||
@ -133,6 +162,20 @@ workflows:
|
||||
when: "<< pipeline.parameters.build-images >>"
|
||||
|
||||
jobs:
|
||||
finish-coverage-report:
|
||||
docker:
|
||||
- <<: *DOCKERHUB_AUTH
|
||||
image: "python:3-slim"
|
||||
|
||||
steps:
|
||||
- run:
|
||||
name: "Indicate completion to coveralls.io"
|
||||
environment:
|
||||
<<: *COVERALLS_ENVIRONMENT
|
||||
command: |
|
||||
pip install coveralls==3.3.1
|
||||
python -m coveralls --finish
|
||||
|
||||
codechecks:
|
||||
docker:
|
||||
- <<: *DOCKERHUB_AUTH
|
||||
@ -151,6 +194,161 @@ jobs:
|
||||
command: |
|
||||
~/.local/bin/tox -e codechecks
|
||||
|
||||
windows-server-2022:
|
||||
parameters:
|
||||
pythonVersion:
|
||||
description: >-
|
||||
An argument to pass to the `py` launcher to choose a Python version.
|
||||
type: "string"
|
||||
default: ""
|
||||
|
||||
executor: "windows"
|
||||
environment:
|
||||
# Tweak Hypothesis to make its behavior more suitable for the CI
|
||||
# environment. This should improve reproducibility and lessen the
|
||||
# effects of variable compute resources.
|
||||
TAHOE_LAFS_HYPOTHESIS_PROFILE: "ci"
|
||||
|
||||
# Tell pip where its download cache lives. This must agree with the
|
||||
# "save_cache" step below or caching won't really work right.
|
||||
PIP_CACHE_DIR: "pip-cache"
|
||||
|
||||
# And tell pip where it can find out cached wheelhouse for fast wheel
|
||||
# installation, even for projects that don't distribute wheels. This
|
||||
# must also agree with the "save_cache" step below.
|
||||
PIP_FIND_LINKS: "wheelhouse"
|
||||
|
||||
steps:
|
||||
- "checkout"
|
||||
|
||||
# If possible, restore a pip download cache to save us from having to
|
||||
# download all our Python dependencies from PyPI.
|
||||
- "restore_cache":
|
||||
keys:
|
||||
# The download cache and/or the wheelhouse may contain Python
|
||||
# version-specific binary packages so include the Python version
|
||||
# in this key, as well as the canonical source of our
|
||||
# dependencies.
|
||||
- &CACHE_KEY "pip-packages-v1-<< parameters.pythonVersion >>-{{ checksum \"setup.py\" }}"
|
||||
|
||||
- "run":
|
||||
name: "Fix $env:PATH"
|
||||
command: |
|
||||
# The Python this job is parameterized is not necessarily the one
|
||||
# at the front of $env:PATH. Modify $env:PATH so that it is so we
|
||||
# can just say "python" in the rest of the steps. Also get the
|
||||
# related Scripts directory so tools from packages we install are
|
||||
# also available.
|
||||
$p = py -<<parameters.pythonVersion>> -c "import sys; print(sys.prefix)"
|
||||
$q = py -<<parameters.pythonVersion>> -c "import sysconfig; print(sysconfig.get_path('scripts'))"
|
||||
|
||||
New-Item $Profile.CurrentUserAllHosts -Force
|
||||
# $p gets "python" on PATH and $q gets tools from packages we
|
||||
# install. Note we carefully construct the string so that
|
||||
# $env:PATH is not substituted now but $p and $q are. ` is the
|
||||
# PowerShell string escape character.
|
||||
Add-Content -Path $Profile.CurrentUserAllHosts -Value "`$env:PATH = `"$p;$q;`$env:PATH`""
|
||||
|
||||
- "run":
|
||||
name: "Display tool versions"
|
||||
command: |
|
||||
python misc/build_helpers/show-tool-versions.py
|
||||
|
||||
- "run":
|
||||
# It's faster to install a wheel than a source package. If we don't
|
||||
# have a cached wheelhouse then build all of the wheels and dump
|
||||
# them into a directory where they can become a cached wheelhouse.
|
||||
# We would have built these wheels during installation anyway so it
|
||||
# doesn't cost us anything extra and saves us effort next time.
|
||||
name: "(Maybe) Build Wheels"
|
||||
command: |
|
||||
if ((Test-Path .\wheelhouse) -and (Test-Path .\wheelhouse\*)) {
|
||||
echo "Found populated wheelhouse, skipping wheel building."
|
||||
} else {
|
||||
python -m pip install wheel
|
||||
python -m pip wheel --wheel-dir $env:PIP_FIND_LINKS .[testenv] .[test]
|
||||
}
|
||||
|
||||
- "save_cache":
|
||||
paths:
|
||||
# Make sure this agrees with PIP_CACHE_DIR in the environment.
|
||||
- "pip-cache"
|
||||
- "wheelhouse"
|
||||
key: *CACHE_KEY
|
||||
|
||||
- "run":
|
||||
name: "Install Dependencies"
|
||||
environment:
|
||||
# By this point we should no longer need an index.
|
||||
PIP_NO_INDEX: "1"
|
||||
command: |
|
||||
python -m pip install .[testenv] .[test]
|
||||
|
||||
- "run":
|
||||
name: "Run Unit Tests"
|
||||
environment:
|
||||
# Configure the results location for the subunitv2-file reporter
|
||||
# from subunitreporter
|
||||
SUBUNITREPORTER_OUTPUT_PATH: "test-results.subunit2"
|
||||
|
||||
# Try to get prompt output from the reporter to avoid no-output
|
||||
# timeouts.
|
||||
PYTHONUNBUFFERED: "1"
|
||||
|
||||
command: |
|
||||
# Run the test suite under coverage measurement using the
|
||||
# parameterized version of Python, writing subunitv2-format
|
||||
# results to the file given in the environment.
|
||||
python -b -m coverage run -m twisted.trial --reporter=subunitv2-file --rterrors allmydata
|
||||
|
||||
- "run":
|
||||
name: "Upload Coverage"
|
||||
environment:
|
||||
<<: *COVERALLS_ENVIRONMENT
|
||||
# Mark the data as just one piece of many because we have more
|
||||
# than one instance of this job (two on Windows now, some on other
|
||||
# platforms later) which collects and reports coverage. This is
|
||||
# necessary to cause Coveralls to merge multiple coverage results
|
||||
# into a single report. Note the merge only happens when we
|
||||
# "finish" a particular build, as identified by its "build_num"
|
||||
# (aka "service_number").
|
||||
COVERALLS_PARALLEL: "true"
|
||||
command: |
|
||||
python -m pip install coveralls==3.3.1
|
||||
|
||||
# .coveragerc sets parallel = True so we don't have a `.coverage`
|
||||
# file but a `.coverage.<unique stuff>` file (or maybe more than
|
||||
# one, but probably not). coveralls can't work with these so
|
||||
# merge them before invoking it.
|
||||
python -m coverage combine
|
||||
|
||||
# Now coveralls will be able to find the data, so have it do the
|
||||
# upload. Also, have it strip the system config-specific prefix
|
||||
# from all of the source paths.
|
||||
$prefix = python -c "import sysconfig; print(sysconfig.get_path('purelib'))"
|
||||
python -m coveralls --basedir $prefix
|
||||
|
||||
- "run":
|
||||
name: "Convert Result Log"
|
||||
command: |
|
||||
# subunit2junitxml exits with error if the result stream it is
|
||||
# converting has test failures in it! So this step might fail.
|
||||
# Since the step in which we actually _ran_ the tests won't fail
|
||||
# even if there are test failures, this is a good thing for now.
|
||||
subunit2junitxml.exe --output-to=test-results.xml test-results.subunit2
|
||||
|
||||
- "store_test_results":
|
||||
path: "test-results.xml"
|
||||
|
||||
- "store_artifacts":
|
||||
path: "_trial_temp/test.log"
|
||||
|
||||
- "store_artifacts":
|
||||
path: "eliot.log"
|
||||
|
||||
- "store_artifacts":
|
||||
path: ".coverage"
|
||||
|
||||
pyinstaller:
|
||||
docker:
|
||||
- <<: *DOCKERHUB_AUTH
|
||||
@ -527,6 +725,15 @@ jobs:
|
||||
# PYTHON_VERSION: "2"
|
||||
|
||||
executors:
|
||||
windows:
|
||||
# Choose a Windows environment that closest matches our testing
|
||||
# requirements and goals.
|
||||
# https://circleci.com/developer/orbs/orb/circleci/windows#executors-server-2022
|
||||
machine:
|
||||
image: "windows-server-2022-gui:2023.06.1"
|
||||
shell: "powershell.exe -ExecutionPolicy Bypass"
|
||||
resource_class: "windows.large"
|
||||
|
||||
nix:
|
||||
docker:
|
||||
# Run in a highly Nix-capable environment.
|
||||
|
@ -19,7 +19,7 @@ skip_covered = True
|
||||
source =
|
||||
# It looks like this in the checkout
|
||||
src/
|
||||
# It looks like this in the Windows build environment
|
||||
# It looks like this in the GitHub Actions Windows build environment
|
||||
D:/a/tahoe-lafs/tahoe-lafs/.tox/py*-coverage/Lib/site-packages/
|
||||
# Although sometimes it looks like this instead. Also it looks like this on macOS.
|
||||
.tox/py*-coverage/lib/python*/site-packages/
|
||||
|
7
.github/workflows/ci.yml
vendored
7
.github/workflows/ci.yml
vendored
@ -44,13 +44,6 @@ jobs:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os:
|
||||
- windows-latest
|
||||
python-version:
|
||||
- "3.8"
|
||||
- "3.9"
|
||||
- "3.10"
|
||||
- "3.11"
|
||||
include:
|
||||
# On macOS don't bother with 3.8, just to get faster builds.
|
||||
- os: macos-12
|
||||
|
@ -23,6 +23,9 @@ import click.testing
|
||||
from ..common_util import (
|
||||
run_cli,
|
||||
)
|
||||
from ..common import (
|
||||
superuser,
|
||||
)
|
||||
from twisted.internet.defer import (
|
||||
inlineCallbacks,
|
||||
)
|
||||
@ -34,7 +37,6 @@ from twisted.python.runtime import (
|
||||
)
|
||||
from allmydata.util import jsonbytes as json
|
||||
|
||||
|
||||
class GridManagerCommandLine(TestCase):
|
||||
"""
|
||||
Test the mechanics of the `grid-manager` command
|
||||
@ -223,7 +225,7 @@ class GridManagerCommandLine(TestCase):
|
||||
)
|
||||
|
||||
@skipIf(platform.isWindows(), "We don't know how to set permissions on Windows.")
|
||||
@skipIf(os.getuid() == 0, "cannot test as superuser with all permissions")
|
||||
@skipIf(superuser, "cannot test as superuser with all permissions")
|
||||
def test_sign_bad_perms(self):
|
||||
"""
|
||||
Error reported if we can't create certificate file
|
||||
|
@ -117,6 +117,10 @@ from subprocess import (
|
||||
PIPE,
|
||||
)
|
||||
|
||||
# Is the process running as an OS user with elevated privileges (ie, root)?
|
||||
# We only know how to determine this for POSIX systems.
|
||||
superuser = getattr(os, "getuid", lambda: -1)() == 0
|
||||
|
||||
EMPTY_CLIENT_CONFIG = config_from_string(
|
||||
"/dev/null",
|
||||
"tub.port",
|
||||
|
@ -77,6 +77,7 @@ from allmydata.scripts.common import (
|
||||
from foolscap.api import flushEventualQueue
|
||||
import allmydata.test.common_util as testutil
|
||||
from .common import (
|
||||
superuser,
|
||||
EMPTY_CLIENT_CONFIG,
|
||||
SyncTestCase,
|
||||
AsyncBrokenTestCase,
|
||||
@ -151,7 +152,7 @@ class Basic(testutil.ReallyEqualMixin, unittest.TestCase):
|
||||
# EnvironmentError when reading a file that really exists), on
|
||||
# windows, please fix this
|
||||
@skipIf(platform.isWindows(), "We don't know how to set permissions on Windows.")
|
||||
@skipIf(os.getuid() == 0, "cannot test as superuser with all permissions")
|
||||
@skipIf(superuser, "cannot test as superuser with all permissions")
|
||||
def test_unreadable_config(self):
|
||||
basedir = "test_client.Basic.test_unreadable_config"
|
||||
os.mkdir(basedir)
|
||||
|
@ -62,6 +62,7 @@ from .common import (
|
||||
ConstantAddresses,
|
||||
SameProcessStreamEndpointAssigner,
|
||||
UseNode,
|
||||
superuser,
|
||||
)
|
||||
|
||||
def port_numbers():
|
||||
@ -325,7 +326,7 @@ class TestCase(testutil.SignalMixin, unittest.TestCase):
|
||||
self.assertEqual(config.items("nosuch", default), default)
|
||||
|
||||
@skipIf(platform.isWindows(), "We don't know how to set permissions on Windows.")
|
||||
@skipIf(os.getuid() == 0, "cannot test as superuser with all permissions")
|
||||
@skipIf(superuser, "cannot test as superuser with all permissions")
|
||||
def test_private_config_unreadable(self):
|
||||
"""
|
||||
Asking for inaccessible private config is an error
|
||||
@ -341,7 +342,7 @@ class TestCase(testutil.SignalMixin, unittest.TestCase):
|
||||
config.get_or_create_private_config("foo")
|
||||
|
||||
@skipIf(platform.isWindows(), "We don't know how to set permissions on Windows.")
|
||||
@skipIf(os.getuid() == 0, "cannot test as superuser with all permissions")
|
||||
@skipIf(superuser, "cannot test as superuser with all permissions")
|
||||
def test_private_config_unreadable_preexisting(self):
|
||||
"""
|
||||
error if reading private config data fails
|
||||
@ -398,7 +399,7 @@ class TestCase(testutil.SignalMixin, unittest.TestCase):
|
||||
self.assertEqual(len(counter), 1) # don't call unless necessary
|
||||
self.assertEqual(value, "newer")
|
||||
|
||||
@skipIf(os.getuid() == 0, "cannot test as superuser with all permissions")
|
||||
@skipIf(superuser, "cannot test as superuser with all permissions")
|
||||
def test_write_config_unwritable_file(self):
|
||||
"""
|
||||
Existing behavior merely logs any errors upon writing
|
||||
|
Loading…
Reference in New Issue
Block a user