Skip to content

feat!: add project support to every project-scoped command - #23

Draft
jiatolentino wants to merge 9 commits into
mainfrom
DM-4395-project-support
Draft

jiatolentino wants to merge 9 commits into
mainfrom
DM-4395-project-support

Conversation

@jiatolentino

@jiatolentino jiatolentino commented Oct 28, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

dm works with DataMasque projects. Every project-scoped command takes --project, list commands show each resource's project, the ruleset bundle commands export and import through the v2 endpoints, which file each item under its project, and new dm projects and dm resources move commands manage projects and move resources between them.

Note

Draft until a released datamasque-python has projects. See Dependency.

Why

DataMasque v3.26.21.0 puts every connection, ruleset, library, discovery config, seed, file and table reference in a project, and libraries use projects in place of namespaces. Without --project the CLI cannot choose where a resource goes or which of two same-named resources it means.

What changed

  • --project (a project name in any case, or its numeric ID) on connections, rulesets, libraries, discovery configs, discovery config libraries, seeds, files, table references, runs and discovery runs.
    • List commands show a Project column, and --project lists one project's resources (dm seeds list also keeps the built-in seeds).
    • Create, upload and validate commands use the --project project, else the instance's only project. With several projects and no --project they fail and ask for one.
    • Get, update and delete commands find a name in any project, and ask for --project when it exists in more than one.
    • dm table-references create and update look up --connection in the reference's own project first, then in every project.
  • --namespace is removed from dm libraries and dm discover libraries; use --project.
  • dm rulesets export-bundle and import-bundle go through the client's export_bundle and import_bundle, which use the v2 endpoints.
    • export-bundle --include-seed-files also bundles the custom seed files the rulesets and libraries use.
    • import-bundle --fallback-project names the project for items a bundle files under no project (omitted: the server's default), and the CLI says which project took them. The client warns about an older-format bundle.
  • dm projects: list (--include-deleted adds deleted projects), get, create, update (rename or change the description) and delete.
    • delete takes --to, the project that receives the deleted project's resources. When a resource cannot move, the server deletes nothing and the CLI lists each conflict and exits with the conflict code. --check lists the conflicts without deleting.
  • dm resources move --to <project> moves resources selected by --project, --type, --search or exact names, with their files and runs.
    • It needs at least one selector, and leaves out built-in seeds and resources already in the destination.
    • A name that matches none of the selected resources aborts with the not_found code and lists each such name, so nothing moves.
    • A resource that clashes with the destination stays where it is and the others move. The CLI lists each one that stayed and exits with the conflict code. --check lists the selection and its conflicts without moving anything.
  • src/datamasque_cli/projects.py: the shared --project resolution and output helpers.
  • README Projects section, and the bundled skills, updated for --project, dm projects and dm resources move.

Breaking: --namespace is gone, and the CLI needs a DataMasque version with projects. The --project and bundle commits carry a BREAKING CHANGE: footer.

Testing

  • make check: ruff, format, mypy and deptry clean; 486 unit tests pass. install-smoke fails as described under Dependency.
  • Against a DataMasque development build with projects, with two projects:
    • every command group: create, list, get, update and delete in each project, the "name in more than one project" and "project not found" paths, runs and discovery runs;
    • export-bundle writes a v2 bundle with each item under its project, and re-importing it skips each item by ID;
    • export-bundle --include-seed-files adds each seed file under its project, and without it the bundle has none;
    • a v1 bundle with --fallback-project lands in that project and names it, without it lands in the server's default project, and an unknown project exits 3 before uploading;
    • dm resources move with a mistyped name, or a name --type leaves out, exits 3 naming it and moves nothing.
  • dm projects and dm resources move against a development build with project rename, on a new instance: create, a name clash, get, rename, description change, list --include-deleted, delete with and without a conflict, --check, declining the prompt, moving one ruleset, and moving a project with one conflict (the rest moved, exit code conflict).
  • Integration tests: the two rewritten for projects pass. The rest create without --project and expect a single-project instance; they are still to run on one.

Dependency

  • Needs a released datamasque-python with projects. The first commit (build: install datamasque-python from TestPyPI until a release has projects) pins >=1.7.0.dev11 from TestPyPI and is dropped before merging, in favour of the released version.
  • Until then install-smoke fails: it installs the wheel from PyPI, where the newest datamasque-python is 1.5.0. Lint, mypy and pytest resolve the TestPyPI build from uv.lock.
  • Needs DataMasque v3.26.21.0, which adds projects. The bundle commands also need its v2 export and import endpoints, which are not final yet; the bundle commit follows any change to them.
  • The changelog entry and version bump come with the switch to the released client.

Comment thread src/datamasque_cli/commands/rulesets.py Resolved
Comment thread src/datamasque_cli/commands/runs.py Resolved
Comment thread tests/commands/test_project_options.py Resolved
Comment thread tests/commands/test_rulesets.py Resolved
Comment thread tests/test_projects.py Resolved
…ojects

Drop before merging: switch to the released datamasque-python with project support.
…pace

List commands show each resource's project and take --project to list one
project's resources. Create, upload and validate commands put the resource
in the --project project, else the instance's only project. Get, update and
delete commands find a name in any project and ask for --project when the
name exists in more than one.

BREAKING CHANGE: --namespace is removed from `dm libraries` and
`dm discover libraries`; use --project. The CLI needs a DataMasque version
with projects.
`dm rulesets export-bundle` and `import-bundle` call the v2 endpoints, so a
bundle files each item under its project and an import puts it back there.
`import-bundle --fallback-project` names the project, by name or id, for the
items a bundle files under no project, and the command warns when the server
marks the bundle as the older format.

BREAKING CHANGE: the bundle commands need a server with the v2 export and import
endpoints.
…oject first

Without --project, a connection name that several projects share now resolves to the
one in the reference's project instead of aborting as ambiguous. A connection in another
project is still found. Also drop the repeated listing request before a create.
`dm projects` lists, shows, creates, renames and deletes projects.
`list --include-deleted` adds deleted projects. Delete takes `--to`, the project that receives
the deleted project's resources, and `--check` lists what would stop the delete without deleting.

`dm projects update` needs a datamasque-python release with `update_project`.
`dm resources move --to <project>` moves resources selected by `--project`, `--type`, `--search`
or exact names. Resources that clash with the destination stay where they are; the command lists
each one and exits with the `conflict` code. `--check` previews the move.
… a deleted project

- dm resources move lists a conflict detail once when several resources
  clash the same way, and says no resources moved when none did.
- dm projects get finds a deleted project by its id, as projects list
  --include-deleted shows it, and its output says whether the project is
  deleted. A name still resolves among the active projects only.
@jiatolentino
jiatolentino force-pushed the DM-4395-project-support branch from 070bef2 to c903061 Compare November 3, 2026 07:35
@jiatolentino jiatolentino self-assigned this Nov 3, 2026
Comment thread src/datamasque_cli/commands/rulesets.py Resolved
Comment thread src/datamasque_cli/projects.py Resolved
…exact test results

- dm resources move aborts with not-found, naming each name that matches
  none of the resources the other filters select, instead of moving the
  rest and exiting 0.
- dm rulesets export-bundle and import-bundle call the client's
  export_bundle and import_bundle. export-bundle gains
  --include-seed-files, so its seed files are bundled only on request.
- import-bundle names the project that took the items the bundle files
  under no project, and leaves the older-bundle warning to the client,
  which already logs it.
- Rename project_names to get_project_names_by_reference and in_project
  to filter_by_project, and make the test helper _with_deleted_projects
  private.
- Tests compare the full JSON or message where the exact result is known.

from datamasque_cli.errors import ErrorCode, abort

PROJECT_OPTION_HELP = "Project name or id"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

PROJECT_OPTION_HELP defined here; the text "Project name or id" is repeated inline in --project help strings (e.g. connections.py, rulesets.py, files.py) could you build them from this?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Done, every --project help now builds from PROJECT_OPTION_HELP, the repeated "two projects share a name" ones through get_same_name_project_help.

The commands that find a resource by a name that two projects can share take their --project help from get_same_name_project_help, and the seed list and bundle import help start from the constant too. The help text is unchanged.

This branch has not been deployed

No deployments
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.

3 participants