Lakehouse-Aligned YAML Kit for Engineering Rules
Project description
Lakehouse‑Aligned YAML Kit for Engineering Rules
Declarative table metadata control for Databricks & Spark.
Layker turns a YAML spec into safe, validated DDL with a built‑in audit log.
If nothing needs to change, Layker exits cleanly. If something must change, you’ll see it first.
What is Layker?
Layker is a Python package for managing table DDL, metadata, and auditing with a single YAML file as the source of truth.
Highlights
- Declarative – author schemas, tags, constraints, and properties in YAML.
- Diff‑first – Layker computes a diff against the live table; “no diff” = no work.
- Safe evolution – add/rename/drop column intents are detected and gated by required Delta properties.
- Auditable – every applied change is logged with before/after snapshots and a concise differences dictionary.
- Serverless‑friendly – gracefully skips
REFRESH TABLEon serverless (prints a warning).
Installation
Stable:
pip install layker
Latest (main):
pip install "git+https://github.com/Levi-Gagne/layker.git"
Python 3.8+ and Spark 3.3+ are recommended.
Quickstart
1) Author a YAML spec
Minimal example (save as src/layker/resources/example.yaml):
catalog: dq_dev
schema: lmg_sandbox
table: layker_test
columns:
1:
name: id
datatype: bigint
nullable: false
active: true
2:
name: name
datatype: string
nullable: true
active: true
table_comment: Demo table managed by Layker
table_properties:
delta.columnMapping.mode: "name"
delta.minReaderVersion: "2"
delta.minWriterVersion: "5"
primary_key: [id]
tags:
domain: demo
owner: team-data
2) Sync from Python
from pyspark.sql import SparkSession
from layker.main import run_table_load
spark = SparkSession.builder.appName("layker").getOrCreate()
run_table_load(
yaml_path="src/layker/resources/example.yaml",
env="prd",
dry_run=False,
mode="all", # validate | diff | apply | all
audit_log_table=True # True=default audit YAML, False=disable, or str path to an audit YAML
)
3) Or via CLI
python -m layker src/layker/resources/example.yaml prd false all true
When
audit_log_table=True, Layker uses the packaged default:layker/resources/layker_audit.yaml.
You can also pass a custom YAML path. Either way, the YAML defines the audit table’s location.
How it works (at a glance)
- Validate YAML → fast fail with exact reasons, or proceed.
- Snapshot live table (if it exists).
- Compute differences between YAML snapshot and table snapshot.
- If no changes (i.e., the diff contains only
full_table_name), exit with a success message and no audit row is written.
- If no changes (i.e., the diff contains only
- Validate differences (schema‑evolution preflight):
- Detects add/rename/drop column intents.
- Requires Delta properties for evolution:
delta.columnMapping.mode = namedelta.minReaderVersion = 2delta.minWriterVersion = 5
- On missing requirements, prints details and exits.
- Apply changes (create/alter) using generated SQL.
- Audit (only if changes were applied and auditing is enabled):
- Writes a row containing:
before_value(JSON),differences(JSON),after_value(JSON)change_category(createorupdate)change_key(human‑readable sequence per table, see below)env,yaml_path,fqn, timestamps, actor, etc.
- Writes a row containing:
Audit log model
The default audit YAML (layker/resources/layker_audit.yaml) defines these columns (in order):
- change_id – UUID per row
- run_id – optional job/run identifier
- env – environment/catalog prefix
- yaml_path – the source YAML path that initiated the change
- fqn – fully qualified table name
- change_category –
createorupdate(based on whether a “before” snapshot was present) - change_key – readable sequence per table:
- First ever create:
create-1 - Subsequent updates on that lineage:
create-1~update-1,create-1~update-2, … - If the table is later dropped & re‑created: the next lineage becomes
create-2, etc.
- First ever create:
- before_value – JSON snapshot before change (may be null on first create)
- differences – JSON diff dict that was applied
- after_value – JSON snapshot after change
- notes – optional free text
- created_at / created_by / updated_at / updated_by
Uniqueness expectation: (fqn, change_key) is effectively unique over time.
Modes & parameters
- mode:
validate|diff|apply|allvalidate: only YAML validation (exits on success)diff: prints proposed changes and exitsapply: applies changes onlyall: validate → diff → apply → audit
- audit_log_table:
False– disable auditingTrue– use defaultlayker/resources/layker_audit.yamlstr– path to a custom audit YAML (the YAML governs the destination table)
- No‑op safety: if there are no changes, Layker exits early and skips audit.
Notes on serverless
Databricks serverless does not support REFRESH TABLE.
Layker detects this and prints a warning; the rest of the flow continues.
Repository layout (typical)
src/
layker/
__init__.py
__main__.py
main.py
differences.py
loader.py
logger.py
snapshot_yaml.py
snapshot_table.py
resources/
layker_audit.yaml
utils/
color.py
printer.py
spark.py
timer.py
paths.py
table.py
validators/
params.py
differences.py
Troubleshooting
- Spark Connect / serverless: Layker avoids schema inference issues by using explicit schemas when writing the audit row.
- Single quotes in comments: Layker sanitizes YAML comments to avoid SQL quoting errors.
- No changes but I still see output: A diff containing only
full_table_namemeans no change; Layker exits early with a success message and writes no audit row.
Contributing & License
PRs and issues welcome.
License: see LICENSE in the repo.
🐟 LAYKER 🐟
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file layker-0.1.0.tar.gz.
File metadata
- Download URL: layker-0.1.0.tar.gz
- Upload date:
- Size: 53.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.12.9
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ec78695fe93a07839a114248831c13afd3d6352534ab1eaa9e21b661b7bb1159
|
|
| MD5 |
f63122319cab1a638100bf85baca21b2
|
|
| BLAKE2b-256 |
34ef0862893e9f94d5ca5599a179edf17c357a9e44e87d6b9681602293526490
|
Provenance
The following attestation bundles were made for layker-0.1.0.tar.gz:
Publisher:
workflow.yaml on Levi-Gagne/layker
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
layker-0.1.0.tar.gz -
Subject digest:
ec78695fe93a07839a114248831c13afd3d6352534ab1eaa9e21b661b7bb1159 - Sigstore transparency entry: 377148101
- Sigstore integration time:
-
Permalink:
Levi-Gagne/layker@3e4e050065f1337bebda6e0ea700592bc3ab8f2a -
Branch / Tag:
refs/heads/main - Owner: https://github.com/Levi-Gagne
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
workflow.yaml@3e4e050065f1337bebda6e0ea700592bc3ab8f2a -
Trigger Event:
workflow_dispatch
-
Statement type:
File details
Details for the file layker-0.1.0-py3-none-any.whl.
File metadata
- Download URL: layker-0.1.0-py3-none-any.whl
- Upload date:
- Size: 55.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.12.9
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
eadf8a512a2b0a670ca9c7deb7cc9b694ad7425f79204083cb1b48457bb49237
|
|
| MD5 |
5409385e3c9fab335a94016d8b83ca84
|
|
| BLAKE2b-256 |
eee3113f8757d2f648c28f63b9e25d6ddedbbf93303a1c9f77f2379797662b86
|
Provenance
The following attestation bundles were made for layker-0.1.0-py3-none-any.whl:
Publisher:
workflow.yaml on Levi-Gagne/layker
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
layker-0.1.0-py3-none-any.whl -
Subject digest:
eadf8a512a2b0a670ca9c7deb7cc9b694ad7425f79204083cb1b48457bb49237 - Sigstore transparency entry: 377148109
- Sigstore integration time:
-
Permalink:
Levi-Gagne/layker@3e4e050065f1337bebda6e0ea700592bc3ab8f2a -
Branch / Tag:
refs/heads/main - Owner: https://github.com/Levi-Gagne
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
workflow.yaml@3e4e050065f1337bebda6e0ea700592bc3ab8f2a -
Trigger Event:
workflow_dispatch
-
Statement type: