diff --git a/.circleci/config.yml b/.circleci/config.yml index ff1f283..2c2a055 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -1,20 +1,101 @@ -version: 2 -jobs: - unit-test: +version: 2.1 +executors: + ubuntu_docker: docker: # Match target OS of TLJH - image: ubuntu:18.04 - working_directory: ~/repo + +commands: + setup_venv: + description: Setup hub venv + steps: + - run: + name: Setup venv + command: | + python3 -m venv /srv/venv + echo 'export PATH=/srv/venv/bin:$PATH' >> $BASH_ENV + + install_python: + description: Install python3, venv, git and make + steps: + - run: + name: install python + command: | + apt-get update --yes && apt-get install --yes python3 python3-venv git make + + build_systemd_image: + steps: + - run: + name: build systemd image + command: | + .circleci/integration-test.py build-image + + basic_tests: + parameters: + # Whether or not we should run update tests + upgrade: + type: string + default: "" + steps: + - run: + name: Run basic tests + command: | + BOOTSTRAP_PIP_SPEC=git+https://github.com/$CIRCLE_PROJECT_USERNAME/the-littlest-jupyterhub.git@$CIRCLE_SHA1 + + .circleci/integration-test.py run-test basic-tests \ + "$BOOTSTRAP_PIP_SPEC" test_hub.py test_install.py test_extensions.py \ + << parameters.upgrade >> + admin_tests: + parameters: + upgrade: + type: string + default: "" + steps: + - run: + name: Run admin tests + command: | + BOOTSTRAP_PIP_SPEC=git+https://github.com/$CIRCLE_PROJECT_USERNAME/the-littlest-jupyterhub.git@$CIRCLE_SHA1 + + .circleci/integration-test.py run-test \ + --installer-args "--admin admin:admin" \ + basic-tests $BOOTSTRAP_PIP_SPEC test_admin_installer.py \ + << parameters.upgrade >> + + plugin_tests: + parameters: + upgrade: + type: string + default: "" + steps: + - run: + name: Run plugin tests + command: | + BOOTSTRAP_PIP_SPEC=git+https://github.com/$CIRCLE_PROJECT_USERNAME/the-littlest-jupyterhub.git@$CIRCLE_SHA1 + + .circleci/integration-test.py run-test \ + --installer-args "--plugin /srv/src/integration-tests/plugins/simplest" \ + plugins $BOOTSTRAP_PIP_SPEC test_simplest_plugin.py \ + << parameters.upgrade >> + + bootstrap_checks: + parameters: + steps: + - run: + name: Run bootstrap checks + command: | + py.test integration-tests/test_bootstrap.py + + +jobs: + unit-test: + executor: ubuntu_docker steps: - checkout # Setup Python - - run: - name: install python - command: | - apt-get update --yes && apt-get install --yes python3 python3-venv git + - install_python # Download and cache dependencies - restore_cache: @@ -22,12 +103,7 @@ jobs: - v1-dependencies-py3.6-{{ checksum "setup.py" }}-{{ checksum "dev-requirements.txt" }} - v1-dependencies-py3.6- - - run: - name: Setup venv - command: | - python3 -m venv /srv/venv - echo 'export PATH=/srv/venv/bin:$PATH' >> $BASH_ENV - + - setup_venv - run: name: install dependencies command: | @@ -60,64 +136,69 @@ jobs: apk add --no-cache python3 pytest - checkout + - setup_remote_docker + - build_systemd_image + + - basic_tests + + - admin_tests + + - plugin_tests + + - bootstrap_checks + + + upgrade-test: + docker: + - image: docker:18.05.0-ce-git + + steps: - run: - name: build systemd image + name: Check upgrade testing command: | - .circleci/integration-test.py build-image + if [ "$CIRCLE_BRANCH" == "master" ]; then + echo "On master, no upgrade to test..." + circleci-agent step halt + else + echo "PR detected, testing upgrade..." + fi - run: - name: Run basic tests + name: setup python3 command: | - .circleci/integration-test.py run-test basic-tests test_hub.py test_install.py test_extensions.py + apk add --no-cache python3 pytest - - run: - name: Run admin tests - command: | - .circleci/integration-test.py run-test --installer-args "--admin admin:admin" basic-tests test_admin_installer.py + - checkout + - setup_remote_docker - - run: - name: Run plugin tests - command: | - .circleci/integration-test.py run-test \ - --installer-args "--plugin /srv/src/integration-tests/plugins/simplest" \ - plugins test_simplest_plugin.py + - build_systemd_image - - run: - name: Run bootstrap checks - command: | - py.test integration-tests/test_bootstrap.py + - basic_tests: + upgrade: "--upgrade" + - admin_tests: + upgrade: "--upgrade" + + - plugin_tests: + upgrade: "--upgrade" documentation: - docker: - # Match target OS of TLJH - - image: ubuntu:18.04 - - working_directory: ~/repo - + executor: ubuntu_docker steps: - checkout # Setup Python - - run: - name: install python - command: | - apt-get update --yes && apt-get install --yes python3 python3-venv git make + - install_python # Download and cache dependencies - restore_cache: key: v1-dependencies-py3.6-sphinx - - run: - name: Setup venv - command: | - python3 -m venv /srv/venv - echo 'export PATH=/srv/venv/bin:$PATH' >> $BASH_ENV - + - setup_venv - run: name: install dependencies command: | @@ -145,4 +226,5 @@ workflows: jobs: - unit-test - integration-test + - upgrade-test - documentation diff --git a/.circleci/integration-test.py b/.circleci/integration-test.py index 85d66ec..00f15e8 100755 --- a/.circleci/integration-test.py +++ b/.circleci/integration-test.py @@ -15,7 +15,7 @@ def build_systemd_image(image_name, source_path): ]) -def run_systemd_image(image_name, container_name): +def run_systemd_image(image_name, container_name, bootstrap_pip_spec): """ Run docker image with systemd @@ -23,7 +23,7 @@ def run_systemd_image(image_name, container_name): Container named container_name will be started. """ - subprocess.check_call([ + cmd = [ 'docker', 'run', '--privileged', '--mount', 'type=bind,source=/sys/fs/cgroup,target=/sys/fs/cgroup', @@ -33,8 +33,15 @@ def run_systemd_image(image_name, container_name): # to need at least this much RAM to build. Boo? # If we change this, need to change all other references to this number. '--memory', '1G', - image_name - ]) + ] + + if bootstrap_pip_spec: + cmd.append('-e') + cmd.append(f'TLJH_BOOTSTRAP_PIP_SPEC={bootstrap_pip_spec}') + + cmd.append(image_name) + + subprocess.check_call(cmd) def stop_container(container_name): @@ -74,29 +81,42 @@ def copy_to_container(container_name, src_path, dest_path): ]) -def run_test(image_name, test_name, test_files, installer_args): +def run_test(image_name, test_name, bootstrap_pip_spec, test_files, upgrade, installer_args): """ Wrapper that sets up tljh with installer_args & runs test_name """ stop_container(test_name) - run_systemd_image(image_name, test_name) + run_systemd_image(image_name, test_name, bootstrap_pip_spec) source_path = os.path.abspath( os.path.join(os.path.dirname(__file__), os.pardir) ) - copy_to_container(test_name, source_path, '/srv/src') + copy_to_container(test_name, os.path.join(source_path, 'bootstrap/.'), '/srv/src') + copy_to_container(test_name, os.path.join(source_path, 'integration-tests/'), '/srv/src') + + + # Install TLJH master first to test upgrades + if upgrade: + run_container_command( + test_name, + f'curl https://raw.githubusercontent.com/jupyterhub/the-littlest-jupyterhub/master/bootstrap/bootstrap.py | python3 -' + ) + run_container_command( test_name, - f'python3 /srv/src/bootstrap/bootstrap.py {installer_args}' + f'python3 /srv/src/bootstrap.py {installer_args}' + ) + + # Install pkgs from requirements in hub's pip, where + # the bootstrap script installed the others + run_container_command( + test_name, + '/opt/tljh/hub/bin/python3 -m pip install -r /srv/src/integration-tests/requirements.txt' ) run_container_command( test_name, - 'python3 -m pip install -r /srv/src/integration-tests/requirements.txt' - ) - run_container_command( - test_name, - 'python3 -m pytest -v {}'.format( + '/opt/tljh/hub/bin/python3 -m pytest -v {}'.format( ' '.join([os.path.join('/srv/src/integration-tests/', f) for f in test_files]) ) ) @@ -137,7 +157,9 @@ def main(): run_test_parser = subparsers.add_parser('run-test') run_test_parser.add_argument('--installer-args', default='') + run_test_parser.add_argument('--upgrade', action='store_true') run_test_parser.add_argument('test_name') + run_test_parser.add_argument('bootstrap_pip_spec') run_test_parser.add_argument('test_files', nargs='+') show_logs_parser = subparsers.add_parser('show-logs') @@ -148,7 +170,7 @@ def main(): image_name = 'tljh-systemd' if args.action == 'run-test': - run_test(image_name, args.test_name, args.test_files, args.installer_args) + run_test(image_name, args.test_name, args.bootstrap_pip_spec, args.test_files, args.upgrade, args.installer_args) elif args.action == 'show-logs': show_logs(args.container_name) elif args.action == 'run': @@ -156,7 +178,7 @@ def main(): elif args.action == 'copy': copy_to_container(args.container_name, args.src, args.dest) elif args.action == 'start-container': - run_systemd_image(image_name, args.container_name) + run_systemd_image(image_name, args.container_name, args.bootstrap_pip_spec) elif args.action == 'stop-container': stop_container(args.container_name) elif args.action == 'build-image': diff --git a/integration-tests/Dockerfile b/integration-tests/Dockerfile index 7fc244e..8972189 100644 --- a/integration-tests/Dockerfile +++ b/integration-tests/Dockerfile @@ -20,9 +20,9 @@ RUN systemctl set-default multi-user.target STOPSIGNAL SIGRTMIN+3 -# Set up image to be useful out of the box for development & CI -ENV TLJH_BOOTSTRAP_DEV=yes -ENV TLJH_BOOTSTRAP_PIP_SPEC=/srv/src -ENV PATH=/opt/tljh/hub/bin:${PATH} +# Uncomment these lines for a development install +#ENV TLJH_BOOTSTRAP_DEV=yes +#ENV TLJH_BOOTSTRAP_PIP_SPEC=/srv/src +#ENV PATH=/opt/tljh/hub/bin:${PATH} CMD ["/bin/bash", "-c", "exec /sbin/init --log-target=journal 3>&1"] diff --git a/integration-tests/requirements.txt b/integration-tests/requirements.txt index 271c563..a6f3d17 100644 --- a/integration-tests/requirements.txt +++ b/integration-tests/requirements.txt @@ -1,3 +1,3 @@ pytest pytest-asyncio -git+https://github.com/yuvipanda/hubtraf.git \ No newline at end of file +git+https://github.com/yuvipanda/hubtraf.git