Skip to content

fix(cla-assistant): make the allowlist bots only, and default it here (ENG-2017) - #56

Merged
mindsdb-devops merged 1 commit into
mainfrom
chore/eng-2017-allowlist-bots-only
Aug 28, 2026
Merged

fix(cla-assistant): make the allowlist bots only, and default it here (ENG-2017)#56
mindsdb-devops merged 1 commit into
mainfrom
chore/eng-2017-allowlist-bots-only

Conversation

@lucas-koontz

Copy link
Copy Markdown
Contributor

User story

As whoever has to know who is exempt from signing our contributor agreement
I want that answer in one file, and to be a list of bots rather than a list of people
So that nobody has to prune six copies of a stale employee roster, and nobody forgets to

Why this matters

Fifteen repositories carried six different hand-maintained allowlists, naming 25 people between them. They are not six policies. They are six snapshots of who worked here when each repository was last touched.

11 of those 25 are no longer in the mindsdb org: George3d6, Ricram2, ala12326571, dusvyat, dylanketterer, ilia-tsyplenkov, maximlopin, mindsdbadmin, paxcema, tmichaeldb, tomhuds. An allowlist entry exempts that account from signing, so each is a former colleague who can contribute to GPL-3.0 and Elastic-2.0 code without signing anything.

A list of people is an access-control list. It needs an owner and a review, and nobody was ever going to give six copies either.

What changes

Staff sign like everybody else. It is one comment, it produces an actual signed record rather than an assumption that somebody's employment agreement was in place and covered the work, and it deletes the stale-list problem instead of managing it.

Bots stay, and that is not a shortcut. A bot cannot post the agreement sentence, so with no exemption its pull request is red forever. Measured across all fifteen repositories, exactly two bots open pull requests here:

42  dependabot[bot]
13  mindsdb-release-train[bot]

lightwood alone has 36 Dependabot pull requests in its last 100. github-actions[bot] needs no entry, because the action already drops user id 41898282 in graphql.ts before the allowlist is consulted.

The list lives here and defaults. A wrapper now passes path-to-document and nothing else.

Two live defects this removes

Both come out of checkAllowList.ts, and both were in all fifteen repositories.

bot* was never a prefix match. The action compiles it to new RegExp("bot.*") and calls .test(), which is unanchored and searches anywhere in the string. So it also exempted any login containing "bot". I ran the action's own matcher:

login exempt?
dependabot[bot] yes, intended
robotnik yes
sabotage yes
elliotbotson yes

That is an opt-out anybody could grant themselves by choosing a username. Naming the two bots removes the wildcard and the hole with it.

Stpmax never matched StpMax. Non-wildcard entries are compared with pattern === committer, exact and case-sensitive. Every one of the six lists writes Stpmax; the real login is StpMax. He has been exempt in zero repositories and asked to sign every time. Dropping the human entries makes the whole class unreachable.

Acceptance criteria

  • The reusable's allowlist input defaults, so a caller can omit it.
  • The default contains no *, so no lookalike login is exempt.
  • The default contains no human logins.
  • dependabot[bot] and mindsdb-release-train[bot] stay exempt, so bot pull requests do not go permanently red.
  • CI fails if any of the above stops being true.
  • Negative: a caller that still passes allowlist keeps working. Making a required input optional is backward compatible, which is what lets the thirteen wrappers drop it in any order after this merges.

How to test

  1. Merge this, then open a pull request on a converted repository from an account that is not a bot. Confirm the CLA bot asks for a signature, including for staff.
  2. Confirm a Dependabot pull request on lightwood still passes the CLA check with no comment.
  3. Run uv run --with pyyaml --with pytest --python 3.12 -m pytest tests/test_cla_allowlist.py -q. Then put bot*, ZoranPandovski back as the default and run it again; it should go red.

Notes for the reviewer

Everyone at MindsDB will be asked to sign, once per repository, the first time they open a pull request there. That is the intended cost and it is worth saying out loud before this merges, because it will surprise people. Fourteen current org members are affected. It is one comment each.

The mindsdbadmin question is left open on purpose. It is in every one of the six lists, it is not an org member, and engine's and minds_python_sdk's release jobs still guard on github.actor != 'mindsdbadmin', so something still uses it. Whether it needs an exemption is a question for whoever owns that account, not something to guess at here.

Ex-staff lose their exemption, and I think that is correct rather than a regression. All eleven are already out of the org. If they contribute again they sign, like any other outside contributor. Say if you would rather grandfather any of them, because it is one entry.

The test is a real guard, not coverage theatre. Against the old list it fails 8 of its 11 cases, including all four lookalike logins.

Verified locally

Check What I observed
pytest tests/ -q 148 passed in 0.33s. 137 before, 11 new.
The guard actually bites Replaced the default with bot*, ZoranPandovski, torrmal, Stpmax, mindsdbadmin and re-ran: 8 failed, 3 passed. Restored: 11 passed.
actionlint Clean across all 12 workflows, v1.7.12.
workflow_graph.py --allow-external-reusables "Checked 12 workflow(s): every local reusable call composes, and every event produces exactly one run tree."
Which bots actually open pull requests gh api repos/mindsdb/<repo>/pulls?state=all&per_page=100 across all 15: dependabot[bot] 42, mindsdb-release-train[bot] 13, nothing else.
github-actions[bot] is filtered upstream graphql.ts drops id 41898282; gh api user/41898282 resolves to github-actions[bot].
Who is still in the org gh api orgs/mindsdb/members/<login> for all 25 named logins: 14 members, 11 not.

Ships with

The thirteen wrappers that currently pass their own list drop it, in any order
after this merges. Making a required input optional is backward compatible, so
nothing breaks in the window between.

Merge order: this one first. A wrapper that drops allowlist while the
input is still required: true fails to load.

Refs: ENG-2017

… (ENG-2017)

Staff sign like everybody else now. The allowlist defaults in this file and a
wrapper stops passing one.

Fifteen repos carried six different hand-maintained lists naming 25 people
between them, and 11 of those 25 had already left the org, so each was a former
colleague still exempt from signing a CLA on GPL-3.0 and Elastic-2.0 code. A
list of people is an access-control list: it needs an owner and a review, and
nobody was going to give six copies either. One comment from an employee is
cheaper than that, and it produces a signature instead of an assumption that an
employment agreement was in place and covered the work.

Bots stay, because a bot cannot sign. It cannot post the agreement sentence, so
with no exemption its pull request is red forever, and lightwood alone has 36
Dependabot pull requests in its last 100. Only the two that actually open pull
requests in this org are listed. github-actions[bot] needs no entry: the action
already drops user id 41898282 in graphql.ts.

Dropping the human entries also removes two live defects. checkAllowList.ts
compares non-wildcard entries with `pattern === committer`, exact and
case-sensitive, so every list's `Stpmax` never once matched the real login
`StpMax`. And `bot*` compiled to an UNANCHORED `new RegExp("bot.*").test(login)`,
which matches any login containing "bot": `robotnik`, `sabotage` and
`elliotbotson` were all exempt from the CLA in all fifteen repos. Naming the two
bots removes the wildcard and the hole with it.

tests/test_cla_allowlist.py pins all three: no wildcard, no humans, and the
lookalikes stay unexempt. Against the old list it fails 8 of its 11 cases.
@lucas-koontz
lucas-koontz requested a review from a team as a code owner August 28, 2026 00:14
lucas-koontz added a commit to mindsdb/dataprep_ml that referenced this pull request Aug 28, 2026
…2017)

The 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. A bot cannot sign, so the two that
actually open pull requests in this org stay exempt in the reusable.

Dropping the line also drops two defects that rode inside it. `bot*` compiled to
an unanchored `new RegExp("bot.*").test(login)`, so it exempted any login
containing "bot", `robotnik` and `sabotage` included. And `Stpmax` never matched
the real login `StpMax`, because non-wildcard entries are compared with a
case-sensitive `===`.

Needs mindsdb/github-actions#56 first, which gives the input a default.
lucas-koontz added a commit to mindsdb/lightwood that referenced this pull request Aug 28, 2026
…2017)

The 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. A bot cannot sign, so the two that
actually open pull requests in this org stay exempt in the reusable.

Dropping the line also drops two defects that rode inside it. `bot*` compiled to
an unanchored `new RegExp("bot.*").test(login)`, so it exempted any login
containing "bot", `robotnik` and `sabotage` included. And `Stpmax` never matched
the real login `StpMax`, because non-wildcard entries are compared with a
case-sensitive `===`.

Needs mindsdb/github-actions#56 first, which gives the input a default.
lucas-koontz added a commit to mindsdb/minds_python_sdk that referenced this pull request Aug 28, 2026
…2017)

The 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. A bot cannot sign, so the two that
actually open pull requests in this org stay exempt in the reusable.

Dropping the line also drops two defects that rode inside it. `bot*` compiled to
an unanchored `new RegExp("bot.*").test(login)`, so it exempted any login
containing "bot", `robotnik` and `sabotage` included. And `Stpmax` never matched
the real login `StpMax`, because non-wildcard entries are compared with a
case-sensitive `===`.

Needs mindsdb/github-actions#56 first, which gives the input a default.
lucas-koontz added a commit to mindsdb/mindsdb-js-sdk that referenced this pull request Aug 28, 2026
…2017)

The 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. A bot cannot sign, so the two that
actually open pull requests in this org stay exempt in the reusable.

Dropping the line also drops two defects that rode inside it. `bot*` compiled to
an unanchored `new RegExp("bot.*").test(login)`, so it exempted any login
containing "bot", `robotnik` and `sabotage` included. And `Stpmax` never matched
the real login `StpMax`, because non-wildcard entries are compared with a
case-sensitive `===`.

Needs mindsdb/github-actions#56 first, which gives the input a default.
lucas-koontz added a commit to mindsdb/mindsdb_evaluator that referenced this pull request Aug 28, 2026
…2017)

The 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. A bot cannot sign, so the two that
actually open pull requests in this org stay exempt in the reusable.

Dropping the line also drops two defects that rode inside it. `bot*` compiled to
an unanchored `new RegExp("bot.*").test(login)`, so it exempted any login
containing "bot", `robotnik` and `sabotage` included. And `Stpmax` never matched
the real login `StpMax`, because non-wildcard entries are compared with a
case-sensitive `===`.

Needs mindsdb/github-actions#56 first, which gives the input a default.
lucas-koontz added a commit to mindsdb/mindsdb_python_sdk that referenced this pull request Aug 28, 2026
…2017)

The 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. A bot cannot sign, so the two that
actually open pull requests in this org stay exempt in the reusable.

Dropping the line also drops two defects that rode inside it. `bot*` compiled to
an unanchored `new RegExp("bot.*").test(login)`, so it exempted any login
containing "bot", `robotnik` and `sabotage` included. And `Stpmax` never matched
the real login `StpMax`, because non-wildcard entries are compared with a
case-sensitive `===`.

Needs mindsdb/github-actions#56 first, which gives the input a default.
lucas-koontz added a commit to mindsdb/type_infer that referenced this pull request Aug 28, 2026
…2017)

The 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. A bot cannot sign, so the two that
actually open pull requests in this org stay exempt in the reusable.

Dropping the line also drops two defects that rode inside it. `bot*` compiled to
an unanchored `new RegExp("bot.*").test(login)`, so it exempted any login
containing "bot", `robotnik` and `sabotage` included. And `Stpmax` never matched
the real login `StpMax`, because non-wildcard entries are compared with a
case-sensitive `===`.

Needs mindsdb/github-actions#56 first, which gives the input a default.
lucas-koontz added a commit to mindsdb/anton that referenced this pull request Aug 28, 2026
…2017)

The 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. A bot cannot sign, so the two that
actually open pull requests in this org stay exempt in the reusable.

Dropping the line also drops two defects that rode inside it. `bot*` compiled to
an unanchored `new RegExp("bot.*").test(login)`, so it exempted any login
containing "bot", `robotnik` and `sabotage` included. And `Stpmax` never matched
the real login `StpMax`, because non-wildcard entries are compared with a
case-sensitive `===`.

Needs mindsdb/github-actions#56 first, which gives the input a default.
lucas-koontz added a commit to mindsdb/cowork that referenced this pull request Aug 28, 2026
…2017)

The 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. A bot cannot sign, so the two that
actually open pull requests in this org stay exempt in the reusable.

Dropping the line also drops two defects that rode inside it. `bot*` compiled to
an unanchored `new RegExp("bot.*").test(login)`, so it exempted any login
containing "bot", `robotnik` and `sabotage` included. And `Stpmax` never matched
the real login `StpMax`, because non-wildcard entries are compared with a
case-sensitive `===`.

Needs mindsdb/github-actions#56 first, which gives the input a default.
lucas-koontz added a commit to mindsdb/cowork-server that referenced this pull request Aug 28, 2026
…2017)

The 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. A bot cannot sign, so the two that
actually open pull requests in this org stay exempt in the reusable.

Dropping the line also drops two defects that rode inside it. `bot*` compiled to
an unanchored `new RegExp("bot.*").test(login)`, so it exempted any login
containing "bot", `robotnik` and `sabotage` included. And `Stpmax` never matched
the real login `StpMax`, because non-wildcard entries are compared with a
case-sensitive `===`.

Needs mindsdb/github-actions#56 first, which gives the input a default.
lucas-koontz added a commit to mindsdb/engine that referenced this pull request Aug 28, 2026
…egration 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.
lucas-koontz added a commit to mindsdb/data-vault that referenced this pull request Aug 28, 2026
…egration 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.
@mindsdb-devops
mindsdb-devops merged commit 747a0de into main Aug 28, 2026
5 checks passed
@mindsdb-devops
mindsdb-devops deleted the chore/eng-2017-allowlist-bots-only branch August 28, 2026 00:32
mindsdb-devops pushed a commit to mindsdb/lightwood that referenced this pull request Aug 28, 2026
… (ENG-2017) (#1294)

* chore(cla): call the shared CLA reusable instead of a self-hosted job (ENG-2017)

The CLA check ran on mdb-dev, a pod inside the newdev cluster. Its triggers,
pull_request_target and issue_comment, both run in base-repo context, so
GitHub's fork-approval gate never applied and any account could start that pod
by opening a pull request or leaving a comment.

Replace the hand-rolled job with the reusable anton, cowork and cowork-server
already call. It runs on ubuntu-latest, pins the third-party action to a commit,
grants actions read rather than write, and skips the job outright for a comment
that is not a CLA comment.

Refs: ENG-2017

* 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

* chore(cla): stop passing an allowlist, the reusable owns it now (ENG-2017)

The 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. A bot cannot sign, so the two that
actually open pull requests in this org stay exempt in the reusable.

Dropping the line also drops two defects that rode inside it. `bot*` compiled to
an unanchored `new RegExp("bot.*").test(login)`, so it exempted any login
containing "bot", `robotnik` and `sabotage` included. And `Stpmax` never matched
the real login `StpMax`, because non-wildcard entries are compared with a
case-sensitive `===`.

Needs mindsdb/github-actions#56 first, which gives the input a default.

* chore(ci): require DevOps review on .github/ (ENG-2017)

This repo accepts pull requests from outside contributors and had no CODEOWNERS
at all, so a workflow change here needed no particular reviewer. Everything
under .github/ decides what runs in CI, on which runner, and with which secrets
in scope, which is a trust boundary rather than product code.

Auto-request only for now. Making it a hard gate needs require_code_owner_reviews
in branch protection, which this repo does not have; that rides ENG-2013's org
ruleset.
mindsdb-devops pushed a commit to mindsdb/cowork that referenced this pull request Aug 28, 2026
…-2017) (#745)

* chore(cla): point the agreement link at the canonical repository (ENG-2017)

The URL this passed was an alias that redirects to the repository actually
holding the file, and it served byte-identical content, so nothing a
contributor reads changes. An alias stops being harmless the moment somebody
creates a repository at that name, and this is the page a contributor reads
before agreeing to it. Ten library repos moved to the canonical name in the
same change set; this makes all thirteen agree.

Refs: ENG-2017

* chore(cla): grant actions read rather than write (ENG-2017)

The shared reusable now declares `actions: read`, so write buys this caller
nothing: a called workflow can never hold more than its caller grants, and
the callee's own declaration caps it further. The only write the scope would
buy is pullRerunRunner.ts re-running a previously failed CLA run, and that
API refuses a GITHUB_TOKEN. Dropping the scope entirely is not an option,
because the same file lists the repo's workflows first and main.ts turns any
throw into a failed job.

This is the grant the README documents for a caller, and this repo was one of
three still on the old one.

* chore(cla): stop passing an allowlist, the reusable owns it now (ENG-2017)

The 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. A bot cannot sign, so the two that
actually open pull requests in this org stay exempt in the reusable.

Dropping the line also drops two defects that rode inside it. `bot*` compiled to
an unanchored `new RegExp("bot.*").test(login)`, so it exempted any login
containing "bot", `robotnik` and `sabotage` included. And `Stpmax` never matched
the real login `StpMax`, because non-wildcard entries are compared with a
case-sensitive `===`.

Needs mindsdb/github-actions#56 first, which gives the input a default.
mindsdb-devops pushed a commit to mindsdb/anton that referenced this pull request Aug 28, 2026
…-2017) (#409)

* chore(cla): point the agreement link at the canonical repository (ENG-2017)

The URL this passed was an alias that redirects to the repository actually
holding the file, and it served byte-identical content, so nothing a
contributor reads changes. An alias stops being harmless the moment somebody
creates a repository at that name, and this is the page a contributor reads
before agreeing to it. Ten library repos moved to the canonical name in the
same change set; this makes all thirteen agree.

Refs: ENG-2017

* chore(cla): grant actions read rather than write (ENG-2017)

The shared reusable now declares `actions: read`, so write buys this caller
nothing: a called workflow can never hold more than its caller grants, and
the callee's own declaration caps it further. The only write the scope would
buy is pullRerunRunner.ts re-running a previously failed CLA run, and that
API refuses a GITHUB_TOKEN. Dropping the scope entirely is not an option,
because the same file lists the repo's workflows first and main.ts turns any
throw into a failed job.

This is the grant the README documents for a caller, and this repo was one of
three still on the old one.

* chore(cla): stop passing an allowlist, the reusable owns it now (ENG-2017)

The 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. A bot cannot sign, so the two that
actually open pull requests in this org stay exempt in the reusable.

Dropping the line also drops two defects that rode inside it. `bot*` compiled to
an unanchored `new RegExp("bot.*").test(login)`, so it exempted any login
containing "bot", `robotnik` and `sabotage` included. And `Stpmax` never matched
the real login `StpMax`, because non-wildcard entries are compared with a
case-sensitive `===`.

Needs mindsdb/github-actions#56 first, which gives the input a default.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants