Contributing to metasurvey.core
Source:CONTRIBUTING.md
Thank you for your interest in contributing to metasurvey.core, the local engine of the metasurvey ecosystem. This document outlines how to propose changes, report bugs, and contribute code.
Bug reports
If you find a bug, please file an issue on GitHub with a minimal reproducible example using the reprex package.
Include:
- A description of the expected behavior vs. actual behavior.
- The output of
sessionInfo(). - A minimal dataset, or use
make_test_survey()from the test helpers.
If the bug involves the remote registry, the Shiny explorer, ANDA downloads, or the STATA transpiler, it likely belongs in a companion package — see the ecosystem table to find the right repository.
Feature requests and improvements
Use GitHub Discussions to propose new features, improvements, and ideas. Post in the “Ideas” category with a clear description of the problem and your proposed solution. Issues are reserved for confirmed bugs.
Development environment
git clone https://github.com/metasurveyr/metasurvey.core.git
cd metasurvey.core
# Install dependencies
Rscript -e 'pak::local_install_dev_deps()'
# Install pre-commit hooks (requires Python 3)
pip3 install pre-commit
pre-commit installThe usual devtools cycle applies:
devtools::document() # regenerate man/ and NAMESPACE
devtools::test() # run the test suite (1500+ tests)
devtools::check() # full R CMD checkPre-commit hooks
Pre-commit runs automatically on every commit (see .pre-commit-config.yaml). Among other things, the hooks format R code with styler::tidyverse_style(), lint against .lintr, spell-check documentation against inst/WORDLIST, and block artifacts like .RData or private keys. Roxygen docs are not regenerated by the hooks: run devtools::document() yourself before committing (CI checks that man/ and NAMESPACE are up to date).
Architecture
The main files in R/ (not exhaustive):
R/
├── survey.R # Survey R6 class
├── PanelSurvey.R # RotativePanelSurvey + PoolSurvey R6 classes
├── Step.R # Step R6 class (lazy transformation unit) + bake_steps()
├── steps.R # step_*() functional API: compute, recode, rename,
│ # remove, join, filter, validate, quantile, ...
├── Recipes.R # Recipe R6 class + read_recipe()
├── RecipeWorkflow.R # RecipeWorkflow R6 class
├── RecipeRegistry.R # Local (JSON) recipe registry
├── WorkflowRegistry.R # Local (JSON) workflow registry
├── RecipeAPI.R # RecipeBackend class ("local" + injectable "api")
├── WorkflowBackend.R # WorkflowBackend class ("local" + injectable "api")
├── backend-provider.R # .backend_api_call() hook for remote providers
├── recipe_tidy_api.R # Tidy search/filter API for recipes
├── workflow_tidy_api.R # Tidy search/filter API for workflows
├── workflow.R # workflow() — svymean/svytotal/svyratio/svyby
├── workflow_table.R # Tabular output for workflow results
├── load_survey.R # Survey loading helpers
├── harmonize.R # Cross-edition harmonisation
├── provenance.R # Variable provenance tracking
├── set_engine.R # Processing engine selection
├── utils.R # Package options (use_copy, lazy_processing, ...)
└── meta.R # .onLoad hooks and package messages
Key patterns:
-
Lazy evaluation:
step_*()functions record but don’t execute. Callbake_steps()to materialize. -
data.table everywhere: internal data ops use
data.tablesyntax, neverdplyr. Use:=,set(),merge.data.table(). -
No rlang: all metaprogramming uses base R (
substitute(),eval(),match.call()). rlang is prohibited. -
R6 classes: PascalCase names,
$initialize(),$print(),$clone(). Step functions are functional wrappers that create Step objects internally. -
Copy semantics: the
use_copyoption controls whether steps clone data. DefaultTRUEfor safety. Useset_data()instead of$data <-assignment. -
Local only: this package must work with no network access. Anything that talks to a remote service belongs in a companion package and reaches core only through the
.backend_api_call()provider hook.
Pull requests
- Fork the repo and create a branch from
main. - Run
pre-commit run --all-filesto check code quality. - Add or update tests in
tests/testthat/. - Run
devtools::test()and ensure all tests pass. - Run
devtools::check()and fix any warnings or notes. - Submit a PR to
main.
Code style
- Use
data.tablesyntax for internal data operations. - Follow existing naming conventions:
step_*for step functions, R6 classes use PascalCase. - Keep functions focused and avoid over-engineering.
- No rlang — use base R metaprogramming only.
Testing
- Use testthat edition 3.
- Test helpers are in
tests/testthat/helper-survey.R(make_test_survey(),make_test_panel()). - Integration tests that need external data should use
skip_on_cran(). -
print()calls in tests are fine (used to test R6$print()methods).
Code of Conduct
Please note that this project is released with a Contributor Code of Conduct. By participating in this project you agree to abide by its terms.