Exercise 8 · Publish to Entropy Data
Make your data products discoverable on a data product platform.
Make your data products discoverable on a data product platform.
YAML files in Git work well for a single team. But how do other teams discover your data products, browse the contracts, and request access? That's what a data product platform is for. In this exercise, you publish everything from Parts A and B to Entropy Data with the Entropy Data CLI.
Pick one option.
Option 1: Cloud. Go to app.entropy-data.com, create an account, and set up an organization named tutorial-<yourname>, e.g. tutorial-simon.
Names are unique across the platform. Use lowercase letters, digits, and hyphens only.
In the organization settings, create an API key with organization write permissions.
Option 2: Community Edition, locally. Start it in Docker and run the setup script. It creates an account, an organization named acme, and an API key:
docker compose -f entropy-data-ce/docker-compose.yaml up -d
./scripts/setup-entropy-data-ce.sh…
Creating account [email protected] ...
Logging in ...
Creating organization acme ...
Creating organization API key ...
Writing ENTROPY_DATA_API_KEY and ENTROPY_DATA_HOST to .env ...
Done. Log in at http://localhost:8081 with [email protected] / workshop (organization: acme)
Verify the CLI connection with: entropy-data connection testLog in at http://localhost:8081 with [email protected] / workshop.
Below, use acme wherever it says tutorial-<yourname>.
The install script from Setup already installed the Entropy Data CLI. Check:
entropy-data --versionentropy-data 0.3.13Cloud: set your API key as an environment variable in your terminal:
export ENTROPY_DATA_API_KEY=ed_...
export ENTROPY_DATA_HOST=https://api.entropy-data.comCommunity Edition: the setup script wrote the key and ENTROPY_DATA_HOST=http://localhost:8081 into .env. Keep it out of Git anyway: check git status before you commit and undo the change with git checkout .env. Never run git add .env.
Test the connection:
entropy-data connection testConnection successful.Contracts and data products name a team as owner. The team must exist before you publish anything that references it:
cat <<EOF | entropy-data teams put order_data_team --file -
id: order_data_team
name: Order Data Team
type: team
description: Owns the orders data
EOF
cat <<EOF | entropy-data teams put purchasing_analytics_team --file -
id: purchasing_analytics_team
name: Purchasing Analytics Team
type: team
description: Builds analytical data products for purchasing
EOF
entropy-data teams listTeam 'order_data_team' saved.
Team 'purchasing_analytics_team' saved.
teams (page 0)
┏━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━┳━━━━━━━━┓
┃ ID ┃ Name ┃ Type ┃ Parent ┃
┡━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━╇━━━━━━━━┩
│ governance-group │ Governance Group │ Governance Group │ │
│ platform-team │ Platform Team │ Platform Team │ │
│ order_data_team │ Order Data Team │ team │ │
│ purchasing_analytics_team │ Purchasing Analytics Team │ team │ │
└───────────────────────────┴───────────────────────────┴──────────────────┴────────┘The team.name in your ODCS and ODPS files must match the team ID, e.g. order_data_team.
The ID argument must match the id field in each contract:
entropy-data datacontracts put orders_v1 --file orders_v1.odcs.yaml
entropy-data datacontracts put orders_v2 --file orders_v2.odcs.yaml
entropy-data datacontracts put sku_sales_per_year --file sku_sales_per_year.odcs.yaml
entropy-data datacontracts put orders_v2_consumer_sku_sales --file orders_v2.consumer_sku_sales.odcs.yaml
entropy-data datacontracts listData contract 'orders_v1' saved.
Open https://app.entropy-data.com/tutorial-simon/datacontracts/orders_v1
Data contract 'orders_v2' saved.
Open https://app.entropy-data.com/tutorial-simon/datacontracts/orders_v2
Data contract 'sku_sales_per_year' saved.
Open https://app.entropy-data.com/tutorial-simon/datacontracts/sku_sales_per_year
Data contract 'orders_v2_consumer_sku_sales' saved.
Open https://app.entropy-data.com/tutorial-simon/datacontracts/orders_v2_consumer_sku_sales
datacontracts (page 0)
┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
┃ ID ┃ Title ┃ Version ┃ Owner ┃
┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━┩
│ orders_v1 │ Orders │ 1.0.0 │ order_data_team │
│ orders_v2 │ Orders │ 2.0.0 │ order_data_team │
│ sku_sales_per_year │ SKU Sales per Year │ 1.0.0 │ purchasing_analytics_team │
│ orders_v2_consumer_sku_sales │ Orders (SKU Sales) │ 2.0.0 │ purchasing_analytics_team │
└──────────────────────────────┴────────────────────┴─────────┴───────────────────────────┘Entropy Data supports ODPS natively, so you publish the files as they are.
The ID argument must match the id field in the file:
entropy-data dataproducts put orders --file orders.odps.yaml
entropy-data dataproducts put sku_sales --file sku_sales_per_year.odps.yaml
entropy-data dataproducts listData product 'orders' saved.
Data product 'sku_sales' saved.
dataproducts (page 0)
┏━━━━━━━━━━━┳━━━━━━━━━━━┳━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
┃ ID ┃ Title ┃ Status ┃ Owner ┃
┡━━━━━━━━━━━╇━━━━━━━━━━━╇━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━┩
│ orders │ Orders │ active │ order_data_team │
│ sku_sales │ SKU Sales │ draft │ purchasing_analytics_team │
└───────────┴───────────┴────────┴───────────────────────────┘On the platform, the dependency is an access agreement: SKU Sales consumes the orders_v2 output port of Orders. Create it directly as approved:
cat <<EOF | entropy-data access put sku_sales_consumes_orders --file -
dataUsageAgreementSpecification: 0.0.1
id: sku_sales_consumes_orders
info:
purpose: SKU Sales aggregates orders and line items per SKU and year for the purchasing team
status: approved
startDate: "2026-01-01"
provider:
dataProductId: orders
outputPortId: orders_v2
dataContractId: orders_v2
consumer:
dataProductId: sku_sales
EOFAccess agreement 'sku_sales_consumes_orders' saved.With status approved and a startDate in the past, the agreement is active.
Open the web UI (app.entropy-data.com or localhost:8081):
sku_sales_per_year contract and compare it with the Data Contract Editor.The platform shows whether a contract is currently upheld, if you send it test results.
Run your tests with --publish and your host's test results endpoint:
Cloud:
datacontract test sku_sales_per_year.odcs.yaml --publish https://api.entropy-data.com/api/test-resultsTesting sku_sales_per_year.odcs.yaml
🚀 Open https://app.entropy-data.com/tutorial-simon/datacontracts/sku_sales_per_year/servers/postgres/checks
Server: postgres (type=postgres, host=localhost, port=5433, database=workshop, schema=analytics)
╭────────┬──────────────────────────────────────────────────┬─────────────┬─────────╮
│ Result │ Check │ Field │ Details │
├────────┼──────────────────────────────────────────────────┼─────────────┼─────────┤
│ passed │ Ensure the view has data │ │ │
│ passed │ Check that field 'order_count' is present │ order_count │ │
│ … │ │ │ │
│ passed │ Ensure year is plausible │ year │ │
╰────────┴──────────────────────────────────────────────────┴─────────────┴─────────╯
🟢 data contract is valid. Run 15 checks. Took 0.58 seconds.Community Edition:
datacontract test sku_sales_per_year.odcs.yaml --publish http://localhost:8081/api/test-resultsThe CLI sends your API key only if the URL belongs to the host in ENTROPY_DATA_HOST. Find the results on the contract page in the UI.
Publish test results from CI. In your fork on GitHub, go to Settings → Secrets and variables → Actions and add a repository secret ENTROPY_DATA_API_KEY. In the workflow from CI/CD with GitHub Actions, pass it to the test step and add --publish:
- name: Test data contracts
env:
ENTROPY_DATA_API_KEY: ${{ secrets.ENTROPY_DATA_API_KEY }}
ENTROPY_DATA_HOST: https://api.entropy-data.com
run: datacontract ci *.odcs.yaml --publish https://api.entropy-data.com/api/test-resultsThis works only with the cloud: GitHub's runners can't reach your local Community Edition.
Keep Git as the source of truth. Look at entropy-data datacontracts import-from-git --help. How would you publish contracts automatically on every merge to main?