diff --git a/.github/workflows/build_deploy_dev.yml b/.github/workflows/build_deploy_dev.yml index 5c5543eb5a..d852d94afa 100644 --- a/.github/workflows/build_deploy_dev.yml +++ b/.github/workflows/build_deploy_dev.yml @@ -1,10 +1,8 @@ -name: Build and deploy to dev +name: Test pull request permissions: contents: read - pull-requests: write - pages: write - id-token: write + pull-requests: read on: pull_request: @@ -14,7 +12,7 @@ on: - 'releases/*' # Cancel any existing runs of this workflow on the same branch/pr -# We always want to build/deploy/test a new commit over an older one +# We always want to test a new commit over an older one concurrency: group: ${{ github.workflow_ref }} cancel-in-progress: true @@ -27,7 +25,10 @@ jobs: outputs: not-docs: ${{ steps.filter.outputs.not-docs }} steps: - - uses: dorny/paths-filter@v3 + # A pull request that changes only docs, images or Markdown skips the unit + # tests. Every other change runs them, including a version bump, because + # setup.py builds the package from mindsdb/__about__.py. + - uses: dorny/paths-filter@0e4a8c6effa4802afeda77dc8d303f8176d7dfad # v3.0.4 id: filter with: predicate-quantifier: "every" @@ -36,126 +37,28 @@ jobs: - '!docs/**' - '!assets/**' - '!**/*.md' - - '!.github/workflows/build_deploy_dev.yml' - - '!.github/workflows/test_on_deploy.yml' - - '!mindsdb/__about__.py' - # Start running unit tests early - we want to run them always - # and they don't depend on build or deployment run_unit_tests: name: Run Unit Tests needs: [changes] if: ${{ needs.changes.outputs.not-docs == 'true' }} + # tests_unit.yml asks for these permissions itself, and a called workflow + # can only keep or lower what the job that calls it grants. + permissions: + contents: read + pull-requests: write + pages: write + id-token: write uses: ./.github/workflows/tests_unit.yml - secrets: inherit - - # Looks for labels like "deploy-to-" attached to a PR so we can deploy to those envs - get-deploy-labels: - if: ${{ !github.event.pull_request.head.repo.fork }} - name: Get Deploy Envs - runs-on: mdb-dev - needs: [changes] - outputs: - deploy-envs: ${{ steps.get-labels.outputs.deploy-envs }} - steps: - - id: get-labels - uses: mindsdb/github-actions/get-deploy-labels@main - - # Build our docker images based on our bake file - build: - if: ${{ !github.event.pull_request.head.repo.fork && needs.get-deploy-labels.outputs.deploy-envs != '[]' }} - name: Build Docker Images - runs-on: mdb-dev - needs: [get-deploy-labels] - steps: - - uses: actions/checkout@v4 - # Build the bakefile and push - - uses: mindsdb/github-actions/docker-bake@main - with: - git-sha: ${{ github.event.pull_request.head.sha }} - target: cloud-cpu - platforms: linux/amd64 - push-cache: false - - scan-keycloak: - if: ${{ !github.event.pull_request.head.repo.fork }} - runs-on: mdb-dev - needs: [ build ] - name: Scan cloud-cpu image - steps: - - uses: actions/checkout@v4 - - uses: mindsdb/github-actions/snyk-docker-scan@main - with: - image: 168681354662.dkr.ecr.us-east-1.amazonaws.com/mindsdb:${{ github.event.pull_request.head.sha }}-cloud-cpu - snyk-token: ${{ secrets.SNYK_TOKEN }} - dockerfile: docker/mindsdb.Dockerfile - - # Push cache layers to docker registry - # This is separate to the build step so we can do other stuff in parallel - build-cache: - if: ${{ !github.event.pull_request.head.repo.fork }} - name: Push Docker Cache - runs-on: mdb-dev - needs: [build] - steps: - - uses: actions/checkout@v4 - # Build the bakefile and push - - uses: mindsdb/github-actions/docker-bake@main - with: - git-sha: ${{ github.event.pull_request.head.sha }} - target: cloud-cpu - platforms: linux/amd64 - push-cache: true - cache-only: true - - # This will run the deployment workflow in the base branch, not in the PR. - # So if you change the deploy workflow in your PR, the changes won't be reflected in this run. - deploy: - if: ${{ !github.event.pull_request.head.repo.fork && needs.get-deploy-labels.outputs.deploy-envs != '[]' }} - name: Deploy - needs: [build, get-deploy-labels] - uses: ./.github/workflows/deploy.yml - with: - deploy-envs: ${{ needs.get-deploy-labels.outputs.deploy-envs }} - image-tag: ${{ github.event.pull_request.head.sha }} - secrets: inherit - - # Run integration tests against the deployed environment - run_integration_tests: - if: ${{ !github.event.pull_request.head.repo.fork }} - name: Run Integration Tests - needs: [deploy, get-deploy-labels] - strategy: - fail-fast: false - matrix: - deploy-env: ${{ fromJson(needs.get-deploy-labels.outputs.deploy-envs) }} - concurrency: - group: deploy-${{ matrix.deploy-env }} - cancel-in-progress: false - uses: ./.github/workflows/tests_integration.yml - with: - deploy-env: ${{ matrix.deploy-env }} - secrets: inherit # This is a collection point for all of the matrix tests above so we can have a single required job tests_completed: name: All Tests Succeeded - needs: [run_unit_tests, run_integration_tests, changes, get-deploy-labels] + needs: [run_unit_tests, changes] runs-on: ubuntu-latest if: always() steps: - # A skipped `run_integration_tests` means two different things. With no - # deploy label there was nothing to run them against, which is fine. A - # deploy that failed also leaves them skipped, which is not. Reading - # `!= 'success'` treated both the same, so this job failed on every - # first-party pull request that carried no deploy label and its red said - # nothing. Gate on whether anything was actually deployed instead. - name: fail if tests failed or didnt run - if: >- - ${{ needs.changes.outputs.not-docs == 'true' - && (needs.run_unit_tests.result != 'success' - || (needs.get-deploy-labels.outputs.deploy-envs != '[]' - && !github.event.pull_request.head.repo.fork - && needs.run_integration_tests.result != 'success')) }} + if: ${{ needs.changes.result != 'success' || (needs.changes.outputs.not-docs == 'true' && needs.run_unit_tests.result != 'success') }} run: exit 1 - run: echo "Tests ran successfully" diff --git a/.github/workflows/build_deploy_prod.yml b/.github/workflows/build_deploy_prod.yml deleted file mode 100644 index f4fc723047..0000000000 --- a/.github/workflows/build_deploy_prod.yml +++ /dev/null @@ -1,206 +0,0 @@ -name: Build and deploy release - -permissions: - contents: read - pull-requests: write - pages: write - id-token: write - -on: - release: - types: [published] - paths-ignore: - - "docs/**" - - "README.md" - -env: - UV_LINK_MODE: "symlink" - -concurrency: - group: release - cancel-in-progress: false - -jobs: - run_unit_tests: - name: Run Unit Tests - uses: ./.github/workflows/tests_unit.yml - secrets: inherit - - # Check that the version defined in the github release is valid - check-version: - name: Check Code Version - runs-on: mdb-dev - needs: [run_unit_tests] - if: github.actor != 'mindsdbadmin' - steps: - - uses: actions/checkout@v4 - - uses: FranzDiebold/github-env-vars-action@v2 - - name: Set up Python - uses: actions/setup-python@v5.1.0 - with: - python-version: ${{ vars.CI_PYTHON_VERSION }} - - name: Check Version - run: | - PYTHONPATH=./ python tests/scripts/check_version.py ${{ env.CI_REF_NAME }} ${{ github.event.release.prerelease }} - - # Push a new release to PyPI - deploy_to_pypi: - name: Publish to PyPI - runs-on: mdb-dev - needs: [check-version, run_unit_tests] - if: github.actor != 'mindsdbadmin' - steps: - - uses: actions/checkout@v4 - - name: Setup uv - uses: astral-sh/setup-uv@v5 - with: - cache-local-path: "/home/runner/_work/_tool/uv-local-cache" # Place cache in the tool dir because we mount this in our runnners - prune-cache: false # We want to save all cache because it's in the mount^ - python-version: ${{ vars.CI_PYTHON_VERSION || '3.11' }} # Default to 3.11 where vars aren't available (PRs from forks) - - name: Install dependencies - run: | - uv pip install -r requirements/requirements-dev.txt - - name: Build and publish - env: - TWINE_USERNAME: __token__ - TWINE_PASSWORD: ${{ secrets.PYPI_PASSWORD }} - run: | - # This uses the version string from __about__.py, which we checked matches the git tag above - uv pip install build - python -m build - twine upload dist/* - - # Build our docker images based on our bake file - # This will tag with the release version tag and push to both dockerhub and ECR - build: - name: Build Docker Images - runs-on: mdb-dev - needs: [check-version, run_unit_tests] - if: github.actor != 'mindsdbadmin' - steps: - - uses: actions/checkout@v4 - - name: Docker Login - uses: docker/login-action@v1 - with: - username: ${{ secrets.DOCKER_USERNAME }} - password: ${{ secrets.DOCKER_PASSWORD }} - # Build the bakefile and push - - uses: mindsdb/github-actions/docker-bake@main - with: - push-to-dockerhub: true - push-cache: false - - # Push cache layers to docker registry - # This is separate to the build step so we can do other stuff in parallel - build-cache: - name: Push Docker Cache - runs-on: mdb-dev - needs: [build] - steps: - - uses: actions/checkout@v4 - # Build the bakefile and push - - uses: mindsdb/github-actions/docker-bake@main - with: - push-cache: true - cache-only: true - - # Call our deployment workflow - deploy: - name: Deploy to Prod - needs: [build] - uses: ./.github/workflows/deploy.yml - with: - deploy-envs: '["prod"]' - image-tag: ${{ github.event.release.tag_name }} - prod: true - secrets: inherit - - # Trigger private repo to deploy the docker desktop extension - trigger_dd_extension_release: - name: Deploy Docker Desktop Extension - runs-on: mdb-dev - needs: [build] - if: github.actor != 'mindsdbadmin' - steps: - - uses: FranzDiebold/github-env-vars-action@v2 - - uses: convictional/trigger-workflow-and-wait@v1.6.5 - with: - owner: mindsdb - repo: mindsdb-docker-extension - github_token: ${{ secrets.REPO_DISPATCH_PAT_TOKEN }} - workflow_file_name: bump-mindsdb-version.yml - ref: main - client_payload: '{"image-tag": "${{ env.CI_REF_NAME }}"}' - - # Run integration tests - run_integration_tests: - name: Run Integration Tests - needs: [deploy] - concurrency: - group: deploy-prod - cancel-in-progress: false - uses: ./.github/workflows/tests_integration.yml - with: - git-sha: ${{ github.event.release.tag_name }} - deploy-env: prod - runs-on: mdb-prod - secrets: inherit - - tests_completed: - name: All Tests Succeeded - needs: [run_unit_tests, run_integration_tests] - runs-on: mdb-dev - steps: - - name: fail if tests failed or didnt run - if: ${{ needs.run_unit_tests.result != 'success' || needs.run_integration_tests.result != 'success'}} - run: exit 1 - - run: echo "Tests ran successfully" - - slack_message: - if: failure() && !cancelled() - name: Notify Slack - # Every previous job needs to be in here, because failure() will only return true if the job that failed is in 'needs' - needs: [check-version, run_unit_tests, deploy_to_pypi, build, build-cache, deploy, trigger_dd_extension_release, run_integration_tests, tests_completed] - runs-on: mdb-dev - steps: - - name: Notify of failing tests - uses: slackapi/slack-github-action@v1.26.0 - with: - channel-id: ${{ secrets.SLACK_ENG_CHANNEL_ID }} - payload: | - { - "attachments": [ - { - "color": "#FF4444", - "blocks": [ - { - "type": "header", - "text": { - "type": "plain_text", - "text": "TEST RUN FAILED ON RELEASE ${{ github.event.release.tag_name }}", - "emoji": true - } - }, - { - "type": "section", - "text": { - "type": "mrkdwn", - "text": " " - }, - "fields": [ - { - "type": "mrkdwn", - "text": "*Commit*\n<${{ github.server_url }}/${{ github.repository }}/commit/${{ github.sha }}|${{ github.sha }}>" - }, - { - "type": "mrkdwn", - "text": "*Workflow Run*\n<${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}|${{ github.workflow }}>" - } - ] - } - ] - } - ] - } - env: - SLACK_BOT_TOKEN: ${{ secrets.GH_ACTIONS_SLACK_BOT_TOKEN }} diff --git a/.github/workflows/build_deploy_staging.yml b/.github/workflows/build_deploy_staging.yml deleted file mode 100644 index f580f8baa5..0000000000 --- a/.github/workflows/build_deploy_staging.yml +++ /dev/null @@ -1,147 +0,0 @@ -name: Build and deploy to staging - -permissions: - contents: read - pull-requests: write - pages: write - id-token: write - -on: - # Using pull_request instead of push on main because we want access to the pull request's details via 'github.event' - # But it means we need to check below if this PR was merged and not just closed - pull_request: - types: - - closed - branches: - - 'main' - - 'releases/*' - -concurrency: - group: ${{ github.workflow_ref }} - cancel-in-progress: true - -jobs: - - run_unit_tests: - name: Run Unit Tests - if: github.event.pull_request.merged == true - uses: ./.github/workflows/tests_unit.yml - secrets: inherit - - # Build our docker images based on our bake file - build: - if: github.event.pull_request.merged == true - name: Build Docker Images - runs-on: mdb-dev - steps: - # Check out the merge commit on the base branch - - uses: actions/checkout@v4 - with: - ref: ${{ github.event.pull_request.merge_commit_sha }} - # Build the bakefile and push - - uses: mindsdb/github-actions/docker-bake@main - with: - push-cache: false - - # Push cache layers to docker registry - # This is separate to the build step so we can do other stuff in parallel - build-cache: - name: Push Docker Cache - runs-on: mdb-dev - needs: [build] - steps: - # Check out the merge commit on the base branch - - uses: actions/checkout@v4 - with: - ref: ${{ github.event.pull_request.merge_commit_sha }} - # Build the bakefile and push - - uses: mindsdb/github-actions/docker-bake@main - with: - push-cache: true - cache-only: true - - # Call our deployment workflow - deploy: - name: Deploy to Staging - needs: [build] - uses: ./.github/workflows/deploy.yml - with: - deploy-envs: '["staging", "dev", "alpha-dev"]' - image-tag: ${{ github.event.pull_request.merge_commit_sha }} - secrets: inherit - - # Run integration tests - run_integration_tests: - if: github.event.pull_request.merged == true - name: Run Integration Tests - needs: [deploy] - concurrency: - group: deploy-staging - cancel-in-progress: false - uses: ./.github/workflows/tests_integration.yml - with: - git-sha: ${{ github.event.pull_request.merge_commit_sha }} - deploy-env: staging - secrets: inherit - - tests_completed: - if: always() && github.event.pull_request.merged == true - name: All Tests Succeeded - needs: [run_unit_tests, run_integration_tests] - runs-on: mdb-dev - steps: - - name: fail if tests failed or didnt run - if: ${{ needs.run_unit_tests.result != 'success' || needs.run_integration_tests.result != 'success'}} - run: exit 1 - - run: echo "Tests ran successfully" - - slack_message: - if: failure() && !cancelled() && github.event.pull_request.merged == true - name: Notify Slack - # Every previous job needs to be in here, because failure() will only return true if the job that failed is in 'needs' - needs: [run_unit_tests, build, build-cache, deploy, run_integration_tests, tests_completed] - runs-on: mdb-dev - steps: - - name: Notify of failing tests - if: ${{ needs.tests_completed.result != 'success' && needs.tests_completed.result != 'cancelled' }} - uses: slackapi/slack-github-action@v1.26.0 - with: - channel-id: ${{ secrets.SLACK_ENG_CHANNEL_ID }} - payload: | - { - "attachments": [ - { - "color": "#FF4444", - "blocks": [ - { - "type": "header", - "text": { - "type": "plain_text", - "text": "TEST RUN FAILED ON ${{ github.base_ref }}", - "emoji": true - } - }, - { - "type": "section", - "text": { - "type": "mrkdwn", - "text": " " - }, - "fields": [ - { - "type": "mrkdwn", - "text": "*Commit*\n<${{ github.server_url }}/${{ github.repository }}/commit/${{ github.sha }}|${{ github.sha }}>" - }, - { - "type": "mrkdwn", - "text": "*Workflow Run*\n<${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}|${{ github.workflow }}>" - } - ] - } - ] - } - ] - } - env: - SLACK_BOT_TOKEN: ${{ secrets.GH_ACTIONS_SLACK_BOT_TOKEN }} - diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml deleted file mode 100644 index 93f6326ea2..0000000000 --- a/.github/workflows/deploy.yml +++ /dev/null @@ -1,107 +0,0 @@ -permissions: - contents: read - -on: - workflow_call: - inputs: - deploy-envs: - required: true - type: string - image-tag: - required: true - type: string - prod: - required: false - type: boolean - default: false - secrets: - SLACK_DEPLOYMENTS_CHANNEL_ID: - required: true - REPO_DISPATCH_PAT_TOKEN: - required: true - MINDSDB_DB_URI: - required: true - - -jobs: - migrate: - if: github.actor != 'mindsdbadmin' - runs-on: ${{ matrix.deploy-env == 'prod' && 'mdb-prod' || 'mdb-dev' }} - strategy: - fail-fast: false - matrix: - deploy-env: ${{ fromJson(inputs.deploy-envs) }} - concurrency: - group: deploy-${{ matrix.deploy-env }} - cancel-in-progress: false - environment: - name: ${{ matrix.deploy-env }} - url: ${{ vars.MDB_ENV_URL }} - # We only want to run one deploy job for an env at a time - # Don't cancel in progress jobs because it may be for a different PR - env: - MINDSDB_DB_CON: ${{ secrets.MINDSDB_DB_URI }} - UV_LINK_MODE: "symlink" - steps: - - uses: actions/checkout@v4 - - name: Setup uv - uses: astral-sh/setup-uv@v5 - with: - # Place cache in the tool dir because we mount this in our runnners - cache-local-path: "/home/runner/_work/_tool/uv-local-cache" - prune-cache: false - python-version: ${{ vars.CI_PYTHON_VERSION || '3.11' }} - - name: Install dependencies - run: | - uv pip install -r requirements/requirements.txt - - name: Migrate DB - run: | - cd mindsdb/migrations - env PYTHONPATH=../../ alembic upgrade head - - - # Trigger private repo to deploy - trigger_deploy: - if: github.actor != 'mindsdbadmin' - needs: migrate - runs-on: mdb-dev - strategy: - fail-fast: false - matrix: - deploy-env: ${{ fromJson(inputs.deploy-envs) }} - concurrency: - group: deploy-${{ matrix.deploy-env }} - cancel-in-progress: false - environment: - name: ${{ matrix.deploy-env }} - url: ${{ vars.MDB_ENV_URL }} - steps: - - uses: FranzDiebold/github-env-vars-action@v2 - - name: Notify of deployment starting - id: slack - uses: mindsdb/github-actions/slack-deploy-msg@main - with: - channel-id: ${{ secrets.SLACK_DEPLOYMENTS_CHANNEL_ID }} - status: "started" - color: "#0099CC" - env-name: ${{ matrix.deploy-env }} - env-url: ${{ vars.MDB_ENV_URL }} - slack-token: ${{ secrets.GH_ACTIONS_SLACK_BOT_TOKEN }} - - uses: mindsdb/github-actions/dispatch-and-wait@main - with: - owner: mindsdb - repo: INTERNAL-mindsdb-build-deploy-to-kubernetes - token: ${{ secrets.REPO_DISPATCH_PAT_TOKEN }} - workflow: ${{ inputs.prod && 'deploy-prod.yml' || 'deploy-dev.yml' }} - workflow_inputs: '{"image-tag-prefix": "${{ inputs.image-tag }}", "deploy-env": "${{ matrix.deploy-env }}"}' - - name: Notify of deployment finish - uses: mindsdb/github-actions/slack-deploy-msg@main - if: always() - with: - channel-id: ${{ secrets.SLACK_DEPLOYMENTS_CHANNEL_ID }} - status: "${{ job.status == 'success' && 'finished' || 'failed' }}" - color: "${{ job.status == 'success' && '#00C851' || '#FF4444' }}" - env-name: ${{ matrix.deploy-env }} - env-url: ${{ vars.MDB_ENV_URL }} - slack-token: ${{ secrets.GH_ACTIONS_SLACK_BOT_TOKEN }} - update-message-id: ${{ steps.slack.outputs.ts }} \ No newline at end of file diff --git a/.github/workflows/tests_integration.yml b/.github/workflows/tests_integration.yml deleted file mode 100644 index 3edd71e1c0..0000000000 --- a/.github/workflows/tests_integration.yml +++ /dev/null @@ -1,74 +0,0 @@ -name: Test on Deploy - -permissions: - contents: read - -on: - workflow_call: - inputs: - git-sha: - required: false - type: string - default: "" - deploy-env: - required: true - type: string - runs-on: - required: false - type: string - default: "mdb-dev" - secrets: - OPENAI_API_KEY: - required: true - workflow_dispatch: - inputs: - git-sha: - required: false - type: string - default: "" - deploy-env: - required: true - type: string - runs-on: - required: false - type: string - default: "mdb-dev" - secrets: - OPENAI_API_KEY: - required: true - -defaults: - run: - shell: bash - -env: - UV_LINK_MODE: "symlink" - -jobs: - # Run our integration tests - test: - environment: - name: ${{ inputs.deploy-env }} - url: ${{ vars.MDB_ENV_URL }} - name: Run integration tests on deploy - runs-on: ${{ inputs.runs-on }} - steps: - - uses: actions/checkout@v4 - with: - ref: ${{ inputs.git-sha }} - - name: Setup uv - uses: astral-sh/setup-uv@v5 - with: - # Place cache in the tool dir because we mount this in our runnners - cache-local-path: "/home/runner/_work/_tool/uv-local-cache" - prune-cache: false - python-version: ${{ vars.CI_PYTHON_VERSION || '3.11' }} - - name: Install dependencies - run: | - uv pip install -r requirements/requirements-test.txt - - name: Run Integration Tests on Deploy - run: | - make integration_tests_slow - env: - OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }} - INTERNAL_URL: ${{ vars.MINDSDB_INTERNAL_URL }} diff --git a/scripts/run_integration_tests.sh b/scripts/run_integration_tests.sh index 757a10b046..ad12216f95 100755 --- a/scripts/run_integration_tests.sh +++ b/scripts/run_integration_tests.sh @@ -1,7 +1,6 @@ #!/usr/bin/env bash # # Local Integration Test Runner for macOS -# Replicates the GitHub Actions workflow from .github/workflows/tests_integration.yml # # Usage: # ./run_integration_tests.sh # Run all integration tests (slow)