From a5fa323efdcca28d9bb37c39a38351c6a836be36 Mon Sep 17 00:00:00 2001 From: Lucas Koontz Date: Thu, 27 Aug 2026 10:35:57 -0700 Subject: [PATCH 1/4] chore(ci): take fork-reachable jobs off the self-hosted runners (ENG-2017) Four jobs reached mdb-dev from a pull request with no fork guard: changes, tests_completed, and code_checking and matrix_prep inside tests_unit. Of those code_checking is the one that matters, because it checks out the fork's tree and then runs a script and a pre-commit config the fork controls. Move all four to GitHub-hosted runners rather than skipping them, so an external contribution still gets CI and the collection job a branch rule points at still reports. code_checking swaps the FSx cache path for the hosted cache the matrix jobs in the same file already use; that path only exists on the self-hosted image. matrix_prep now rejects a runner label that is not GitHub-hosted. matrix_includes.json is read from the pull request's own checkout and feeds runs-on directly, so a fork could have named mdb-dev there without touching a workflow file. scan-keycloak gains the explicit fork guard its four neighbours carry. It was already unreachable for a fork, but only through a needs edge on a guarded job. The CLA workflow moves to the shared reusable in the same change, which takes it off mdb-dev and pins the third-party action it runs. Refs: ENG-2017 --- .github/workflows/build_deploy_dev.yml | 5 ++-- .github/workflows/cla.yml | 18 ++++----------- .github/workflows/tests_unit.yml | 32 ++++++++++++++++++++++---- 3 files changed, 36 insertions(+), 19 deletions(-) diff --git a/.github/workflows/build_deploy_dev.yml b/.github/workflows/build_deploy_dev.yml index cc9d25f7ed..35eac7bf9d 100644 --- a/.github/workflows/build_deploy_dev.yml +++ b/.github/workflows/build_deploy_dev.yml @@ -23,7 +23,7 @@ jobs: changes: name: Filter changed files - runs-on: mdb-dev + runs-on: ubuntu-latest outputs: not-docs: ${{ steps.filter.outputs.not-docs }} steps: @@ -78,6 +78,7 @@ jobs: push-cache: false scan-keycloak: + if: ${{ !github.event.pull_request.head.repo.fork }} runs-on: mdb-dev needs: [ build ] name: Scan cloud-cpu image @@ -140,7 +141,7 @@ jobs: tests_completed: name: All Tests Succeeded needs: [run_unit_tests, run_integration_tests, changes] - runs-on: mdb-dev + runs-on: ubuntu-latest if: always() steps: - name: fail if tests failed or didnt run diff --git a/.github/workflows/cla.yml b/.github/workflows/cla.yml index 796fc2c0a2..3794c4d404 100644 --- a/.github/workflows/cla.yml +++ b/.github/workflows/cla.yml @@ -1,7 +1,7 @@ name: "MindsDB CLA Assistant" permissions: - actions: write + actions: read contents: write pull-requests: write statuses: write @@ -14,15 +14,7 @@ on: jobs: CLAssistant: - runs-on: mdb-dev - steps: - - name: "CLA Assistant" - if: (github.event.comment.body == 'recheck' || github.event.comment.body == 'I have read the CLA Document and I hereby sign the CLA') || github.event_name == 'pull_request_target' - uses: contributor-assistant/github-action@v2.6.1 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - with: - path-to-signatures: 'assets/contributions-agreement/signatures/cla.json' - path-to-document: 'https://github.com/mindsdb/mindsdb/blob/main/assets/contributions-agreement/individual-contributor.md' - branch: 'cla' - allowlist: bot*, ZoranPandovski, torrmal, Stpmax, mindsdbadmin, ea-rus, tmichaeldb, dusvyat, hamishfagg, MinuraPunchihewa, martyna-mindsdb, dylanketterer, ala12326571 + uses: mindsdb/github-actions/.github/workflows/cla-assistant.yml@main + with: + path-to-document: 'https://github.com/mindsdb/mindsdb/blob/main/assets/contributions-agreement/individual-contributor.md' + allowlist: bot*, ZoranPandovski, torrmal, Stpmax, mindsdbadmin, ea-rus, tmichaeldb, dusvyat, hamishfagg, MinuraPunchihewa, martyna-mindsdb, dylanketterer, ala12326571 diff --git a/.github/workflows/tests_unit.yml b/.github/workflows/tests_unit.yml index 876972852f..bccd117cd3 100644 --- a/.github/workflows/tests_unit.yml +++ b/.github/workflows/tests_unit.yml @@ -47,7 +47,7 @@ jobs: # Run all of our static code checks here code_checking: name: Run static code checks - runs-on: mdb-dev + runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkout@v4 @@ -57,8 +57,7 @@ jobs: - 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^ + enable-cache: true python-version: ${{ vars.CI_PYTHON_VERSION || '3.11' }} # Default to 3.11 where vars aren't available (PRs from forks) # Checks the codebase for print() statements and fails if any are found # We should be using loggers instead @@ -86,7 +85,7 @@ jobs: # Creates a matrix of environments to test against using matrix_includes.json matrix_prep: name: Prepare matrix - runs-on: mdb-dev + runs-on: ubuntu-latest outputs: matrix: ${{ steps.set-matrix.outputs.matrix }} steps: @@ -97,6 +96,31 @@ jobs: uses: JoshuaTheMiller/conditional-build-matrix@v2.0.1 with: filter: "[?runOnBranch==`${{ github.ref }}` || runOnBranch==`always`]" + # matrix_includes.json is read from the pull request's own checkout, so on + # a fork PR the contributor chooses these labels. The jobs below feed them + # straight into `runs-on`, which is how a fork would put its own code on a + # pod inside our clusters without touching a workflow file. + - name: Reject runner labels that are not GitHub-hosted + env: + MATRIX: ${{ steps.set-matrix.outputs.matrix }} + run: | + set -euo pipefail + # tostring and the array branch matter: `runs-on` also accepts a list + # of labels, and an entry with no `runs_on` at all reads as null. Both + # have to reach the comparison as strings rather than crashing jq, + # which would report nothing. + BAD=$(jq -r ' + [(.include // [])[].runs_on] + | map(if type == "array" then .[] else . end) + | map(tostring) + - ["ubuntu-latest","ubuntu-24.04","ubuntu-22.04","windows-latest","macos-latest"] + | unique | join(", ") + ' <<< "$MATRIX") + # Expect: empty, so every matrix entry names a GitHub-hosted runner + if [ -n "$BAD" ]; then + echo "::error::matrix_includes.json asks for runner labels that are not GitHub-hosted: $BAD" + exit 1 + fi check_install: name: Check pip installation From 384907e60637680f49995bc6377318eee17cf2d2 Mon Sep 17 00:00:00 2001 From: Lucas Koontz Date: Thu, 27 Aug 2026 14:31:51 -0700 Subject: [PATCH 2/4] fix(cla): point the agreement link at the canonical repository (ENG-2017) Both URLs the org uses for this document are rename redirects that resolve to the same repository and serve byte-identical content. A redirect is fine until somebody creates a repository at the old name, and this is the page a contributor reads before agreeing to it. Name the repository that actually holds the file. Refs: ENG-2017 --- .github/workflows/cla.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/cla.yml b/.github/workflows/cla.yml index 3794c4d404..b5b6475f49 100644 --- a/.github/workflows/cla.yml +++ b/.github/workflows/cla.yml @@ -16,5 +16,5 @@ jobs: CLAssistant: uses: mindsdb/github-actions/.github/workflows/cla-assistant.yml@main with: - path-to-document: 'https://github.com/mindsdb/mindsdb/blob/main/assets/contributions-agreement/individual-contributor.md' + path-to-document: 'https://github.com/mindsdb/mindshub/blob/main/assets/contributions-agreement/individual-contributor.md' allowlist: bot*, ZoranPandovski, torrmal, Stpmax, mindsdbadmin, ea-rus, tmichaeldb, dusvyat, hamishfagg, MinuraPunchihewa, martyna-mindsdb, dylanketterer, ala12326571 From 0b9d4d0b8a9a262a83104e0a5270641020acb2e5 Mon Sep 17 00:00:00 2001 From: Lucas Koontz Date: Thu, 27 Aug 2026 15:28:22 -0700 Subject: [PATCH 3/4] chore(ci): say why the runner allowlist is an allowlist (ENG-2017) The jq subtracts a fixed set of GitHub-hosted labels rather than matching our own self-hosted ones, so a label nobody has thought of yet fails instead of passing. That is the right direction and it is not obvious from the code: the next person adding a hosted image to matrix_includes.json will hit the error and needs to know the allowlist is where to add it. No behaviour change. jq reads `#` to end of line inside the program, and the validator still passes the real matrix and still rejects mdb-dev, a bare self-hosted, the list form and a missing runs_on. --- .github/workflows/tests_unit.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/tests_unit.yml b/.github/workflows/tests_unit.yml index bccd117cd3..f490c8454d 100644 --- a/.github/workflows/tests_unit.yml +++ b/.github/workflows/tests_unit.yml @@ -113,6 +113,10 @@ jobs: [(.include // [])[].runs_on] | map(if type == "array" then .[] else . end) | map(tostring) + # An allowlist, not a denylist of our own labels, so a label nobody + # has thought of yet fails rather than passes. Adding a new + # GitHub-hosted image to matrix_includes.json means adding it here + # too, and the error below says which label was rejected. - ["ubuntu-latest","ubuntu-24.04","ubuntu-22.04","windows-latest","macos-latest"] | unique | join(", ") ' <<< "$MATRIX") From dee07f30a14bae7b5f2b1ce435fdac14ad47b77d Mon Sep 17 00:00:00 2001 From: Lucas Koontz Date: Thu, 27 Aug 2026 17:17:01 -0700 Subject: [PATCH 4/4] chore(ci): stop passing an allowlist, and stop failing on skipped integration tests (ENG-2017) Two changes, both about a check saying nothing useful. The CLA allowlist moved into mindsdb/github-actions and is bots only. This repo carried one of six hand-maintained copies naming people, and 11 of the 25 names across those copies had already left the org while still being exempt from signing. Staff sign like everybody else now. Dropping the line also drops two defects that rode inside it: `bot*` compiled to an unanchored regex that exempted any login containing "bot", and `Stpmax` never matched the real login `StpMax` because the comparison is a case-sensitive `===`. Needs mindsdb/github-actions#56 first, which gives the input a default. `All Tests Succeeded` failed on every first-party pull request that carried no deploy label, so its red carried no information. A skipped run_integration_tests means two different things: with no deploy label there was nothing to run them against, which is fine, and a deploy that failed also leaves them skipped, which is not. Reading `!= 'success'` treated both the same. It now gates on whether anything was actually deployed, so a genuine deploy failure still fails the collection job and an unlabelled pull request does not. --- .github/workflows/build_deploy_dev.yml | 15 +++++++++++++-- .github/workflows/cla.yml | 1 - 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build_deploy_dev.yml b/.github/workflows/build_deploy_dev.yml index 35eac7bf9d..5c5543eb5a 100644 --- a/.github/workflows/build_deploy_dev.yml +++ b/.github/workflows/build_deploy_dev.yml @@ -140,11 +140,22 @@ jobs: # 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] + needs: [run_unit_tests, run_integration_tests, changes, get-deploy-labels] 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.run_unit_tests.result != 'success' || (needs.run_integration_tests.result != 'success' && !github.event.pull_request.head.repo.fork)) && needs.changes.outputs.not-docs == 'true' }} + 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')) }} run: exit 1 - run: echo "Tests ran successfully" diff --git a/.github/workflows/cla.yml b/.github/workflows/cla.yml index b5b6475f49..cf8d54d6fb 100644 --- a/.github/workflows/cla.yml +++ b/.github/workflows/cla.yml @@ -17,4 +17,3 @@ jobs: uses: mindsdb/github-actions/.github/workflows/cla-assistant.yml@main with: path-to-document: 'https://github.com/mindsdb/mindshub/blob/main/assets/contributions-agreement/individual-contributor.md' - allowlist: bot*, ZoranPandovski, torrmal, Stpmax, mindsdbadmin, ea-rus, tmichaeldb, dusvyat, hamishfagg, MinuraPunchihewa, martyna-mindsdb, dylanketterer, ala12326571