diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml new file mode 100644 index 00000000..5cecf38f --- /dev/null +++ b/.github/workflows/nightly.yml @@ -0,0 +1,150 @@ +# **what?** +# Runs unit tests and functional tests using the latest nightly DuckDB build. +# Any tests that use community extensions are skipped because these are not released nightly. + +# **why?** +# Ensure code for dbt is compatible with the bleeding edge version of DuckDB. + +# **when?** +# This will run nightly, after DuckDB releases its nightly build. + +name: Tests and Code Checks (DuckDB nightly) + +on: + schedule: + - cron: '0 0 * * *' # every 24 hours, top of the hour + workflow_dispatch: + +permissions: read-all + +defaults: + run: + shell: bash + +jobs: + nightly: + name: nightly test / python ${{ matrix.python-version }} + + runs-on: ubuntu-latest + + strategy: + fail-fast: false + matrix: + python-version: ['3.9', '3.10', '3.11', '3.12'] + + env: + TOXENV: "nightly" + PYTEST_ADDOPTS: "-v --color=yes --csv unit_results.csv" + + steps: + - name: Check out the repository + uses: actions/checkout@v4 + with: + persist-credentials: false + + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v5 + with: + python-version: ${{ matrix.python-version }} + + - name: Install python dependencies + run: | + python -m pip install tox + python -m pip --version + tox --version + + - name: Run tox + run: tox + + - name: Get current date + if: always() + id: date + run: echo "date=$(date +'%Y-%m-%dT%H_%M_%S')" >> $GITHUB_OUTPUT #no colons allowed for artifacts + + - uses: actions/upload-artifact@v3 + if: always() + with: + name: unit_results_${{ matrix.python-version }}-${{ steps.date.outputs.date }}.csv + path: unit_results.csv + + build: + name: build packages + + runs-on: ubuntu-latest + + steps: + - name: Check out the repository + uses: actions/checkout@v4 + with: + persist-credentials: false + + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version: '3.11' + + - name: Install python dependencies + run: | + pip install --upgrade setuptools wheel twine check-wheel-contents + pip --version + - name: Build distributions + run: ./scripts/build-dist.sh + + - name: Show distributions + run: ls -lh dist/ + + - name: Check distribution descriptions + run: | + twine check dist/* + - name: Check wheel contents + run: | + check-wheel-contents dist/*.whl --ignore W002,W007,W008 + + - uses: actions/upload-artifact@v3 + with: + name: dist + path: dist/ + + test-build: + name: verify packages / python ${{ matrix.python-version }} / ${{ matrix.os }} + + needs: build + + runs-on: ${{ matrix.os }} + + strategy: + fail-fast: false + matrix: + os: [ubuntu-latest, macos-latest, windows-latest] + python-version: ['3.9', '3.10', '3.11', '3.12'] + + steps: + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v5 + with: + python-version: ${{ matrix.python-version }} + + - name: Install python dependencies + run: | + pip install --upgrade wheel + pip --version + - uses: actions/download-artifact@v3 + with: + name: dist + path: dist/ + + - name: Show distributions + run: ls -lh dist/ + + - name: Install wheel distributions + run: | + find ./dist/*.whl -maxdepth 1 -type f | xargs pip install --force-reinstall --find-links=dist/ + - name: Check wheel distributions + run: | + dbt --version + - name: Install source distributions + run: | + find ./dist/*.gz -maxdepth 1 -type f | xargs pip install --force-reinstall --find-links=dist/ + - name: Check source distributions + run: | + dbt --version diff --git a/tests/conftest.py b/tests/conftest.py index 0d734ae5..e1dcb912 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -83,7 +83,7 @@ def dbt_profile_target(profile_type, bv_server_process, tmpdir_factory): profile["token"] = os.environ.get(MOTHERDUCK_TOKEN, os.environ.get(MOTHERDUCK_TOKEN.lower())) profile["disable_transactions"] = True profile["path"] = "md:test" - elif profile_type == "memory": + elif profile_type in ["memory", "nightly"]: pass # use the default path-less profile else: raise ValueError(f"Invalid profile type '{profile_type}'") diff --git a/tests/functional/adapter/test_community_extensions.py b/tests/functional/adapter/test_community_extensions.py index b0bebfc4..dc00135f 100644 --- a/tests/functional/adapter/test_community_extensions.py +++ b/tests/functional/adapter/test_community_extensions.py @@ -7,6 +7,7 @@ run_dbt, ) +@pytest.mark.skip_profile("nightly", reason="Cannot install community extensions for nightly release") class BaseCommunityExtensions: @pytest.fixture(scope="class") @@ -49,6 +50,7 @@ def test_base(self, project): } check_relation_types(project.adapter, expected) +@pytest.mark.skip_profile("nightly", reason="Cannot install community extensions for nightly release") @pytest.mark.skip_profile("buenavista") class TestCommunityExtensions(BaseCommunityExtensions): pass diff --git a/tests/unit/test_credentials.py b/tests/unit/test_credentials.py index fd0756a3..191c450b 100644 --- a/tests/unit/test_credentials.py +++ b/tests/unit/test_credentials.py @@ -94,6 +94,7 @@ def test_add_unsupported_secret(): assert "Secret type 'scrooge_mcduck' not found" in str(e) +@pytest.mark.skip_profile("nightly") def test_add_unsupported_secret_param(): creds = DuckDBCredentials( secrets=[ diff --git a/tox.ini b/tox.ini index d87bac25..2112ca19 100644 --- a/tox.ini +++ b/tox.ini @@ -11,7 +11,6 @@ deps = -rdev-requirements.txt -e. - [testenv:{functional,py38,py39,py310,py311,py312,py}] description = adapter functional testing skip_install = True @@ -65,3 +64,15 @@ commands = {envpython} -m pytest {posargs} --profile=file tests/functional/plugi deps = -rdev-requirements.txt -e. + +[testenv:{nightly,py38,py39,py310,py311,py312,py}] +description = duckdb nightly release testing +skip_install = True +passenv = * +commands = + {envpython} -m pip install --upgrade --pre duckdb + {envpython} -m pip show duckdb + {envpython} -m pytest {posargs} --profile=nightly tests/unit tests/functional/adapter +deps = + -rdev-requirements.txt + -e.