duckpad 0.1.0__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.
- duckpad-0.1.0/.agents/skills/repository-conventions/SKILL.md +54 -0
- duckpad-0.1.0/.dockerignore +20 -0
- duckpad-0.1.0/.github/workflows/ci.yml +37 -0
- duckpad-0.1.0/.github/workflows/release.yml +119 -0
- duckpad-0.1.0/.gitignore +19 -0
- duckpad-0.1.0/AGENTS.md +24 -0
- duckpad-0.1.0/Dockerfile +33 -0
- duckpad-0.1.0/Dockerfile.duckdb +13 -0
- duckpad-0.1.0/LICENSE +21 -0
- duckpad-0.1.0/PKG-INFO +123 -0
- duckpad-0.1.0/README.md +93 -0
- duckpad-0.1.0/SPEC.md +308 -0
- duckpad-0.1.0/cliff.toml +60 -0
- duckpad-0.1.0/docs/ARCHITECTURE.md +53 -0
- duckpad-0.1.0/docs/AUTHORING.md +62 -0
- duckpad-0.1.0/docs/CONNECTORS.md +69 -0
- duckpad-0.1.0/docs/EXAMPLE.md +33 -0
- duckpad-0.1.0/docs/EXECUTION_SERVICE.md +27 -0
- duckpad-0.1.0/docs/IMPLEMENTATION.md +23 -0
- duckpad-0.1.0/docs/LINEAGE.md +49 -0
- duckpad-0.1.0/docs/MULTICA.md +95 -0
- duckpad-0.1.0/docs/RELEASING.md +107 -0
- duckpad-0.1.0/docs/VALIDATION.md +46 -0
- duckpad-0.1.0/docs/images/lineage.png +0 -0
- duckpad-0.1.0/docs/images/workspace.png +0 -0
- duckpad-0.1.0/docs/validation/benchmark.json +233 -0
- duckpad-0.1.0/docs/validation/checks.json +22 -0
- duckpad-0.1.0/docs/validation/jobs.json +31 -0
- duckpad-0.1.0/docs/validation/oracle.json +42 -0
- duckpad-0.1.0/docs/validation/s3.json +19 -0
- duckpad-0.1.0/docs/validation/wheel.json +12 -0
- duckpad-0.1.0/frontend/e2e/dashboard.spec.ts +206 -0
- duckpad-0.1.0/frontend/e2e/preferences.spec.ts +132 -0
- duckpad-0.1.0/frontend/e2e/resources.spec.ts +211 -0
- duckpad-0.1.0/frontend/e2e/workspace.spec.ts +1004 -0
- duckpad-0.1.0/frontend/index.html +1 -0
- duckpad-0.1.0/frontend/package-lock.json +2233 -0
- duckpad-0.1.0/frontend/package.json +29 -0
- duckpad-0.1.0/frontend/playwright.config.ts +41 -0
- duckpad-0.1.0/frontend/src/AccountMenu.tsx +160 -0
- duckpad-0.1.0/frontend/src/App.tsx +1642 -0
- duckpad-0.1.0/frontend/src/Canvas.tsx +467 -0
- duckpad-0.1.0/frontend/src/Editor.tsx +48 -0
- duckpad-0.1.0/frontend/src/Inspector.tsx +579 -0
- duckpad-0.1.0/frontend/src/LineagePanel.tsx +297 -0
- duckpad-0.1.0/frontend/src/Panels.tsx +785 -0
- duckpad-0.1.0/frontend/src/Preview.tsx +317 -0
- duckpad-0.1.0/frontend/src/ProjectDashboard.tsx +91 -0
- duckpad-0.1.0/frontend/src/QueryBuilder.tsx +235 -0
- duckpad-0.1.0/frontend/src/ResourceMonitor.tsx +225 -0
- duckpad-0.1.0/frontend/src/WorkspacePanels.tsx +204 -0
- duckpad-0.1.0/frontend/src/i18n.tsx +35 -0
- duckpad-0.1.0/frontend/src/locales/en.json +279 -0
- duckpad-0.1.0/frontend/src/locales/fr.json +279 -0
- duckpad-0.1.0/frontend/src/main.tsx +9 -0
- duckpad-0.1.0/frontend/src/styles.css +2890 -0
- duckpad-0.1.0/frontend/src/types.ts +89 -0
- duckpad-0.1.0/frontend/src/vite-env.d.ts +1 -0
- duckpad-0.1.0/frontend/tsconfig.json +16 -0
- duckpad-0.1.0/frontend/vite.config.ts +7 -0
- duckpad-0.1.0/pyproject.toml +45 -0
- duckpad-0.1.0/scripts/benchmark.py +195 -0
- duckpad-0.1.0/scripts/build_hook.py +19 -0
- duckpad-0.1.0/scripts/e2e_server.py +17 -0
- duckpad-0.1.0/scripts/integration.py +297 -0
- duckpad-0.1.0/scripts/preview.sh +53 -0
- duckpad-0.1.0/scripts/prototype_jobs.py +159 -0
- duckpad-0.1.0/scripts/provision-runtime.sh +41 -0
- duckpad-0.1.0/scripts/release.py +79 -0
- duckpad-0.1.0/scripts/setup.sh +26 -0
- duckpad-0.1.0/scripts/smoke_wheel.py +108 -0
- duckpad-0.1.0/scripts/verify_preview.py +76 -0
- duckpad-0.1.0/src/duckpad/__init__.py +3 -0
- duckpad-0.1.0/src/duckpad/app.py +353 -0
- duckpad-0.1.0/src/duckpad/auth.py +47 -0
- duckpad-0.1.0/src/duckpad/catalog.py +278 -0
- duckpad-0.1.0/src/duckpad/cli.py +57 -0
- duckpad-0.1.0/src/duckpad/components.py +308 -0
- duckpad-0.1.0/src/duckpad/engine.py +663 -0
- duckpad-0.1.0/src/duckpad/example.py +282 -0
- duckpad-0.1.0/src/duckpad/lineage.py +761 -0
- duckpad-0.1.0/src/duckpad/materialize.py +126 -0
- duckpad-0.1.0/src/duckpad/projects.py +522 -0
- duckpad-0.1.0/src/duckpad/resources.py +103 -0
- duckpad-0.1.0/src/duckpad/static/assets/Editor-DyX1CsEw.css +1 -0
- duckpad-0.1.0/src/duckpad/static/assets/Editor-t9xBSzyU.js +679 -0
- duckpad-0.1.0/src/duckpad/static/assets/editor.worker-BCzxt1at.js +12 -0
- duckpad-0.1.0/src/duckpad/static/assets/index-CHSQY8z7.css +1 -0
- duckpad-0.1.0/src/duckpad/static/assets/index-GIKY3NsH.js +325 -0
- duckpad-0.1.0/src/duckpad/static/assets/json.worker-B7c_PmGb.js +49 -0
- duckpad-0.1.0/src/duckpad/static/assets/jsonMode-BbQxTeWp.js +15 -0
- duckpad-0.1.0/src/duckpad/static/assets/sql-CCSDG5nI.js +6 -0
- duckpad-0.1.0/src/duckpad/static/index.html +3 -0
- duckpad-0.1.0/src/duckpad/store.py +48 -0
- duckpad-0.1.0/src/duckpad/templates.py +375 -0
- duckpad-0.1.0/src/duckpad/util.py +82 -0
- duckpad-0.1.0/tests/conftest.py +69 -0
- duckpad-0.1.0/tests/test_cancellation.py +166 -0
- duckpad-0.1.0/tests/test_catalog.py +104 -0
- duckpad-0.1.0/tests/test_execution.py +121 -0
- duckpad-0.1.0/tests/test_lineage.py +218 -0
- duckpad-0.1.0/tests/test_native_semantics.py +36 -0
- duckpad-0.1.0/tests/test_preview_auth.py +18 -0
- duckpad-0.1.0/tests/test_projects.py +226 -0
- duckpad-0.1.0/tests/test_release.py +126 -0
- duckpad-0.1.0/tests/test_resources.py +159 -0
- duckpad-0.1.0/uv.lock +2240 -0
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: repository-conventions
|
|
3
|
+
description: Apply this repository's English writing rules, UI translation exception, and Conventional Commits rules whenever creating or editing files, reviewing changes, or preparing commit messages.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Repository Conventions
|
|
7
|
+
|
|
8
|
+
## Write repository content in English
|
|
9
|
+
|
|
10
|
+
- Write all new or modified repository content in English, even when the user
|
|
11
|
+
gives instructions in French, except for the UI translation resources below.
|
|
12
|
+
- Use English for documentation, comments, identifiers, file names, test names,
|
|
13
|
+
example text, default user-facing strings, log messages, and error messages.
|
|
14
|
+
- Allow French only in localized UI values stored in dedicated translation
|
|
15
|
+
resource files, including translations of user-facing error messages. Keep
|
|
16
|
+
translation keys, file names, and comments in English. Use translation keys
|
|
17
|
+
from application code instead of embedding French strings there.
|
|
18
|
+
- Translate French wording into English before adding it elsewhere in the
|
|
19
|
+
repository.
|
|
20
|
+
- Keep conversational replies in the user's preferred language.
|
|
21
|
+
|
|
22
|
+
## Use Conventional Commits
|
|
23
|
+
|
|
24
|
+
Every commit message must follow this structure:
|
|
25
|
+
|
|
26
|
+
```text
|
|
27
|
+
<type>[optional scope][optional !]: <English summary>
|
|
28
|
+
|
|
29
|
+
[optional English body]
|
|
30
|
+
|
|
31
|
+
[optional footers]
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
- Use a lowercase type that describes the change: `feat`, `fix`, `docs`, `style`,
|
|
35
|
+
`refactor`, `perf`, `test`, `build`, `ci`, `chore`, or `revert`.
|
|
36
|
+
- Add a short English scope when it helps identify the affected component.
|
|
37
|
+
- Write a concise English summary in the imperative, such as `add`, `fix`, or
|
|
38
|
+
`update`. Keep body text and footer descriptions in English as well.
|
|
39
|
+
- Mark breaking changes with `!` before the colon or a
|
|
40
|
+
`BREAKING CHANGE: <English explanation>` footer.
|
|
41
|
+
- Apply the same format to merge, squash, revert, and amended commit messages;
|
|
42
|
+
replace generated messages when necessary.
|
|
43
|
+
|
|
44
|
+
Examples:
|
|
45
|
+
|
|
46
|
+
```text
|
|
47
|
+
docs(agents): add repository conventions
|
|
48
|
+
fix(editor): preserve selection when saving
|
|
49
|
+
feat(api)!: require authentication for note updates
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
Before finishing a change, verify that any French text is limited to localized
|
|
53
|
+
UI values in dedicated translation resources, and check any proposed commit
|
|
54
|
+
message against the format above.
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
.git
|
|
2
|
+
.agents
|
|
3
|
+
.multica
|
|
4
|
+
.venv
|
|
5
|
+
.duckpad-dev
|
|
6
|
+
.env
|
|
7
|
+
.env.*
|
|
8
|
+
**/__pycache__
|
|
9
|
+
**/node_modules
|
|
10
|
+
**/*.tsbuildinfo
|
|
11
|
+
.pytest_cache
|
|
12
|
+
.ruff_cache
|
|
13
|
+
dist
|
|
14
|
+
src/duckpad/static
|
|
15
|
+
test-results
|
|
16
|
+
playwright-report
|
|
17
|
+
frontend/test-results
|
|
18
|
+
frontend/playwright-report
|
|
19
|
+
docs
|
|
20
|
+
tests
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
name: Validate Duckpad
|
|
2
|
+
on:
|
|
3
|
+
push:
|
|
4
|
+
pull_request:
|
|
5
|
+
permissions:
|
|
6
|
+
contents: read
|
|
7
|
+
jobs:
|
|
8
|
+
acceptance:
|
|
9
|
+
runs-on: ubuntu-latest
|
|
10
|
+
strategy:
|
|
11
|
+
matrix:
|
|
12
|
+
python: ['3.11', '3.13']
|
|
13
|
+
steps:
|
|
14
|
+
- uses: actions/checkout@v4
|
|
15
|
+
- uses: actions/setup-python@v5
|
|
16
|
+
with:
|
|
17
|
+
python-version: ${{ matrix.python }}
|
|
18
|
+
- uses: actions/setup-node@v4
|
|
19
|
+
with:
|
|
20
|
+
node-version: '22'
|
|
21
|
+
cache: npm
|
|
22
|
+
cache-dependency-path: frontend/package-lock.json
|
|
23
|
+
- uses: astral-sh/setup-uv@v6
|
|
24
|
+
- run: uv sync --extra dev --locked
|
|
25
|
+
- run: uv run ruff check src tests scripts
|
|
26
|
+
- run: uv run ruff format --check src tests scripts
|
|
27
|
+
- run: uv run pytest -q
|
|
28
|
+
- run: npm ci --prefix frontend
|
|
29
|
+
- run: npm run build --prefix frontend
|
|
30
|
+
- run: npm exec --prefix frontend -- playwright install --with-deps chromium
|
|
31
|
+
- run: npm run test:e2e --prefix frontend
|
|
32
|
+
- run: uv build
|
|
33
|
+
- uses: actions/upload-artifact@v4
|
|
34
|
+
if: failure()
|
|
35
|
+
with:
|
|
36
|
+
name: browser-diagnostics-${{ matrix.python }}
|
|
37
|
+
path: frontend/test-results/
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
name: Release Duckpad
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
tags: ['v*']
|
|
6
|
+
|
|
7
|
+
permissions:
|
|
8
|
+
contents: read
|
|
9
|
+
|
|
10
|
+
concurrency:
|
|
11
|
+
group: release-${{ github.ref }}
|
|
12
|
+
cancel-in-progress: false
|
|
13
|
+
|
|
14
|
+
jobs:
|
|
15
|
+
build:
|
|
16
|
+
name: Validate and build release
|
|
17
|
+
runs-on: ubuntu-latest
|
|
18
|
+
outputs:
|
|
19
|
+
version: ${{ steps.release.outputs.version }}
|
|
20
|
+
prerelease: ${{ steps.release.outputs.prerelease }}
|
|
21
|
+
steps:
|
|
22
|
+
- uses: actions/checkout@v4
|
|
23
|
+
with:
|
|
24
|
+
fetch-depth: 0
|
|
25
|
+
persist-credentials: false
|
|
26
|
+
- uses: actions/setup-python@v5
|
|
27
|
+
with:
|
|
28
|
+
python-version: '3.12'
|
|
29
|
+
- uses: actions/setup-node@v4
|
|
30
|
+
with:
|
|
31
|
+
node-version: '22'
|
|
32
|
+
cache: npm
|
|
33
|
+
cache-dependency-path: frontend/package-lock.json
|
|
34
|
+
- uses: astral-sh/setup-uv@v6
|
|
35
|
+
- run: uv sync --extra dev --locked
|
|
36
|
+
- name: Validate tag and generate release notes
|
|
37
|
+
id: release
|
|
38
|
+
env:
|
|
39
|
+
RELEASE_TAG: ${{ github.ref_name }}
|
|
40
|
+
RELEASE_REPOSITORY: ${{ github.repository }}
|
|
41
|
+
run: uv run python scripts/release.py "$RELEASE_TAG" --repository "$RELEASE_REPOSITORY" --output release-notes.md
|
|
42
|
+
- run: uv run ruff check src tests scripts
|
|
43
|
+
- run: uv run ruff format --check src tests scripts
|
|
44
|
+
- run: uv run pytest -q
|
|
45
|
+
- run: npm ci --prefix frontend
|
|
46
|
+
- run: npm run build --prefix frontend
|
|
47
|
+
- run: npm exec --prefix frontend -- playwright install --with-deps chromium
|
|
48
|
+
- run: npm run test:e2e --prefix frontend
|
|
49
|
+
# uv builds the wheel from the sdist, checking that the source archive is complete.
|
|
50
|
+
- run: uv build
|
|
51
|
+
- run: uv tool run --from twine==7.0.0 twine check --strict dist/*
|
|
52
|
+
- name: Smoke test the installed wheel outside the checkout
|
|
53
|
+
run: |
|
|
54
|
+
uv venv /tmp/duckpad-release-smoke
|
|
55
|
+
uv pip install --python /tmp/duckpad-release-smoke/bin/python dist/*.whl
|
|
56
|
+
uv run python scripts/smoke_wheel.py --python /tmp/duckpad-release-smoke/bin/python
|
|
57
|
+
- name: Calculate distribution checksums
|
|
58
|
+
working-directory: dist
|
|
59
|
+
run: sha256sum *.whl *.tar.gz > SHA256SUMS
|
|
60
|
+
- uses: actions/upload-artifact@v4
|
|
61
|
+
with:
|
|
62
|
+
name: release-bundle
|
|
63
|
+
path: |
|
|
64
|
+
dist/
|
|
65
|
+
release-notes.md
|
|
66
|
+
if-no-files-found: error
|
|
67
|
+
- uses: actions/upload-artifact@v4
|
|
68
|
+
if: failure()
|
|
69
|
+
with:
|
|
70
|
+
name: release-browser-diagnostics
|
|
71
|
+
path: frontend/test-results/
|
|
72
|
+
|
|
73
|
+
publish-pypi:
|
|
74
|
+
name: Publish to PyPI
|
|
75
|
+
needs: build
|
|
76
|
+
runs-on: ubuntu-latest
|
|
77
|
+
environment:
|
|
78
|
+
name: pypi
|
|
79
|
+
url: https://pypi.org/project/duckpad/${{ needs.build.outputs.version }}/
|
|
80
|
+
permissions:
|
|
81
|
+
id-token: write
|
|
82
|
+
steps:
|
|
83
|
+
- uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4
|
|
84
|
+
with:
|
|
85
|
+
name: release-bundle
|
|
86
|
+
- name: Verify and stage distributions
|
|
87
|
+
run: |
|
|
88
|
+
(cd dist && sha256sum --check SHA256SUMS)
|
|
89
|
+
mkdir packages
|
|
90
|
+
cp dist/*.whl dist/*.tar.gz packages/
|
|
91
|
+
- name: Publish with Trusted Publishing
|
|
92
|
+
uses: pypa/gh-action-pypi-publish@7245906fb61fa33a13554f9d5fb856fe61758086 # release/v1
|
|
93
|
+
with:
|
|
94
|
+
packages-dir: packages/
|
|
95
|
+
|
|
96
|
+
publish-github:
|
|
97
|
+
name: Publish GitHub release
|
|
98
|
+
needs: [build, publish-pypi]
|
|
99
|
+
runs-on: ubuntu-latest
|
|
100
|
+
permissions:
|
|
101
|
+
contents: write
|
|
102
|
+
steps:
|
|
103
|
+
- uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4
|
|
104
|
+
with:
|
|
105
|
+
name: release-bundle
|
|
106
|
+
- name: Publish notes and the exact PyPI artifacts
|
|
107
|
+
env:
|
|
108
|
+
GH_TOKEN: ${{ github.token }}
|
|
109
|
+
GH_REPO: ${{ github.repository }}
|
|
110
|
+
RELEASE_TAG: ${{ github.ref_name }}
|
|
111
|
+
PRERELEASE: ${{ needs.build.outputs.prerelease }}
|
|
112
|
+
run: |
|
|
113
|
+
(cd dist && sha256sum --check SHA256SUMS)
|
|
114
|
+
flags=()
|
|
115
|
+
if [[ "$PRERELEASE" == true ]]; then
|
|
116
|
+
flags+=(--prerelease --latest=false)
|
|
117
|
+
fi
|
|
118
|
+
gh release create "$RELEASE_TAG" dist/*.whl dist/*.tar.gz dist/SHA256SUMS \
|
|
119
|
+
--verify-tag --title "Duckpad $RELEASE_TAG" --notes-file release-notes.md "${flags[@]}"
|
duckpad-0.1.0/.gitignore
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
.venv/
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.pyc
|
|
4
|
+
.pytest_cache/
|
|
5
|
+
.ruff_cache/
|
|
6
|
+
node_modules/
|
|
7
|
+
dist/
|
|
8
|
+
src/duckpad/static/
|
|
9
|
+
.duckpad-dev/
|
|
10
|
+
test-results/
|
|
11
|
+
playwright-report/
|
|
12
|
+
*.egg-info/
|
|
13
|
+
.coverage
|
|
14
|
+
release-notes.md
|
|
15
|
+
*.tsbuildinfo
|
|
16
|
+
.multica/
|
|
17
|
+
.env
|
|
18
|
+
.env.*
|
|
19
|
+
!.env.example
|
duckpad-0.1.0/AGENTS.md
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# Repository Instructions
|
|
2
|
+
|
|
3
|
+
Before modifying files or preparing commits in this repository, read and follow
|
|
4
|
+
[the repository-conventions skill](.agents/skills/repository-conventions/SKILL.md).
|
|
5
|
+
Apply it to every change, even when it is not explicitly invoked.
|
|
6
|
+
|
|
7
|
+
- Write repository content in English, except localized UI values in dedicated
|
|
8
|
+
translation resource files, where French is allowed. Keep translation keys,
|
|
9
|
+
file names, code, comments, and documentation in English.
|
|
10
|
+
- Use Conventional Commits for every commit message, written in English.
|
|
11
|
+
|
|
12
|
+
## Multica development
|
|
13
|
+
|
|
14
|
+
Follow [the Multica workflow](docs/MULTICA.md) for issues handled through Multica.
|
|
15
|
+
Use a dedicated branch and pull request for every issue, deploy and verify its
|
|
16
|
+
preview, then wait for the designated human reviewer's explicit approval before merging into `main` and
|
|
17
|
+
publishing the merge to GitHub. Never interpret ticket creation or a successful
|
|
18
|
+
check as merge approval. Use `bash scripts/preview.sh` for Duckpad previews.
|
|
19
|
+
|
|
20
|
+
Keep private infrastructure details outside this public repository. Never include
|
|
21
|
+
personal domains, preview URLs, server names, deployment identifiers, or credentials
|
|
22
|
+
in tracked files, commits, GitHub pull requests, or public build output. Share
|
|
23
|
+
preview URLs only in the private Multica issue; retrieve deployment configuration
|
|
24
|
+
from the operator's private environment. Do not include credentials in tickets.
|
duckpad-0.1.0/Dockerfile
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
FROM node:22-bookworm-slim AS frontend
|
|
2
|
+
WORKDIR /build/frontend
|
|
3
|
+
COPY frontend/package.json frontend/package-lock.json ./
|
|
4
|
+
RUN npm ci
|
|
5
|
+
COPY frontend/ ./
|
|
6
|
+
RUN npm run build
|
|
7
|
+
|
|
8
|
+
# Prepared once on the preview server by scripts/provision-runtime.sh.
|
|
9
|
+
FROM duckpad-python:3.12-duckdb2.0.0 AS backend
|
|
10
|
+
WORKDIR /app
|
|
11
|
+
ENV UV_LINK_MODE=copy UV_PYTHON_DOWNLOADS=never
|
|
12
|
+
COPY pyproject.toml uv.lock README.md LICENSE .gitignore ./
|
|
13
|
+
RUN uv sync --locked --no-dev --no-install-project --no-build-package duckdb \
|
|
14
|
+
&& .venv/bin/python -c "import duckdb; assert duckdb.__version__ == '2.0.0'"
|
|
15
|
+
COPY scripts/build_hook.py scripts/build_hook.py
|
|
16
|
+
COPY src/ src/
|
|
17
|
+
COPY --from=frontend /build/src/duckpad/static/ src/duckpad/static/
|
|
18
|
+
RUN uv sync --locked --no-dev --no-editable --no-build-package duckdb
|
|
19
|
+
|
|
20
|
+
FROM python:3.12-slim-bookworm AS runtime
|
|
21
|
+
RUN apt-get update && apt-get install -y --no-install-recommends git ca-certificates libstdc++6 \
|
|
22
|
+
&& rm -rf /var/lib/apt/lists/* \
|
|
23
|
+
&& groupadd --gid 10001 duckpad \
|
|
24
|
+
&& useradd --uid 10001 --gid duckpad --home-dir /data --create-home duckpad
|
|
25
|
+
WORKDIR /app
|
|
26
|
+
COPY --from=backend /app/.venv/ /app/.venv/
|
|
27
|
+
# Public previews use HTTPS even though the private proxy hop uses HTTP.
|
|
28
|
+
ENV PATH="/app/.venv/bin:$PATH" PYTHONUNBUFFERED=1 DUCKPAD_SECURE_COOKIES=1
|
|
29
|
+
USER duckpad
|
|
30
|
+
EXPOSE 8765
|
|
31
|
+
HEALTHCHECK --interval=15s --timeout=5s --start-period=20s --retries=3 \
|
|
32
|
+
CMD python -c "import urllib.request; urllib.request.urlopen('http://127.0.0.1:8765/', timeout=4)"
|
|
33
|
+
CMD ["duckpad", "start", "--home", "/data/duckpad", "--host", "0.0.0.0", "--port", "8765", "--no-browser"]
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# Build context: the validated wheel directory, not the repository root.
|
|
2
|
+
FROM python:3.12-slim-bookworm
|
|
3
|
+
# Coolify's cleanup skips tagged images carrying this label.
|
|
4
|
+
LABEL coolify.managed="true" org.opencontainers.image.title="Duckpad portable DuckDB 2.0 runtime"
|
|
5
|
+
COPY --from=ghcr.io/astral-sh/uv:0.9.5 /uv /usr/local/bin/uv
|
|
6
|
+
RUN apt-get update && apt-get install -y --no-install-recommends libstdc++6 \
|
|
7
|
+
&& rm -rf /var/lib/apt/lists/*
|
|
8
|
+
COPY *.whl /tmp/duckdb-wheels/
|
|
9
|
+
RUN uv venv /app/.venv \
|
|
10
|
+
&& uv pip install --python /app/.venv/bin/python --no-index \
|
|
11
|
+
--find-links /tmp/duckdb-wheels duckdb==2.0.0 \
|
|
12
|
+
&& /app/.venv/bin/python -c "import duckdb; assert duckdb.__version__ == '2.0.0'; assert duckdb.sql('select 42').fetchall() == [(42,)]" \
|
|
13
|
+
&& rm -rf /tmp/duckdb-wheels
|
duckpad-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Hugues
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
duckpad-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: duckpad
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: A local SQL canvas with reproducible execution and cell lineage
|
|
5
|
+
License-Expression: MIT
|
|
6
|
+
License-File: LICENSE
|
|
7
|
+
Requires-Python: >=3.11
|
|
8
|
+
Requires-Dist: duckdb>=2.0
|
|
9
|
+
Requires-Dist: fastapi>=0.115
|
|
10
|
+
Requires-Dist: filelock>=3.18
|
|
11
|
+
Requires-Dist: psutil>=7.2
|
|
12
|
+
Requires-Dist: pydantic>=2.10
|
|
13
|
+
Requires-Dist: python-multipart>=0.0.20
|
|
14
|
+
Requires-Dist: sqlglot>=27
|
|
15
|
+
Requires-Dist: uvicorn>=0.34
|
|
16
|
+
Provides-Extra: dev
|
|
17
|
+
Requires-Dist: apscheduler<4,>=3.11; extra == 'dev'
|
|
18
|
+
Requires-Dist: build>=1.2; extra == 'dev'
|
|
19
|
+
Requires-Dist: git-cliff==2.14.2; extra == 'dev'
|
|
20
|
+
Requires-Dist: httpx>=0.28; extra == 'dev'
|
|
21
|
+
Requires-Dist: huey>=2.5; extra == 'dev'
|
|
22
|
+
Requires-Dist: pytest>=8; extra == 'dev'
|
|
23
|
+
Requires-Dist: ruff>=0.11; extra == 'dev'
|
|
24
|
+
Requires-Dist: sqlalchemy>=2; extra == 'dev'
|
|
25
|
+
Provides-Extra: integration
|
|
26
|
+
Requires-Dist: boto3>=1.38; extra == 'integration'
|
|
27
|
+
Requires-Dist: moto[server]>=5; extra == 'integration'
|
|
28
|
+
Requires-Dist: oracledb>=3; extra == 'integration'
|
|
29
|
+
Description-Content-Type: text/markdown
|
|
30
|
+
|
|
31
|
+
# Duckpad
|
|
32
|
+
|
|
33
|
+
Build local DuckDB pipelines on a visual canvas, inspect their results, and explain individual values back to their source cells. Duckpad combines a React/TypeScript interface with a Python/FastAPI execution service.
|
|
34
|
+
|
|
35
|
+
## Start
|
|
36
|
+
|
|
37
|
+
Requires **Python 3.11+ and Git** on `PATH`. Release wheels include the frontend, Monaco and its workers; Node.js is not needed to run the installed application.
|
|
38
|
+
|
|
39
|
+
```sh
|
|
40
|
+
pip install ./dist/duckpad-0.1.0-py3-none-any.whl
|
|
41
|
+
duckpad start
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
The distribution is named `duckpad`. Version tags publish the package to PyPI and create a GitHub release with Conventional Commit notes and downloadable distributions. After the first release, install it with `pip install duckpad`. See the [release guide](docs/RELEASING.md) for one-time publishing setup and tagging instructions.
|
|
45
|
+
|
|
46
|
+
Open the localhost address printed in the terminal. Sign in as `admin` using the password printed **once** on the first launch. The same password remains valid after a restart. The default instance directory is `$XDG_DATA_HOME/duckpad`, or `~/.local/share/duckpad`. Authentication, connection settings and execution history are kept there, outside project repositories.
|
|
47
|
+
|
|
48
|
+
```sh
|
|
49
|
+
duckpad start --home /path/to/my-instance --port 8765 --no-browser
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
Only one backend may own an instance directory at a time. Use separate `--home` directories for independent instances. The default address is `127.0.0.1`.
|
|
53
|
+
|
|
54
|
+
## Try the complete example
|
|
55
|
+
|
|
56
|
+
Choose **Open example project** and **Run pipeline**. The Northstar example creates CSV and Parquet inputs, joins customers to orders, computes ordered outputs, uses nested reusable components twice with separate parameters, computes aggregates, distinct counts, set operations and window ranks, and exports two CSV reports. Its `dev` and `prod` data are deliberately different.
|
|
57
|
+
|
|
58
|
+
Select **Regional revenue**, choose the `report` output, then click a revenue cell. Follow a contribution into the nested aggregate and page through its source amounts. No external accounts are required for this example. See the [example tour](docs/EXAMPLE.md).
|
|
59
|
+
|
|
60
|
+

|
|
61
|
+
|
|
62
|
+
## Included workflows
|
|
63
|
+
|
|
64
|
+
- Drag templates onto the canvas, connect ports, configure typed parameters, and edit shared SQL definitions in Monaco.
|
|
65
|
+
- Use guided filter, join-key and aggregate forms, or edit their generated SQL expressions.
|
|
66
|
+
- Preview, filter and sort results; explain valid cells with five contributions per page and complete counts.
|
|
67
|
+
- Group nodes into nested components, expose parameters, and import independent copies between projects.
|
|
68
|
+
- Save automatically to Git, inspect diffs, open isolated branches or historical revisions, and explicitly merge changes.
|
|
69
|
+
- Detect concurrent UI/file edits and resolve recoverable conflicts without losing either proposal.
|
|
70
|
+
- Recompute manually, stop active SQL, retain stale previews after failure, and inspect durable execution history.
|
|
71
|
+
- Configure reusable connections and environments outside project Git, with local, S3 and Oracle presets.
|
|
72
|
+
- Switch English/French and light/dark themes without changing the project.
|
|
73
|
+
- Monitor Duckpad server CPU and RAM as percentages with subtle background bars;
|
|
74
|
+
click for two minutes of history and RAM used / total in MiB or GiB. Samples
|
|
75
|
+
refresh every two seconds while the workspace is open; history resets on reload
|
|
76
|
+
or sign-out. Process memory comes from [psutil](https://psutil.io/platform/),
|
|
77
|
+
supporting Linux, macOS, and Windows. CPU includes all server threads, normalized
|
|
78
|
+
to the available CPU capacity (100% means fully used); RAM is current resident
|
|
79
|
+
memory divided by total capacity. CPU affinity and visible Linux cgroup v1/v2
|
|
80
|
+
limits constrain those capacities; otherwise system totals apply. Measurements
|
|
81
|
+
cover the Duckpad server process. Missing measurements are shown as unavailable.
|
|
82
|
+
|
|
83
|
+
Language defaults to the first supported language in your browser preferences
|
|
84
|
+
(English or French, with English as the fallback), and the theme defaults to your
|
|
85
|
+
system color scheme. Manual choices are saved in this browser and take priority
|
|
86
|
+
on subsequent visits.
|
|
87
|
+
|
|
88
|
+
Results live in memory per worktree and environment. After a backend restart, history remains available but previews and lineage require another manual run. Editing or changing an external source does not launch a run automatically.
|
|
89
|
+
|
|
90
|
+
## Develop and verify
|
|
91
|
+
|
|
92
|
+
```sh
|
|
93
|
+
bash scripts/setup.sh
|
|
94
|
+
uv run duckpad start --home .duckpad-dev --no-browser
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
For frontend development, `npm run dev --prefix frontend` proxies `/api` to the backend on port 8765.
|
|
98
|
+
|
|
99
|
+
```sh
|
|
100
|
+
uv run ruff check src tests scripts
|
|
101
|
+
uv run ruff format --check src tests scripts
|
|
102
|
+
uv run pytest -q
|
|
103
|
+
npm run check --prefix frontend
|
|
104
|
+
npm exec --prefix frontend -- playwright install chromium
|
|
105
|
+
npm run build --prefix frontend
|
|
106
|
+
npm run test:e2e --prefix frontend
|
|
107
|
+
uv build
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
The Playwright suite starts a disposable instance on port 8766. `DUCKPAD_CHROMIUM_EXECUTABLE` can point to an already installed Chromium executable. Building a release without compiled assets fails with an actionable message; editable installation permits building them afterward.
|
|
111
|
+
|
|
112
|
+
## Documentation
|
|
113
|
+
|
|
114
|
+
- [Release automation and publishing](docs/RELEASING.md)
|
|
115
|
+
- [Multica issue workflow and preview deployment](docs/MULTICA.md)
|
|
116
|
+
- [Architecture and execution invariants](docs/ARCHITECTURE.md)
|
|
117
|
+
- [Project files, templates and components](docs/AUTHORING.md)
|
|
118
|
+
- [Lineage coverage and limitations](docs/LINEAGE.md)
|
|
119
|
+
- [Connector setup and validated compatibility](docs/CONNECTORS.md)
|
|
120
|
+
- [Execution-service prototype and scheduling decision](docs/EXECUTION_SERVICE.md)
|
|
121
|
+
- [Validation results and performance reference](docs/VALIDATION.md)
|
|
122
|
+
|
|
123
|
+
The required dependency is `duckdb>=2.0`; the recorded validation uses **DuckDB 2.0.0 on Linux x86_64**. Oracle needs a matching OraDuck extension and Oracle Instant Client. S3 validation uses a local S3 emulator; live AWS IAM, TLS and deployment-specific behavior need their own integration checks. Details and reproducible commands are in the connector guide.
|
duckpad-0.1.0/README.md
ADDED
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
# Duckpad
|
|
2
|
+
|
|
3
|
+
Build local DuckDB pipelines on a visual canvas, inspect their results, and explain individual values back to their source cells. Duckpad combines a React/TypeScript interface with a Python/FastAPI execution service.
|
|
4
|
+
|
|
5
|
+
## Start
|
|
6
|
+
|
|
7
|
+
Requires **Python 3.11+ and Git** on `PATH`. Release wheels include the frontend, Monaco and its workers; Node.js is not needed to run the installed application.
|
|
8
|
+
|
|
9
|
+
```sh
|
|
10
|
+
pip install ./dist/duckpad-0.1.0-py3-none-any.whl
|
|
11
|
+
duckpad start
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
The distribution is named `duckpad`. Version tags publish the package to PyPI and create a GitHub release with Conventional Commit notes and downloadable distributions. After the first release, install it with `pip install duckpad`. See the [release guide](docs/RELEASING.md) for one-time publishing setup and tagging instructions.
|
|
15
|
+
|
|
16
|
+
Open the localhost address printed in the terminal. Sign in as `admin` using the password printed **once** on the first launch. The same password remains valid after a restart. The default instance directory is `$XDG_DATA_HOME/duckpad`, or `~/.local/share/duckpad`. Authentication, connection settings and execution history are kept there, outside project repositories.
|
|
17
|
+
|
|
18
|
+
```sh
|
|
19
|
+
duckpad start --home /path/to/my-instance --port 8765 --no-browser
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
Only one backend may own an instance directory at a time. Use separate `--home` directories for independent instances. The default address is `127.0.0.1`.
|
|
23
|
+
|
|
24
|
+
## Try the complete example
|
|
25
|
+
|
|
26
|
+
Choose **Open example project** and **Run pipeline**. The Northstar example creates CSV and Parquet inputs, joins customers to orders, computes ordered outputs, uses nested reusable components twice with separate parameters, computes aggregates, distinct counts, set operations and window ranks, and exports two CSV reports. Its `dev` and `prod` data are deliberately different.
|
|
27
|
+
|
|
28
|
+
Select **Regional revenue**, choose the `report` output, then click a revenue cell. Follow a contribution into the nested aggregate and page through its source amounts. No external accounts are required for this example. See the [example tour](docs/EXAMPLE.md).
|
|
29
|
+
|
|
30
|
+

|
|
31
|
+
|
|
32
|
+
## Included workflows
|
|
33
|
+
|
|
34
|
+
- Drag templates onto the canvas, connect ports, configure typed parameters, and edit shared SQL definitions in Monaco.
|
|
35
|
+
- Use guided filter, join-key and aggregate forms, or edit their generated SQL expressions.
|
|
36
|
+
- Preview, filter and sort results; explain valid cells with five contributions per page and complete counts.
|
|
37
|
+
- Group nodes into nested components, expose parameters, and import independent copies between projects.
|
|
38
|
+
- Save automatically to Git, inspect diffs, open isolated branches or historical revisions, and explicitly merge changes.
|
|
39
|
+
- Detect concurrent UI/file edits and resolve recoverable conflicts without losing either proposal.
|
|
40
|
+
- Recompute manually, stop active SQL, retain stale previews after failure, and inspect durable execution history.
|
|
41
|
+
- Configure reusable connections and environments outside project Git, with local, S3 and Oracle presets.
|
|
42
|
+
- Switch English/French and light/dark themes without changing the project.
|
|
43
|
+
- Monitor Duckpad server CPU and RAM as percentages with subtle background bars;
|
|
44
|
+
click for two minutes of history and RAM used / total in MiB or GiB. Samples
|
|
45
|
+
refresh every two seconds while the workspace is open; history resets on reload
|
|
46
|
+
or sign-out. Process memory comes from [psutil](https://psutil.io/platform/),
|
|
47
|
+
supporting Linux, macOS, and Windows. CPU includes all server threads, normalized
|
|
48
|
+
to the available CPU capacity (100% means fully used); RAM is current resident
|
|
49
|
+
memory divided by total capacity. CPU affinity and visible Linux cgroup v1/v2
|
|
50
|
+
limits constrain those capacities; otherwise system totals apply. Measurements
|
|
51
|
+
cover the Duckpad server process. Missing measurements are shown as unavailable.
|
|
52
|
+
|
|
53
|
+
Language defaults to the first supported language in your browser preferences
|
|
54
|
+
(English or French, with English as the fallback), and the theme defaults to your
|
|
55
|
+
system color scheme. Manual choices are saved in this browser and take priority
|
|
56
|
+
on subsequent visits.
|
|
57
|
+
|
|
58
|
+
Results live in memory per worktree and environment. After a backend restart, history remains available but previews and lineage require another manual run. Editing or changing an external source does not launch a run automatically.
|
|
59
|
+
|
|
60
|
+
## Develop and verify
|
|
61
|
+
|
|
62
|
+
```sh
|
|
63
|
+
bash scripts/setup.sh
|
|
64
|
+
uv run duckpad start --home .duckpad-dev --no-browser
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
For frontend development, `npm run dev --prefix frontend` proxies `/api` to the backend on port 8765.
|
|
68
|
+
|
|
69
|
+
```sh
|
|
70
|
+
uv run ruff check src tests scripts
|
|
71
|
+
uv run ruff format --check src tests scripts
|
|
72
|
+
uv run pytest -q
|
|
73
|
+
npm run check --prefix frontend
|
|
74
|
+
npm exec --prefix frontend -- playwright install chromium
|
|
75
|
+
npm run build --prefix frontend
|
|
76
|
+
npm run test:e2e --prefix frontend
|
|
77
|
+
uv build
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
The Playwright suite starts a disposable instance on port 8766. `DUCKPAD_CHROMIUM_EXECUTABLE` can point to an already installed Chromium executable. Building a release without compiled assets fails with an actionable message; editable installation permits building them afterward.
|
|
81
|
+
|
|
82
|
+
## Documentation
|
|
83
|
+
|
|
84
|
+
- [Release automation and publishing](docs/RELEASING.md)
|
|
85
|
+
- [Multica issue workflow and preview deployment](docs/MULTICA.md)
|
|
86
|
+
- [Architecture and execution invariants](docs/ARCHITECTURE.md)
|
|
87
|
+
- [Project files, templates and components](docs/AUTHORING.md)
|
|
88
|
+
- [Lineage coverage and limitations](docs/LINEAGE.md)
|
|
89
|
+
- [Connector setup and validated compatibility](docs/CONNECTORS.md)
|
|
90
|
+
- [Execution-service prototype and scheduling decision](docs/EXECUTION_SERVICE.md)
|
|
91
|
+
- [Validation results and performance reference](docs/VALIDATION.md)
|
|
92
|
+
|
|
93
|
+
The required dependency is `duckdb>=2.0`; the recorded validation uses **DuckDB 2.0.0 on Linux x86_64**. Oracle needs a matching OraDuck extension and Oracle Instant Client. S3 validation uses a local S3 emulator; live AWS IAM, TLS and deployment-specific behavior need their own integration checks. Details and reproducible commands are in the connector guide.
|