Prerequisites: pixi for environment management.
git clone --recurse-submodules <repo>
cd sirius
pixi shell # activate environment
CMAKE_BUILD_PARALLEL_LEVEL=$(nproc) makeIf you create a new git worktree, initialize submodules manually:
git submodule update --init --recursive# C++ unit tests
build/release/extension/sirius/test/cpp/sirius_unittest
# Run a specific tag or test name
build/release/extension/sirius/test/cpp/sirius_unittest "[cpu_cache]"
build/release/extension/sirius/test/cpp/sirius_unittest "test_cpu_cache_basic_string_single_col"
# SQL logic tests (end-to-end)
make testTest logs are written to build/release/extension/sirius/test/cpp/log/.
Sirius uses pre-commit hooks for formatting and linting. Install them once after cloning:
pre-commit installTo run all checks manually:
pre-commit run -aTools enforced: clang-format (C++/CUDA), black (Python), cmake-format, codespell, and
rumdl (Markdown links and anchors).
The duckdb/, duckdb-python/, and vcpkg/ directories are third-party submodules. Their CONTRIBUTING.md files apply to contributing to those upstream projects, not to Sirius. Do not modify submodule contents directly.
When the C++ unit test job fails or times out, the workflow automatically uploads log artifacts to GitHub Actions. Download them from the Summary tab of the failed run.
| Artifact | Contents | Retained |
|---|---|---|
unittest-logs-<run_id> |
Sirius log files from the failing test run | 14 days |
tpch-run-<run_id> |
TPC-H benchmark comparison and validation CSV | 14 days |
- Open the failed GitHub Actions run
- Scroll to the Artifacts section at the bottom of the Summary tab
- Click the artifact name to download a zip
- The unit test log is at
sirius_<YYYY-MM-DD>.loginside the zip
- The last test number logged before output stops — this is the test that hung or crashed
- Any CUDA error messages preceding the hang
- Stack traces if the binary aborted
Sirius uses CODEOWNERS to automatically route PRs to the right reviewers based on the files changed. Reviewers are assigned from component teams (e.g. sirius-core, sirius-io) — one member per team via load balancing. You do not need to manually request reviewers.
Approval from any maintainer is sufficient to merge — it does not have to be the auto-assigned reviewer.
The component teams can also be mentioned directly in PR comments and issues to bring the right people into a discussion without a Slack ping — useful when you need expert input on a specific area:
| Team | Components |
|---|---|
@sirius-db/sirius-core |
Planner, Executors, Operators & Expressions |
@sirius-db/sirius-io |
Scan & I/O, Memory & Compression |
@sirius-db/sirius-integrations |
Integrations |
@sirius-db/sirius-telemetry |
Telemetry & Observability |
@sirius-db/sirius-cmake |
CMake |
@sirius-db/sirius-build |
CI & Build |
@sirius-db/sirius-docs |
Documentation |
@sirius-db/sirius-rust |
Rust |
@sirius-db/sirius-python |
Python |
When you open or update a PR, you will also be automatically assigned as the author. This helps maintainers track ownership and is not a request for you to review your own work.
Sirius uses Self-contained PRs submitted from contributor forks as our primary method of contributing to Sirius. There are two approved exceptions, both restricted to Maintainers: Stacked PRs as a secondary contribution method, and break-glass CI & Critical changes.
| PR Type | PR Author | Push To | Reasoning |
|---|---|---|---|
| Primary - Self-contained | Any Contributor | Personal fork | This allows all contributors to submit PRs from their forks, keeping the main repo focused on development, releases, and Stacked PRs |
| Secondary - Stacked PRs (dependent changes) | Only Maintainers | sirius-db/sirius repo with stacked/ prefix for branch names |
Stacked PRs help developers contribute larger changes to the code base in smaller pieces that are easier to review and have fewer conflicts compared to a single large PR. See Stacked PRs below for more information |
| Break-glass - CI & Critical | Only Maintainers | sirius-db/sirius repo |
By exception there may be CI and Critical PRs that must be pushed to this repo if there are CI tests or other triggers necessary before merging; examples: workflow_dispatch and certain workflows using secrets and tokens not available in forks |
NOTE: Branches of PRs pushed to the main repo and personal forks are cleaned up automatically; this repo has "Automatically delete head branches" enabled, so merged branches don't need manual deletion.
sirius-db/sirius repo in order to work. Currently
this development option is restricted to Maintainers. If you are interested in becoming a
maintainer, see GOVERNANCE.md for details.
For a chain of dependent changes, Sirius uses the gh-stack
gh CLI extension — it's the only supported tool for stacked PRs. Don't use Graphite,
git-spice, ghstack, or similar; a mix of tools operating on the same branches will conflict.
If needed, follow these instructions to install GitHub CLI.
# Install Stacked PRs extension
gh extension install github/gh-stack- Every branch in a stack must be prefixed
stacked/(e.g.stacked/docs-contributing-gh-stacks) so stacked work is identifiable and groupable, separate from regular single-branch PRs. stacked/-prefixed branches may be pushed directly toorigin(this repo)- If you are working on a local copy that is your fork, you will need to ensure
originpoints to this repo and not your fork. - This is a workaround for gh-stack#381, where
gh stack's--remoteflag doesn't actually control which repo it operates against, onlyorigindoes. Once that's fixed upstream, this remote-renaming step should no longer be necessary. - Run the following command replacing
$USERwith your name; otherwise it will use your local username:# Rename current origin to local user's name and set origin to main Sirius repo git remote rename origin $USER git remote add origin "git@github.com:sirius-db/sirius.git"
- If you are working on a local copy that is your fork, you will need to ensure
See gh stack --help for the full set:
gh stack init stacked/<branch1> stacked/<branch2> ... # create a new stack
gh stack add stacked/<branch> # add a branch on top of the current stack
gh stack submit # push all branches and create/update PRs
gh stack sync # rebase and sync the stack with GitHubMove between layers without typing branch names:
gh stack top # check out the top branch (furthest from dev)
gh stack bottom # check out the bottom branch (closest to dev)
gh stack up # check out one branch up (further from dev)
gh stack down # check out one branch down (closer to dev)
gh stack trunk # check out dev
gh stack switch # interactively pick a branch in the stackgh stack checkout <stack-number|PR-number|PR-URL|branch> resumes a stack you don't currently
have checked out, for example one someone else started or one you left a while ago.
gh stack modify opens an interactive editor to reorder, insert, drop, or fold branches in a
stack, useful if a stack's layering needs to change after the fact.
Adding layers to a stack
gh stack CLI can manage the stack, adding layers as needed with gh stack add stacked/<branch>.
This can also be done in the Web UI by clicking on the stack icon (next to the PR status button,
in the top left of the PR page). There you can see the full stack of PRs, and an option to add
to the stack.
Collaborating with existing stacks
Any Maintainer can use gh stack checkout <PR-number> to check out an existing stack to contribute
code or to manage the stack during the "bottom-up" merge process.
Managing conflicts
During active development of the stack, always use gh stack rebase to manage conflicts with dev
or between your stacked layers. If you have submitted your stack, run gh stack submit to push
these changes to the repo and open PRs.
Conflicts can also occur while merging "bottom-up" as described below. The two-step process above
can be shortened to gh stack sync --prune during merging to handle the merge conflicts between
the stack layers as they are merged.
Rebase stack notifications
GitHub's support for stacked PRs includes a "Rebase stack" option in the Web UI when the target base
(usually dev) has moved forward; it is not recommended to use this method.
NOTE: CI and the merge queue both test the combined merge commit of the PR and the latest
dev before merging. Rebasing is not necessary unless there is a conflict. If you have a conflict,
follow the instructions in Managing conflicts.
Unstacking PRs
Sometimes it may be necessary to unstack PRs. This can be done in the CLI with
gh stack unstack or in the Web UI clicking on the stack icon and selecting the stack icon with
an "x" labeled "Unstack pull requests." Both methods remove the stack and convert the PRs to
self-contained PRs targeting dev.
Note: each PR's page always shows "wants to merge into <branch>" pointing at the layer
directly below it; that's just its git base for diffing, not the actual merge order. Merges
always land bottom-up regardless of what that header displays.
gh stack merge (CLI). We tested both
against this repo's actual merge queue settings (1 PR built and merged at a time) and confirmed
they do not reliably merge the whole stack through. This is a tested limitation of GitHub's
support for merge queues using squash commits. Until this is fixed, we can use the following
bottom-up merging method in this repo.
Merging bottom-up
Steps 1-4 and 7 only need GitHub Web UI, so any maintainer with merge permission can do them, not just the stack's author. Steps 5-6 need a local checkout with the stack tracked to manage (see Managing a stack above).
- Web UI - Open the bottom-most unmerged PR of the stack (the stack panel on any PR in it,
click the
N/Mbadge next to the PR title, shows the whole stack in order). - Web UI - Confirm it's approved and its required checks have passed.
- Web UI - Click "Enqueue pull request" on that PR's own page to
merge just that one PR. Do not click "Enqueue stack" (this is only on the top-most layer of
the stack) and don't use
gh stack merge. - Web UI - Wait for it to clear the merge queue and merge to
dev. GitHub automatically retargets the next layer's base todevonce the branch it was targeting is deleted; no manual action is needed for the retargeting. - GH CLI - If the next layer's PR now shows "This branch has conflicts that must be
resolved" / "Unable to merge", run
gh stack sync --pruneto rebase the remaining branches onto the updateddevand clean up local branches for the merged PR. Always resolve stack conflicts via the CLI. - GH CLI - Confirm it worked via
gh stack view: the merged layer should show a✓under a╌╌╌ merged ╌╌╌marker, and the remaining branches shouldn't show a⚠warning icon. If they still do, repeat step 5. - Web UI - Open the new bottom-most unmerged PR and repeat from step 2, until the whole stack is merged.
Our goal is to automate this process in the future; however, this is the current merge method that works with our repo's merge queue settings.
PRs sometimes stall for weeks after a reviewer is assigned, simply because the PR wasn't actually ready to review the moment CODEOWNERS pinged someone. Before marking a PR ready for review, please do the following:
- State the motivation, not just the mechanics. Link the originating issue (
Closes #NNN/Refs #NNN) if one exists; if there isn't one, the description itself should explain why the change is needed, not just summarize the diff. - Scope the PR to one reviewable sitting. If a reviewer can't get through it start-to-finish without losing context, either split it (see Stacked PRs) or explicitly justify in the description why it can't be split.
- Make the description self-sufficient. A reviewer should be able to start reviewing without needing to ask what changed or why — cover what changed, why, how it was verified, and anything non-obvious (e.g. "intentionally doesn't handle X, tracked in #NNN").
- Open as a draft until 1-3 are actually true, then convert to "Ready for review" — that's
the point CODEOWNERS review requests and author auto-assignment (
auto-assign.yml) trigger, so converting early means a reviewer gets pinged before there's anything reviewable yet.
Sirius squash-merges PRs, the PR titles become the commit message on merge. Commits and PR titles follow Conventional Commits format for readability.
Example of Conventional Commits:
<type>[optional scope]: <description>
[optional body]
[optional footer(s)]
Scope is optional — use it when the change is clearly localized to a subsystem (e.g. fix(join):, ci(distribution):), omit it for cross-cutting changes.
New contributors: put your best title — reviewers will help refine it before merge.
If your PR changes any Sirius configuration option:
- Document the change inline where the config lives (code comments, settings files)
- Summarize the change in the PR description for reviewers and the changelog