Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Windows compatibility #3

Draft
wants to merge 11 commits into
base: master
Choose a base branch
from
75 changes: 75 additions & 0 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
name: Tests
on:
push:
branches: [ master ]
pull_request:
branches: [ master ]
jobs:
tests:
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ ubuntu-latest, macos-latest, windows-latest ]
python-version: ["3.6", "3.7", "3.8", "3.9", "3.10"]
include:
- os: ubuntu-latest
path: ~/.cache/pip
- os: macos-latest
path: ~/Library/Caches/pip
- os: windows-latest
path: ~\AppData\Local\pip\Cache
env:
OS: ${{ matrix.os }}
PYTHON: ${{ matrix.python-version }}

defaults:
run:
shell: bash

name: Python ${{ matrix.python-version }} on OS ${{ matrix.os }}
steps:

- name: Acquire sources
uses: actions/checkout@v2

- name: Setup Python
uses: actions/setup-python@v2
with:
python-version: ${{ matrix.python-version }}
architecture: x64

- uses: actions/cache@v2
with:
path: ${{ matrix.path }}
key: ${{ runner.os }}-py${{ matrix.python-version }}-${{ hashFiles('requirements-test.txt') }}

- name: Run tests
run: |
pip install --requirement=requirements-test.txt
pytest

- name: Upload test results to wacklig
if: always()
continue-on-error: true
env:
WACKLIG_TOKEN: ${{ secrets.WACKLIG_TOKEN }}
shell: bash
run: |
curl -s https://raw.githubusercontent.com/pipifein/wacklig-uploader/master/wacklig.py | python - --token $WACKLIG_TOKEN \
&& echo "Upload to wacklig succeeded" \
|| errcode=$?; echo "Upload to wacklig failed"; exit $errcode

# - name: Generate coverage report
# if: matrix.os == 'ubuntu-latest' && matrix.python-version == '3.9'
# run: |
# coverage xml
#
# - name: Upload coverage to Codecov
# if: matrix.os == 'ubuntu-latest' && matrix.python-version == '3.9'
# uses: codecov/codecov-action@v2
# with:
# files: ./coverage.xml
# flags: unittests
# env_vars: OS,PYTHON
# name: codecov-umbrella
# fail_ci_if_error: false
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
/.idea
/.venv*
/test-results
/.coverage
__pycache__
36 changes: 36 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# wacklig-uploader changelog


## in progress

- Tests: Add test harness
- Fix finding test report files recursively
- Tests: Add test for `main` function
- Tests: Run test harness on GHA
- Tests: Add Windows to test matrix on CI/GHA
- Tests: Fix tests on Windows
- Add compatibility with Windows regarding exclusive write-lock
at `NamedTemporaryFile` vs. `tarfile.open`


## 0.3.0 (2021-07-01)

- Make glob path to pick up test results less restrictive
- Detect GitHub Action environment


## 0.2.0 (2021-02-19)

- Don't print args/ci_info but server result instead


## 0.1.0 (2021-01-28)

- Adapt upload URI
- Add token and local/git ci info
- Add license and minimal readme


## 0.0.0 (2021-01-07)

- Initial commit
19 changes: 17 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,22 @@
# wacklig-uploader

A python script to upload test results to [wacklig][1].
## About

A Python script to upload test results to [wacklig].


[1]: https://wacklig.pipifein.dev/
## Tests

```shell
python3 -m venv .venv
source .venv/bin/activate
pip install --requirement=requirements-test.txt

# Run all tests.
pytest

# Run specific tests.
pytest -k test_upload_files
```

[wacklig]: https://wacklig.pipifein.dev/
24 changes: 24 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
[tool.isort]
profile = "black"
extend_skip = "wacklig.py"


[tool.black]
line_length = 120
extend_exclude = "wacklig.py"


[tool.pytest.ini_options]
addopts = """
-vvv
--cov --cov-report=term-missing
--junit-xml=test-results/test/junit.xml
"""

junit_suite_name = "wacklig_uploader"

# TODO: Write captured log messages to JUnit report: one of no|log|system-out|system-err|out-err|all
# junit_logging =

# TODO: Emit XML for schema: one of legacy|xunit1|xunit2
# junit_family =
5 changes: 5 additions & 0 deletions requirements-test.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
pytest>=6,<7
pytest-mock>=3,<4
pytest-cov>=3,<4
pyfakefs>=4,<5
mocket>=3,<4
7 changes: 7 additions & 0 deletions tests/conftest.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import os
import sys

# Make sure that the application source directory (this directory's parent) is
# on sys.path.
here = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
sys.path.insert(0, here)
31 changes: 31 additions & 0 deletions tests/junit-example.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<?xml version="1.0" encoding="utf-8"?>
<testsuites>
<testsuite name="wacklig_uploader" errors="0" failures="1" skipped="0" tests="9" time="0.118" timestamp="2021-12-18T03:51:53.894578" hostname="sink.local">
<testcase classname="tests.test_uploader" name="test_search_env_found" time="0.001"/>
<testcase classname="tests.test_uploader" name="test_search_env_notfound" time="0.000"/>
<testcase classname="tests.test_uploader" name="test_jenkins_env" time="0.002"/>
<testcase classname="tests.test_uploader" name="test_github_action_env" time="0.002"/>
<testcase classname="tests.test_uploader" name="test_get_ci_info_jenkins" time="0.002"/>
<testcase classname="tests.test_uploader" name="test_get_ci_info_github" time="0.001"/>
<testcase classname="tests.test_uploader" name="test_get_ci_info_local" time="0.001"/>
<testcase classname="tests.test_uploader" name="test_upload_files_empty" time="0.000"/>
<testcase classname="tests.test_uploader" name="test_upload_files_foo" time="0.003">
<failure message="SystemExit: No test files found">tmp_path = PosixPath('/private/var/folders/06/w9pzygdj7vx53n_0l9q_lhph0000gn/T/pytest-of-amo/pytest-5/test_upload_files_foo0')

def test_upload_files_foo(tmp_path):
&gt; upload_files(token=None, server=None, ci_info=None, files=None)

tests/test_uploader.py:95:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

token = None, server = None, ci_info = None, files = None

def upload_files(token, server, ci_info, files):
if not files:
&gt; raise SystemExit('No test files found')
E SystemExit: No test files found

wacklig.py:76: SystemExit</failure>
</testcase>
</testsuite>
</testsuites>
78 changes: 78 additions & 0 deletions tests/test_environment.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
import os
from unittest import mock
from unittest.mock import Mock

from wacklig import get_ci_info, github_action_env, jenkins_env, search_env


@mock.patch.dict(os.environ, {"CI_FOOBAR": "bazqux"})
def test_search_env_found():
value = search_env("CI_FOOBAR")
assert value == "bazqux"


def test_search_env_notfound():
value = search_env("CI_FOOBAR")
assert value is None


@mock.patch.dict(os.environ, {"JENKINS_URL": "https://jenkins.example.org/job/3f786850e3"})
@mock.patch.dict(os.environ, {"ghprbSourceBranch": "testdrive"})
@mock.patch.dict(os.environ, {"GIT_COMMIT": "3f786850e387550fdab836ed7e6dc881de23001b"})
@mock.patch.dict(os.environ, {"ghprbPullId": "111"})
@mock.patch.dict(os.environ, {"BUILD_NUMBER": "42"})
def test_get_ci_info_jenkins():
data = get_ci_info()
assert data == {
"service": "jenkins",
"branch": "testdrive",
"commit": "3f786850e387550fdab836ed7e6dc881de23001b",
"pr": "111",
"build": "42",
}


@mock.patch.dict(os.environ, {"GITHUB_ACTION": "true"})
@mock.patch.dict(os.environ, {"GITHUB_SHA": "3f786850e387550fdab836ed7e6dc881de23001b"})
@mock.patch.dict(os.environ, {"GITHUB_REF": "refs/pull/111/merge"})
@mock.patch.dict(os.environ, {"GITHUB_HEAD_REF": "feature-branch-1"})
@mock.patch.dict(os.environ, {"GITHUB_RUN_ID": "42"})
def test_get_ci_info_github_with_pr():
data = get_ci_info()
assert data == {
"service": "github-actions",
"commit": "3f786850e387550fdab836ed7e6dc881de23001b",
"build": "42",
"branch": "feature-branch-1",
"pr": "111",
}


@mock.patch.dict(os.environ, {"GITHUB_ACTION": "true"})
@mock.patch.dict(os.environ, {"GITHUB_SHA": "3f786850e387550fdab836ed7e6dc881de23001b"})
@mock.patch.dict(os.environ, {"GITHUB_REF": "refs/heads/feature-branch-1"})
@mock.patch.dict(os.environ, {"GITHUB_HEAD_REF": ""})
@mock.patch.dict(os.environ, {"GITHUB_RUN_ID": "42"})
def test_get_ci_info_github_with_branch():
data = get_ci_info()
assert data == {
"service": "github-actions",
"commit": "3f786850e387550fdab836ed7e6dc881de23001b",
"build": "42",
"branch": "feature-branch-1",
}


@mock.patch.dict(os.environ, {"JENKINS_URL": ""})
@mock.patch.dict(os.environ, {"GITHUB_ACTION": ""})
@mock.patch(
"wacklig.check_output",
Mock(side_effect=["testdrive", "3f786850e387550fdab836ed7e6dc881de23001b"]),
)
def test_get_ci_info_local():
data = get_ci_info()
assert data == {
"service": "local",
"branch": "testdrive",
"commit": "3f786850e387550fdab836ed7e6dc881de23001b",
}
Loading