Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Write Customization tests in python #2918

Merged
merged 18 commits into from
Mar 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 24 additions & 7 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -55,11 +55,11 @@ jobs:
integration-test:
if: github.repository_owner == 'getsentry'
runs-on: ubuntu-20.04
name: "integration test"
name: integration test ${{ matrix.compose_version }} - customizations ${{ matrix.customizations }}
strategy:
fail-fast: false
matrix:
test_type: ["initial-install", "customizations"]
customizations: ["disabled", "enabled"]
compose_version: ["v2.0.1", "v2.7.0"]
include:
- compose_version: "v2.0.1"
Expand All @@ -68,18 +68,19 @@ jobs:
compose_path: "/usr/local/lib/docker/cli-plugins"
env:
COMPOSE_PROJECT_NAME: self-hosted-${{ strategy.job-index }}
SENTRY_DSN: https://[email protected]/6627632
REPORT_SELF_HOSTED_ISSUES: 1
REPORT_SELF_HOSTED_ISSUES: 0
SELF_HOSTED_TESTING_DSN: ${{ vars.SELF_HOSTED_TESTING_DSN }}
steps:
- name: Checkout
uses: actions/checkout@v4

- name: Setup dev environment
run: |
pip install -r requirements-dev.txt
echo "PY_COLORS=1" >> "$GITHUB_ENV"
### pytest-sentry configuration ###
if [ "$GITHUB_REPOSITORY" = "getsentry/self-hosted" ]; then
echo "PYTEST_SENTRY_DSN=${{ env.SELF_HOSTED_TESTING_DSN }}" >> $GITHUB_ENV
echo "PYTEST_SENTRY_DSN=$SELF_HOSTED_TESTING_DSN" >> $GITHUB_ENV
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was previously not being picked up correctly

echo "PYTEST_SENTRY_TRACES_SAMPLE_RATE=0" >> $GITHUB_ENV

# This records failures on master to sentry in order to detect flakey tests, as it's
Expand All @@ -102,13 +103,29 @@ jobs:
sudo chmod +x "${{ matrix.compose_path }}/docker-compose"

- name: Install self-hosted
run: ./install.sh
uses: nick-fields/retry@v3
with:
timeout_minutes: 10
max_attempts: 3
command: ./install.sh

- name: Integration Test
run: ./integration-test.sh --${{ matrix.test_type }}
run: pytest --cov --junitxml=junit.xml --reruns 3 _integration-test/ --customizations=${{ matrix.customizations }}

- name: Inspect failure
if: failure()
run: |
docker compose ps
docker compose logs

- name: Upload coverage to Codecov
uses: codecov/codecov-action@v4
with:
token: ${{ secrets.CODECOV_TOKEN }}
slug: getsentry/self-hosted

- name: Upload test results to Codecov
if: ${{ !cancelled() }}
uses: codecov/test-results-action@v1
with:
token: ${{ secrets.CODECOV_TOKEN }}
31 changes: 29 additions & 2 deletions _integration-test/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,27 +10,49 @@
TEST_PASS = "test123TEST"
TIMEOUT_SECONDS = 60

def pytest_addoption(parser):
parser.addoption("--customizations", default="disabled")

@pytest.fixture(scope="session", autouse=True)
def configure_self_hosted_environment():
def configure_self_hosted_environment(request):
subprocess.run(["docker", "compose", "--ansi", "never", "up", "-d"], check=True)
for i in range(TIMEOUT_SECONDS):
try:
response = httpx.get(SENTRY_TEST_HOST, follow_redirects=True)
except httpx.ConnectionError:
except httpx.NetworkError:
time.sleep(1)
else:
if response.status_code == 200:
break
else:
raise AssertionError("timeout waiting for self-hosted to come up")

if request.config.getoption("--customizations") == "enabled":
os.environ['TEST_CUSTOMIZATIONS'] = "enabled"
script_content = '''\

Check warning on line 32 in _integration-test/conftest.py

View check run for this annotation

Codecov / codecov/patch

_integration-test/conftest.py#L31-L32

Added lines #L31 - L32 were not covered by tests
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These lines are definitely covered by testing, not sure why Codecov is complaining here.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's the reason why Test / integration test (True, v2.0.1) and Test / integration test (True, v2.7.0) are taking 8 minutes longer

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: It's pretty hard for a naive observer to figure out what the "True" in these variants means. Maybe we could have values be Customization Enabled vs Customization Disabled rather than True/False?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Apparently, you can create a custom name for the job. Now it looks like
Test / integration test v2.0.1 - customizations disabled

#!/bin/bash
touch /created-by-enhance-image
apt-get update
apt-get install -y gcc libsasl2-dev python-dev libldap2-dev libssl-dev
'''

with open('sentry/enhance-image.sh', 'w') as script_file:
script_file.write(script_content)

Check warning on line 40 in _integration-test/conftest.py

View check run for this annotation

Codecov / codecov/patch

_integration-test/conftest.py#L39-L40

Added lines #L39 - L40 were not covered by tests
# Set executable permissions for the shell script
os.chmod('sentry/enhance-image.sh', 0o755)

Check warning on line 42 in _integration-test/conftest.py

View check run for this annotation

Codecov / codecov/patch

_integration-test/conftest.py#L42

Added line #L42 was not covered by tests

# Write content to the requirements.txt file
with open('sentry/requirements.txt', 'w') as req_file:
req_file.write('python-ldap\n')
os.environ['MINIMIZE_DOWNTIME'] = "1"
subprocess.run(["./install.sh"], check=True)

Check warning on line 48 in _integration-test/conftest.py

View check run for this annotation

Codecov / codecov/patch

_integration-test/conftest.py#L45-L48

Added lines #L45 - L48 were not covered by tests
# Create test user
subprocess.run(
[
"docker",
"compose",
"exec",
"-T",
"web",
"sentry",
"createuser",
Expand All @@ -45,3 +67,8 @@
check=True,
text=True,
)

@pytest.fixture()
def setup_backup_restore_env_variables():
os.environ['SENTRY_DOCKER_IO_DIR'] = os.path.join(os.getcwd(), 'sentry')
os.environ['SKIP_USER_CREATION'] = "1"
13 changes: 0 additions & 13 deletions _integration-test/ensure-customizations-not-present.sh

This file was deleted.

13 changes: 0 additions & 13 deletions _integration-test/ensure-customizations-work.sh

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,13 +1,8 @@
import subprocess
import os
import pytest

@pytest.fixture()
def setup_env():
os.environ['SENTRY_DOCKER_IO_DIR'] = os.path.join(os.getcwd(), 'sentry')
os.environ['SKIP_USER_CREATION'] = "1"

def test_backup(setup_env):
def test_backup(setup_backup_restore_env_variables):
# Docker was giving me permissioning issues when trying to create this file and write to it even after giving read + write access
# to group and owner. Instead, try creating the empty file and then give everyone write access to the backup file
file_path = os.path.join(os.getcwd(), 'sentry', 'backup.json')
Expand All @@ -18,7 +13,7 @@ def test_backup(setup_env):
subprocess.run([sentry_admin_sh, "export", "global", "/sentry-admin/backup.json", "--no-prompt"], check=True)
assert os.path.getsize(file_path) > 0

def test_import(setup_env):
def test_import(setup_backup_restore_env_variables):
# Bring postgres down and recreate the docker volume
subprocess.run(["docker", "compose", "--ansi", "never", "stop", "postgres"], check=True)
subprocess.run(["docker", "compose", "--ansi", "never", "rm", "-f", "-v", "postgres"], check=True)
Expand Down
74 changes: 73 additions & 1 deletion _integration-test/run.py → _integration-test/test_run.py
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,18 @@
try:
subprocess.run(["./_integration-test/custom-ca-roots/setup.sh"], check=True)
subprocess.run(
["docker", "compose", "--ansi", "never", "run", "--no-deps", "web", "python3", "/etc/sentry/test-custom-ca-roots.py"], check=True
[
"docker",
"compose",
"--ansi",
"never",
"run",
"--no-deps",
"web",
"python3",
"/etc/sentry/test-custom-ca-roots.py",
],
check=True,
)
finally:
subprocess.run(["./_integration-test/custom-ca-roots/teardown.sh"], check=True)
Expand Down Expand Up @@ -171,3 +182,64 @@
client,
lambda x: len(json.loads(x)["data"]) > 0,
)


def test_customizations():
commands = [
[
"docker",
"compose",
"--ansi",
"never",
"run",
"--no-deps",
"web",
"bash",
"-c",
"if [ ! -e /created-by-enhance-image ]; then exit 1; fi",
],
[
"docker",
"compose",
"--ansi",
"never",
"run",
"--no-deps",
"--entrypoint=/etc/sentry/entrypoint.sh",
"sentry-cleanup",
"bash",
"-c",
"if [ ! -e /created-by-enhance-image ]; then exit 1; fi",
],
[
"docker",
"compose",
"--ansi",
"never",
"run",
"--no-deps",
"web",
"python",
"-c",
"import ldap",
],
[
"docker",
"compose",
"--ansi",
"never",
"run",
"--no-deps",
"--entrypoint=/etc/sentry/entrypoint.sh",
"sentry-cleanup",
"python",
"-c",
"import ldap",
]
]
for command in commands:
result = subprocess.run(command, check=False)
if os.getenv("TEST_CUSTOMIZATIONS", "disabled") == "enabled":
assert result.returncode == 0

Check warning on line 243 in _integration-test/test_run.py

View check run for this annotation

Codecov / codecov/patch

_integration-test/test_run.py#L243

Added line #L243 was not covered by tests
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does test_customization run in both matrix variants?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, it does. If customizations enabled, it checks to ensure that they are truly enabled by making sure a dependency can be imported that is included in the custom image (ldap). If not, it checks to ensure that an error is thrown when trying to import a dependency that comes from the custom image.

else:
assert result.returncode != 0
40 changes: 0 additions & 40 deletions integration-test.sh

This file was deleted.

2 changes: 2 additions & 0 deletions requirements-dev.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
codecov-cli>=0.4.8
sentry-sdk>=1.39.2
pytest>=8.0.0
pytest-cov>=4.1.0
pytest-rerunfailures>=11.0
pytest-sentry>=0.1.11
httpx>=0.25.2
Expand Down
Loading