diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index cc23ecc..4f6231d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -19,6 +19,10 @@ jobs: os: ubuntu-latest - python: "3.10" os: ubuntu-latest + - python: "3.11" + os: ubuntu-latest + - python: "3.12" + os: ubuntu-latest - python: "3.10" os: macos-latest steps: @@ -31,7 +35,7 @@ jobs: with: python-version: ${{ matrix.python }} - - name: Install system packages + - name: Install system packages (linux) if: matrix.os == 'ubuntu-latest' run: | sudo apt-get update && \ @@ -39,12 +43,15 @@ jobs: tmux \ ; - - name: Install system packages + - name: Install system packages (macos) if: matrix.os == 'macos-latest' run: | brew install \ tmux \ + gpg \ ; + which -a gpg + gpg --version - name: Install tox run: pip install tox diff --git a/setup.py b/setup.py index c5c03d1..116c3ef 100644 --- a/setup.py +++ b/setup.py @@ -6,6 +6,7 @@ PyScaffold helps you to put up the scaffold of your new Python project. Learn more under: https://pyscaffold.org/ """ + from setuptools import setup if __name__ == "__main__": diff --git a/tests/conftest.py b/tests/conftest.py index 356467d..2671a66 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -13,6 +13,11 @@ from ansible_sign.signing import GPGSigner +if gnupg.__version__ >= "1.0": + # https://stackoverflow.com/q/35028852/99834 + pytest.exit("Unsupported gnupg library found, repair it with: pip3 uninstall -y gnupg && pip3 install python-gnupg") + + @pytest.fixture def tmux_session(request): """ diff --git a/tests/requirements.txt b/tests/requirements.txt index 45e2cf4..151006d 100644 --- a/tests/requirements.txt +++ b/tests/requirements.txt @@ -3,4 +3,4 @@ pytest pytest-mock flake8 yamllint -black +black>=24.3.0 diff --git a/tests/test_cli.py b/tests/test_cli.py index 005cab8..5f28c9b 100644 --- a/tests/test_cli.py +++ b/tests/test_cli.py @@ -1,4 +1,5 @@ import os +import sys import pytest from ansible_sign.cli import main @@ -6,6 +7,7 @@ __author__ = "Rick Elrod" __copyright__ = "(c) 2022 Red Hat, Inc." __license__ = "MIT" +IS_GITHUB_ACTION_MACOS = sys.platform == "darwin" and os.environ.get("CI", "false") == "true" @pytest.mark.parametrize( @@ -13,6 +15,8 @@ [ ( [ + "--debug", + "--nocolor", "project", "gpg-sign", "tests/fixtures/checksum/missing-manifest", @@ -23,6 +27,8 @@ ), ( [ + "--debug", + "--nocolor", "project", "gpg-sign", "tests/fixtures/checksum/manifest-syntax-error", @@ -33,6 +39,8 @@ ), ( [ + "--debug", + "--nocolor", "project", "gpg-verify", "tests/fixtures/checksum/manifest-success", @@ -43,6 +51,8 @@ ), ( [ + "--debug", + "--nocolor", "project", "gpg-verify", "--gnupg-home=/dir/that/does/not/exist/321", @@ -75,6 +85,8 @@ def test_main(capsys, args, exp_stdout_substr, exp_stderr_substr, exp_rc): [ ( [ + "--debug", + "--nocolor", "project", "gpg-verify", "--keyring={gpghome}/pubring.kbx", @@ -86,6 +98,8 @@ def test_main(capsys, args, exp_stdout_substr, exp_stderr_substr, exp_rc): ), ( [ + "--debug", + "--nocolor", "project", "gpg-verify", "--gnupg-home={gpghome}", @@ -97,6 +111,8 @@ def test_main(capsys, args, exp_stdout_substr, exp_stderr_substr, exp_rc): ), ( [ + "--debug", + "--nocolor", "project", "gpg-verify", "--gnupg-home={gpghome}", @@ -129,20 +145,40 @@ def test_main_with_pubkey_in_keyring(capsys, gpg_home_with_hao_pubkey, args, exp @pytest.mark.parametrize( "project_fixture, exp_stdout_substr, exp_stderr_substr, exp_rc", [ - ("signed_project_and_gpg", "GPG signature verification succeeded", "", 0), - ("signed_project_broken_manifest", "Invalid line encountered in checksum manifest", "", 1), - ("signed_project_missing_manifest", "Checksum manifest file does not exist:", "", 1), - ("signed_project_modified_manifest", "Checksum validation failed.", "", 2), - ("signed_project_with_different_gpg_home", "Re-run with the global --debug flag", "", 3), - ("signed_project_broken_manifest_in", "An error was encountered while parsing MANIFEST.in: unknown action 'invalid-directive'", "", 1), - ], - ids=[ - "valid checksum file and signature", - "valid signature but broken checksum file", - "missing checksum file entirely", - "checksum file with wrong hashes", - "matching pubkey does not exist in gpg home", - "broken MANIFEST.in after signing", + pytest.param( + "signed_project_and_gpg", + "GPG signature verification succeeded", + "", + 0, + id="valid checksum file and signature", + marks=pytest.mark.xfail(IS_GITHUB_ACTION_MACOS, reason="https://github.com/ansible/ansible-sign/issues/51"), + ), + pytest.param( + "signed_project_broken_manifest", + "Invalid line encountered in checksum manifest", + "", + 1, + id="valid signature but broken checksum file", + marks=pytest.mark.xfail(IS_GITHUB_ACTION_MACOS, reason="https://github.com/ansible/ansible-sign/issues/51"), + ), + pytest.param("signed_project_missing_manifest", "Checksum manifest file does not exist:", "", 1, id="missing checksum file entirely"), + pytest.param( + "signed_project_modified_manifest", + "Checksum validation failed.", + "", + 2, + id="checksum file with wrong hashes", + marks=pytest.mark.xfail(IS_GITHUB_ACTION_MACOS, reason="https://github.com/ansible/ansible-sign/issues/51"), + ), + pytest.param("signed_project_with_different_gpg_home", "Re-run with the global --debug flag", "", 3, id="matching pubkey does not exist in gpg home"), + pytest.param( + "signed_project_broken_manifest_in", + "An error was encountered while parsing MANIFEST.in: unknown action 'invalid-directive'", + "", + 1, + id="broken MANIFEST.in after signing", + marks=pytest.mark.xfail(IS_GITHUB_ACTION_MACOS, reason="https://github.com/ansible/ansible-sign/issues/51"), + ), ], ) def test_gpg_verify_manifest_scenario(capsys, request, project_fixture, exp_stdout_substr, exp_stderr_substr, exp_rc): @@ -153,6 +189,8 @@ def test_gpg_verify_manifest_scenario(capsys, request, project_fixture, exp_stdo (project_root, gpg_home) = request.getfixturevalue(project_fixture) keyring = os.path.join(gpg_home, "pubring.kbx") args = [ + "--debug", + "--nocolor", "project", "gpg-verify", f"--keyring={keyring}", diff --git a/tests/test_cli_pinentry.py b/tests/test_cli_pinentry.py index 91a1dfc..5b0bc9d 100644 --- a/tests/test_cli_pinentry.py +++ b/tests/test_cli_pinentry.py @@ -1,3 +1,5 @@ +import pytest +import sys import time __author__ = "Rick Elrod" @@ -5,6 +7,8 @@ __license__ = "MIT" +# On MacOS the is a dialog popup asking for password, not a console prompt. +@pytest.mark.skipif(sys.platform == "darwin", reason="Interactive test not working on MacOS") def test_pinentry_simple(tmux_session, gpg_home_with_secret_key, unsigned_project_with_checksum_manifest): """Test that we can sign a file with a pinentry program.""" home = gpg_home_with_secret_key @@ -17,9 +21,13 @@ def test_pinentry_simple(tmux_session, gpg_home_with_secret_key, unsigned_projec pane.send_keys(f"cd {unsigned_project_with_checksum_manifest}") pane.send_keys(f"ansible-sign project gpg-sign --gnupg-home {home} .") time.sleep(2) # Give the pinentry prompt time to show up. - out = "\n".join(pane.cmd("capture-pane", "-p").stdout) + cmd = pane.cmd("capture-pane", "-p") + assert cmd.returncode == 0 + out = "\n".join(cmd.stdout) assert "Passphrase: _" in out pane.send_keys("doYouEvenPassphrase") time.sleep(2) # Give time for returning to ansible-sign and signing to finish. - out = "\n".join(pane.cmd("capture-pane", "-p").stdout) + cmd = pane.cmd("capture-pane", "-p") + assert cmd.returncode == 0 + out = "\n".join(cmd.stdout) assert "GPG signing successful!" in out diff --git a/tox.ini b/tox.ini index 8c44fbe..7087438 100644 --- a/tox.ini +++ b/tox.ini @@ -11,6 +11,8 @@ deps = setenv = TOXINIDIR = {toxinidir} passenv = + CI + GITHUB_* HOME SETUPTOOLS_* extras =