Skip to content

Commit 0cf6a71

Browse files
committed
Add initial test suite
1 parent 1f6bb7d commit 0cf6a71

16 files changed

Lines changed: 670 additions & 163 deletions

File tree

.github/workflows/cli_setup.yml

Lines changed: 60 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -11,24 +11,27 @@ jobs:
1111
runs-on: ubuntu-latest
1212
container: ghcr.io/qmk/qmk_base_container
1313

14-
env:
15-
QMK_HOME: ~/qmk_firmware
16-
1714
steps:
1815
- uses: actions/checkout@v6
1916

2017
- name: Install dependencies
2118
run: apt-get update && apt-get install -y python3-venv
2219

20+
- name: Run unit test
21+
run:
22+
python3 -m venv .ci_venv
23+
source .ci_venv/bin/activate
24+
python3 -m pip install -r requirements-dev.txt
25+
pytest
26+
2327
- name: Run ci_tests
24-
run: ./ci_tests -a
28+
run: ./ci_tests
2529

2630
test_cli_linux_macos:
2731
needs: test_cli_base_container
2832

2933
runs-on: ${{ matrix.os }}
30-
env:
31-
QMK_HOME: ~/qmk_firmware
34+
3235
strategy:
3336
matrix:
3437
os: [macos-latest, ubuntu-latest]
@@ -43,14 +46,12 @@ jobs:
4346
python-version: ${{ matrix.python-version }}
4447

4548
- name: Run ci_tests
46-
run: ./ci_tests -a
49+
run: ./ci_tests
4750

4851
test_cli_win:
4952
needs: test_cli_base_container
5053

5154
runs-on: windows-latest
52-
env:
53-
QMK_HOME: $HOME/qmk_firmware
5455

5556
steps:
5657
- uses: actions/checkout@v6
@@ -59,19 +60,63 @@ jobs:
5960
uses: msys2/setup-msys2@v2
6061
with:
6162
update: true
62-
install: git mingw-w64-x86_64-toolchain mingw-w64-x86_64-python-pip mingw-w64-x86_64-python-build mingw-w64-x86_64-python-pillow mingw-w64-x86_64-rust
63+
install: git mingw-w64-x86_64-toolchain mingw-w64-x86_64-python-pip mingw-w64-x86_64-python-build mingw-w64-x86_64-python-pillow mingw-w64-x86_64-rust mingw-w64-x86_64-python-halo mingw-w64-x86_64-python-nh3 mingw-w64-x86_64-python-rpds-py
6364

6465
# Upgrade pip due to msys packaging + pypa/build/pull/736 issues
6566
- name: (MSYS2) Install Python dependencies
6667
shell: msys2 {0}
6768
run: |
6869
python3 -m pip install --break-system-packages --force-reinstall --upgrade pip
6970
70-
- name: (MSYS2) Install QMK CLI from source
71+
- name: Run ci_tests
7172
shell: msys2 {0}
73+
run: ./ci_tests
74+
75+
test_docker_container:
76+
needs: test_cli_base_container
77+
78+
runs-on: ubuntu-latest
79+
80+
env:
81+
TEST_TAG: qmkfm/qmk_cli:test
82+
83+
steps:
84+
- name: Set up Python
85+
uses: actions/setup-python@v6
86+
with:
87+
python-version: '3.9'
88+
89+
- name: Set up QEMU
90+
uses: docker/setup-qemu-action@v4
91+
92+
- name: Set up Docker Buildx
93+
uses: docker/setup-buildx-action@v4
94+
95+
- uses: actions/checkout@v6
96+
97+
- name: Install dependencies
98+
run: |
99+
python3 -m pip install --upgrade pip
100+
pip install setuptools wheel
101+
pip install -r requirements-dev.txt
102+
103+
- name: Build Python
72104
run: |
73105
python3 -m build
74-
python3 -m pip install --break-system-packages dist/qmk-*.tar.gz
75-
- name: (MSYS2) Run qmk setup -y
76-
shell: msys2 {0}
77-
run: qmk setup -y
106+
107+
- name: Build Test Container
108+
uses: docker/build-push-action@v7
109+
with:
110+
context: .
111+
load: true
112+
tags: ${{ env.TEST_TAG }}
113+
114+
- name: Test
115+
run: |
116+
docker run --rm ${{ env.TEST_TAG }} qmk setup -y
117+
118+
- name: Build All Containers
119+
uses: docker/build-push-action@v7
120+
with:
121+
context: .
122+
platforms: linux/amd64,linux/arm64

.github/workflows/docker-pr.yml

Lines changed: 0 additions & 42 deletions
This file was deleted.

ci_tests

Lines changed: 10 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -3,57 +3,23 @@
33
set -e
44
#set -x
55

6-
ADVANCED=false
76
TMPDIR=$(mktemp -d)
8-
QMK_HOME="$TMPDIR/qmk_firmware"
9-
export QMK_HOME
10-
11-
for arg in $@; do
12-
if [ "$arg" = "-a" ]; then
13-
ADVANCED=true
14-
fi
15-
done
16-
17-
if [ $ADVANCED = true ]; then
18-
echo "*** Running in advanced mode with tmp files in $TMPDIR"
19-
else
20-
echo "*** Running in basic mode with tmp files in $TMPDIR"
21-
fi
227

23-
# Setup our virtualenv
24-
if [ -e .ci_venv ]; then
25-
rm -rf .ci_venv
8+
trap "rm -rf $TMPDIR" EXIT
9+
10+
CI_VENV="$TMPDIR/.ci_venv"
11+
12+
# Avoid issues with building pillow as we install mingw-w64-x86_64-python-pillow
13+
if [[ "$(uname -s)" =~ ^MINGW64_NT.* ]]; then
14+
CI_VENV_ARGS="--system-site-packages"
2615
fi
2716

28-
python3 -m venv .ci_venv
29-
source .ci_venv/bin/activate
17+
python3 -m venv $CI_VENV_ARGS $CI_VENV
18+
source $CI_VENV/bin/activate
3019

3120
# Install dependencies
3221
python3 -m pip install -U pip wheel
3322
python3 -m pip install .
3423
python3 -m pip install -r requirements-dev.txt
3524

36-
# Ensure that qmk works
37-
echo "*** Testing 'qmk clone -h'"
38-
qmk clone -h
39-
#echo "*** Testing 'qmk config -a'" # Test disabled as `milc` at least 1.6.8+ returns False and thus non-zero exit code
40-
#qmk config -a
41-
echo "*** Testing 'qmk setup -n'"
42-
qmk setup -n
43-
44-
echo
45-
echo "*** Basic tests completed successfully!"
46-
47-
# Run advanced test if requested
48-
if [ $ADVANCED = true ]; then
49-
echo
50-
echo "*** Testing 'qmk setup -y'"
51-
qmk setup -y
52-
53-
echo
54-
echo "*** Advanced tests completed successfully!"
55-
fi
56-
57-
# Cleanup
58-
deactivate
59-
rm -rf .ci_venv $TMPDIR
25+
pytest -vv -m system --qmk=real

pyproject.toml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,10 @@ requires = [
44
"wheel"
55
]
66
build-backend = "setuptools.build_meta"
7+
8+
[tool.pytest.ini_options]
9+
markers = [
10+
"integration",
11+
"system",
12+
]
13+
addopts = "-m 'not (integration or system)'"

qmk_cli/git.py

Lines changed: 53 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,23 @@
11
"""Helpers for working with git.
22
"""
33
import subprocess
4+
import shutil
45

56
from milc import cli
67

7-
default_repo = 'qmk_firmware'
8-
default_fork = 'qmk/' + default_repo
9-
default_branch = 'master'
8+
DEFAULT_UPSTREAM = 'https://github.com/qmk/qmk_firmware'
109

1110

1211
def git_clone(url, destination, branch):
1312
git_clone = [
1413
'git',
1514
'clone',
1615
'--recurse-submodules',
17-
'--branch=' + branch,
16+
f'--branch={branch}',
1817
url,
1918
str(destination),
2019
]
21-
cli.log.debug('Git clone command: %s', git_clone)
20+
cli.log.debug(f'Git clone command: {git_clone}')
2221

2322
try:
2423
with subprocess.Popen(git_clone, stderr=subprocess.STDOUT, stdout=subprocess.PIPE, bufsize=1, universal_newlines=True, encoding='utf-8') as p:
@@ -28,13 +27,56 @@ def git_clone(url, destination, branch):
2827
except Exception as e:
2928
git_cmd = ' '.join([s.replace(' ', r'\ ') for s in git_clone])
3029

31-
cli.log.error("Could not run '%s': %s: %s", git_cmd, e.__class__.__name__, e)
30+
cli.log.error(f"Could not run '{git_cmd}': {e.__class__.__name__}:{e}")
3231
return False
3332

34-
if p.returncode == 0:
35-
cli.log.info('Successfully cloned %s to %s!', url, destination)
36-
return True
33+
if p.returncode != 0:
34+
cli.log.error(f'git clone exited {p.returncode}')
35+
return False
36+
37+
cli.log.info(f'Successfully cloned {url} to {destination}!')
38+
return True
39+
40+
41+
def git_set_upstream(destination):
42+
"""Add the qmk/qmk_firmware upstream to a qmk_firmware clone.
43+
"""
44+
git_cmd = [
45+
'git',
46+
'-C',
47+
destination,
48+
'remote',
49+
'add',
50+
'upstream',
51+
DEFAULT_UPSTREAM,
52+
]
3753

38-
else:
39-
cli.log.error('git clone exited %d', p.returncode)
54+
try:
55+
with subprocess.Popen(git_cmd, stderr=subprocess.STDOUT, stdout=subprocess.PIPE, bufsize=1, universal_newlines=True, encoding='utf-8') as p:
56+
for line in p.stdout:
57+
print(line, end='')
58+
59+
except Exception as e:
60+
git_cmd = ' '.join([s.replace(' ', r'\ ') for s in git_cmd])
61+
62+
cli.log.error(f"Could not run '{git_cmd}': {e.__class__.__name__}:{e}")
63+
return False
64+
65+
if p.returncode != 0:
66+
cli.log.error(f'git remote add exited {p.returncode}')
67+
return False
68+
69+
cli.log.info(f'Added {DEFAULT_UPSTREAM} as remote upstream.')
70+
return True
71+
72+
73+
def git_clone_fork(destination, baseurl, fork, branch, force=False):
74+
url = '/'.join((baseurl, fork))
75+
76+
if force:
77+
shutil.rmtree(destination)
78+
79+
if not git_clone(url, destination, branch):
4080
return False
81+
82+
return git_set_upstream(destination)

qmk_cli/subcommands/clone.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,6 @@ def clone(cli):
2323
# Exists (but not an empty dir)
2424
if cli.args.destination.exists() and any(cli.args.destination.iterdir()):
2525
cli.log.error('Destination already exists: %s', cli.args.destination)
26-
exit(1)
26+
return False
2727

2828
return git_clone(git_url, cli.args.destination, cli.args.branch)

qmk_cli/subcommands/env.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
"""Prints environment information.
22
"""
33
import os
4+
import sys
45
from pathlib import Path
56

67
from milc import cli
@@ -26,6 +27,10 @@ def env(cli):
2627
data[converted_key] = val
2728

2829
if cli.args.var:
30+
if cli.args.var not in data:
31+
print(f'Variable "{cli.args.var}" does not exist!', file=sys.stderr)
32+
return False
33+
2934
# dump out requested arg
3035
print(data[cli.args.var])
3136
else:

0 commit comments

Comments
 (0)