diff --git a/.github/workflows/functional-tests.yml b/.github/workflows/functional-tests.yml new file mode 100644 index 00000000..6e739ac0 --- /dev/null +++ b/.github/workflows/functional-tests.yml @@ -0,0 +1,147 @@ +name: Functional Tests + +on: + pull_request: + branches: [main] + +permissions: + contents: read + +jobs: + functional-tests: + name: "Pulp Functional Tests" + runs-on: ubuntu-latest + timeout-minutes: 45 + steps: + - uses: actions/checkout@v4 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v4 + + - name: Build dev container + uses: docker/build-push-action@v7 + with: + context: . + file: dev-container/Dockerfile + load: true + tags: pulp-dev:test + cache-from: type=gha,scope=dev-container + cache-to: type=gha,mode=max,scope=dev-container + + - name: Start dev container + run: | + docker run -d \ + --name pulp-dev \ + -e PULP_API_WORKERS=1 \ + -e PULP_CONTENT_WORKERS=1 \ + -e PULP_WORKERS=2 \ + pulp-dev:test + + - name: Wait for Pulp API + run: | + echo "Waiting for Pulp API to become ready..." + for i in $(seq 1 120); do + if docker exec pulp-dev curl -sf http://localhost:24817/api/pulp/api/v3/status/ > /dev/null 2>&1; then + echo "API ready after ${i}s" + exit 0 + fi + sleep 1 + done + echo "ERROR: API not ready after 120s" + docker logs pulp-dev + exit 1 + + - name: Install test dependencies and generate bindings + run: | + docker exec pulp-dev bash -c "pip install 'pytest<8' pytest-django gnupg 2>&1 | tail -1" + docker exec pulp-dev bash -c "\ + curl -sf -o /tmp/functest_requirements.txt \ + https://raw.githubusercontent.com/pulp/pulp_rpm/main/functest_requirements.txt && \ + curl -sf -o /tmp/unittest_requirements.txt \ + https://raw.githubusercontent.com/pulp/pulp_rpm/main/unittest_requirements.txt && \ + pip install -r /tmp/functest_requirements.txt -r /tmp/unittest_requirements.txt 2>&1 | tail -1" + docker exec pulp-dev pulp-test --bindings-only + + - name: "Test 1/6: pulp_rpm parallel (test_download_content)" + run: | + docker exec pulp-dev bash -c "\ + API_PROTOCOL=http API_HOST=localhost API_PORT=24817 \ + ADMIN_USERNAME=admin ADMIN_PASSWORD=password \ + pytest -v -r sx --color=yes \ + --suppress-no-test-exit-code \ + --pyargs pulp_rpm.tests.functional \ + -m parallel -n 4 -k 'test_download_content' \ + --junitxml=/tmp/junit-rpm-parallel.xml" + + - name: "Test 2/6: pulp_rpm serial (test_download_policies)" + run: | + docker exec pulp-dev bash -c "\ + API_PROTOCOL=http API_HOST=localhost API_PORT=24817 \ + ADMIN_USERNAME=admin ADMIN_PASSWORD=password \ + pytest -v -r sx --color=yes \ + --pyargs pulp_rpm.tests.functional \ + -m 'not parallel' -k 'test_download_policies' \ + --junitxml=/tmp/junit-rpm-serial.xml" + + - name: "Test 3/6: pulpcore (test_jq_header_remote_auth)" + run: | + docker exec pulp-dev bash -c "\ + API_PROTOCOL=http API_HOST=localhost API_PORT=24817 \ + ADMIN_USERNAME=admin ADMIN_PASSWORD=password \ + pytest -v -r sx --color=yes \ + --pyargs pulpcore.tests.functional \ + -m parallel -n 4 -k 'test_jq_header_remote_auth' \ + --junitxml=/tmp/junit-core.xml" + + - name: "Test 4/6: pulp_maven (test_download_content)" + run: | + docker exec pulp-dev bash -c "\ + API_PROTOCOL=http API_HOST=localhost API_PORT=24817 \ + ADMIN_USERNAME=admin ADMIN_PASSWORD=password \ + pytest -v -r sx --color=yes \ + --pyargs pulp_maven.tests.functional.api.test_download_content \ + --junitxml=/tmp/junit-maven.xml" + + - name: "Test 5/6: pulp_npm (test_pull_through_install)" + run: | + docker exec pulp-dev bash -c "\ + API_PROTOCOL=http API_HOST=localhost API_PORT=24817 \ + ADMIN_USERNAME=admin ADMIN_PASSWORD=password \ + pytest -v -r sx --color=yes \ + --pyargs pulp_npm.tests.functional \ + -k 'test_pull_through_install' \ + --junitxml=/tmp/junit-npm.xml" + + - name: "Test 6/6: pulp_service functional" + run: | + docker exec pulp-dev bash -c "\ + API_PROTOCOL=http API_HOST=localhost API_PORT=24817 \ + ADMIN_USERNAME=admin ADMIN_PASSWORD=password \ + pytest -v -r sx --color=yes \ + --pyargs pulp_service.tests.functional \ + -m 'not parallel' \ + -k 'not test_forbidden_feature_service and not test_entitled_feature_service' \ + --junitxml=/tmp/junit-service.xml" + + - name: Collect test results + if: always() + run: | + mkdir -p test-results + docker cp pulp-dev:/tmp/junit-rpm-parallel.xml test-results/ 2>/dev/null || true + docker cp pulp-dev:/tmp/junit-rpm-serial.xml test-results/ 2>/dev/null || true + docker cp pulp-dev:/tmp/junit-core.xml test-results/ 2>/dev/null || true + docker cp pulp-dev:/tmp/junit-maven.xml test-results/ 2>/dev/null || true + docker cp pulp-dev:/tmp/junit-npm.xml test-results/ 2>/dev/null || true + docker cp pulp-dev:/tmp/junit-service.xml test-results/ 2>/dev/null || true + + - name: Upload test results + if: always() + uses: actions/upload-artifact@v4 + with: + name: junit-results + path: test-results/ + retention-days: 14 + + - name: Dump container logs on failure + if: failure() + run: docker logs pulp-dev diff --git a/.tekton/pulp-deploy-and-test.yaml b/.tekton/pulp-deploy-and-test.yaml index a8c999d6..d48709e5 100644 --- a/.tekton/pulp-deploy-and-test.yaml +++ b/.tekton/pulp-deploy-and-test.yaml @@ -697,132 +697,6 @@ spec: cat __tmp_init__.py | cmd_stdin_prefix bash -c "cat > /tmp/home/.local/lib/python3.11/site-packages/pulpcore/__init__.py" cat __tmp_init__.py | cmd_stdin_prefix bash -c "cat > /tmp/home/.local/lib/python3.11/site-packages/pulpcore/client/__init__.py" - - name: pulp-functional-tests - when: - - input: '$(tasks.test-metadata.results.test-event-type)' - operator: in - values: ["pull_request"] - runAfter: - - install-bindings - params: - - name: BONFIRE_IMAGE - value: "$(params.BONFIRE_IMAGE)" - - name: NS - value: "$(tasks.reserve-namespace.results.NS)" - - name: EPHEMERAL_ENV_PROVIDER_SECRET - value: "$(params.EPHEMERAL_ENV_PROVIDER_SECRET)" - taskSpec: - params: - - name: BONFIRE_IMAGE - type: string - description: The container Bonfire image to use for the tekton tasks - default: quay.io/redhat-user-workloads/hcc-devprod-tenant/hcc-cicd-tools/cicd-tools:834176766e3f911ffa24bfacff59dd15126e4b3a - - name: EPHEMERAL_ENV_PROVIDER_SECRET - type: string - default: ephemeral-env-provider - - name: NS - type: string - description: Namespace name to deploy the application to - steps: - - name: functional-tests - image: "$(params.BONFIRE_IMAGE)" - env: - - name: OC_LOGIN_TOKEN - valueFrom: - secretKeyRef: - name: $(params.EPHEMERAL_ENV_PROVIDER_SECRET) - key: token - - name: OC_LOGIN_SERVER - valueFrom: - secretKeyRef: - name: $(params.EPHEMERAL_ENV_PROVIDER_SECRET) - key: url - - name: NS - value: $(params.NS) - script: | - set -ex - - login.sh - - if [ -n "$NS" ]; then - oc_wrapper project $NS - else - export NS=$(oc_wrapper project | grep -oE 'ephemeral-......') - fi - echo "Namespace is $NS" - - PASSWORD=$(oc_wrapper extract secret/pulp-admin-password --to=-) - - POD=$(oc_wrapper get pod | grep -oE "pulp-api\S*") - echo $POD - oc_wrapper get pod $POD -o yaml | grep memory: - - oc_wrapper get clowdenvironment env-$(oc_wrapper project | grep -oE 'ephemeral-......') -o yaml - - oc_wrapper get clowdapp pulp -o yaml - - ### Adapted from ./.github/workflows/scripts/utils.sh - # Run a command - cmd_prefix() { - oc_wrapper exec -c pulp-api deployment/pulp-api -- "$@" - } - - # Run a command, and pass STDIN - cmd_stdin_prefix() { - oc_wrapper exec -c pulp-api -i deployment/pulp-api -- "$@" - } - ### END Adapted from ./.github/workflows/scripts/utils.sh - - debug_and_fail() { - oc_wrapper logs $(oc_wrapper get pod | grep -oE "pulp-content\S*") - oc_wrapper logs $(oc_wrapper get pod | grep -oE "pulp-api\S*") - for pod in $(oc_wrapper get pod | grep -oE "pulp-worker\S*"); do - oc_wrapper logs "$pod" - done - echo "CURL OUTPUT" - curl https://env-${NS}.apps.crc-eph.r9lp.p1.openshiftapps.com/api/pulp-content/default/ - echo "ROUTES" - oc_wrapper get route - exit 1 - } - - cmd_prefix bash -c "HOME=/tmp/home pip3 install pytest\<8 gnupg" - - curl -o functest_requirements.txt https://raw.githubusercontent.com/pulp/pulp_rpm/main/functest_requirements.txt - curl -o unittest_requirements.txt https://raw.githubusercontent.com/pulp/pulp_rpm/main/unittest_requirements.txt - - ### Adapted from ./.github/workflows/scripts/script.sh - cat unittest_requirements.txt | cmd_stdin_prefix bash -c "cat > /tmp/unittest_requirements.txt" - cat functest_requirements.txt | cmd_stdin_prefix bash -c "cat > /tmp/functest_requirements.txt" - cmd_prefix bash -c "HOME=/tmp/home pip3 install -r /tmp/unittest_requirements.txt -r /tmp/functest_requirements.txt" - # Because we pass the path to pytest -o cache_dir=/tmp/home/.cache/pytest_cache, pulpcore-manager must be in the same dir - cmd_prefix bash -c "ln -s /usr/local/lib/pulp/bin/pulpcore-manager /tmp/home/.local/bin/pulpcore-manager || /bin/true" - echo "CURL OUTPUT" - curl https://env-${NS}.apps.crc-eph.r9lp.p1.openshiftapps.com/api/pulp-content/default/ - echo "ROUTES" - oc_wrapper get route - set +e - # Only testing test_download_content because it is a very thorough test that tests that all the components of pulp can work - cmd_prefix bash -c "HOME=/tmp/home PYTHONPATH=/tmp/home/.local/lib/python3.11/site-packages/ XDG_CONFIG_HOME=/tmp/home/.config API_PROTOCOL=http API_HOST=pulp-api API_PORT=8000 ADMIN_USERNAME=admin ADMIN_PASSWORD=$PASSWORD /tmp/home/.local/bin/pytest -o cache_dir=/tmp/home/.cache/pytest_cache -v -r sx --color=yes --suppress-no-test-exit-code --pyargs pulp_rpm.tests.functional -m parallel -n 8 -k 'test_download_content' --junitxml=/tmp/home/junit-pulp-parallel.xml" || debug_and_fail - # Never test test_package_manager_consume because they require sudo - # Do not test test_domain_create because it requires more than 2GB of RAM - # Only testing test_download_policies because they are very thorough tests that test that all the components of pulp can work - cmd_prefix bash -c "HOME=/tmp/home PYTHONPATH=/tmp/home/.local/lib/python3.11/site-packages/ XDG_CONFIG_HOME=/tmp/home/.config API_PROTOCOL=http API_HOST=pulp-api API_PORT=8000 ADMIN_USERNAME=admin ADMIN_PASSWORD=$PASSWORD /tmp/home/.local/bin/pytest -o cache_dir=/tmp/home/.cache/pytest_cache -v -r sx --color=yes --pyargs pulp_rpm.tests.functional -m 'not parallel' -k 'test_download_policies' --junitxml=/tmp/home/junit-pulp-serial.xml" || debug_and_fail - - # Run the jq header auth test - cmd_prefix bash -c "HOME=/tmp/home PYTHONPATH=/tmp/home/.local/lib/python3.11/site-packages/ XDG_CONFIG_HOME=/tmp/home/.config API_PROTOCOL=http API_HOST=pulp-api API_PORT=8000 ADMIN_USERNAME=admin ADMIN_PASSWORD=$PASSWORD /tmp/home/.local/bin/pytest -o cache_dir=/tmp/home/.cache/pytest_cache -v -r sx --color=yes --pyargs pulpcore.tests.functional -m 'parallel' -n 8 -k 'test_jq_header_remote_auth' --junitxml=/tmp/home/junit-pulp-serial.xml" || debug_and_fail - - ### END Adapted from ./.github/workflows/scripts/script.sh - - # Run pulp_maven functional tests - cmd_prefix bash -c "HOME=/tmp/home PYTHONPATH=/tmp/home/.local/lib/python3.11/site-packages/ XDG_CONFIG_HOME=/tmp/home/.config API_PROTOCOL=http API_HOST=pulp-api API_PORT=8000 ADMIN_USERNAME=admin ADMIN_PASSWORD=$PASSWORD /tmp/home/.local/bin/pytest -o cache_dir=/tmp/home/.cache/pytest_cache -v -r sx --color=yes --pyargs pulp_maven.tests.functional.api.test_download_content --junitxml=/tmp/home/junit-pulp-serial.xml" || debug_and_fail - - # Run pulp_npm functional tests - cmd_prefix bash -c "HOME=/tmp/home PYTHONPATH=/tmp/home/.local/lib/python3.11/site-packages/ XDG_CONFIG_HOME=/tmp/home/.config API_PROTOCOL=http API_HOST=pulp-api API_PORT=8000 ADMIN_USERNAME=admin ADMIN_PASSWORD=$PASSWORD /tmp/home/.local/bin/pytest -o cache_dir=/tmp/home/.cache/pytest_cache -v -r sx --color=yes --pyargs pulp_npm.tests.functional -k 'test_pull_through_install' --junitxml=/tmp/home/junit-pulp-serial.xml" || debug_and_fail - - # Run pulp_service functional tests - cmd_prefix bash -c "HOME=/tmp/home PYTHONPATH=/tmp/home/.local/lib/python3.11/site-packages/ XDG_CONFIG_HOME=/tmp/home/.config API_PROTOCOL=http API_HOST=pulp-api API_PORT=8000 ADMIN_USERNAME=admin ADMIN_PASSWORD=$PASSWORD /tmp/home/.local/bin/pytest -o cache_dir=/tmp/home/.cache/pytest_cache -v -r sx --color=yes --pyargs pulp_service.tests.functional -m 'not parallel' --junitxml=/tmp/home/junit-pulp-serial.xml" || debug_and_fail - - name: push-api-json-files-to-pulp when: - input: '$(tasks.test-metadata.results.test-event-type)' @@ -838,7 +712,7 @@ spec: - name: SNAPSHOT value: "$(params.SNAPSHOT)" runAfter: - - pulp-functional-tests + - install-bindings taskSpec: params: - name: BONFIRE_IMAGE diff --git a/dev-container/Dockerfile b/dev-container/Dockerfile index e9c2b8e0..7e7b7dfa 100644 --- a/dev-container/Dockerfile +++ b/dev-container/Dockerfile @@ -120,7 +120,8 @@ from cryptography.hazmat.primitives import serialization; \ key = rsa.generate_private_key(65537, 4096); \ open('/etc/pki/attestation/test-key-private.pem','wb').write(key.private_bytes(serialization.Encoding.PEM, serialization.PrivateFormat.PKCS8, serialization.NoEncryption())); \ open('/etc/pki/attestation/test-key.pem','wb').write(key.public_key().public_bytes(serialization.Encoding.PEM, serialization.PublicFormat.SubjectPublicKeyInfo))" && \ - chmod 600 /etc/pki/attestation/test-key-private.pem && \ + chown -R 700:0 /etc/pki/attestation && \ + chmod 640 /etc/pki/attestation/test-key-private.pem && \ chmod 644 /etc/pki/attestation/test-key.pem RUN dnf -y install java-17-openjdk-headless && dnf clean all