diff --git a/.github/workflows/build-docker.yml b/.github/workflows/build-docker.yml index 49928c094..6535da407 100644 --- a/.github/workflows/build-docker.yml +++ b/.github/workflows/build-docker.yml @@ -154,7 +154,7 @@ jobs: with: token: ${{ secrets.GITHUB_TOKEN }} - name: Setup Selenium - run: pip install selenium==4.10.0 + run: pip install selenium - name: Wait for container startup run: | @@ -421,7 +421,7 @@ jobs: with: token: ${{ secrets.GITHUB_TOKEN }} - name: Setup Selenium - run: pip install selenium==4.10.0 + run: pip install selenium - name: Wait for container startup run: | set -e diff --git a/.github/workflows/build-lxd.yml b/.github/workflows/build-lxd.yml index 98738a94f..9b81a693c 100644 --- a/.github/workflows/build-lxd.yml +++ b/.github/workflows/build-lxd.yml @@ -208,7 +208,7 @@ jobs: with: token: ${{ secrets.GITHUB_TOKEN }} - name: Setup Selenium - run: pip install selenium==4.10.0 + run: pip install selenium - name: download LXD image from artifact store uses: actions/download-artifact@v3 with: @@ -331,7 +331,7 @@ jobs: with: token: ${{ secrets.GITHUB_TOKEN }} - name: Setup Selenium - run: pip install selenium==4.10.0 + run: pip install selenium - name: download LXD image from artifact store uses: actions/download-artifact@v3 with: diff --git a/.github/workflows/build-sd-images.yml b/.github/workflows/build-sd-images.yml index accd568eb..fededd8a5 100644 --- a/.github/workflows/build-sd-images.yml +++ b/.github/workflows/build-sd-images.yml @@ -173,7 +173,7 @@ jobs: set -x mv output/${ARTIFACT_FILE?} ncp.img sudo apt-get install -y systemd-container - sudo pip install selenium==4.10.0 + sudo pip install selenium sudo rm -rf raspbian_root . ./build/buildlib.sh mount_raspbian "ncp.img" diff --git a/.github/workflows/publish-image.yml b/.github/workflows/publish-image.yml index 3d09f30ff..49a083e80 100644 --- a/.github/workflows/publish-image.yml +++ b/.github/workflows/publish-image.yml @@ -64,7 +64,7 @@ jobs: success=false for i in {1..5} do - body="$(hub release show -f "%b" "${VERSION}")" + body="$(gh release view --json body "${VERSION}" | jq -r '.body')" if ! [[ "$body" =~ .*'**Checksums:**'.* ]] then @@ -80,7 +80,7 @@ jobs: \`\`\`" gh release edit "${VERSION?}" -n "$body" - if hub release show -f "%b" "${VERSION}" | grep "$checksum" + if gh release view --json body "${VERSION}" | jq -r '.body' | grep "$checksum" then success=true break diff --git a/.github/workflows/vm-tests.yml b/.github/workflows/vm-tests.yml index 289d878b9..e396fb6df 100644 --- a/.github/workflows/vm-tests.yml +++ b/.github/workflows/vm-tests.yml @@ -145,7 +145,8 @@ jobs: setup-ssh-port-forwarding "$SERVER_ADDRESS" echo "Run integration tests" - test-ncp-instance -a -f "$SNAPSHOT_ID" -b "${VERSION}" "root@${SERVER_ADDRESS}" "localhost" "8443" "9443" || { + ssh -o "StrictHostKeyChecking=no" -o "UserKnownHostsFile=/dev/null" "root@${SERVER_ADDRESS}" cat /usr/local/etc/instance.cfg + test-ncp-instance -a -f "$SNAPSHOT_ID" -b "${VERSION}" --systemtest-args "--skip-update-test" "root@${SERVER_ADDRESS}" "localhost" "8443" "9443" || { echo "Integration tests failed" echo "Here are the last lines of ncp-install.log:" @@ -217,7 +218,7 @@ jobs: echo "Run integration tests" setup-ssh-port-forwarding "$SERVER_ADDRESS" - test-ncp-instance -a -f "$SNAPSHOT_ID" -b "${VERSION}" "root@${SERVER_ADDRESS}" "localhost" "8443" "9443" || { + test-ncp-instance -a -f "$SNAPSHOT_ID" -b "${VERSION}" --systemtest-args "--skip-update-test" "root@${SERVER_ADDRESS}" "localhost" "8443" "9443" || { echo "Integration tests failed" echo "Here are the last lines of ncp-install.log:" diff --git a/bin/ncp-check-version b/bin/ncp-check-version index b60909a59..dc499ad65 100755 --- a/bin/ncp-check-version +++ b/bin/ncp-check-version @@ -16,7 +16,9 @@ git clone -b "$BRANCH" --depth 20 -q --bare https://github.com/nextcloud/nextclo cd "$TEMPDIR" || exit 1 VER=$( git describe --always --tags | grep -oP "v\d+\.\d+\.\d+" ) -canary="$(get_app_param ncp-community.sh CANARY)" +canary="$(. /usr/local/etc/library.sh; find_app_param ncp-community.sh CANARY)" +# TODO: Remove temporary canary override after staged rollouts test +canary="no" [[ "$canary" != "yes" ]] && [[ -f "/usr/local/etc/instance.cfg" ]] && { cohorte_id="$(jq .cohorteId /usr/local/etc/instance.cfg)" diff --git a/bin/ncp-provisioning.sh b/bin/ncp-provisioning.sh index 88960eda3..a34ac934f 100644 --- a/bin/ncp-provisioning.sh +++ b/bin/ncp-provisioning.sh @@ -3,7 +3,7 @@ # this script runs at startup to provide an unique random passwords for each instance source /usr/local/etc/library.sh - +set -x ## redis provisioning CFG=/var/www/nextcloud/config/config.php @@ -73,12 +73,13 @@ if needs_decrypt; then fi [[ -f /usr/local/etc/instance.cfg ]] || { - cohorte_id=$((1 + RANDOM % 100)) + cohorte_id=$((RANDOM % 100)) cat > /usr/local/etc/instance.cfg < CompletedProcess: + if r.returncode != 0: + print(f"{tc.red}error{tc.normal}\n{r.stdout.decode('utf-8') if r.stdout else ''}\n{r.stderr.decode('utf-8') if r.stderr else ''}" + f" -- command failed: '{' '.join(r.args)}'") + raise ProcessExecutionException() + return CompletedProcess(r.args, + r.returncode, + r.stdout.decode('utf-8') if r.stdout else '', + r.stderr.decode('utf-8') if r.stderr else '') + + def set_cohorte_id(cohorte_id: int) -> CompletedProcess: + proc = subprocess.Popen(pre_cmd + ['cat', '/usr/local/etc/instance.cfg'], stdout=subprocess.PIPE, shell=False) + #handle_error(run(pre_cmd + ['cat', '/usr/local/etc/instance.cfg'], stdout=subprocess.STDOUT, stderr=subprocess.STDOUT)) + #r = handle_error(run(pre_cmd + ['cat', '/usr/local/etc/instance.cfg'], stdout=PIPE, stderr=PIPE)) + (out, err) = proc.communicate() + if proc.returncode != 0: + raise ProcessExecutionException() + try: + instance_cfg = json.loads(out) + except json.decoder.JSONDecodeError as e: + print(f"{tc.red}error{tc.normal} /usr/local/etc/instance.cfg could not be parsed, was: {out}\n{err}") + print(f"Command: '{' '.join(pre_cmd + ['cat', '/usr/local/etc/instance.cfg'])}'") + raise e + + instance_cfg['cohorteId'] = cohorte_id + return handle_error(run(pre_cmd + ['bash', '-c', f'echo \'{json.dumps(instance_cfg)}\' > /usr/local/etc/instance.cfg'], stdout=PIPE, stderr=PIPE)) + + print(f"[updates] {tc.brown}staged rollouts{tc.normal}", end=' ') + try: + result = handle_error(run(pre_cmd + ['cat', '/usr/local/etc/ncp-version'], stdout=PIPE, stderr=PIPE)) + if 'v99.99.99' in result.stdout: + print(f"{tc.yellow}skipped{tc.normal} (already updated to v99.99.99)") + return True + handle_error(run(pre_cmd + ['rm', '-f', '/var/run/.ncp-latest-version'])) + handle_error(run(pre_cmd + ['sed', '-i', 's|BRANCH="master"|BRANCH="testing/staged-rollouts-1"|', '/usr/local/bin/ncp-check-version'], stdout=PIPE, stderr=PIPE)) + set_cohorte_id(1) + result = run(pre_cmd + ['test', '-f', '/var/run/.ncp-latest-version'], stdout=PIPE, stderr=PIPE) + if result.returncode == 0: + result = handle_error(run(pre_cmd + ['cat', '/var/run/.ncp-latest-version'], stdout=PIPE, stderr=PIPE)) + if 'v99.99.99' in result.stdout: + print(f"{tc.red}error{tc.normal} Auto update to v99.99.99 was unexpectedly not prevented by disabled cohorte id") + return False + + set_cohorte_id(99) + handle_error(run(pre_cmd + ['/usr/local/bin/ncp-check-version'], stdout=PIPE, stderr=PIPE)) + result = handle_error(run(pre_cmd + ['cat', '/var/run/.ncp-latest-version'], stdout=PIPE, stderr=PIPE)) + if 'v99.99.99' not in result.stdout: + print(f"{tc.red}error{tc.normal} Expected latest detected version to be v99.99.99, was {result.stdout}") + return False + + handle_error(run(pre_cmd + ['/usr/local/bin/ncp-test-updates'])) + handle_error(run(pre_cmd + ['ncp-update', 'testing/staged-rollouts-1'], stdout=PIPE, stderr=PIPE)) + result = handle_error(run(pre_cmd + ['cat', '/usr/local/etc/v99.99.99.success'], stdout=PIPE, stderr=PIPE)) + if 'updated' not in result.stdout: + print(f"{tc.red}error{tc.normal} update to v99.99.99 did not succeed") + return False + print(f"{tc.green}ok{tc.normal}") + + except ProcessExecutionException: + return False + + return True + if __name__ == "__main__": signal.signal(signal.SIGINT, signal_handler) # parse options try: - opts, args = getopt.getopt(sys.argv[1:], 'h', ['help', 'no-ping', 'non-interactive']) + opts, args = getopt.getopt(sys.argv[1:], 'h', ['help', 'no-ping', 'non-interactive', 'skip-update-test']) except getopt.GetoptError: usage() sys.exit(2) skip_ping = False interactive = True + skip_update_test = False for opt, arg in opts: if opt in ('-h', '--help'): usage() sys.exit(2) + elif opt == '--skip-update-test': + print("Skipping update test") + skip_update_test = True elif opt == '--no-ping': skip_ping = True elif opt == '--non-interactive': @@ -256,7 +331,7 @@ def signal_handler(sig, frame): tc.yellow + ssh_cmd + tc.normal + "...") binaries_must_be_installed = binaries_must_be_installed + binaries_no_docker pre_cmd = ['ssh', '-o UserKnownHostsFile=/dev/null' , '-o PasswordAuthentication=no', - '-o StrictHostKeyChecking=no', '-o ConnectTimeout=1', ssh_cmd[4:]] + '-o StrictHostKeyChecking=no', '-o ConnectTimeout=10', ssh_cmd[4:]] if not skip_ping: at_char = ssh_cmd.index('@') @@ -282,8 +357,9 @@ def signal_handler(sig, frame): files1_result = check_files_exist(files_must_exist) files2_result = check_files_dont_exist(files_must_not_exist) notify_push_result = check_notify_push() + update_test_result = True if skip_update_test else test_autoupdates() - if running_result and install_result and files1_result and files2_result and notify_push_result: + if running_result and install_result and files1_result and files2_result and notify_push_result and update_test_result: sys.exit(0) else: sys.exit(1) diff --git a/updates/1.52.5.sh b/updates/1.53.0sh similarity index 97% rename from updates/1.52.5.sh rename to updates/1.53.0sh index a81f3c9ba..c2c4fa807 100644 --- a/updates/1.52.5.sh +++ b/updates/1.53.0sh @@ -4,7 +4,7 @@ cohorte_id=$((RANDOM % 100)) cat > /usr/local/etc/instance.cfg <