Skip to content

Commit

Permalink
GitHub ci (#10)
Browse files Browse the repository at this point in the history
Migrating to github CI

* additional type checking on places
* included GPG test on the CI platform of Github
* refactored internet and CI detection for those test that require it.
  • Loading branch information
jberends authored Nov 26, 2019
1 parent 803a33f commit bdcd0e3
Show file tree
Hide file tree
Showing 13 changed files with 169 additions and 43 deletions.
4 changes: 2 additions & 2 deletions .env.template
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,6 @@
## KECHAIN_SCOPE_ID - the UUID of the project / scope.
##

KECHAIN_URL=https://kec2api.ke-chain.com
KECHAIN_URL=https://pim3-test.ke-chain.com
KECHAIN_TOKEN=... token from your user account ...
KECHAIN_SCOPE_ID = 6f7bc9f0-228e-4d3a-9dc0-ec5a75d73e1d
KECHAIN_SCOPE_ID=12345678-1234-5678-123456-7812345678
27 changes: 27 additions & 0 deletions .github/workflows/python_publish.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
name: Release kecpkg-tools

on:
release:
types: [created]

jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1
- name: Set up Python
uses: actions/setup-python@v1
with:
python-version: '3.7'
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install setuptools wheel twine>=2.0.0
- name: Build and publish
env:
TWINE_USERNAME: '__token__'
TWINE_PASSWORD: ${{ secrets.PYPI_TOKEN }}
TWINE_NON_INTERACTIVE: '1'
run: |
python setup.py sdist bdist_wheel --universal
twine upload dist/* --disable-progress-bar
56 changes: 56 additions & 0 deletions .github/workflows/python_testing.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
name: Test kecpkg-tools

on: [push]

jobs:
build:

runs-on: ubuntu-latest
strategy:
max-parallel: 7
fail-fast: False
matrix:
python-version: [2.7, 3.5, 3.6, 3.7, 3.8-dev, pypy2, pypy3]

steps:
- uses: actions/checkout@v1
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v1
with:
python-version: ${{ matrix.python-version }}

- name: Install OS dependencies
run: |
sudo apt-get install gpg --yes
- name: Install basic dependencies
run: |
python -m pip install --upgrade pip
pip install -U setuptools>=38.6.0 wheel>=0.31.0
pip install -r requirements.txt
- name: Perform Testing
run: |
pip install pytest pytest-runner pytest-cov coverage
python setup.py --quiet clean develop
pytest --cov=kecpkg tests
- name: Upload coverage to coveralls.io
if: matrix.python-version == 3.6
env:
COVERALLS_REPO_TOKEN: ${{ secrets.COVERALLS_REPO_TOKEN }}
run: |
pip install coveralls
coveralls
- name: Check docs and distribution
if: matrix.python-version == 3.6
run: |
pip install flake8 pydocstyle check-manifest readme_renderer[md] twine>=2.0.0
flake8 kecpkg --count --show-source --statistics
pydocstyle kecpkg
check-manifest
python setup.py check -m -s
python setup.py bdist_wheel --universal
twine check dist/*
1 change: 1 addition & 0 deletions .pyup.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
pin: False
File renamed without changes.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# Changelog

## 1.0.4 (26NOV19)
* Maintenance release.
* changed CI setup to use github actions. No end-user facing changes. #10

## 1.0.3 (21NOV19)
* Added the capability to change the `requirements.txt` path in the generated `package_info.json`. Thanks to @bastiaanbeijer

Expand Down
4 changes: 4 additions & 0 deletions MANIFEST.in
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ include requirements.txt
include Pipfile
include tox.ini
include .coveragerc
include snapcraft.yaml

graft tests
graft kecpkg
Expand All @@ -16,5 +17,8 @@ exclude build_release.sh
recursive-include kecpkg *.template

global-exclude *.pyc
exclude *-OFF
exclude *.yml
prune .github


2 changes: 1 addition & 1 deletion kecpkg/__init__.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
__version__ = '1.0.3'
__version__ = '1.0.4'
20 changes: 19 additions & 1 deletion kecpkg/gpg.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
import six

from kecpkg.settings import GNUPG_KECPKG_HOME
from kecpkg.utils import ON_LINUX, ON_WINDOWS, ON_MACOS, echo_failure, read_chunks, echo_info
from kecpkg.utils import ON_LINUX, ON_WINDOWS, ON_MACOS, echo_failure, read_chunks, echo_info, ensure_dir_exists

LOGLEVEL = logging.INFO

Expand All @@ -27,6 +27,20 @@ def hash_of_file(path, algorithm='sha256'):
__gpg = None # type: gnupg.GPG or None


def has_gpg():
# type: () -> bool
"""
Detect the presence of GPG in the OS.
:returns: true if GPG binary is found on the system, false if not
"""
try:
_ = get_gpg()
except SystemExit:
return False
return True


def get_gpg():
# type: () -> gnupg.GPG
"""Return the GPG objects instantiated with custom KECPKG keyring in custom KECPKG GNUPG home."""
Expand Down Expand Up @@ -63,6 +77,10 @@ def get_gpg():
echo_failure("- For Windows please install GnuPG using the downloads via: https://gnupg.org/download/")
sys.exit(1)

if not os.path.exists(GNUPG_KECPKG_HOME):
# create the GNUPG_KECPKG_HOME when not exist, otherwise the GPG will fail
ensure_dir_exists(GNUPG_KECPKG_HOME)

__gpg = gnupg.GPG(gpgbinary=gpg_bin, gnupghome=GNUPG_KECPKG_HOME)

return __gpg
Expand Down
12 changes: 10 additions & 2 deletions kecpkg/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,13 @@


def ensure_dir_exists(d):
"""Ensure that directory exists, otherwise make directory."""
# type: (str) -> None
"""Ensure that directory exists, otherwise make directory.
:param d: directory name
:type d: basestring
:return: None
"""
if not os.path.exists(d):
os.makedirs(d)

Expand All @@ -26,14 +32,16 @@ def create_file(filepath, content=None, overwrite=True):
Create file and optionally fill it with content.
Will overwrite file already in place if overwrite flag is set.
If a list is provided each line in the list is written on a new line in the file (`fp.writelines`)
otherwise the string will be written as such and newline characters (`\\\\n`) will be respected.
:param filepath: full path to a file to create
:param content: textual content.
:type content: list or string
:param overwrite: boolean if you want to overwrite
:return:
:return: None is file is created
:raises SystemExit: when the file already exists
"""
ensure_dir_exists(os.path.dirname(os.path.abspath(filepath)))
# if overwrite is set to True overwrite file, otherwise if file exist, exit.
Expand Down
38 changes: 21 additions & 17 deletions tests/commands/test_sign.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,17 @@
import os
import sys
from unittest import skipIf

import six

from kecpkg.cli import kecpkg
from kecpkg.gpg import list_keys, get_gpg
from kecpkg.gpg import list_keys, get_gpg, has_gpg
from kecpkg.utils import create_file
from tests.utils import BaseTestCase, temp_chdir

TEST_SECRET_KEY = """
# NOTE:
# For those that crawl on the internet to discover secrets
# This is not a secret key and purely generated for tests

TEST_THIS_IS_NOT_A_SECRET_KEY__NO_REALLY_NOT = """
-----BEGIN PGP PRIVATE KEY BLOCK-----
lQIGBFzLAUQBBADZqa2AjOwDRb6D/lkuNKRFwTHF1x2SnhinTv5bosUZDRakZ6zd
Expand All @@ -30,23 +34,22 @@
=Xq/K
-----END PGP PRIVATE KEY BLOCK-----
"""
TEST_SECRET_KEY_PASSPHRASE = "test"
TEST_SECRET_KEY_FINGERPRINT = "8D092FCC060BCC1E97CEC48987A177AAB2371E68"
TEST_THIS_IS_NOT_A_SECRET_PASSPHRASE = "test"
TEST_THIS_IS_NOT_A_SECRET_KEY_FINGERPRINT = "8D092FCC060BCC1E97CEC48987A177AAB2371E68"


@skipIf("TRAVIS" in os.environ and os.environ["TRAVIS"] == "true", "Skipping this test on Travis CI.")
@skipIf("sys.version_info <= (2, 7)",
reason="Skipping tests for python 2.7, as PGP signing cannot be provided")
@skipIf(six.PY2, reason="Skipping tests for python 2.7, as PGP signing cannot be provided")
@skipIf(not has_gpg(), reason='GPG not found on the system or python version is < 3.')
class TestCommandSign(BaseTestCase):

def _import_test_key(self):
with self.runner.isolated_filesystem() as d:
create_file('TESTKEY.asc', TEST_SECRET_KEY)
create_file('TESTKEY.asc', TEST_THIS_IS_NOT_A_SECRET_KEY__NO_REALLY_NOT)
self.runner.invoke(kecpkg, ['sign', '--import-key', 'TESTKEY.asc'])

def tearDown(self):
super(TestCommandSign, self).tearDown()
self.runner.invoke(kecpkg, ['sign', '--delete-key', TEST_SECRET_KEY_FINGERPRINT])
self.runner.invoke(kecpkg, ['sign', '--delete-key', TEST_THIS_IS_NOT_A_SECRET_KEY_FINGERPRINT])

def test_sign_list_keys(self):
self._import_test_key()
Expand All @@ -55,18 +58,18 @@ def test_sign_list_keys(self):

def test_import_key(self):
with temp_chdir() as d:
create_file('TESTKEY.asc', TEST_SECRET_KEY)
create_file('TESTKEY.asc', TEST_THIS_IS_NOT_A_SECRET_KEY__NO_REALLY_NOT)
result = self.runner.invoke(kecpkg, ['sign', '--import-key', 'TESTKEY.asc'])
self.assertEqual(result.exit_code, 0, "Results of the run were: \n---\n{}\n---".format(result.output))

# teardown
result = self.runner.invoke(kecpkg, ['sign', '--delete-key', TEST_SECRET_KEY_FINGERPRINT])
result = self.runner.invoke(kecpkg, ['sign', '--delete-key', TEST_THIS_IS_NOT_A_SECRET_KEY_FINGERPRINT])
self.assertEqual(result.exit_code, 0, "Results of the run were: \n---\n{}\n---".format(result.output))

def test_delete_key(self):
self._import_test_key()

result = self.runner.invoke(kecpkg, ['sign', '--delete-key', TEST_SECRET_KEY_FINGERPRINT])
result = self.runner.invoke(kecpkg, ['sign', '--delete-key', TEST_THIS_IS_NOT_A_SECRET_KEY_FINGERPRINT])
self.assertEqual(result.exit_code, 0, "Results of the run were: \n---\n{}\n---".format(result.output))

def test_delete_key_wrong_fingerprint(self):
Expand Down Expand Up @@ -98,13 +101,14 @@ def test_export_key(self):
with self.runner.isolated_filesystem() as d:
result = self.runner.invoke(kecpkg, ['sign',
'--export-key', 'out.asc',
'--keyid', TEST_SECRET_KEY_FINGERPRINT])
'--keyid', TEST_THIS_IS_NOT_A_SECRET_KEY_FINGERPRINT])
self.assertEqual(result.exit_code, 0, "Results of the run were: \n---\n{}\n---".format(result.output))
self.assertExists('out.asc')


@skipIf("sys.version_info >= (3, 4)", reason="These tests are for python 2 only.")
@skipIf(not has_gpg(), reason='GPG not found on the system or python version is < 3.')
@skipIf(six.PY3, reason="These tests are for python 2 only.")
class TestCommandSign27(BaseTestCase):
def test_sign_capability_unaivable(self):
def test_sign_capability_unavailable(self):
result = self.runner.invoke(kecpkg, ['sign', '--list'])
self.assertEqual(result.exit_code, 1, "Results of the run were: \n---\n{}\n---".format(result.output))
5 changes: 2 additions & 3 deletions tests/commands/test_upload.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,10 @@

from kecpkg.cli import kecpkg
from kecpkg.utils import get_package_dir
from tests.utils import temp_chdir, BaseTestCase
from tests.utils import temp_chdir, BaseTestCase, running_on_ci


@skipIf("os.getenv('TRAVIS', False)",
reason="Skipping tests when using Travis, as upload of services cannot be testing securely")
@skipIf(running_on_ci(), reason="Test do not work on a CI environment")
@skipIf("os.getenv('KECHAIN_URL') is None",
reason="Skipping test as the KECHAIN_URL is not available as environment variable. Cannot upload kecpkg to "
"test this functionality. Provice a `.env` file locally to enable these tests.")
Expand Down
39 changes: 22 additions & 17 deletions tests/utils.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
import os
import socket
from contextlib import contextmanager

from unittest import TestCase

import pytest
import six
from click.testing import CliRunner

Expand All @@ -16,10 +14,12 @@ def setUp(self):
def assertExists(self, path):
self.assertTrue(os.path.exists(path), "Path `{}` does not exists".format(path))


def is_travis():
"""Predicate to determine if the test is running in the context of Travis."""
return "TRAVIS" in os.environ and os.environ["TRAVIS"] == "true"


def is_python27():
"""Predicate to determine if the runtime version of python is version 2."""
import sys
Expand All @@ -41,36 +41,41 @@ def temp_chdir(cwd=None):
else:
from tempfile import mkdtemp
tempwd = mkdtemp(prefix="kecpkg_")
origin=cwd or os.getcwd()
origin = cwd or os.getcwd()
os.chdir(tempwd)
try:
yield tempwd if os.path.exists(tempwd) else ''
finally:
os.chdir(origin)


def touch_file(path):
"""Create an empty file in path.
:param path: path (filename)
"""
with open(path, 'a'):
os.utime(path, None)


def connected_to_internet(): # no cov
if os.environ.get('CI') and os.environ.get('TRAVIS'):
# type: () -> bool
"""If the system is connected to the internet."""
if running_on_ci():
return True
try:
# Test availability of DNS first
host = socket.gethostbyname('www.google.com')
host = socket.gethostbyname('ke-works.com')
# Test connection
socket.create_connection((host, 80), 2)
return True
except:
return False

def touch_file(path):
"""Create an empty file in path.

:param path: path (filename)
"""
with open(path, 'a'):
os.utime(path, None)



requires_internet = pytest.mark.skipif(
not connected_to_internet(), reason='Not connected to internet'
)
def running_on_ci(): # no cov
# type: () -> bool
"""If the system is running on a CI platform."""
if os.environ.get('CI') or os.environ.get('TRAVIS') or os.environ.get('GITHUB_ACTIONS'):
return True
return False

0 comments on commit bdcd0e3

Please sign in to comment.