From 9f7b6bdb261355db15157e0d457bd269ff15f2c6 Mon Sep 17 00:00:00 2001 From: Fabricio Aguiar Date: Tue, 18 May 2021 18:08:23 -0300 Subject: [PATCH] Upgrade tests Required PR: https://github.com/pulp/pulpcore/pull/1337 https://pulp.plan.io/issues/8719 closes #8719 --- .ci/ansible/settings.py.j2 | 2 +- .ci/scripts/cherrypick.sh | 64 +++++++++ .ci/scripts/publish_client_gem.sh | 4 +- .ci/scripts/publish_client_pypi.sh | 4 +- .ci/scripts/publish_plugin_pypi.sh | 6 +- .ci/scripts/release.py | 114 ++++++++++------ .ci/scripts/validate_commit_message.py | 11 +- .github/workflows/ci.yml | 79 +++++++++++ .github/workflows/scripts/before_install.sh | 76 ++++++++--- .github/workflows/scripts/before_script.sh | 2 +- .github/workflows/scripts/check_commit.sh | 1 + .github/workflows/scripts/install.sh | 2 +- .github/workflows/scripts/script.sh | 52 ++++++- CHANGES/8719.misc | 1 + pulp_file/tests/upgrade/__init__.py | 0 pulp_file/tests/upgrade/post/__init__.py | 0 pulp_file/tests/upgrade/post/test_publish.py | 136 +++++++++++++++++++ pulp_file/tests/upgrade/pre/__init__.py | 0 pulp_file/tests/upgrade/pre/test_publish.py | 124 +++++++++++++++++ template_config.yml | 13 +- 20 files changed, 615 insertions(+), 76 deletions(-) create mode 100755 .ci/scripts/cherrypick.sh create mode 100644 CHANGES/8719.misc create mode 100644 pulp_file/tests/upgrade/__init__.py create mode 100644 pulp_file/tests/upgrade/post/__init__.py create mode 100644 pulp_file/tests/upgrade/post/test_publish.py create mode 100644 pulp_file/tests/upgrade/pre/__init__.py create mode 100644 pulp_file/tests/upgrade/pre/test_publish.py diff --git a/.ci/ansible/settings.py.j2 b/.ci/ansible/settings.py.j2 index 56794bc03..3de131929 100644 --- a/.ci/ansible/settings.py.j2 +++ b/.ci/ansible/settings.py.j2 @@ -3,7 +3,7 @@ ANSIBLE_API_HOSTNAME = "http://pulp:80" ANSIBLE_CONTENT_HOSTNAME = "http://pulp:80/pulp/content" PRIVATE_KEY_PATH = "/etc/pulp/certs/token_private_key.pem" PUBLIC_KEY_PATH = "/etc/pulp/certs/token_public_key.pem" -TOKEN_SERVER = "http://pulp:80/token" +TOKEN_SERVER = "http://pulp:80/token/" TOKEN_SIGNATURE_ALGORITHM = "ES256" {% if pulp_settings %} diff --git a/.ci/scripts/cherrypick.sh b/.ci/scripts/cherrypick.sh new file mode 100755 index 000000000..537a826df --- /dev/null +++ b/.ci/scripts/cherrypick.sh @@ -0,0 +1,64 @@ +#!/bin/bash + +# WARNING: DO NOT EDIT! +# +# This file was generated by plugin_template, and is managed by it. Please use +# './plugin-template --github pulp_file' to update this file. +# +# For more info visit https://github.com/pulp/plugin_template + +set -e + +if [ $# -lt 3 ] +then + echo "Usage: .ci/scripts/cherrypick.sh [commit-hash] [original-issue-id] [backport-issue-id]" + echo " ex: .ci/scripts/cherrypick.sh abcd1234 1234 4567" + echo "" + echo "Note: make sure you are on a fork of the release branch before running this script." + exit +fi + +commit="$(git rev-parse $1)" +issue="$2" +backport="$3" +commit_message=$(git log --format=%B -n 1 $commit) + +if ! echo $commit_message | tr '[:upper:]' '[:lower:]' | grep -q "\[noissue\]" +then + if ! echo $commit_message | tr '[:upper:]' '[:lower:]' | grep -q -E "(fixes|closes).*#$issue" + then + echo "Error: issue $issue not detected in commit message." && exit 1 + fi +fi + +if [ "$4" = "--continue" ] +then + echo "Continue after manually resolving conflicts..." +elif [ "$4" = "" ] +then + if ! git cherry-pick --no-commit "$commit" + then + echo "Please resolve and add merge conflicts and restart this command with appended '--continue'." + exit 1 + fi +else + exit 1 +fi + +for file in $(find CHANGES -name "$issue.*") +do + newfile="${file/$issue/$backport}" + git mv "$file" "$newfile" + sed -i -e "\$a (backported from #$issue)" "$newfile" + git add "$newfile" +done + +commit_message="$(printf "$commit_message" | sed -E 's/(fixes|closes)/backports/i')" +commit_message="$commit_message + +fixes #$backport + +(cherry picked from commit $commit)" +git commit -m "$commit_message" + +printf "\nSuccessfully backported commit $1.\n" diff --git a/.ci/scripts/publish_client_gem.sh b/.ci/scripts/publish_client_gem.sh index 2d8364f6c..f28854d45 100755 --- a/.ci/scripts/publish_client_gem.sh +++ b/.ci/scripts/publish_client_gem.sh @@ -12,13 +12,15 @@ set -euv # make sure this script runs at the repo root cd "$(dirname "$(realpath -e "$0")")"/../.. +export PULP_URL="${PULP_URL:-http://pulp}" + mkdir ~/.gem || true touch ~/.gem/credentials echo "--- :rubygems_api_key: $RUBYGEMS_API_KEY" > ~/.gem/credentials sudo chmod 600 ~/.gem/credentials -export REPORTED_VERSION=$(http pulp/pulp/api/v3/status/ | jq --arg plugin file -r '.versions[] | select(.component == $plugin) | .version') +export REPORTED_VERSION=$(http pulp/pulp/api/v3/status/ | jq --arg plugin file --arg legacy_plugin pulp_file -r '.versions[] | select(.component == $plugin or .component == $legacy_plugin) | .version') export DESCRIPTION="$(git describe --all --exact-match `git rev-parse HEAD`)" if [[ $DESCRIPTION == 'tags/'$REPORTED_VERSION ]]; then export VERSION=${REPORTED_VERSION} diff --git a/.ci/scripts/publish_client_pypi.sh b/.ci/scripts/publish_client_pypi.sh index 0af52ad15..620e8ae2a 100755 --- a/.ci/scripts/publish_client_pypi.sh +++ b/.ci/scripts/publish_client_pypi.sh @@ -9,12 +9,14 @@ set -euv +export PULP_URL="${PULP_URL:-http://pulp}" + # make sure this script runs at the repo root cd "$(dirname "$(realpath -e "$0")")"/../.. pip install twine -export REPORTED_VERSION=$(http pulp/pulp/api/v3/status/ | jq --arg plugin file -r '.versions[] | select(.component == $plugin) | .version') +export REPORTED_VERSION=$(http pulp/pulp/api/v3/status/ | jq --arg plugin file --arg legacy_plugin pulp_file -r '.versions[] | select(.component == $plugin or .component == $legacy_plugin) | .version') export DESCRIPTION="$(git describe --all --exact-match `git rev-parse HEAD`)" if [[ $DESCRIPTION == 'tags/'$REPORTED_VERSION ]]; then export VERSION=${REPORTED_VERSION} diff --git a/.ci/scripts/publish_plugin_pypi.sh b/.ci/scripts/publish_plugin_pypi.sh index 3392df248..574555dcd 100755 --- a/.ci/scripts/publish_plugin_pypi.sh +++ b/.ci/scripts/publish_plugin_pypi.sh @@ -12,8 +12,10 @@ cd "$(dirname "$(realpath -e "$0")")"/../.. set -euv -export VERSION=$(http pulp/pulp/api/v3/status/ | jq --arg plugin file -r '.versions[] | select(.component == $plugin) | .version') -export response=$(curl --write-out %{http_code} --silent --output /dev/null https://pypi.org/project/pulp-file-client/$VERSION/) +export PULP_URL="${PULP_URL:-http://pulp}" + +export VERSION=$(http pulp/pulp/api/v3/status/ | jq --arg plugin file --arg legacy_plugin pulp_file -r '.versions[] | select(.component == $plugin or .component == $legacy_plugin) | .version') +export response=$(curl --write-out %{http_code} --silent --output /dev/null https://pypi.org/project/pulp-file/$VERSION/) if [ "$response" == "200" ]; then echo "pulp_file $VERSION has already been released. Skipping." diff --git a/.ci/scripts/release.py b/.ci/scripts/release.py index 9d271ed8d..7ed9cfeb8 100644 --- a/.ci/scripts/release.py +++ b/.ci/scripts/release.py @@ -6,90 +6,79 @@ # For more info visit https://github.com/pulp/plugin_template import argparse -import json import re import os import textwrap -from collections import defaultdict -from pathlib import Path from git import Repo + +from collections import defaultdict +from pathlib import Path from redminelib import Redmine -from redminelib.exceptions import ResourceAttrError +from redminelib.exceptions import ResourceAttrError, ResourceSetIndexError +import json REDMINE_URL = "https://pulp.plan.io" REDMINE_QUERY_URL = f"{REDMINE_URL}/issues?set_filter=1&status_id=*&issue_id=" +REDMINE_PROJECT = "pulp_file" -def validate_redmine_data(redmine_query_url, redmine_issues): +def validate_redmine_data(redmine_query_url, redmine_issues, release_version): """Validate redmine milestone.""" + error_messages = [] redmine = Redmine("https://pulp.plan.io") - project_set = set() + redmine_project = redmine.project.get(REDMINE_PROJECT) + if redmine_project is None: + error_messages.append(f"Redmine project {REDMINE_PROJECT} not found.") + try: + milestone = redmine_project.versions.filter(name=release_version)[0] + except ResourceSetIndexError: + error_messages.append(f"Milestone {release_version} not found.") + stats = defaultdict(list) - milestone_url = "\n[noissue]" - milestone_id = None for issue in redmine_issues: redmine_issue = redmine.issue.get(int(issue)) project_name = redmine_issue.project.name - project_set.update([project_name]) stats[f"project_{project_name.lower().replace(' ', '_')}"].append(issue) + if project_name != redmine_project.name: + stats["wrong_project"].append(issue) status = redmine_issue.status.name if "CLOSE" not in status and status != "MODIFIED": stats["status_not_modified"].append(issue) try: - milestone = redmine_issue.fixed_version.name - milestone_id = redmine_issue.fixed_version.id - stats[f"milestone_{milestone}"].append(issue) + issue_milestone = redmine_issue.fixed_version + if redmine_issue.fixed_version.id != milestone.id: + stats["wrong_milestone"].append(issue) + stats[f"milestone_{issue_milestone.name}"].append(issue) except ResourceAttrError: stats["without_milestone"].append(issue) - if milestone_id is not None: - milestone_url = f"Redmine Milestone: {REDMINE_URL}/versions/{milestone_id}.json\n[noissue]" - print(f"\n\nRedmine stats: {json.dumps(stats, indent=2)}") - error_messages = [] + if stats.get("wrong_project"): + error_messages.append( + f"One or more issues are associated to the wrong project {stats['wrong_project']}" + ) if stats.get("status_not_modified"): error_messages.append(f"One or more issues are not MODIFIED {stats['status_not_modified']}") if stats.get("without_milestone"): error_messages.append( f"One or more issues are not associated with a milestone {stats['without_milestone']}" ) - if len(project_set) > 1: - error_messages.append(f"Issues with different projects - {project_set}") + if stats.get("wrong_milestone"): + error_messages.append( + f"One or more issues are associated to the wrong milestone {stats['wrong_milestone']}" + ) + if error_messages: error_messages.append(f"Verify at {redmine_query_url}") raise RuntimeError("\n".join(error_messages)) - return milestone_url - + return f"{milestone.url}.json" -release_path = os.path.dirname(os.path.abspath(__file__)) -plugin_path = release_path.split("/.ci")[0] - -plugin_name = "pulp_file" -version = None -with open(f"{plugin_path}/setup.py") as fp: - for line in fp.readlines(): - if "version=" in line: - version = re.split("\"|'", line)[1] - if not version: - raise RuntimeError("Could not detect existing version ... aborting.") -release_version = version.replace(".dev", "") - - -issues_to_close = set() -for filename in Path(f"{plugin_path}/CHANGES").rglob("*"): - if filename.stem.isdigit(): - issue = filename.stem - issues_to_close.add(issue) - -issues = ",".join(issues_to_close) -redmine_final_query = f"{REDMINE_QUERY_URL}{issues}" -milestone_url = validate_redmine_data(redmine_final_query, issues_to_close) helper = textwrap.dedent( """\ @@ -127,6 +116,31 @@ def validate_redmine_data(redmine_query_url, redmine_issues): args = parser.parse_args() +release_path = os.path.dirname(os.path.abspath(__file__)) +plugin_path = release_path.split("/.ci")[0] + +plugin_name = "pulp_file" +version = None +with open(f"{plugin_path}/setup.py") as fp: + for line in fp.readlines(): + if "version=" in line: + version = re.split("\"|'", line)[1] + if not version: + raise RuntimeError("Could not detect existing version ... aborting.") +release_version = version.replace(".dev", "") + + +issues_to_close = set() +for filename in Path(f"{plugin_path}/CHANGES").rglob("*"): + if filename.stem.isdigit(): + issue = filename.stem + issues_to_close.add(issue) + +issues = ",".join(issues_to_close) +redmine_final_query = f"{REDMINE_QUERY_URL}{issues}" +milestone_url = validate_redmine_data(redmine_final_query, issues_to_close, release_version) + + release_type = args.release_type if "pulpcore" not in release_path: @@ -164,11 +178,21 @@ def validate_redmine_data(redmine_query_url, redmine_issues): git.add(f"{plugin_path}/setup.py") git.add(f"{plugin_path}/requirements.txt") git.add(f"{plugin_path}/.bumpversion.cfg") + git.commit( "-m", - f"Release {release_version}\n\nRedmine Query: {redmine_final_query}\n{milestone_url}", + "\n".join( + [ + f"Release {release_version}", + "", + f"Redmine Query: {redmine_final_query}", + f"Redmine Milestone: {milestone_url}", + "[noissue]", + ] + ), ) + sha = repo.head.object.hexsha short_sha = git.rev_parse(sha, short=7) @@ -198,6 +222,8 @@ def validate_redmine_data(redmine_query_url, redmine_issues): git.add(f"{plugin_path}/.bumpversion.cfg") git.commit("-m", f"Bump to {new_dev_version}\n\n[noissue]") + print(f"\n\nRedmine query of issues to close:\n{redmine_final_query}") + print(f"Release commit == {short_sha}") print(f"All changes were committed on branch: release_{release_version}") diff --git a/.ci/scripts/validate_commit_message.py b/.ci/scripts/validate_commit_message.py index 84e8766bd..e25162ec4 100644 --- a/.ci/scripts/validate_commit_message.py +++ b/.ci/scripts/validate_commit_message.py @@ -6,16 +6,21 @@ # For more info visit https://github.com/pulp/plugin_template import re -import requests import subprocess import sys from pathlib import Path -KEYWORDS = ["fixes", "closes", "re", "ref"] + +import requests + + NO_ISSUE = "[noissue]" +CHANGELOG_EXTS = [".feature", ".bugfix", ".doc", ".removal", ".misc", ".deprecation"] + + +KEYWORDS = ["fixes", "closes", "re", "ref"] STATUSES = ["NEW", "ASSIGNED", "POST", "MODIFIED"] REDMINE_URL = "https://pulp.plan.io" -CHANGELOG_EXTS = [".feature", ".bugfix", ".doc", ".removal", ".misc", ".deprecation"] sha = sys.argv[1] project = "pulp_file" diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 6a5a4057b..ebd7463de 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -128,3 +128,82 @@ jobs: docker exec pulp ls -latr /etc/yum.repos.d/ || true docker exec pulp cat /etc/yum.repos.d/* || true docker exec pulp pip3 list + + upgrade: + runs-on: ubuntu-latest + needs: lint + strategy: + fail-fast: false + matrix: + include: + - FROM_PULPCORE_BRANCH: "3.11" + FROM_PULP_FILE_BRANCH: "1.6" + FROM_PULP_CERTGUARD_BRANCH: "1.2" + - FROM_PULPCORE_BRANCH: "3.10" + FROM_PULP_FILE_BRANCH: "1.5" + FROM_PULP_CERTGUARD_BRANCH: "1.2" + - FROM_PULPCORE_BRANCH: "3.9" + FROM_PULP_FILE_BRANCH: "1.4" + FROM_PULP_CERTGUARD_BRANCH: "1.1" + + steps: + - uses: actions/checkout@v2 + with: + # by default, it uses a depth of 1 + # this fetches all history so that we can read each commit + fetch-depth: 0 + + - uses: actions/setup-python@v2 + with: + python-version: "3.7" + + - name: Install httpie + run: | + echo ::group::HTTPIE + sudo apt-get update -yq + sudo -E apt-get -yq --no-install-suggests --no-install-recommends install httpie + echo ::endgroup:: + echo "TEST=upgrade" >> $GITHUB_ENV + echo "HTTPIE_CONFIG_DIR=$GITHUB_WORKSPACE/.ci/assets/httpie/" >> $GITHUB_ENV + echo "FROM_PULP_FILE_BRANCH=${{ matrix.FROM_PULP_FILE_BRANCH }}" >> $GITHUB_ENV + echo "FROM_PULPCORE_BRANCH=${{ matrix.FROM_PULPCORE_BRANCH }}" >> $GITHUB_ENV + echo "FROM_PULP_CERTGUARD_BRANCH=${{ matrix.FROM_PULP_CERTGUARD_BRANCH }}" >> $GITHUB_ENV + + - name: Install python dependencies + run: | + echo ::group::PYDEPS + pip install wheel + echo ::endgroup:: + + - name: Before Install + run: .github/workflows/scripts/before_install.sh + shell: bash + + - name: Install + run: .github/workflows/scripts/install.sh + env: + PY_COLORS: '1' + ANSIBLE_FORCE_COLOR: '1' + shell: bash + + - name: Before Script + run: .github/workflows/scripts/before_script.sh + + - name: Setting secrets + run: python3 .github/workflows/scripts/secrets.py "$SECRETS_CONTEXT" + env: + SECRETS_CONTEXT: ${{ toJson(secrets) }} + + - name: Upgrade test + run: .github/workflows/scripts/script.sh + + - name: After failure + if: failure() + run: | + http --timeout 30 --check-status --pretty format --print hb http://pulp/pulp/api/v3/status/ || true + docker images || true + docker ps -a || true + docker logs pulp || true + docker exec pulp ls -latr /etc/yum.repos.d/ || true + docker exec pulp cat /etc/yum.repos.d/* || true + docker exec pulp pip3 list diff --git a/.github/workflows/scripts/before_install.sh b/.github/workflows/scripts/before_install.sh index 049049469..3eb109e85 100755 --- a/.github/workflows/scripts/before_install.sh +++ b/.github/workflows/scripts/before_install.sh @@ -27,6 +27,18 @@ else BRANCH="${GITHUB_REF##refs/tags/}" fi +if [[ "$TEST" == "upgrade" ]]; then + git checkout -b ci_upgrade_test + cp -R .github /tmp/.github + cp -R .ci /tmp/.ci + git checkout $FROM_PULP_FILE_BRANCH + rm -rf .ci .github + cp -R /tmp/.github . + cp -R /tmp/.ci . + # Pin deps + sed -i "s/~/=/g" requirements.txt +fi + if [[ "$TEST" == "plugin-from-pypi" ]]; then COMPONENT_VERSION=$(http https://pypi.org/pypi/pulp-file/json | jq -r '.info.version') else @@ -70,6 +82,7 @@ else export CI_BASE_IMAGE= fi + cd .. git clone --depth=1 https://github.com/pulp/pulp-openapi-generator.git @@ -80,25 +93,6 @@ if [ -n "$PULP_OPENAPI_GENERATOR_PR_NUMBER" ]; then cd .. fi -cd pulp-openapi-generator -sed -i -e 's/localhost:24817/pulp/g' generate.sh -sed -i -e 's/:24817/pulp/g' generate.sh -cd .. - - -git clone --depth=1 https://github.com/pulp/pulp-cli.git -if [ -n "$PULP_CLI_PR_NUMBER" ]; then - cd pulp-cli - git fetch origin pull/$PULP_CLI_PR_NUMBER/head:$PULP_CLI_PR_NUMBER - git checkout $PULP_CLI_PR_NUMBER - cd .. -fi - -cd pulp-cli -pip install -e . -pulp config create --base-url http://pulp --location tests/settings.toml -cd .. - git clone --depth=1 https://github.com/pulp/pulpcore.git --branch master @@ -122,6 +116,21 @@ fi pip install --upgrade --force-reinstall ./pulp-smash +git clone --depth=1 https://github.com/pulp/pulp-cli.git +if [ -n "$PULP_CLI_PR_NUMBER" ]; then + cd pulp-cli + git fetch origin pull/$PULP_CLI_PR_NUMBER/head:$PULP_CLI_PR_NUMBER + git checkout $PULP_CLI_PR_NUMBER + cd .. +fi + +cd pulp-cli +pip install -e . +pulp config create --base-url http://pulp --location tests/settings.toml +sed -i "s/true/false/g" tests/settings.toml +mkdir ~/.config/pulp +cp tests/settings.toml ~/.config/pulp/settings.toml +cd .. git clone --depth=1 https://github.com/pulp/pulp-certguard.git --branch master if [ -n "$PULP_CERTGUARD_PR_NUMBER" ]; then @@ -131,10 +140,37 @@ if [ -n "$PULP_CERTGUARD_PR_NUMBER" ]; then cd .. fi + +if [[ "$TEST" == "upgrade" ]]; then + cd pulpcore + git checkout -b ci_upgrade_test + git fetch --depth=1 origin heads/$FROM_PULPCORE_BRANCH:$FROM_PULPCORE_BRANCH + git checkout $FROM_PULPCORE_BRANCH + # Pin deps + sed -i "s/~/=/g" requirements.txt + cd .. + cd pulp-certguard + git checkout -b ci_upgrade_test + git fetch --depth=1 origin heads/$FROM_PULP_CERTGUARD_BRANCH:$FROM_PULP_CERTGUARD_BRANCH + git checkout $FROM_PULP_CERTGUARD_BRANCH + # Pin deps + sed -i "s/~/=/g" requirements.txt + cd .. +fi + + # Intall requirements for ansible playbooks pip install docker netaddr boto3 ansible -ansible-galaxy collection install amazon.aws +for i in {1..3} +do + ansible-galaxy collection install amazon.aws && s=0 && break || s=$? && sleep 3 +done +if [[ $s -gt 0 ]] +then + echo "Failed to install amazon.aws" + exit $s +fi cd pulp_file diff --git a/.github/workflows/scripts/before_script.sh b/.github/workflows/scripts/before_script.sh index 177caa1c4..1d0920935 100755 --- a/.github/workflows/scripts/before_script.sh +++ b/.github/workflows/scripts/before_script.sh @@ -29,7 +29,7 @@ tail -v -n +1 .ci/ansible/vars/main.yaml echo "PULP CONFIG:" tail -v -n +1 .ci/ansible/settings/settings.* ~/.config/pulp_smash/settings.json -if [[ "$TEST" == 'pulp' || "$TEST" == 'performance' || "$TEST" == 's3' || "$TEST" == "plugin-from-pypi" ]]; then +if [[ "$TEST" == 'pulp' || "$TEST" == 'performance' || "$TEST" == 'upgrade' || "$TEST" == 's3' || "$TEST" == "plugin-from-pypi" ]]; then # Many functional tests require these cmd_prefix dnf install -yq lsof which dnf-plugins-core fi diff --git a/.github/workflows/scripts/check_commit.sh b/.github/workflows/scripts/check_commit.sh index b5d7e6ade..c26c1f5c8 100755 --- a/.github/workflows/scripts/check_commit.sh +++ b/.github/workflows/scripts/check_commit.sh @@ -14,6 +14,7 @@ set -euv echo ::group::REQUESTS pip3 install requests + echo ::endgroup:: for sha in $(curl $GITHUB_CONTEXT | jq '.[].sha' | sed 's/"//g') diff --git a/.github/workflows/scripts/install.sh b/.github/workflows/scripts/install.sh index 854407ebb..4e9748992 100755 --- a/.github/workflows/scripts/install.sh +++ b/.github/workflows/scripts/install.sh @@ -87,7 +87,7 @@ cat >> vars/main.yaml << VARSYAML pulp_settings: {"allowed_content_checksums": ["sha1", "sha224", "sha256", "sha384", "sha512"], "allowed_export_paths": ["/tmp"], "allowed_import_paths": ["/tmp"]} VARSYAML -if [[ "$TEST" == "pulp" || "$TEST" == "performance" || "$TEST" == "s3" || "$TEST" == "plugin-from-pypi" ]]; then +if [[ "$TEST" == "pulp" || "$TEST" == "performance" || "$TEST" == "upgrade" || "$TEST" == "s3" || "$TEST" == "plugin-from-pypi" ]]; then sed -i -e '/^services:/a \ - name: pulp-fixtures\ image: docker.io/pulp/pulp-fixtures:latest\ diff --git a/.github/workflows/scripts/script.sh b/.github/workflows/scripts/script.sh index 4857950b9..259342c1e 100755 --- a/.github/workflows/scripts/script.sh +++ b/.github/workflows/scripts/script.sh @@ -26,9 +26,11 @@ export FUNC_TEST_SCRIPT=$PWD/.github/workflows/scripts/func_test_script.sh export DJANGO_SETTINGS_MODULE=pulpcore.app.settings export PULP_SETTINGS=$PWD/.ci/ansible/settings/settings.py +export PULP_URL="http://pulp" + if [[ "$TEST" = "docs" || "$TEST" = "publish" ]]; then cd docs - make PULP_URL="http://pulp" html + make PULP_URL="$PULP_URL" html cd .. echo "Validating OpenAPI schema..." @@ -97,6 +99,54 @@ cmd_prefix bash -c "PULP_DATABASES__default__USER=postgres django-admin test --n # Run functional tests export PYTHONPATH=$REPO_ROOT:$REPO_ROOT/../pulpcore${PYTHONPATH:+:${PYTHONPATH}} + +if [[ "$TEST" == "upgrade" ]]; then + git checkout ci_upgrade_test -- pulp_file/tests/ + + # Handle app label change: + sed -i "/require_pulp_plugins/d" pulp_file/tests/functional/utils.py + + # Running pre upgrade tests: + pytest -v -r sx --color=yes --pyargs -capture=no pulp_file.tests.upgrade.pre + + # Checking out ci_upgrade_test branch and upgrading plugins + cmd_prefix bash -c "cd pulp_file; git checkout -f ci_upgrade_test; pip install ." + cmd_prefix bash -c "cd pulp-certguard; git checkout -f ci_upgrade_test; pip install ." + cmd_prefix bash -c "cd pulpcore; git checkout -f ci_upgrade_test; pip install ." + + # Migrating + cmd_prefix bash -c "django-admin migrate --no-input" + + # Restarting single container services + cmd_prefix bash -c "s6-svc -r /var/run/s6/services/pulpcore-api" + cmd_prefix bash -c "s6-svc -r /var/run/s6/services/pulpcore-content" + cmd_prefix bash -c "s6-svc -r /var/run/s6/services/pulpcore-resource-manager" + cmd_prefix bash -c "s6-svc -r /var/run/s6/services/pulpcore-worker@1" + cmd_prefix bash -c "s6-svc -r /var/run/s6/services/pulpcore-worker@2" + + echo "Restarting in 60 seconds" + sleep 60 + + # CLI commands to display plugin versions and content data + pulp status + pulp file content list + + # Rebuilding bindings + cd ../pulp-openapi-generator + ./generate.sh pulpcore python + pip install ./pulpcore-client + ./generate.sh pulp_file python + pip install ./pulp_file-client + ./generate.sh pulp_certguard python + pip install ./pulp_certguard-client + cd $REPO_ROOT + + # Running post upgrade tests + pytest -v -r sx --color=yes --pyargs -capture=no pulp_file.tests.upgrade.post + exit +fi + + if [[ "$TEST" == "performance" ]]; then if [[ -z ${PERFORMANCE_TEST+x} ]]; then pytest -vv -r sx --color=yes --pyargs --capture=no --durations=0 pulp_file.tests.performance diff --git a/CHANGES/8719.misc b/CHANGES/8719.misc new file mode 100644 index 000000000..e9eb90567 --- /dev/null +++ b/CHANGES/8719.misc @@ -0,0 +1 @@ +Inroduce upgrade tests diff --git a/pulp_file/tests/upgrade/__init__.py b/pulp_file/tests/upgrade/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/pulp_file/tests/upgrade/post/__init__.py b/pulp_file/tests/upgrade/post/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/pulp_file/tests/upgrade/post/test_publish.py b/pulp_file/tests/upgrade/post/test_publish.py new file mode 100644 index 000000000..159430bd9 --- /dev/null +++ b/pulp_file/tests/upgrade/post/test_publish.py @@ -0,0 +1,136 @@ +# coding=utf-8 +"""Tests that publish file plugin repositories.""" +import unittest +from random import choice + +from pulp_smash import config +from pulp_smash.pulp3.bindings import monitor_task +from pulp_smash.pulp3.utils import ( + gen_repo, + get_content, + gen_distribution, + get_versions, + modify_repo, +) + +from pulp_file.tests.functional.constants import FILE_CONTENT_NAME +from pulp_file.tests.functional.utils import ( + gen_file_client, + gen_file_remote, +) +from pulp_file.tests.functional.utils import set_up_module as setUpModule # noqa:F401 + +from pulpcore.client.pulp_file import ( + DistributionsFileApi, + PublicationsFileApi, + RepositoriesFileApi, + RepositorySyncURL, + RemotesFileApi, + FileFilePublication, +) +from pulpcore.client.pulp_file.exceptions import ApiException + + +class PublishAnyRepoVersionTestCase(unittest.TestCase): + """Test whether a particular repository version can be published. + + This test targets the following issues: + + * `Pulp #3324 `_ + * `Pulp Smash #897 `_ + """ + + @classmethod + def setUpClass(cls): + """Create class-wide variables.""" + cls.cfg = config.get_config() + + client = gen_file_client() + cls.repo_api = RepositoriesFileApi(client) + cls.remote_api = RemotesFileApi(client) + cls.publications = PublicationsFileApi(client) + cls.distributions = DistributionsFileApi(client) + + def setUp(self): + """Create a new repository before each test.""" + manifest_path = "/pulp/content/pulp_pre_upgrade_test/PULP_MANIFEST" + url = self.cfg.get_content_host_base_url() + manifest_path + body = gen_file_remote(url=url) + remote = self.remote_api.create(body) + + repo = self.repo_api.create(gen_repo()) + + repository_sync_data = RepositorySyncURL(remote=remote.pulp_href) + sync_response = self.repo_api.sync(repo.pulp_href, repository_sync_data) + monitor_task(sync_response.task) + + self.repo = self.repo_api.read(repo.pulp_href) + + def test_all(self): + """Test whether a particular repository version can be published. + + 1. Create a repository with at least 2 repository versions. + 2. Create a publication by supplying the latest ``repository_version``. + 3. Assert that the publication ``repository_version`` attribute points + to the latest repository version. + 4. Create a publication by supplying the non-latest ``repository_version``. + 5. Create distribution. + 6. Assert that the publication ``repository_version`` attribute points + to the supplied repository version. + 7. Assert that an exception is raised when providing two different + repository versions to be published at same time. + """ + # Step 1 + for file_content in get_content(self.repo.to_dict())[FILE_CONTENT_NAME]: + modify_repo(self.cfg, self.repo.to_dict(), remove_units=[file_content]) + version_hrefs = tuple(ver["pulp_href"] for ver in get_versions(self.repo.to_dict())) + non_latest = choice(version_hrefs[:-1]) + + # Step 2 + publish_data = FileFilePublication(repository=self.repo.pulp_href) + publication = self.create_publication(publish_data) + + # Step 3 + self.assertEqual(publication.repository_version, version_hrefs[-1]) + + # Step 4 + publish_data = FileFilePublication(repository_version=non_latest) + publication = self.create_publication(publish_data) + + # Step 5 + body = gen_distribution() + body["base_path"] = "pulp_post_upgrade_test" + body["publication"] = publication.pulp_href + + distribution_response = self.distributions.create(body) + created_resources = monitor_task(distribution_response.task).created_resources + distribution = self.distributions.read(created_resources[0]) + + # Step 6 + self.assertEqual(publication.repository_version, non_latest) + + # Step 7 + with self.assertRaises(ApiException): + body = {"repository": self.repo.pulp_href, "repository_version": non_latest} + self.publications.create(body) + + # Step 8 + url = self.cfg.get_content_host_base_url() + "/pulp/content/pulp_post_upgrade_test/" + self.assertEqual(url, distribution.base_url, url) + + def test_custom_manifest(self): + """Test whether a repository version can be published with a specified manifest.""" + publish_data = FileFilePublication(repository=self.repo.pulp_href) + publication = self.create_publication(publish_data) + self.assertEqual(publication.manifest, "PULP_MANIFEST") + + publish_data = FileFilePublication(repository=self.repo.pulp_href, manifest="listing") + publication = self.create_publication(publish_data) + self.assertEqual(publication.manifest, "listing") + + def create_publication(self, publish_data): + """Create a new publication from the passed data.""" + publish_response = self.publications.create(publish_data) + created_resources = monitor_task(publish_response.task).created_resources + publication_href = created_resources[0] + return self.publications.read(publication_href) diff --git a/pulp_file/tests/upgrade/pre/__init__.py b/pulp_file/tests/upgrade/pre/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/pulp_file/tests/upgrade/pre/test_publish.py b/pulp_file/tests/upgrade/pre/test_publish.py new file mode 100644 index 000000000..90916aa21 --- /dev/null +++ b/pulp_file/tests/upgrade/pre/test_publish.py @@ -0,0 +1,124 @@ +# coding=utf-8 +"""Tests that publish file plugin repositories.""" +import unittest +from random import choice + +from pulp_smash import config +from pulp_smash.pulp3.bindings import monitor_task +from pulp_smash.pulp3.utils import ( + gen_repo, + get_content, + gen_distribution, + get_versions, + modify_repo, +) + +from pulp_file.tests.functional.constants import FILE_CONTENT_NAME +from pulp_file.tests.functional.utils import ( + gen_file_client, + gen_file_remote, +) +from pulp_file.tests.functional.utils import set_up_module as setUpModule # noqa:F401 + +from pulpcore.client.pulp_file import ( + DistributionsFileApi, + PublicationsFileApi, + RepositoriesFileApi, + RepositorySyncURL, + RemotesFileApi, + FileFilePublication, +) +from pulpcore.client.pulp_file.exceptions import ApiException + + +class PublishAnyRepoVersionTestCase(unittest.TestCase): + """Test whether a particular repository version can be published. + + This test targets the following issues: + + * `Pulp #3324 `_ + * `Pulp Smash #897 `_ + """ + + @classmethod + def setUpClass(cls): + """Create class-wide variables.""" + cls.cfg = config.get_config() + + client = gen_file_client() + cls.repo_api = RepositoriesFileApi(client) + cls.remote_api = RemotesFileApi(client) + cls.publications = PublicationsFileApi(client) + cls.distributions = DistributionsFileApi(client) + + def setUp(self): + """Create a new repository before each test.""" + body = gen_file_remote() + remote = self.remote_api.create(body) + + repo = self.repo_api.create(gen_repo()) + + repository_sync_data = RepositorySyncURL(remote=remote.pulp_href) + sync_response = self.repo_api.sync(repo.pulp_href, repository_sync_data) + monitor_task(sync_response.task) + + self.repo = self.repo_api.read(repo.pulp_href) + + def test_all(self): + """Test whether a particular repository version can be published. + + 1. Create a repository with at least 2 repository versions. + 2. Create a publication by supplying the latest ``repository_version``. + 3. Assert that the publication ``repository_version`` attribute points + to the latest repository version. + 4. Create a publication by supplying the non-latest ``repository_version``. + 5. Create distribution. + 6. Assert that the publication ``repository_version`` attribute points + to the supplied repository version. + 7. Assert that an exception is raised when providing two different + repository versions to be published at same time. + """ + # Step 1 + for file_content in get_content(self.repo.to_dict())[FILE_CONTENT_NAME]: + modify_repo(self.cfg, self.repo.to_dict(), remove_units=[file_content]) + version_hrefs = tuple(ver["pulp_href"] for ver in get_versions(self.repo.to_dict())) + non_latest = choice(version_hrefs[:-1]) + + # Step 2 + publish_data = FileFilePublication(repository=self.repo.pulp_href) + publication = self.create_publication(publish_data) + + # Step 3 + self.assertEqual(publication.repository_version, version_hrefs[-1]) + + # Step 4 + publish_data = FileFilePublication(repository_version=non_latest) + publication = self.create_publication(publish_data) + + # Step 5 + body = gen_distribution() + body["base_path"] = "pulp_pre_upgrade_test" + body["publication"] = publication.pulp_href + + distribution_response = self.distributions.create(body) + created_resources = monitor_task(distribution_response.task).created_resources + distribution = self.distributions.read(created_resources[0]) + + # Step 6 + self.assertEqual(publication.repository_version, non_latest) + + # Step 7 + with self.assertRaises(ApiException): + body = {"repository": self.repo.pulp_href, "repository_version": non_latest} + self.publications.create(body) + + # Step 8 + url = self.cfg.get_content_host_base_url() + "/pulp/content/pulp_pre_upgrade_test/" + self.assertEqual(url, distribution.base_url, url) + + def create_publication(self, publish_data): + """Create a new publication from the passed data.""" + publish_response = self.publications.create(publish_data) + created_resources = monitor_task(publish_response.task).created_resources + publication_href = created_resources[0] + return self.publications.read(publication_href) diff --git a/template_config.yml b/template_config.yml index ab86c102a..dfd2c59ed 100644 --- a/template_config.yml +++ b/template_config.yml @@ -10,6 +10,7 @@ bootstrap: false check_commit_message: true check_gettext: true check_manifest: true +check_openapi_schema: true check_stray_pulpcore_imports: true cherry_pick_automation: false coverage: false @@ -21,6 +22,7 @@ deploy_to_pypi: true docker_fixtures: true docs: false docs_test: true +issue_tracker: redmine plugin_app_label: file plugin_camel: PulpFile plugin_camel_short: File @@ -66,4 +68,13 @@ travis_notifications: on_failure: always on_success: change update_redmine: true - +upgrade_range: +- pulp_file_branch: 1.6 + pulpcore_branch: 3.11 + pulp-certguard_branch: 1.2 +- pulp_file_branch: 1.5 + pulpcore_branch: '3.10' + pulp-certguard_branch: 1.2 +- pulp_file_branch: 1.4 + pulpcore_branch: 3.9 + pulp-certguard_branch: 1.1