sequenceDiagram
autonumber
actor Author
participant Lesson
box rgb(255, 214, 216) The Workbench
participant {sandpaper}
participant {pegboard}
participant {varnish}
end
Author ->> {sandpaper}: sandpaper::serve()
activate Author
{sandpaper} --) Author: website preview
note left of {sandpaper}: monitor for changes
Author ->> Lesson: make an edit
deactivate Author
Lesson -->> {sandpaper}: READ changed file(s)
{sandpaper} -->> {pegboard}: validate Lesson
activate {pegboard}
note left of {sandpaper}: provision global menu elements
{pegboard} --) Author: report accessibility
deactivate {pegboard}
activate {sandpaper}
note left of {sandpaper}: WRITE markdown
{varnish} -->> {sandpaper}: load and apply website template
note left of {sandpaper}: WRITE website
{sandpaper} --) Author: website preview
deactivate {sandpaper}
1 Introduction
The core of The Carpentries Workbench consists of three packages:
- {sandpaper}: user interface and workflow engine
- {pegboard}: parsing and validation engine
- {varnish}: HTML templates, CSS, and JS elements
These packages are all available and released to the Carpentries R-Universe, which checks for updates to the source packages hourly.
These packages are also compiled into a Docker image that are used in GitHub Actions within many lesson repositories, providing a consistent route to building lessons via Continuous Integration (CI). This Docker image can also be used locally.
1.1 Building Lessons
The Workbench takes standard markdown or Rmarkdown files, and renders them into consistent and reproducible HTML pages.
{sandpaper} manages the heavy lifting of this process when calling sandpaper::serve() or sandpaper::build_lesson(). The interaction between the three Workbench packages, the lesson content, and the author can be summarised like this where the author makes an edit:
This content is a general picture of what happens between the packages. For a more in-depth discussion and more detailed diagrams, please visit the Flow Diagrams page.
In terms of folder structure, the workflow runs the two-step workflow to first render markdown files into site/built and then uses those files to render the HTML, CSS, and JavaScript into site/built. These workflows are detailed in The Workflows Chapter.
flowchart TB
classDef default color:#383838,fill:#FFF7F1,stroke-width:1px
classDef external color:#383838,fill:#E6EEF8,stroke-width:1px
classDef normal color:#081457,fill:#E3E6FC,stroke-width:1px
classDef local fill:#FFC700,stroke:#333,stroke-width:1px
classDef remote fill:#D2BDF2, color:#201434,stroke-width:1px
SERVE("serve()"):::normal
BLESS("build_lesson()"):::normal
subgraph "Core Workflow"
BUILT["site/built"]:::local
SITE["site/docs"]:::local
VLESS("validate_lesson()"):::normal
BUILDMD(["build_markdown()"]):::normal
BUILDSITE(["build_site()"]):::normal
end
%%BUILT ~~~ SITE
SERVE --> BLESS
%% SERVE ~~~ VLESS
%% SERVE ~~~ BUILDMD
BLESS --> VLESS
VLESS -.- BUILDMD
BLESS --> BUILDMD
BUILDMD --> BUILT
BUILT -.- BUILDSITE
VLESS -.- BUILDSITE
BLESS --> BUILDSITE
BUILDSITE --> SITE
The names of the folders inside site/ are considered internal resources and they can change at any time. The final website output is held in site/docs/ - this is a historic artifact of using the {pkgdown} package to provision the website without needing to bundle the templates inside of {sandpaper}.
The site/docs folder contains the full website that can be safely used offline. This is the core of the workflow and is used both locally and in a remote setting. The only difference with the remote setting is that we use Git to provision the markdown cache without needing to store it in the default branch.
1.2 Building Lessons Remotely (e.g. on GitHub)
In the remote workflow, we still use the same workflow as above, except now we use sandpaper::ci_deploy(). This links the branches and folders using “worktrees”, which are basically Git branches assigned to separate folders.
The workflows used to build lessons on GitHub can be found in the {sandpaper} inst/workflows folder. These workflows are present in any lesson repository that wants to automate build and deployment management.
At the time of developing the Workbench, GitHub was the most widely used platform for social coding that represented the easiest way for newcomers to contribute to our lessons. We used this knowledge to build the workflows for the lessons on GitHub, but we were also aware of the valid criticisms of GitHub and the dangers of vendor lock-in.
Thus, while the lessons are deployed using GitHub workflows and we have features that handle pull requests and updates, the core deployment features remain platform-independent. The workflows are merely instructions that we provide for GitHub to set up the workbench and to run the individual functions. In theory, any platform can be configured to deploy lessons via The Workbench.
In fact, in a pinch when GitHub workflows are not working properly, a lesson maintainer could run sandpaper:::ci_deploy() to render and deploy a local copy of the lesson.
flowchart TB
classDef default color:#383838,fill:#FFF7F1,stroke-width:1px
classDef external color:#383838,fill:#E6EEF8,stroke-width:1px
classDef normal color:#081457,fill:#E3E6FC,stroke-width:1px
classDef local fill:#FFC700,stroke:#333,stroke-width:1px
classDef remote fill:#D2BDF2,stroke:#201434,stroke-width:1px
classDef notouch fill:#F99697,stroke:#A4050E,stroke-width:1px
GH[("@main")]:::remote
MDOUT[("@md-outputs")]:::notouch
PAGES[("@gh-pages")]:::notouch
DEPLOY(["ci_deploy()"]):::external
CIBUILDMD(["ci_build_markdown()"]):::external
CIBUILDSITE(["ci_build_site()"]):::external
subgraph virtual machine
REPO["[repo]"]:::local
BUILT["[repo]/site/built"]:::local
SITE["[repo]/site/docs"]:::local
VLESS("validate_lesson()"):::normal
BUILDMD(["build_markdown()"]):::normal
BUILDSITE(["build_site()"]):::normal
end
GH ---> REPO
GH ~~~ DEPLOY
REPO -.- VLESS
DEPLOY ---> VLESS
DEPLOY ---> CIBUILDMD
DEPLOY ---> CIBUILDSITE
VLESS -.- BUILDMD
CIBUILDMD ---> MDOUT
MDOUT <-.-> BUILT
CIBUILDMD ---> BUILDMD
CIBUILDSITE ---> PAGES
PAGES <-.-> SITE
CIBUILDSITE ---> BUILDSITE
BUILT -.- BUILDSITE
VLESS -.- BUILDSITE
BUILDMD --> BUILT
BUILDSITE --> SITE
1.3 Development of the Workbench
Development of the Workbench is overseen by members of the Carpentries Core Team. Currently, the lead maintainer of the Workbench packages and documentation is Rob Davey, Director of Technology for The Carpentries. The Workbench was originally developed by Zhian Kamvar.
New features are added incrementally as pull requests. Pushes to the main branch are rare and discouraged. New features must have tests associated with them (with the exception of {varnish}).
For more information, please see the documentation for the release process.
1.4 Documentation
Reference documentation for individual functions for each package is written alongside the function using {roxygen2}.
This documentation is generated by devtools::document()
1.5 Testing
Tests for each package live in tests/testthat/ and follow a test-[file-name].R naming convention. These are controlled by the {testthat} package and run by devtools::test().
You can find more information about testing the core packages in Testing The Workbench
1.6 Continous Integration
The continous integration for each package tests on Ubuntu, MacOS, and Windows systems with a selection of the most recent versions of R (same as the RStudio convention).
More information about the Continous Integration can be found in the Continuous Integration section of the testing section.
Coming up:
- Testing Pull Requests (Locally and on your fork)
- Resources for R package development
- Adding functionality to {sandpaper}
- Adding functionality to {pegboard}
- Adding styling elements to {varnish}
- Adding functionality to carpentries/actions
- GitHub Actions and Docker