Contributing to FielDHub
Source:CONTRIBUTING.md
First of all, thanks for considering contributing to FielDHub! 👍 It’s people like you that make it rewarding for us - the project maintainers - to work on FielDHub. 😊
FielDHub is an open-source project, maintained by people who care.
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.
How you can contribute
There are several ways you can contribute to this project. If you want to know more about why and how to contribute to open source projects like this one, see this Open Source Guide.
Share the love ❤️
Think FielDHub is useful? Let others discover it, by telling them in person, via Twitter or a blog post.
Using FielDHub for a paper you are writing? Consider citing it.
Ask a question ⁉️
Using FielDHub and got stuck? Browse the documentation to see if you can find a solution. Still stuck? Post your question as an issue on GitHub. While we cannot offer user support, we’ll try to do our best to address it, as questions often lead to better documentation or the discovery of bugs.
Want to ask a question in private? Contact the package maintainer by email.
Propose an idea 💡
Have an idea for a new FielDHub feature? Take a look at the documentation and issue list to see if it isn’t included or suggested yet. If not, suggest your idea as an issue on GitHub. While we can’t promise to implement your idea, it helps to:
- Explain in detail how it would work.
- Keep the scope as narrow as possible.
See below if you want to contribute code for your idea as well.
Report a bug 🐛
Using FielDHub and discovered a bug? That’s annoying! Don’t let others have the same experience and report it as an issue on GitHub so we can fix it. A good bug report makes it easier for us to do so, so please include:
- Your operating system name and version (e.g. Mac OS 10.13.6).
- Any details about your local setup that might be helpful in troubleshooting.
- Detailed steps to reproduce the bug.
Improve the documentation 📖
Noticed a typo on the website? Think a function could use a better example? Good documentation makes all the difference, so your help to improve it is very welcome!
The website
This website is generated with pkgdown. That means we don’t have to write any html: content is pulled together from documentation in the code, vignettes, Markdown files, the package DESCRIPTION and _pkgdown.yml settings. If you know your way around pkgdown, you can propose a file change to improve documentation. If not, report an issue and we can point you in the right direction.
Function documentation
Functions are described as comments near their code and translated to documentation using roxygen2. If you want to improve a function description:
- Go to
R/directory in the code repository. - Look for the file that holds the function: an exported function
f()is inR/fct_f.R(see Source layout for the other files). -
Propose a file change to update the function documentation in the roxygen comments (starting with
#').
Contribute code 📝
Care to fix bugs or implement new functionality for FielDHub? Awesome! 👏 Have a look at the issue list and leave a comment on the things you want to work on. See also the development guidelines below.
Development guidelines
From the repository root, run source("dev/run_dev.R") to load the source package and start the app. This path does not need a configuration file, detach packages, clear your workspace, or regenerate documentation. Stop the app normally before reloading changed source. Installed-package users run FielDHub::run_app(). The standard app dependencies are installed with the package. The root app.R returns the app object for source-based Shiny deployment.
Regenerate documentation separately with devtools::document() when changing roxygen comments. Rscript --vanilla tools/check-launchers.R . checks both entry-script contracts without starting a server or changing the R session.
We try to follow the GitHub flow for development.
- Fork this repo and clone it to your computer. To learn more about this process, see this guide.
- If you have forked and cloned the project before and it has been a while since you worked on it, pull changes from the original repo to your clone by using
git pull upstream master. - Open the RStudio project file (
.Rproj). - Make your changes:
- Add a plain-R regression test that fails before fixing a defect, then implement the fix. Keep scientific logic out of Shiny modules; do not add Shiny server or browser tests.
- Run the full tests with
NOT_CRAN=true FIELDHUB_GOLDEN=true. Golden snapshots are recorded on macOS. Review deliberate scientific output changes and announce affected inputs in NEWS; never accept snapshots blindly. - For output-preserving refactors, compare complete fixed-seed results with the previous implementation using
identical(). Preserve supplied labels, field-book column types, RNG state, and process options. - Document your code (see function documentation above).
- Run
R CMD check --as-cran, build the UI without starting a session, and inspect the completed check log. A development-version NOTE is expected; other findings require investigation. Correctness lint and core coverage are also checked in CI.
- Commit and push your changes.
- Submit a pull request.
Design pages must never be blank while a requested operation is running. Run and Randomize need a centered spinner and short status inside each result tab’s content area, including queued background jobs. The loading state replaces that tab’s content until it is ready; do not add a banner above or outside the tabs. Tab switching must keep the feedback visible in the selected tab without forced scrolling. Plots and tables also need output-loading indicators. Clear task feedback on success, validation failure, worker failure and disconnection; show an explanation for errors. Do not rely only on output-recalculation spinners for asynchronous work, or display a percentage unless the operation reports real progress. Verify these states in a real browser; keep automated tests at the plain-helper and UI-contract level.
Maintainers follow the release checklist, including the full R and platform matrix, reconstruction checks, deployment validation, and reviewed performance benchmarks. Use a minor release for deliberate API or behavior changes; keep migration guidance alongside the change. The deployment guide documents the locked Docker build and distinguishes source checks from verified image execution.
Scientific changes also need independent count, geometry, or numerical checks. Use the plain helpers in tests/testthat/helper-invariants.R, specify expected levels from the inputs (including missing groups), and include corrupted fixtures to prove the checks detect failures. See the scientific validation guide for the family-by-family checks, reference calculations, and computational limits.
Source layout
Read the architecture and compatibility guide and the step-by-step design/format extension guide before adding a new engine or format. The Latin rectangle is a complete registry-driven example, including the shared app page and independent tests.
The .mailmap normalizes display-name aliases using an already shared email address. Propose other identity mappings with the contributor’s confirmation; do not guess from similar names or rewrite historical commits. The release owner and independent reviewer are agreed by maintainers for each release.
Each file in R/ is named <prefix>_<topic>.R. The prefix says what the file is responsible for; the topic says what it holds (for example engine_diagonal_checks.R, layout_planting_path.R, result_methods.R).
| Prefix | Responsibility |
|---|---|
fct_ |
exported design engines (one per exported function) |
engine_ |
internal randomization/allocation/optimization helpers |
layout_ |
field coordinates, planting paths, layout options |
render_ |
drawing only (desplot/ggplot/heatmap data) |
io_ |
uploads, exports, archives |
validate_ |
input validators and parsers |
result_ |
result constructor, schema, S3 methods, reproduction |
sim_ |
response simulation |
api_ |
cross-cutting public documentation |
app_, mod_
|
Shiny layer only |
- A
fct_file is named after its exported function (fct_RCBD.RholdsRCBD()). Helpers used only by that function may sit beside it. - Exception: the allocation and pair-swap result builders (
new_fieldhub_allocation(),validate_fieldhub_allocation(),new_fieldhub_optimization(),validate_fieldhub_optimization()) live infct_do_optim.Randfct_swap_pairs.R, not inresult_files. Each validator reads the arguments of its engine (formals(do_optim),formals(swap_pairs)), so aresult_file would depend on thefct_file that depends on it.fct_reproduce_design.Rcalls both validators. -
api_files hold roxygen documentation only:api_vocabulary.R(argument names) andapi_result_contract.R(the structure of every result, shared by all designs, so it isapi_rather thanresult_). -
app_/mod_files hold the Shiny wiring. Plain helpers the app uses (reading an input, preparing a simulation or an export) live in core prefixes, where they are unit-tested and count toward core coverage. Core files (every other prefix) never refer toapp_/mod_code and make noshiny,DT,bsliborshinyjscalls. - Dependencies between files go one way: no file may depend, directly or through other files, on a file that depends on it. When two files call each other, move the mutually dependent functions into one file, or into a lower layer that both use.
- R loads these files in alphabetical order, so top-level code (such as
x <- f()) may only use objects defined above it in the same file.
Two files are exceptions:
-
globals.Rdeclares the column names used in non-standard evaluation. -
run_app.Rholdsrun_app(), the exported launcher of the Shiny app.
Tests live in tests/testthat/test_<topic>.R and are plain R: never Shiny server or browser tests. test_source_layout.R checks this layout (prefixes, one fct_ file per exported function, no core reference to the Shiny layer, no dependency cycle between core files). Structural checks that must also run under R CMD check, where R/ is not installed, inspect the namespace with core_functions() and app_functions() from helper-source.R. The core coverage gate in CI (inst/ci/compare-core-coverage.R) measures every R/ file except app_*, mod_* and run_app.R.
Attribution
This Contributing is adapted from CONTRIBUTING.