datex-studio-cli 0.4.23__tar.gz → 0.4.25__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- datex_studio_cli-0.4.25/.dockerignore +25 -0
- datex_studio_cli-0.4.25/.github/actionlint.yaml +4 -0
- datex_studio_cli-0.4.25/.github/workflows/build-image.yml +71 -0
- datex_studio_cli-0.4.25/.github/workflows/ci.yml +55 -0
- datex_studio_cli-0.4.25/.github/workflows/promote-prod.yml +104 -0
- datex_studio_cli-0.4.25/.github/workflows/release.yml +106 -0
- {datex_studio_cli-0.4.23 → datex_studio_cli-0.4.25}/PKG-INFO +5 -5
- {datex_studio_cli-0.4.23 → datex_studio_cli-0.4.25}/README.md +4 -4
- {datex_studio_cli-0.4.23 → datex_studio_cli-0.4.25}/pyproject.toml +7 -1
- {datex_studio_cli-0.4.23 → datex_studio_cli-0.4.25}/src/dxs/__init__.py +1 -1
- {datex_studio_cli-0.4.23 → datex_studio_cli-0.4.25}/src/dxs/cli.py +29 -10
- {datex_studio_cli-0.4.23 → datex_studio_cli-0.4.25}/src/dxs/commands/auth.py +1 -1
- {datex_studio_cli-0.4.23 → datex_studio_cli-0.4.25}/src/dxs/commands/branch.py +6 -7
- {datex_studio_cli-0.4.23 → datex_studio_cli-0.4.25}/src/dxs/commands/cascade.py +1 -1
- {datex_studio_cli-0.4.23 → datex_studio_cli-0.4.25}/src/dxs/commands/config.py +18 -17
- {datex_studio_cli-0.4.23 → datex_studio_cli-0.4.25}/src/dxs/commands/configuration.py +1 -1
- {datex_studio_cli-0.4.23 → datex_studio_cli-0.4.25}/src/dxs/commands/crm.py +1 -1
- {datex_studio_cli-0.4.23 → datex_studio_cli-0.4.25}/src/dxs/commands/servicepack.py +5 -5
- {datex_studio_cli-0.4.23 → datex_studio_cli-0.4.25}/src/dxs/commands/source.py +36 -12
- {datex_studio_cli-0.4.23 → datex_studio_cli-0.4.25}/src/dxs/commands/telemetry.py +2 -2
- {datex_studio_cli-0.4.23 → datex_studio_cli-0.4.25}/src/dxs/core/api/__init__.py +3 -0
- {datex_studio_cli-0.4.23 → datex_studio_cli-0.4.25}/src/dxs/core/api/client.py +4 -4
- {datex_studio_cli-0.4.23 → datex_studio_cli-0.4.25}/src/dxs/core/api/endpoints.py +27 -2
- {datex_studio_cli-0.4.23 → datex_studio_cli-0.4.25}/src/dxs/core/api/models.py +16 -0
- datex_studio_cli-0.4.25/src/dxs/core/api/replacements.py +72 -0
- {datex_studio_cli-0.4.23 → datex_studio_cli-0.4.25}/src/dxs/core/auth/msal_client.py +1 -1
- {datex_studio_cli-0.4.23 → datex_studio_cli-0.4.25}/src/dxs/core/dynamics/client.py +2 -2
- {datex_studio_cli-0.4.23 → datex_studio_cli-0.4.25}/src/dxs/core/release_notes.py +71 -20
- {datex_studio_cli-0.4.23 → datex_studio_cli-0.4.25}/src/dxs/core/telemetry/config.py +22 -6
- {datex_studio_cli-0.4.23 → datex_studio_cli-0.4.25}/src/dxs/core/telemetry/recorder.py +8 -1
- {datex_studio_cli-0.4.23 → datex_studio_cli-0.4.25}/src/dxs/utils/config.py +11 -0
- {datex_studio_cli-0.4.23 → datex_studio_cli-0.4.25}/src/dxs/utils/errors.py +1 -1
- {datex_studio_cli-0.4.23 → datex_studio_cli-0.4.25}/src/dxs/web/static/404/index.html +1 -1
- {datex_studio_cli-0.4.23 → datex_studio_cli-0.4.25}/src/dxs/web/static/404.html +1 -1
- datex_studio_cli-0.4.25/src/dxs/web/static/_next/static/chunks/538-b06224e65f71c9a1.js +1 -0
- datex_studio_cli-0.4.23/src/dxs/web/static/_next/static/chunks/app/_not-found/page-ea1be7001c230704.js → datex_studio_cli-0.4.25/src/dxs/web/static/_next/static/chunks/app/_not-found/page-e3c660196c244183.js +1 -1
- datex_studio_cli-0.4.25/src/dxs/web/static/_next/static/chunks/app/design/capture/page-c083dc9f01f32a04.js +1 -0
- datex_studio_cli-0.4.25/src/dxs/web/static/_next/static/chunks/app/design/page-689cd5b9e1d9a74e.js +1 -0
- datex_studio_cli-0.4.23/src/dxs/web/static/_next/static/chunks/app/layout-2cc6eac09e476c91.js → datex_studio_cli-0.4.25/src/dxs/web/static/_next/static/chunks/app/layout-cec86f90e385371d.js +1 -1
- datex_studio_cli-0.4.23/src/dxs/web/static/_next/static/chunks/app/page-20c358395882cdac.js → datex_studio_cli-0.4.25/src/dxs/web/static/_next/static/chunks/app/page-f0380b0f29983264.js +1 -1
- datex_studio_cli-0.4.23/src/dxs/web/static/_next/static/chunks/main-app-b69998d8941231d8.js → datex_studio_cli-0.4.25/src/dxs/web/static/_next/static/chunks/main-app-694cf3568b6c9fa9.js +1 -1
- {datex_studio_cli-0.4.23 → datex_studio_cli-0.4.25}/src/dxs/web/static/design/capture/index.html +1 -1
- {datex_studio_cli-0.4.23 → datex_studio_cli-0.4.25}/src/dxs/web/static/design/capture/index.txt +4 -4
- {datex_studio_cli-0.4.23 → datex_studio_cli-0.4.25}/src/dxs/web/static/design/index.html +1 -1
- {datex_studio_cli-0.4.23 → datex_studio_cli-0.4.25}/src/dxs/web/static/design/index.txt +4 -4
- {datex_studio_cli-0.4.23 → datex_studio_cli-0.4.25}/src/dxs/web/static/index.html +1 -1
- {datex_studio_cli-0.4.23 → datex_studio_cli-0.4.25}/src/dxs/web/static/index.txt +4 -4
- datex_studio_cli-0.4.23/src/dxs/web/static/_next/static/chunks/538-84e2e111415f1fda.js +0 -1
- datex_studio_cli-0.4.23/src/dxs/web/static/_next/static/chunks/app/design/capture/page-a5e129c2d223432c.js +0 -1
- datex_studio_cli-0.4.23/src/dxs/web/static/_next/static/chunks/app/design/page-21ba66a3dd3b03f0.js +0 -1
- {datex_studio_cli-0.4.23 → datex_studio_cli-0.4.25}/.gitignore +0 -0
- {datex_studio_cli-0.4.23 → datex_studio_cli-0.4.25}/CONTEXT.md +0 -0
- {datex_studio_cli-0.4.23 → datex_studio_cli-0.4.25}/otel/.env.example +0 -0
- {datex_studio_cli-0.4.23 → datex_studio_cli-0.4.25}/otel/Dockerfile +0 -0
- {datex_studio_cli-0.4.23 → datex_studio_cli-0.4.25}/otel/README.md +0 -0
- {datex_studio_cli-0.4.23 → datex_studio_cli-0.4.25}/otel/apply-local-cache.js +0 -0
- {datex_studio_cli-0.4.23 → datex_studio_cli-0.4.25}/otel/collector-config.yaml +0 -0
- {datex_studio_cli-0.4.23 → datex_studio_cli-0.4.25}/otel/docker-compose.yml +0 -0
- {datex_studio_cli-0.4.23 → datex_studio_cli-0.4.25}/otel/local-test-settings.json +0 -0
- {datex_studio_cli-0.4.23 → datex_studio_cli-0.4.25}/otel/remote-settings.json +0 -0
- {datex_studio_cli-0.4.23 → datex_studio_cli-0.4.25}/report-creator.skill +0 -0
- {datex_studio_cli-0.4.23 → datex_studio_cli-0.4.25}/scripts/analyze_corpus.py +0 -0
- {datex_studio_cli-0.4.23 → datex_studio_cli-0.4.25}/scripts/generate_rdlx_schema.py +0 -0
- {datex_studio_cli-0.4.23 → datex_studio_cli-0.4.25}/src/dxs/__main__.py +0 -0
- {datex_studio_cli-0.4.23 → datex_studio_cli-0.4.25}/src/dxs/commands/__init__.py +0 -0
- {datex_studio_cli-0.4.23 → datex_studio_cli-0.4.25}/src/dxs/commands/api.py +0 -0
- {datex_studio_cli-0.4.23 → datex_studio_cli-0.4.25}/src/dxs/commands/branch_commit_guard.py +0 -0
- {datex_studio_cli-0.4.23 → datex_studio_cli-0.4.25}/src/dxs/commands/crm_delivery.py +0 -0
- {datex_studio_cli-0.4.23 → datex_studio_cli-0.4.25}/src/dxs/commands/crm_time.py +0 -0
- {datex_studio_cli-0.4.23 → datex_studio_cli-0.4.25}/src/dxs/commands/datasource.py +0 -0
- {datex_studio_cli-0.4.23 → datex_studio_cli-0.4.25}/src/dxs/commands/devops.py +0 -0
- {datex_studio_cli-0.4.23 → datex_studio_cli-0.4.25}/src/dxs/commands/document.py +0 -0
- {datex_studio_cli-0.4.23 → datex_studio_cli-0.4.25}/src/dxs/commands/endpoint.py +0 -0
- {datex_studio_cli-0.4.23 → datex_studio_cli-0.4.25}/src/dxs/commands/env.py +0 -0
- {datex_studio_cli-0.4.23 → datex_studio_cli-0.4.25}/src/dxs/commands/explore.py +0 -0
- {datex_studio_cli-0.4.23 → datex_studio_cli-0.4.25}/src/dxs/commands/function.py +0 -0
- {datex_studio_cli-0.4.23 → datex_studio_cli-0.4.25}/src/dxs/commands/init.py +0 -0
- {datex_studio_cli-0.4.23 → datex_studio_cli-0.4.25}/src/dxs/commands/marketplace.py +0 -0
- {datex_studio_cli-0.4.23 → datex_studio_cli-0.4.25}/src/dxs/commands/ng/__init__.py +0 -0
- {datex_studio_cli-0.4.23 → datex_studio_cli-0.4.25}/src/dxs/commands/ng/_common.py +0 -0
- {datex_studio_cli-0.4.23 → datex_studio_cli-0.4.25}/src/dxs/commands/ng/api.py +0 -0
- {datex_studio_cli-0.4.23 → datex_studio_cli-0.4.25}/src/dxs/commands/ng/create.py +0 -0
- {datex_studio_cli-0.4.23 → datex_studio_cli-0.4.25}/src/dxs/commands/ng/data.py +0 -0
- {datex_studio_cli-0.4.23 → datex_studio_cli-0.4.25}/src/dxs/commands/ng/pack.py +0 -0
- {datex_studio_cli-0.4.23 → datex_studio_cli-0.4.25}/src/dxs/commands/ng/preview.py +0 -0
- {datex_studio_cli-0.4.23 → datex_studio_cli-0.4.25}/src/dxs/commands/odata.py +0 -0
- {datex_studio_cli-0.4.23 → datex_studio_cli-0.4.25}/src/dxs/commands/organization.py +0 -0
- {datex_studio_cli-0.4.23 → datex_studio_cli-0.4.25}/src/dxs/commands/proxy.py +0 -0
- {datex_studio_cli-0.4.23 → datex_studio_cli-0.4.25}/src/dxs/commands/reference.py +0 -0
- {datex_studio_cli-0.4.23 → datex_studio_cli-0.4.25}/src/dxs/commands/release_notes.py +0 -0
- {datex_studio_cli-0.4.23 → datex_studio_cli-0.4.25}/src/dxs/commands/repo.py +0 -0
- {datex_studio_cli-0.4.23 → datex_studio_cli-0.4.25}/src/dxs/commands/report/__init__.py +0 -0
- {datex_studio_cli-0.4.23 → datex_studio_cli-0.4.25}/src/dxs/commands/report/add_cmds.py +0 -0
- {datex_studio_cli-0.4.23 → datex_studio_cli-0.4.25}/src/dxs/commands/report/api.py +0 -0
- {datex_studio_cli-0.4.23 → datex_studio_cli-0.4.25}/src/dxs/commands/report/batch.py +0 -0
- {datex_studio_cli-0.4.23 → datex_studio_cli-0.4.25}/src/dxs/commands/report/create.py +0 -0
- {datex_studio_cli-0.4.23 → datex_studio_cli-0.4.25}/src/dxs/commands/report/data.py +0 -0
- {datex_studio_cli-0.4.23 → datex_studio_cli-0.4.25}/src/dxs/commands/report/dataset.py +0 -0
- {datex_studio_cli-0.4.23 → datex_studio_cli-0.4.25}/src/dxs/commands/report/edit.py +0 -0
- {datex_studio_cli-0.4.23 → datex_studio_cli-0.4.25}/src/dxs/commands/report/folder.py +0 -0
- {datex_studio_cli-0.4.23 → datex_studio_cli-0.4.25}/src/dxs/commands/report/preview.py +0 -0
- {datex_studio_cli-0.4.23 → datex_studio_cli-0.4.25}/src/dxs/commands/report/schema_cmds.py +0 -0
- {datex_studio_cli-0.4.23 → datex_studio_cli-0.4.25}/src/dxs/commands/reset.py +0 -0
- {datex_studio_cli-0.4.23 → datex_studio_cli-0.4.25}/src/dxs/commands/schema.py +0 -0
- {datex_studio_cli-0.4.23 → datex_studio_cli-0.4.25}/src/dxs/commands/studio.py +0 -0
- {datex_studio_cli-0.4.23 → datex_studio_cli-0.4.25}/src/dxs/commands/user.py +0 -0
- {datex_studio_cli-0.4.23 → datex_studio_cli-0.4.25}/src/dxs/commands/validation_report.py +0 -0
- {datex_studio_cli-0.4.23 → datex_studio_cli-0.4.25}/src/dxs/context.py +0 -0
- {datex_studio_cli-0.4.23 → datex_studio_cli-0.4.25}/src/dxs/core/__init__.py +0 -0
- {datex_studio_cli-0.4.23 → datex_studio_cli-0.4.25}/src/dxs/core/agent_browser.py +0 -0
- {datex_studio_cli-0.4.23 → datex_studio_cli-0.4.25}/src/dxs/core/api/app_config.py +0 -0
- {datex_studio_cli-0.4.23 → datex_studio_cli-0.4.25}/src/dxs/core/api/metadata_models.py +0 -0
- {datex_studio_cli-0.4.23 → datex_studio_cli-0.4.25}/src/dxs/core/api/reference_graph.py +0 -0
- {datex_studio_cli-0.4.23 → datex_studio_cli-0.4.25}/src/dxs/core/auth/__init__.py +0 -0
- {datex_studio_cli-0.4.23 → datex_studio_cli-0.4.25}/src/dxs/core/auth/datex_tenant.py +0 -0
- {datex_studio_cli-0.4.23 → datex_studio_cli-0.4.25}/src/dxs/core/auth/decorators.py +0 -0
- {datex_studio_cli-0.4.23 → datex_studio_cli-0.4.25}/src/dxs/core/auth/tenants.py +0 -0
- {datex_studio_cli-0.4.23 → datex_studio_cli-0.4.25}/src/dxs/core/auth/token_cache.py +0 -0
- {datex_studio_cli-0.4.23 → datex_studio_cli-0.4.25}/src/dxs/core/cache.py +0 -0
- {datex_studio_cli-0.4.23 → datex_studio_cli-0.4.25}/src/dxs/core/datasource/__init__.py +0 -0
- {datex_studio_cli-0.4.23 → datex_studio_cli-0.4.25}/src/dxs/core/datasource/flow_generator.py +0 -0
- {datex_studio_cli-0.4.23 → datex_studio_cli-0.4.25}/src/dxs/core/datasource/flow_models.py +0 -0
- {datex_studio_cli-0.4.23 → datex_studio_cli-0.4.25}/src/dxs/core/datasource/flow_shape.py +0 -0
- {datex_studio_cli-0.4.23 → datex_studio_cli-0.4.25}/src/dxs/core/datasource/generator.py +0 -0
- {datex_studio_cli-0.4.23 → datex_studio_cli-0.4.25}/src/dxs/core/datasource/models.py +0 -0
- {datex_studio_cli-0.4.23 → datex_studio_cli-0.4.25}/src/dxs/core/datasource/parsers.py +0 -0
- {datex_studio_cli-0.4.23 → datex_studio_cli-0.4.25}/src/dxs/core/datasource/resolver.py +0 -0
- {datex_studio_cli-0.4.23 → datex_studio_cli-0.4.25}/src/dxs/core/datasource/type_def_parser.py +0 -0
- {datex_studio_cli-0.4.23 → datex_studio_cli-0.4.25}/src/dxs/core/datasource/validator.py +0 -0
- {datex_studio_cli-0.4.23 → datex_studio_cli-0.4.25}/src/dxs/core/designer/__init__.py +0 -0
- {datex_studio_cli-0.4.23 → datex_studio_cli-0.4.25}/src/dxs/core/designer/flow_models.py +0 -0
- {datex_studio_cli-0.4.23 → datex_studio_cli-0.4.25}/src/dxs/core/designer/models.py +0 -0
- {datex_studio_cli-0.4.23 → datex_studio_cli-0.4.25}/src/dxs/core/designer/parsers.py +0 -0
- {datex_studio_cli-0.4.23 → datex_studio_cli-0.4.25}/src/dxs/core/devops/__init__.py +0 -0
- {datex_studio_cli-0.4.23 → datex_studio_cli-0.4.25}/src/dxs/core/devops/client.py +0 -0
- {datex_studio_cli-0.4.23 → datex_studio_cli-0.4.25}/src/dxs/core/devops/helpers.py +0 -0
- {datex_studio_cli-0.4.23 → datex_studio_cli-0.4.25}/src/dxs/core/devops/models.py +0 -0
- {datex_studio_cli-0.4.23 → datex_studio_cli-0.4.25}/src/dxs/core/dynamics/__init__.py +0 -0
- {datex_studio_cli-0.4.23 → datex_studio_cli-0.4.25}/src/dxs/core/dynamics/html.py +0 -0
- {datex_studio_cli-0.4.23 → datex_studio_cli-0.4.25}/src/dxs/core/dynamics/metadata_cache.py +0 -0
- {datex_studio_cli-0.4.23 → datex_studio_cli-0.4.25}/src/dxs/core/dynamics/pagination.py +0 -0
- {datex_studio_cli-0.4.23 → datex_studio_cli-0.4.25}/src/dxs/core/dynamics/resolvers.py +0 -0
- {datex_studio_cli-0.4.23 → datex_studio_cli-0.4.25}/src/dxs/core/dynamics/time_entry.py +0 -0
- {datex_studio_cli-0.4.23 → datex_studio_cli-0.4.25}/src/dxs/core/footprint/__init__.py +0 -0
- {datex_studio_cli-0.4.23 → datex_studio_cli-0.4.25}/src/dxs/core/footprint/client.py +0 -0
- {datex_studio_cli-0.4.23 → datex_studio_cli-0.4.25}/src/dxs/core/footprint/edmx_parser.py +0 -0
- {datex_studio_cli-0.4.23 → datex_studio_cli-0.4.25}/src/dxs/core/footprint/metadata.py +0 -0
- {datex_studio_cli-0.4.23 → datex_studio_cli-0.4.25}/src/dxs/core/function/__init__.py +0 -0
- {datex_studio_cli-0.4.23 → datex_studio_cli-0.4.25}/src/dxs/core/function/generator.py +0 -0
- {datex_studio_cli-0.4.23 → datex_studio_cli-0.4.25}/src/dxs/core/function/models.py +0 -0
- {datex_studio_cli-0.4.23 → datex_studio_cli-0.4.25}/src/dxs/core/function/validator.py +0 -0
- {datex_studio_cli-0.4.23 → datex_studio_cli-0.4.25}/src/dxs/core/graph.py +0 -0
- {datex_studio_cli-0.4.23 → datex_studio_cli-0.4.25}/src/dxs/core/onboarding.py +0 -0
- {datex_studio_cli-0.4.23 → datex_studio_cli-0.4.25}/src/dxs/core/output/__init__.py +0 -0
- {datex_studio_cli-0.4.23 → datex_studio_cli-0.4.25}/src/dxs/core/output/csv_fmt.py +0 -0
- {datex_studio_cli-0.4.23 → datex_studio_cli-0.4.25}/src/dxs/core/output/formatter.py +0 -0
- {datex_studio_cli-0.4.23 → datex_studio_cli-0.4.25}/src/dxs/core/output/json_fmt.py +0 -0
- {datex_studio_cli-0.4.23 → datex_studio_cli-0.4.25}/src/dxs/core/output/redaction.py +0 -0
- {datex_studio_cli-0.4.23 → datex_studio_cli-0.4.25}/src/dxs/core/output/yaml_fmt.py +0 -0
- {datex_studio_cli-0.4.23 → datex_studio_cli-0.4.25}/src/dxs/core/responses.py +0 -0
- {datex_studio_cli-0.4.23 → datex_studio_cli-0.4.25}/src/dxs/core/telemetry/__init__.py +0 -0
- {datex_studio_cli-0.4.23 → datex_studio_cli-0.4.25}/src/dxs/core/telemetry/identity.py +0 -0
- {datex_studio_cli-0.4.23 → datex_studio_cli-0.4.25}/src/dxs/core/telemetry/scrubber.py +0 -0
- {datex_studio_cli-0.4.23 → datex_studio_cli-0.4.25}/src/dxs/core/telemetry/sender.py +0 -0
- {datex_studio_cli-0.4.23 → datex_studio_cli-0.4.25}/src/dxs/models/__init__.py +0 -0
- {datex_studio_cli-0.4.23 → datex_studio_cli-0.4.25}/src/dxs/ng/__init__.py +0 -0
- {datex_studio_cli-0.4.23 → datex_studio_cli-0.4.25}/src/dxs/ng/folder.py +0 -0
- {datex_studio_cli-0.4.23 → datex_studio_cli-0.4.25}/src/dxs/ng/manifest.py +0 -0
- {datex_studio_cli-0.4.23 → datex_studio_cli-0.4.25}/src/dxs/ng/mocks.py +0 -0
- {datex_studio_cli-0.4.23 → datex_studio_cli-0.4.25}/src/dxs/ng/preview.py +0 -0
- {datex_studio_cli-0.4.23 → datex_studio_cli-0.4.25}/src/dxs/ng/scaffold.py +0 -0
- {datex_studio_cli-0.4.23 → datex_studio_cli-0.4.25}/src/dxs/ng/serve_lock.py +0 -0
- {datex_studio_cli-0.4.23 → datex_studio_cli-0.4.25}/src/dxs/py.typed +0 -0
- {datex_studio_cli-0.4.23 → datex_studio_cli-0.4.25}/src/dxs/report/__init__.py +0 -0
- {datex_studio_cli-0.4.23 → datex_studio_cli-0.4.25}/src/dxs/report/datasource_binding.py +0 -0
- {datex_studio_cli-0.4.23 → datex_studio_cli-0.4.25}/src/dxs/report/engine.py +0 -0
- {datex_studio_cli-0.4.23 → datex_studio_cli-0.4.25}/src/dxs/report/field_parser.py +0 -0
- {datex_studio_cli-0.4.23 → datex_studio_cli-0.4.25}/src/dxs/report/folder.py +0 -0
- {datex_studio_cli-0.4.23 → datex_studio_cli-0.4.25}/src/dxs/report/manifest.py +0 -0
- {datex_studio_cli-0.4.23 → datex_studio_cli-0.4.25}/src/dxs/report/models.py +0 -0
- {datex_studio_cli-0.4.23 → datex_studio_cli-0.4.25}/src/dxs/report/preview.py +0 -0
- {datex_studio_cli-0.4.23 → datex_studio_cli-0.4.25}/src/dxs/report/preview_arjs.py +0 -0
- {datex_studio_cli-0.4.23 → datex_studio_cli-0.4.25}/src/dxs/report/schema.py +0 -0
- {datex_studio_cli-0.4.23 → datex_studio_cli-0.4.25}/src/dxs/report/svg_renderer.py +0 -0
- {datex_studio_cli-0.4.23 → datex_studio_cli-0.4.25}/src/dxs/report/templates/__init__.py +0 -0
- {datex_studio_cli-0.4.23 → datex_studio_cli-0.4.25}/src/dxs/report/templates/bill_of_lading.rdlx-json +0 -0
- {datex_studio_cli-0.4.23 → datex_studio_cli-0.4.25}/src/dxs/report/templates/shipping_label.rdlx-json +0 -0
- {datex_studio_cli-0.4.23 → datex_studio_cli-0.4.25}/src/dxs/report/validate_arjs.py +0 -0
- {datex_studio_cli-0.4.23 → datex_studio_cli-0.4.25}/src/dxs/report/validator.py +0 -0
- {datex_studio_cli-0.4.23 → datex_studio_cli-0.4.25}/src/dxs/report/wrapper.py +0 -0
- {datex_studio_cli-0.4.23 → datex_studio_cli-0.4.25}/src/dxs/utils/__init__.py +0 -0
- {datex_studio_cli-0.4.23 → datex_studio_cli-0.4.25}/src/dxs/utils/click_options.py +0 -0
- {datex_studio_cli-0.4.23 → datex_studio_cli-0.4.25}/src/dxs/utils/clipboard.py +0 -0
- {datex_studio_cli-0.4.23 → datex_studio_cli-0.4.25}/src/dxs/utils/filtering.py +0 -0
- {datex_studio_cli-0.4.23 → datex_studio_cli-0.4.25}/src/dxs/utils/image.py +0 -0
- {datex_studio_cli-0.4.23 → datex_studio_cli-0.4.25}/src/dxs/utils/paths.py +0 -0
- {datex_studio_cli-0.4.23 → datex_studio_cli-0.4.25}/src/dxs/utils/resolvers.py +0 -0
- {datex_studio_cli-0.4.23 → datex_studio_cli-0.4.25}/src/dxs/utils/responses.py +0 -0
- {datex_studio_cli-0.4.23 → datex_studio_cli-0.4.25}/src/dxs/utils/restricted.py +0 -0
- {datex_studio_cli-0.4.23 → datex_studio_cli-0.4.25}/src/dxs/utils/sorting.py +0 -0
- {datex_studio_cli-0.4.23 → datex_studio_cli-0.4.25}/src/dxs/utils/update_check.py +0 -0
- {datex_studio_cli-0.4.23 → datex_studio_cli-0.4.25}/src/dxs/utils/versioning.py +0 -0
- {datex_studio_cli-0.4.23 → datex_studio_cli-0.4.25}/src/dxs/web/__init__.py +0 -0
- {datex_studio_cli-0.4.23 → datex_studio_cli-0.4.25}/src/dxs/web/app.py +0 -0
- {datex_studio_cli-0.4.23 → datex_studio_cli-0.4.25}/src/dxs/web/design.py +0 -0
- {datex_studio_cli-0.4.23 → datex_studio_cli-0.4.25}/src/dxs/web/proxy_app.py +0 -0
- {datex_studio_cli-0.4.23/src/dxs/web/static/_next/static/UgyAMtPjH-Pt0RYWOHzIT → datex_studio_cli-0.4.25/src/dxs/web/static/_next/static/BbKuTltyqzuSYoNcVtfWa}/_buildManifest.js +0 -0
- {datex_studio_cli-0.4.23/src/dxs/web/static/_next/static/UgyAMtPjH-Pt0RYWOHzIT → datex_studio_cli-0.4.25/src/dxs/web/static/_next/static/BbKuTltyqzuSYoNcVtfWa}/_ssgManifest.js +0 -0
- {datex_studio_cli-0.4.23 → datex_studio_cli-0.4.25}/src/dxs/web/static/_next/static/chunks/0b24cca5-c1e1c8810348f107.js +0 -0
- {datex_studio_cli-0.4.23 → datex_studio_cli-0.4.25}/src/dxs/web/static/_next/static/chunks/255-102f2e5b2e3dc2ef.js +0 -0
- {datex_studio_cli-0.4.23 → datex_studio_cli-0.4.25}/src/dxs/web/static/_next/static/chunks/4bd1b696-c023c6e3521b1417.js +0 -0
- {datex_studio_cli-0.4.23 → datex_studio_cli-0.4.25}/src/dxs/web/static/_next/static/chunks/697-0e000ab410d9f470.js +0 -0
- {datex_studio_cli-0.4.23 → datex_studio_cli-0.4.25}/src/dxs/web/static/_next/static/chunks/871-1acacdb7b4022abf.js +0 -0
- {datex_studio_cli-0.4.23 → datex_studio_cli-0.4.25}/src/dxs/web/static/_next/static/chunks/8b8f67fc-6295949a4b5485a4.js +0 -0
- {datex_studio_cli-0.4.23 → datex_studio_cli-0.4.25}/src/dxs/web/static/_next/static/chunks/909-c88abba3cf0caec3.js +0 -0
- {datex_studio_cli-0.4.23 → datex_studio_cli-0.4.25}/src/dxs/web/static/_next/static/chunks/framework-de98b93a850cfc71.js +0 -0
- {datex_studio_cli-0.4.23 → datex_studio_cli-0.4.25}/src/dxs/web/static/_next/static/chunks/main-0f18f91200dac003.js +0 -0
- {datex_studio_cli-0.4.23 → datex_studio_cli-0.4.25}/src/dxs/web/static/_next/static/chunks/pages/_app-7d307437aca18ad4.js +0 -0
- {datex_studio_cli-0.4.23 → datex_studio_cli-0.4.25}/src/dxs/web/static/_next/static/chunks/pages/_error-cb2a52f75f2162e2.js +0 -0
- {datex_studio_cli-0.4.23 → datex_studio_cli-0.4.25}/src/dxs/web/static/_next/static/chunks/polyfills-42372ed130431b0a.js +0 -0
- {datex_studio_cli-0.4.23 → datex_studio_cli-0.4.25}/src/dxs/web/static/_next/static/chunks/webpack-2b297ada5306c17f.js +0 -0
- {datex_studio_cli-0.4.23 → datex_studio_cli-0.4.25}/src/dxs/web/static/_next/static/css/360c657de5e04df8.css +0 -0
- {datex_studio_cli-0.4.23 → datex_studio_cli-0.4.25}/src/dxs/web/static/render-cli.js +0 -0
- {datex_studio_cli-0.4.23 → datex_studio_cli-0.4.25}/src/dxs/web/static/report-preview.html +0 -0
- {datex_studio_cli-0.4.23 → datex_studio_cli-0.4.25}/src/dxs/web/static/report-validate.html +0 -0
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# Context for quartermaster/Dockerfile (built from the repo root).
|
|
2
|
+
.git
|
|
3
|
+
.venv
|
|
4
|
+
**/__pycache__
|
|
5
|
+
.pytest_cache
|
|
6
|
+
.mypy_cache
|
|
7
|
+
.ruff_cache
|
|
8
|
+
.claude
|
|
9
|
+
.serena
|
|
10
|
+
node_modules
|
|
11
|
+
**/node_modules
|
|
12
|
+
src/dxs/web/frontend
|
|
13
|
+
tests
|
|
14
|
+
quartermaster/tests
|
|
15
|
+
quartermaster/.env
|
|
16
|
+
docs
|
|
17
|
+
documentation
|
|
18
|
+
exploration
|
|
19
|
+
examples
|
|
20
|
+
example-reports
|
|
21
|
+
exclude
|
|
22
|
+
skills
|
|
23
|
+
otel
|
|
24
|
+
dist
|
|
25
|
+
*.analysis.md
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
# Image build + staging digest bump (spec §5, §6). CI runs in-workflow: red
|
|
2
|
+
# tests produce no image. The final step commits the pushed digest to
|
|
3
|
+
# quartermaster/deploy/staging/values.yaml with GITHUB_TOKEN — which natively
|
|
4
|
+
# triggers no further workflow runs, so the rebuild loop is impossible.
|
|
5
|
+
name: Build image
|
|
6
|
+
|
|
7
|
+
on:
|
|
8
|
+
push:
|
|
9
|
+
branches: [main]
|
|
10
|
+
paths-ignore:
|
|
11
|
+
- "docs/**"
|
|
12
|
+
- "**.md"
|
|
13
|
+
workflow_dispatch:
|
|
14
|
+
|
|
15
|
+
concurrency:
|
|
16
|
+
group: build-image-main
|
|
17
|
+
cancel-in-progress: false
|
|
18
|
+
|
|
19
|
+
permissions:
|
|
20
|
+
contents: write
|
|
21
|
+
packages: write
|
|
22
|
+
|
|
23
|
+
jobs:
|
|
24
|
+
ci:
|
|
25
|
+
uses: ./.github/workflows/ci.yml
|
|
26
|
+
|
|
27
|
+
build:
|
|
28
|
+
needs: ci
|
|
29
|
+
runs-on: arc-dxs
|
|
30
|
+
timeout-minutes: 30
|
|
31
|
+
steps:
|
|
32
|
+
- uses: actions/checkout@v4
|
|
33
|
+
- uses: docker/setup-buildx-action@v3
|
|
34
|
+
- uses: docker/login-action@v3
|
|
35
|
+
with:
|
|
36
|
+
registry: ghcr.io
|
|
37
|
+
username: ${{ github.actor }}
|
|
38
|
+
password: ${{ secrets.GITHUB_TOKEN }}
|
|
39
|
+
- id: meta
|
|
40
|
+
run: echo "datetag=$(date -u +%Y%m%d).${{ github.run_number }}" >> "$GITHUB_OUTPUT"
|
|
41
|
+
- id: build
|
|
42
|
+
uses: docker/build-push-action@v6
|
|
43
|
+
with:
|
|
44
|
+
context: .
|
|
45
|
+
file: quartermaster/Dockerfile
|
|
46
|
+
platforms: linux/amd64
|
|
47
|
+
push: true
|
|
48
|
+
tags: |
|
|
49
|
+
ghcr.io/datex/quartermaster:${{ github.sha }}
|
|
50
|
+
ghcr.io/datex/quartermaster:latest
|
|
51
|
+
ghcr.io/datex/quartermaster:${{ steps.meta.outputs.datetag }}
|
|
52
|
+
- name: Commit the staging digest bump
|
|
53
|
+
run: |
|
|
54
|
+
digest='${{ steps.build.outputs.digest }}'
|
|
55
|
+
sed -i -E "s|^ digest:.*| digest: \"${digest}\"|" quartermaster/deploy/staging/values.yaml
|
|
56
|
+
if git diff --quiet; then
|
|
57
|
+
echo "staging already runs ${digest}; nothing to commit"
|
|
58
|
+
exit 0
|
|
59
|
+
fi
|
|
60
|
+
git config user.name "github-actions[bot]"
|
|
61
|
+
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
|
|
62
|
+
git add quartermaster/deploy/staging/values.yaml
|
|
63
|
+
git commit -m "chore(deploy): staging → ${digest}"
|
|
64
|
+
for attempt in 1 2 3; do
|
|
65
|
+
if git push origin HEAD:main; then
|
|
66
|
+
exit 0
|
|
67
|
+
fi
|
|
68
|
+
git pull --rebase origin main
|
|
69
|
+
done
|
|
70
|
+
echo "digest bump push failed after 3 attempts" >&2
|
|
71
|
+
exit 1
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
# CI (spec §5): two jobs, both always run — the uv workspace couples the CLI
|
|
2
|
+
# and the service. Callable from build-image.yml and release.yml so a red
|
|
3
|
+
# suite produces no image and no release (the pipeline is the gate, not the
|
|
4
|
+
# merge — GitHub Free has no required checks).
|
|
5
|
+
name: CI
|
|
6
|
+
|
|
7
|
+
on:
|
|
8
|
+
pull_request:
|
|
9
|
+
paths-ignore:
|
|
10
|
+
- "docs/**"
|
|
11
|
+
- "**.md"
|
|
12
|
+
workflow_call:
|
|
13
|
+
|
|
14
|
+
concurrency:
|
|
15
|
+
group: ci-${{ github.head_ref || github.run_id }}
|
|
16
|
+
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
|
|
17
|
+
|
|
18
|
+
jobs:
|
|
19
|
+
cli:
|
|
20
|
+
runs-on: arc-dxs
|
|
21
|
+
timeout-minutes: 30
|
|
22
|
+
steps:
|
|
23
|
+
- uses: actions/checkout@v4
|
|
24
|
+
- uses: astral-sh/setup-uv@v5
|
|
25
|
+
with:
|
|
26
|
+
enable-cache: true
|
|
27
|
+
- run: uv python install 3.13
|
|
28
|
+
- uses: actions/setup-node@v4
|
|
29
|
+
with:
|
|
30
|
+
node-version: 22
|
|
31
|
+
- name: Build the report renderer bundle (snapshot tests shell out to it)
|
|
32
|
+
working-directory: src/dxs/web/frontend
|
|
33
|
+
run: |
|
|
34
|
+
npm ci
|
|
35
|
+
npm run build:render-cli
|
|
36
|
+
- run: uv sync --all-packages --extra dev
|
|
37
|
+
- run: uv run ruff check .
|
|
38
|
+
- name: mypy (non-blocking — 21 pre-existing errors, see #171)
|
|
39
|
+
run: uv run mypy src/dxs
|
|
40
|
+
continue-on-error: true
|
|
41
|
+
- run: uv run pytest -q
|
|
42
|
+
|
|
43
|
+
service:
|
|
44
|
+
runs-on: arc-dxs
|
|
45
|
+
timeout-minutes: 20
|
|
46
|
+
steps:
|
|
47
|
+
- uses: actions/checkout@v4
|
|
48
|
+
- uses: astral-sh/setup-uv@v5
|
|
49
|
+
with:
|
|
50
|
+
enable-cache: true
|
|
51
|
+
- run: uv python install 3.13
|
|
52
|
+
- run: uv sync --all-packages --extra dev
|
|
53
|
+
- run: uv run ruff check quartermaster
|
|
54
|
+
- run: uv run --package quartermaster mypy quartermaster/src/quartermaster
|
|
55
|
+
- run: uv run --package quartermaster pytest quartermaster/tests -q
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
# Prod promotion by git commit (spec §6): dispatch-only, typed confirmation,
|
|
2
|
+
# moving-ref rejection, GHCR existence preflight, staging-parity assert
|
|
3
|
+
# (promote-what-you-tested). Rollback = re-dispatch the previous digest with
|
|
4
|
+
# the parity override. Actor and inputs are recorded in the run and commit.
|
|
5
|
+
# NOTE: no `environment:` on jobs — the pre-existing `production` environment
|
|
6
|
+
# carries a protected_branches policy no branch can satisfy on this plan.
|
|
7
|
+
name: Promote prod
|
|
8
|
+
|
|
9
|
+
on:
|
|
10
|
+
workflow_dispatch:
|
|
11
|
+
inputs:
|
|
12
|
+
ref:
|
|
13
|
+
description: "Immutable image digest (sha256:…) or the git SHA of a staging bump commit"
|
|
14
|
+
required: true
|
|
15
|
+
confirm:
|
|
16
|
+
description: 'Type "promote-to-prod" to confirm'
|
|
17
|
+
required: true
|
|
18
|
+
override_parity:
|
|
19
|
+
description: "Promote even though staging is not currently running this digest (rollbacks)"
|
|
20
|
+
type: boolean
|
|
21
|
+
default: false
|
|
22
|
+
|
|
23
|
+
concurrency:
|
|
24
|
+
group: promote-prod
|
|
25
|
+
cancel-in-progress: false
|
|
26
|
+
|
|
27
|
+
permissions:
|
|
28
|
+
contents: write
|
|
29
|
+
packages: read
|
|
30
|
+
|
|
31
|
+
jobs:
|
|
32
|
+
promote:
|
|
33
|
+
runs-on: arc-dxs
|
|
34
|
+
timeout-minutes: 15
|
|
35
|
+
steps:
|
|
36
|
+
- name: Typed confirmation
|
|
37
|
+
run: |
|
|
38
|
+
if [ "${{ inputs.confirm }}" != "promote-to-prod" ]; then
|
|
39
|
+
echo "confirmation mismatch: expected the literal string promote-to-prod" >&2
|
|
40
|
+
exit 1
|
|
41
|
+
fi
|
|
42
|
+
- uses: actions/checkout@v4
|
|
43
|
+
with:
|
|
44
|
+
fetch-depth: 0
|
|
45
|
+
- id: resolve
|
|
46
|
+
name: Resolve digest (moving refs rejected)
|
|
47
|
+
run: |
|
|
48
|
+
ref='${{ inputs.ref }}'
|
|
49
|
+
if echo "$ref" | grep -qE '^sha256:[0-9a-f]{64}$'; then
|
|
50
|
+
digest="$ref"
|
|
51
|
+
elif echo "$ref" | grep -qE '^[0-9a-f]{7,40}$'; then
|
|
52
|
+
digest=$(git show "${ref}:quartermaster/deploy/staging/values.yaml" | awk -F'"' '/^ digest:/ {print $2}')
|
|
53
|
+
if ! echo "$digest" | grep -qE '^sha256:[0-9a-f]{64}$'; then
|
|
54
|
+
echo "commit ${ref} carries no staging digest" >&2
|
|
55
|
+
exit 1
|
|
56
|
+
fi
|
|
57
|
+
else
|
|
58
|
+
echo "ref must be an immutable digest or a git SHA — tags like 'latest' are rejected" >&2
|
|
59
|
+
exit 1
|
|
60
|
+
fi
|
|
61
|
+
echo "digest=${digest}" >> "$GITHUB_OUTPUT"
|
|
62
|
+
- name: GHCR existence preflight
|
|
63
|
+
run: |
|
|
64
|
+
token=$(curl -sf -u "x:${{ secrets.GITHUB_TOKEN }}" \
|
|
65
|
+
"https://ghcr.io/token?scope=repository:datex/quartermaster:pull" | \
|
|
66
|
+
sed -E 's/.*"token":"([^"]+)".*/\1/')
|
|
67
|
+
curl -sf -o /dev/null \
|
|
68
|
+
-H "Authorization: Bearer ${token}" \
|
|
69
|
+
-H "Accept: application/vnd.oci.image.index.v1+json, application/vnd.docker.distribution.manifest.v2+json, application/vnd.oci.image.manifest.v1+json" \
|
|
70
|
+
"https://ghcr.io/v2/datex/quartermaster/manifests/${{ steps.resolve.outputs.digest }}" \
|
|
71
|
+
|| { echo "digest not found in GHCR — nothing to promote" >&2; exit 1; }
|
|
72
|
+
- name: Staging-parity assert (promote-what-you-tested)
|
|
73
|
+
run: |
|
|
74
|
+
staging=$(awk -F'"' '/^ digest:/ {print $2}' quartermaster/deploy/staging/values.yaml)
|
|
75
|
+
if [ "$staging" != "${{ steps.resolve.outputs.digest }}" ]; then
|
|
76
|
+
if [ "${{ inputs.override_parity }}" = "true" ]; then
|
|
77
|
+
echo "parity override: staging runs ${staging}, promoting ${{ steps.resolve.outputs.digest }} anyway"
|
|
78
|
+
else
|
|
79
|
+
echo "staging currently runs ${staging}, not the requested digest — pass override_parity for rollbacks" >&2
|
|
80
|
+
exit 1
|
|
81
|
+
fi
|
|
82
|
+
fi
|
|
83
|
+
- name: Commit the prod digest bump
|
|
84
|
+
run: |
|
|
85
|
+
digest='${{ steps.resolve.outputs.digest }}'
|
|
86
|
+
sed -i -E "s|^ digest:.*| digest: \"${digest}\"|" quartermaster/deploy/prod/values.yaml
|
|
87
|
+
if git diff --quiet; then
|
|
88
|
+
echo "prod already runs ${digest}; nothing to commit"
|
|
89
|
+
exit 0
|
|
90
|
+
fi
|
|
91
|
+
git config user.name "github-actions[bot]"
|
|
92
|
+
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
|
|
93
|
+
git add quartermaster/deploy/prod/values.yaml
|
|
94
|
+
git commit \
|
|
95
|
+
-m "chore(deploy): prod → ${digest}" \
|
|
96
|
+
-m "Promoted by @${{ github.actor }} via promote-prod (ref input: ${{ inputs.ref }})"
|
|
97
|
+
for attempt in 1 2 3; do
|
|
98
|
+
if git push origin HEAD:main; then
|
|
99
|
+
exit 0
|
|
100
|
+
fi
|
|
101
|
+
git pull --rebase origin main
|
|
102
|
+
done
|
|
103
|
+
echo "prod bump push failed after 3 attempts" >&2
|
|
104
|
+
exit 1
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
# The CLI's PyPI release lane (spec §5), retiring publish.sh and ~/.pypirc.
|
|
2
|
+
# Two ways in, one publish path:
|
|
3
|
+
# - tag push vX.Y.Z — versions must already be aligned across pyproject,
|
|
4
|
+
# __init__, and uv.lock (the uv.lock entry is the one nothing else updates)
|
|
5
|
+
# - manual dispatch with an optional `version` input — the workflow bumps
|
|
6
|
+
# pyproject/__init__/uv.lock, commits to main, tags vX.Y.Z, then publishes.
|
|
7
|
+
# A blank input publishes the version already in the files (the retry lane
|
|
8
|
+
# for a release that failed after its bump commit landed).
|
|
9
|
+
# Both lanes: full CI → version-agreement assert → frontend build with a hard
|
|
10
|
+
# existence check (the gitignored web/static/ ships via hatch `artifacts`,
|
|
11
|
+
# which silently includes nothing when absent) → uv build + publish via PyPI
|
|
12
|
+
# trusted publishing.
|
|
13
|
+
# Prerequisite: a trusted publisher for this repo/workflow configured on PyPI.
|
|
14
|
+
name: Release to PyPI
|
|
15
|
+
|
|
16
|
+
on:
|
|
17
|
+
push:
|
|
18
|
+
tags: ["v*"]
|
|
19
|
+
workflow_dispatch:
|
|
20
|
+
inputs:
|
|
21
|
+
version:
|
|
22
|
+
description: "New version (X.Y.Z) — bumps files, commits to main, tags, publishes. Blank — publish the version already in the files."
|
|
23
|
+
required: false
|
|
24
|
+
type: string
|
|
25
|
+
|
|
26
|
+
permissions:
|
|
27
|
+
contents: read
|
|
28
|
+
|
|
29
|
+
concurrency:
|
|
30
|
+
group: release-pypi
|
|
31
|
+
|
|
32
|
+
jobs:
|
|
33
|
+
ci:
|
|
34
|
+
uses: ./.github/workflows/ci.yml
|
|
35
|
+
|
|
36
|
+
publish:
|
|
37
|
+
needs: ci
|
|
38
|
+
runs-on: arc-dxs
|
|
39
|
+
timeout-minutes: 30
|
|
40
|
+
permissions:
|
|
41
|
+
contents: write # the dispatch lane pushes the bump commit + tag
|
|
42
|
+
id-token: write # PyPI trusted publishing
|
|
43
|
+
steps:
|
|
44
|
+
- uses: actions/checkout@v4
|
|
45
|
+
- uses: astral-sh/setup-uv@v5
|
|
46
|
+
with:
|
|
47
|
+
enable-cache: true
|
|
48
|
+
- run: uv python install 3.13
|
|
49
|
+
- name: Bump version, commit, and tag (dispatch with a version input)
|
|
50
|
+
if: github.event_name == 'workflow_dispatch' && inputs.version != ''
|
|
51
|
+
env:
|
|
52
|
+
VERSION: ${{ inputs.version }}
|
|
53
|
+
run: |
|
|
54
|
+
set -euo pipefail
|
|
55
|
+
if [ "${GITHUB_REF}" != "refs/heads/main" ]; then
|
|
56
|
+
echo "version bumps may only be dispatched from main (got ${GITHUB_REF})" >&2
|
|
57
|
+
exit 1
|
|
58
|
+
fi
|
|
59
|
+
if ! echo "$VERSION" | grep -Eq '^[0-9]+\.[0-9]+\.[0-9]+$'; then
|
|
60
|
+
echo "version must be X.Y.Z (got '$VERSION')" >&2
|
|
61
|
+
exit 1
|
|
62
|
+
fi
|
|
63
|
+
current=$(grep -m1 '^version = ' pyproject.toml | cut -d'"' -f2)
|
|
64
|
+
if [ "$VERSION" != "$current" ]; then
|
|
65
|
+
sed -i "s/^version = \".*\"/version = \"$VERSION\"/" pyproject.toml
|
|
66
|
+
sed -i "s/^__version__ = \".*\"/__version__ = \"$VERSION\"/" src/dxs/__init__.py
|
|
67
|
+
uv lock
|
|
68
|
+
git config user.name "github-actions[bot]"
|
|
69
|
+
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
|
|
70
|
+
git add pyproject.toml src/dxs/__init__.py uv.lock
|
|
71
|
+
git commit -m "Bump version to $VERSION"
|
|
72
|
+
git push origin HEAD:main
|
|
73
|
+
fi
|
|
74
|
+
# The tag push is the reuse guard: it fails if v$VERSION already exists.
|
|
75
|
+
git tag "v$VERSION"
|
|
76
|
+
git push origin "v$VERSION"
|
|
77
|
+
- name: Assert expected version == pyproject == __init__ == uv.lock
|
|
78
|
+
env:
|
|
79
|
+
VERSION: ${{ inputs.version }}
|
|
80
|
+
run: |
|
|
81
|
+
pyproject=$(grep -m1 '^version = ' pyproject.toml | cut -d'"' -f2)
|
|
82
|
+
init=$(grep -m1 '__version__' src/dxs/__init__.py | cut -d'"' -f2)
|
|
83
|
+
lock=$(awk '/^name = "datex-studio-cli"$/ {found=1} found && /^version = / {print; exit}' uv.lock | cut -d'"' -f2)
|
|
84
|
+
if [ "${GITHUB_EVENT_NAME}" = "push" ]; then
|
|
85
|
+
expected="${GITHUB_REF#refs/tags/v}"
|
|
86
|
+
else
|
|
87
|
+
expected="${VERSION:-$pyproject}"
|
|
88
|
+
fi
|
|
89
|
+
echo "expected=${expected} pyproject=${pyproject} __init__=${init} uv.lock=${lock}"
|
|
90
|
+
if [ "$expected" != "$pyproject" ] || [ "$pyproject" != "$init" ] || [ "$pyproject" != "$lock" ]; then
|
|
91
|
+
echo "version sources disagree — run 'uv lock' and align all three before releasing" >&2
|
|
92
|
+
exit 1
|
|
93
|
+
fi
|
|
94
|
+
- uses: actions/setup-node@v4
|
|
95
|
+
with:
|
|
96
|
+
node-version: 22
|
|
97
|
+
- name: Build the web UI (shipped via hatch artifacts)
|
|
98
|
+
working-directory: src/dxs/web/frontend
|
|
99
|
+
run: |
|
|
100
|
+
npm ci
|
|
101
|
+
npm run build
|
|
102
|
+
- name: Assert the frontend build actually produced the static export
|
|
103
|
+
run: test -f src/dxs/web/static/index.html
|
|
104
|
+
- run: uv build
|
|
105
|
+
- name: Publish via trusted publishing
|
|
106
|
+
run: uv publish
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: datex-studio-cli
|
|
3
|
-
Version: 0.4.
|
|
3
|
+
Version: 0.4.25
|
|
4
4
|
Summary: CLI for Datex Studio low-code platform, designed for LLM-based AI agents
|
|
5
5
|
Project-URL: Homepage, https://github.com/datex/datex-studio-cli
|
|
6
6
|
Project-URL: Documentation, https://github.com/datex/datex-studio-cli
|
|
@@ -179,13 +179,13 @@ Configuration values are resolved in order:
|
|
|
179
179
|
|
|
180
180
|
```bash
|
|
181
181
|
# View current configuration
|
|
182
|
-
dxs
|
|
182
|
+
dxs settings list
|
|
183
183
|
|
|
184
184
|
# Set a default
|
|
185
|
-
dxs
|
|
185
|
+
dxs settings set default_repo 10
|
|
186
186
|
|
|
187
187
|
# Get a specific value
|
|
188
|
-
dxs
|
|
188
|
+
dxs settings get default_repo
|
|
189
189
|
```
|
|
190
190
|
|
|
191
191
|
Configuration stored in `~/.datex/config.yaml`. Credentials stored separately in `~/.datex/credentials.yaml`.
|
|
@@ -225,7 +225,7 @@ dxs auth list
|
|
|
225
225
|
dxs auth switch other-org
|
|
226
226
|
```
|
|
227
227
|
|
|
228
|
-
###
|
|
228
|
+
### CLI Settings (`dxs settings`)
|
|
229
229
|
|
|
230
230
|
| Command | Description |
|
|
231
231
|
|---------|-------------|
|
|
@@ -126,13 +126,13 @@ Configuration values are resolved in order:
|
|
|
126
126
|
|
|
127
127
|
```bash
|
|
128
128
|
# View current configuration
|
|
129
|
-
dxs
|
|
129
|
+
dxs settings list
|
|
130
130
|
|
|
131
131
|
# Set a default
|
|
132
|
-
dxs
|
|
132
|
+
dxs settings set default_repo 10
|
|
133
133
|
|
|
134
134
|
# Get a specific value
|
|
135
|
-
dxs
|
|
135
|
+
dxs settings get default_repo
|
|
136
136
|
```
|
|
137
137
|
|
|
138
138
|
Configuration stored in `~/.datex/config.yaml`. Credentials stored separately in `~/.datex/credentials.yaml`.
|
|
@@ -172,7 +172,7 @@ dxs auth list
|
|
|
172
172
|
dxs auth switch other-org
|
|
173
173
|
```
|
|
174
174
|
|
|
175
|
-
###
|
|
175
|
+
### CLI Settings (`dxs settings`)
|
|
176
176
|
|
|
177
177
|
| Command | Description |
|
|
178
178
|
|---------|-------------|
|
|
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "datex-studio-cli"
|
|
7
|
-
version = "0.4.
|
|
7
|
+
version = "0.4.25"
|
|
8
8
|
description = "CLI for Datex Studio low-code platform, designed for LLM-based AI agents"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
license = "MIT"
|
|
@@ -102,8 +102,12 @@ exclude = [
|
|
|
102
102
|
"uv.lock",
|
|
103
103
|
"src/dxs/web/frontend/",
|
|
104
104
|
"example-reports/",
|
|
105
|
+
"quartermaster/",
|
|
105
106
|
]
|
|
106
107
|
|
|
108
|
+
[tool.uv.workspace]
|
|
109
|
+
members = ["quartermaster"]
|
|
110
|
+
|
|
107
111
|
[tool.ruff]
|
|
108
112
|
target-version = "py310"
|
|
109
113
|
line-length = 100
|
|
@@ -153,6 +157,8 @@ addopts = "-v --tb=short"
|
|
|
153
157
|
markers = [
|
|
154
158
|
"fidelity: cross-engine SSIM fidelity tests (require agent-browser + ARJS)",
|
|
155
159
|
"internal_commands_gated: exercise the devops/crm visibility gate (no DXS_INTERNAL_COMMANDS override)",
|
|
160
|
+
"real_auth_state: exercise real auth state (no injected DXS_ACCESS_TOKEN; the variable is scrubbed)",
|
|
161
|
+
"telemetry_live: run without the suite-wide DXS_TELEMETRY=0 kill-switch",
|
|
156
162
|
]
|
|
157
163
|
|
|
158
164
|
[tool.coverage.run]
|
|
@@ -111,6 +111,13 @@ CONTEXT_SETTINGS = {
|
|
|
111
111
|
}
|
|
112
112
|
|
|
113
113
|
|
|
114
|
+
# Alias names that resolve but stay out of --help. A command registered under two
|
|
115
|
+
# names shares one Command object, so per-name ``hidden`` is impossible — the
|
|
116
|
+
# listing filter in DxsGroup is what hides the alias. Currently: ``config`` is a
|
|
117
|
+
# compatibility alias for ``settings`` (canonical since the rename).
|
|
118
|
+
HIDDEN_COMMAND_ALIASES = frozenset({"config"})
|
|
119
|
+
|
|
120
|
+
|
|
114
121
|
class DxsGroup(click.Group):
|
|
115
122
|
"""Custom Group that shows global options in subcommand help.
|
|
116
123
|
|
|
@@ -124,8 +131,12 @@ class DxsGroup(click.Group):
|
|
|
124
131
|
return cmd_name in DATEX_INTERNAL_COMMANDS and not internal_commands_available()
|
|
125
132
|
|
|
126
133
|
def list_commands(self, ctx: click.Context) -> list[str]:
|
|
127
|
-
"""List visible subcommands, omitting
|
|
128
|
-
return [
|
|
134
|
+
"""List visible subcommands, omitting hidden aliases and gated groups."""
|
|
135
|
+
return [
|
|
136
|
+
name
|
|
137
|
+
for name in super().list_commands(ctx)
|
|
138
|
+
if name not in HIDDEN_COMMAND_ALIASES and not self._is_gated(name)
|
|
139
|
+
]
|
|
129
140
|
|
|
130
141
|
def get_command(self, ctx: click.Context, cmd_name: str) -> click.Command | None:
|
|
131
142
|
"""Resolve a subcommand, refusing unavailable Datex-internal groups."""
|
|
@@ -329,7 +340,7 @@ def cli(
|
|
|
329
340
|
dxs auth login
|
|
330
341
|
dxs source log --repo 10
|
|
331
342
|
dxs source history userGrid --branch 100
|
|
332
|
-
dxs
|
|
343
|
+
dxs settings list
|
|
333
344
|
dxs --tenant MGD schema entities # run one command as another identity
|
|
334
345
|
|
|
335
346
|
\b
|
|
@@ -489,7 +500,7 @@ def handle_errors(f: F) -> F:
|
|
|
489
500
|
try:
|
|
490
501
|
return ctx.invoke(f, *args, **kwargs)
|
|
491
502
|
except DxsError as e:
|
|
492
|
-
_record_error_silently(e)
|
|
503
|
+
_record_error_silently(e, dxs_ctx)
|
|
493
504
|
dxs_ctx.output_error(e)
|
|
494
505
|
sys.exit(1)
|
|
495
506
|
except (click.ClickException, click.Abort, click.exceptions.Exit):
|
|
@@ -498,19 +509,24 @@ def handle_errors(f: F) -> F:
|
|
|
498
509
|
# not errors and must not be rendered as error envelopes.
|
|
499
510
|
raise
|
|
500
511
|
except Exception as e:
|
|
501
|
-
_record_error_silently(e)
|
|
512
|
+
_record_error_silently(e, dxs_ctx)
|
|
502
513
|
dxs_ctx.output_error(e)
|
|
503
514
|
sys.exit(1)
|
|
504
515
|
|
|
505
516
|
return cast(F, wrapper)
|
|
506
517
|
|
|
507
518
|
|
|
508
|
-
def _record_error_silently(exc: BaseException) -> None:
|
|
509
|
-
"""Emit a telemetry error event; never raises.
|
|
519
|
+
def _record_error_silently(exc: BaseException, dxs_ctx: "DxsContext | None" = None) -> None:
|
|
520
|
+
"""Emit a telemetry error event; never raises.
|
|
521
|
+
|
|
522
|
+
``dxs_ctx`` is available on the handle_errors path and supplies the same
|
|
523
|
+
``ctx_*`` slices success events carry; errors escaping to main() arrive
|
|
524
|
+
after Click tears the context down and go out without them.
|
|
525
|
+
"""
|
|
510
526
|
try:
|
|
511
527
|
from dxs.core.telemetry import record_error
|
|
512
528
|
|
|
513
|
-
record_error(exc)
|
|
529
|
+
record_error(exc, ctx_extras=_ctx_extras(dxs_ctx))
|
|
514
530
|
except Exception: # noqa: BLE001
|
|
515
531
|
pass
|
|
516
532
|
|
|
@@ -546,8 +562,10 @@ def register_commands() -> None:
|
|
|
546
562
|
cli.add_command(api.api)
|
|
547
563
|
cli.add_command(auth.auth)
|
|
548
564
|
cli.add_command(init.init)
|
|
549
|
-
cli.add_command(config.config)
|
|
550
565
|
cli.add_command(config.config, name="settings")
|
|
566
|
+
# Compatibility alias — resolves but is hidden from --help via
|
|
567
|
+
# HIDDEN_COMMAND_ALIASES, since both names share one Command object.
|
|
568
|
+
cli.add_command(config.config)
|
|
551
569
|
cli.add_command(configuration.configuration)
|
|
552
570
|
cli.add_command(crm.crm)
|
|
553
571
|
cli.add_command(datasource.datasource)
|
|
@@ -743,7 +761,8 @@ def update_cmd(yes: bool, check_only: bool) -> None:
|
|
|
743
761
|
try:
|
|
744
762
|
from dxs.core.telemetry import record_end
|
|
745
763
|
|
|
746
|
-
|
|
764
|
+
dxs_ctx = click.get_current_context().find_object(DxsContext)
|
|
765
|
+
record_end(exit_code=0, ctx_extras=_ctx_extras(dxs_ctx))
|
|
747
766
|
except Exception: # noqa: BLE001
|
|
748
767
|
pass
|
|
749
768
|
try:
|
|
@@ -105,7 +105,7 @@ def _run_targeted_consent(ctx: DxsContext, resource_key: str) -> None:
|
|
|
105
105
|
),
|
|
106
106
|
code="DXS-DYNAMICS-CONFIG-001",
|
|
107
107
|
suggestions=[
|
|
108
|
-
"Run: dxs
|
|
108
|
+
"Run: dxs settings set dynamics_crm_url https://yourorg.crm.dynamics.com",
|
|
109
109
|
"Then re-run: dxs auth login --consent crm",
|
|
110
110
|
],
|
|
111
111
|
)
|
|
@@ -22,6 +22,7 @@ from dxs.core.api import (
|
|
|
22
22
|
BranchEndpoints,
|
|
23
23
|
RepoEndpoints,
|
|
24
24
|
SourceControlEndpoints,
|
|
25
|
+
fetch_replacements,
|
|
25
26
|
fetch_settings,
|
|
26
27
|
)
|
|
27
28
|
from dxs.core.api.models import (
|
|
@@ -1047,7 +1048,7 @@ def search(ctx: DxsContext, query: str, repo: int | None) -> None:
|
|
|
1047
1048
|
suggestions=[
|
|
1048
1049
|
"Use --repo flag: dxs branch search 'query' --repo 10",
|
|
1049
1050
|
"Set environment variable: export DXS_REPO=10",
|
|
1050
|
-
"Set config default: dxs
|
|
1051
|
+
"Set config default: dxs settings set default_repo 10",
|
|
1051
1052
|
],
|
|
1052
1053
|
)
|
|
1053
1054
|
|
|
@@ -1137,7 +1138,9 @@ def replacements(ctx: DxsContext, branch_id: int) -> None:
|
|
|
1137
1138
|
"""Show configuration replacements.
|
|
1138
1139
|
|
|
1139
1140
|
Lists all configuration replacements (customizations from component modules)
|
|
1140
|
-
for a branch.
|
|
1141
|
+
for a branch. Each entry names the replaced config
|
|
1142
|
+
(``referenceName`` + ``applicationReferenceName``) and the config replacing
|
|
1143
|
+
it (``replacementReferenceName`` + ``replacementApplicationReferenceName``).
|
|
1141
1144
|
|
|
1142
1145
|
\b
|
|
1143
1146
|
Arguments:
|
|
@@ -1150,11 +1153,7 @@ def replacements(ctx: DxsContext, branch_id: int) -> None:
|
|
|
1150
1153
|
client = ApiClient()
|
|
1151
1154
|
ctx.log(f"Fetching replacements for branch {branch_id}...")
|
|
1152
1155
|
|
|
1153
|
-
replacements_data = client
|
|
1154
|
-
|
|
1155
|
-
# Normalize to list if not already
|
|
1156
|
-
if not isinstance(replacements_data, list):
|
|
1157
|
-
replacements_data = [replacements_data] if replacements_data else []
|
|
1156
|
+
replacements_data = fetch_replacements(client, branch_id)
|
|
1158
1157
|
|
|
1159
1158
|
ctx.output(
|
|
1160
1159
|
list_response(items=replacements_data, semantic_key="replacements", branch_id=branch_id)
|
|
@@ -482,7 +482,7 @@ def execute_cascade_plan(
|
|
|
482
482
|
"Check the package's published versions, then resume the remaining "
|
|
483
483
|
"nodes with 'cascade run --select'.",
|
|
484
484
|
"If local builds are slow, raise the publish timeout: "
|
|
485
|
-
"dxs
|
|
485
|
+
"dxs settings set publish_timeout <seconds>.",
|
|
486
486
|
],
|
|
487
487
|
) from e
|
|
488
488
|
new_version: str | None = requested_version
|