33 Commits

Author SHA1 Message Date
db39
c381d6f7ef Build Debian package using CircleCI ARM executor (#1588)
Resolves #1584 

We've been using Docker+QEMU to emulate 32-bit ARM on AMD64, but this PR
switches to ARM-native CircleCI instances, which skips the emulation.

This achieves a speedup on building Debian packages from about 4m down
to about 70s.

Because Debian package building is fast again, we're changing our CI
workflow to build a Debian package on every commit rather than just on
`master` or just when we manually trigger it.

<a data-ca-tag
href="https://codeapprove.com/pr/tiny-pilot/tinypilot/1588"><img
src="https://codeapprove.com/external/github-tag-allbg.png" alt="Review
on CodeApprove" /></a>

---------

Co-authored-by: Michael Lynch <git@mtlynch.io>
2023-08-29 17:05:03 +01:00
Michael Lynch
a2a7bc4d46 Get rid of uStreamer capture device Ansible vars (#1554)
Resolves https://github.com/tiny-pilot/tinypilot/issues/1501
Resolves #1267

This change gets rid of the `ustreamer_capture_device` Ansible var
(TC358743 vs. HDMI to USB) and the config file where we stored the
result. Instead, we'll track capture device based on whether
`dtoverlay=tc358743` appears in `/boot/config.txt`.

In theory, relying on `/boot/config.txt` will cause incorrect behavior
if a user enables the TC358743 overlay even though they're using HDMI to
USB. That's unlikely to happen in practice, so I think it's worth the
tradeoff, as this assumption eliminates a **lot** of complexity.

As a side-effect of eliminating `ustreamer_capture_device`, we can
remove a lot of cruft from the bundle install file.

### Background

We originally added the "uStreamer settings file" because we needed a
way to keep track of whether the device was using a HDMI to USB dongle
(like a DIY TinyPilot) or a TC358743-based HDMI to CSI chip (like a
Voyager).

At the time of the original implementation, the uStreamer Ansible role
was independent of TinyPilot, so it couldn't write to TinyPilot
settings. So, we created a "uStreamer settings file" at
`/home/ustreamer.config.yml` that would essentially persist the setting
for whether the system was TC358743-based so that the initiator of the
Ansible role wouldn't have to re-specify it every time.

### Implementation notes

* I'm broadening the scope a little bit by tackling #1267 at the same
time, but I feel like the major cost of both those issues is the testing
to make sure everything is correct, so I might as well fix and test both
at the same time.
* With this change, the Ansible role no longer adds the
`dtoverlay=tc358743` line to `/boot/config.txt` because it's now the
user's responsibility to do that in advance if they've got a DIY
TinyPilot with an HDMI to CSI chip. For Pro, Packer will take
responsibility for adding that line.
  * The Ansible role still adds the `dtoverlay=tc358743-audio` line.
* `bundler/bundle/install` used to be responsible for creating
`/home/tinypilot/settings.yml` if it didn't already exist, but this
change moves that responsibility to `tinypilot.postinst`.
* I'm deliberately leaving a `debug` task in the Ansible role because I
think it's helpful to have the output in logs.
* This change drops the `ustreamer_persistent` var and instead always
launches ustreamer with the `--persistent` flag. The setting used to be
unofficially configurable via settings, but we're dropping that
configurability (see
https://github.com/tiny-pilot/tinypilot-pro/issues/972).

### Documentation impact

After we merge this, we need to update our
[wiki](https://github.com/tiny-pilot/tinypilot/wiki/Installation-Options#example-tc358743-hdmi-to-csi-capture-chip)
with the new TC358743 install method, which should simplify down to:

```bash
if ! grep --silent '^dtoverlay=tc358743$' /boot/config.txt; then
  echo 'dtoverlay=tc358743' | sudo tee --append /boot/config.txt
fi
```

Corresponding changes in Pro:
https://github.com/tiny-pilot/tinypilot-pro/compare/no-capture-pro?expand=1
(difference is just Packer config)

### Manual tests

I performed the following manual tests to verify we're not breaking
functionality.

- [x] Verify TinyPilot Community install with HDMI to USB dongle
- [x] Verify TinyPilot Community install with HDMI to CSI bridge
- [x] Verify TinyPilot Pro Hobbyist image
- [x] Verify TinyPilot Pro Voyager image
- [x] Verify installing TinyPilot Pro bundle on top of TinyPilot Pro
2.6.0 Voyager image
- [x] Verify installing TinyPilot Pro bundle on top of TinyPilot Pro
2.6.0 Hobbyist image

<a data-ca-tag
href="https://codeapprove.com/pr/tiny-pilot/tinypilot/1554"><img
src="https://codeapprove.com/external/github-tag-allbg.png" alt="Review
on CodeApprove" /></a>
2023-08-21 08:56:11 -04:00
Jason Wallace
ecc15fa8b9 Migrate to less-frequently-used ports (#1562)
Resolves https://github.com/tiny-pilot/tinypilot/issues/1551

A TinyPilot device uses ports that are also popular with other
applications. This PR migrates our production ports to make them less
likely to collide with other apps:
* TinyPilot port `8000` to port `48000`
   * In dev mode, we still use port `8000`

fa560f4ca7/dev-scripts/serve-dev (L12-L14)
* uStreamer port `8001` to port `48001`
* Janus port `8002` to port `48002`


<a data-ca-tag
href="https://codeapprove.com/pr/tiny-pilot/tinypilot/1562"><img
src="https://codeapprove.com/external/github-tag-allbg.png" alt="Review
on CodeApprove" /></a>
2023-08-11 12:45:47 +02:00
Jason Wallace
04c0772148 Fix instructions on how to manually trigger a bundle build (#1561)
Resolves https://github.com/tiny-pilot/tinypilot/issues/1548

This PR moves the comments that explains how to trigger a code-based
bundle build from `.circleci/config.yml` to
`.circleci/continue_config.yml` and updates the contributing docs to
reference the correct CircleCI config file.

So the correct ways to [manually trigger a bundle
build](1ea663b0ee/CONTRIBUTING.md (installing-a-nightly-bundle))
is either the:
1. Code-based way
> 1. In [the CircleCI configuration](/.circleci/continue_config.yml),
change the `bundle_build_branch` parameter’s `default` value from
`master` to `<< pipeline.git.branch >>`.
> 1. Push your changes as branch to GitHub. CircleCI will now
automatically build bundles for all subsequent commits of that branch.
> 1. Before eventually merging your feature branch, remember to revert
the `bundle_build_branch` parameter to the original value (i.e.,
`master`)
3. CircleCI web UI way
> 1. On CircleCI’s overview page for the respective branch, click the
“Trigger Pipeline” button.
> 1. In the dialog, enter `bundle_build_branch` as parameter name, and
the (exact) name of the branch as parameter value.
> 1. Click the “Trigger Pipeline” button in the dialog. CircleCI will
now build a bundle for the latest commit of that branch.

<a data-ca-tag
href="https://codeapprove.com/pr/tiny-pilot/tinypilot/1561"><img
src="https://codeapprove.com/external/github-tag-allbg.png" alt="Review
on CodeApprove" /></a>
2023-08-10 12:36:25 +02:00
jotaen4tinypilot
3bc5477751 Upgrade Python from 3.7 to 3.9 (#1531)
Part of https://github.com/tiny-pilot/tinypilot-pro/issues/1002.

[Debian Bullseye ships with Python
3.9](https://packages.debian.org/bullseye/python3), so it’s safe for us
to upgrade our Python requirement from 3.7 to 3.9.

I’ve also fixed the URL anchor in the comment in `db/store.py`, which
was outdated.
<a data-ca-tag
href="https://codeapprove.com/pr/tiny-pilot/tinypilot/1531"><img
src="https://codeapprove.com/external/github-tag-allbg.png" alt="Review
on CodeApprove" /></a>
2023-07-27 15:25:56 +02:00
Michael Lynch
e845e1165b Document how we upgrade pip packages (#1528)
<a data-ca-tag
href="https://codeapprove.com/pr/tiny-pilot/tinypilot/1528"><img
src="https://codeapprove.com/external/github-tag-allbg.png" alt="Review
on CodeApprove" /></a>
2023-07-26 14:04:15 -04:00
jotaen4tinypilot
9200d4edfc Trigger one-off bundle build directly via CircleCI (#1518)
Currently, when we want to build a bundle off a PR, we need to
temporarily push a [code change in the Circle
configuration](b20762c924/.circleci/continue_config.yml (L10-L13)),
similar to
dde6828649.
Once we are done with testing, we need to revert that Circle config
change, before merging the PR eventually.

I just discovered that there is a way to trigger the complete build
pipeline on the fly, **without** having to push any code changes:

1. On [CircleCI’s overview page for the respective
branch](https://app.circleci.com/pipelines/github/tiny-pilot/tinypilot?branch=circle-manual-trigger),
click the “Trigger Pipeline“ button, which opens a dialog
2. As parameter, enter `bundle_build_branch` as parameter name, and the
current branch name as value, in this case `circle-manual-trigger`
3. Click the “Trigger Pipeline” button

<img width="1234" alt="Screenshot 2023-07-20 at 19 30 57"
src="https://github.com/tiny-pilot/tinypilot/assets/83721279/7b108baa-7442-430a-97ec-b4b1f6afac75">

The prerequisite for this to work is that we additionally declare the
`bundle_build_branch` parameter in the top-level `config.yml` file, and
not just in the `continue_config.yml` file. Otherwise, CircleCI wouldn’t
recognize the manual trigger parameter, and refuse to run the pipeline.

I think this would be a useful option for us, especially in order to run
one-off builds on the fly. The “old” method would continue to work, so
it’s only an additional method.
<a data-ca-tag
href="https://codeapprove.com/pr/tiny-pilot/tinypilot/1518"><img
src="https://codeapprove.com/external/github-tag-allbg.png" alt="Review
on CodeApprove" /></a>
2023-07-21 17:26:30 +02:00
jotaen4tinypilot
f85eb6a134 Upgrade NodeJS runtime and npm dependencies (#1480)
Part of https://github.com/tiny-pilot/tinypilot/issues/1395.

This PR upgrades the NodeJS runtime to the latest available LTS version,
which [is 18.16.1 currently](https://nodejs.org/en). It also upgrades
most npm dependencies to their latest versions. The only exception is
Prettier, because Prettier obviously changed their formatting rules in a
later version, so I’ll do that in [a follow-up
PR](https://github.com/tiny-pilot/tinypilot/pull/1481).

In regards to the Playwright Circle image, I chose the one that was
closest to what we need, based on the same logic outlined in the comment
(which I also updated).
<a data-ca-tag
href="https://codeapprove.com/pr/tiny-pilot/tinypilot/1480"><img
src="https://codeapprove.com/external/github-tag-allbg.png" alt="Review
on CodeApprove" /></a>
2023-07-05 12:48:23 +02:00
jotaen4tinypilot
067de1f829 Document how to activate bundle building on CI (#1472)
Bundles are no longer built automatically off feature branches, so [we
have to manually trigger this via a one-line change in the CircleCI
config](https://github.com/tiny-pilot/tinypilot/pull/1442). This PR
updates the documentation and describes the procedure.

Along the way, I also changed the list numbering style from `1. 2. 3.`
to `1. 1. 1.`. I think that’s how we generally seem to be doing it in
Markdown files, and it spares us from having to update all consecutive
numbers when prepending a new bullet.
<a data-ca-tag
href="https://codeapprove.com/pr/tiny-pilot/tinypilot/1472"><img
src="https://codeapprove.com/external/github-tag-allbg.png" alt="Review
on CodeApprove" /></a>
2023-06-29 15:06:37 +02:00
Michael Lynch
7c25815df6 Backport end-to-end tests to TinyPilot Community (#1451)
This is code that we already reviewed and merged into Pro, but it would
be useful in Community as well.

The only change here from what's already in Pro is
fd616979e1 as we're adjusting the test for
Community.

<a data-ca-tag
href="https://codeapprove.com/pr/tiny-pilot/tinypilot/1451"><img
src="https://codeapprove.com/external/github-tag-allbg.png" alt="Review
on CodeApprove" /></a>

---------

Co-authored-by: Andrew Farrell <123831+amfarrell@users.noreply.github.com>
Co-authored-by: Andrew M. Farrell <armorsmith42@gmail.com>
2023-06-16 07:45:22 -04:00
jotaen4tinypilot
a0a21115a5 Document dev workflows for testing on device (#1414)
Resolves https://github.com/tiny-pilot/tinypilot/issues/1073.

In our discussion in the [previous draft
PR](https://github.com/tiny-pilot/tinypilot/pull/1407) around dev
scripts and workflow documentation for remote testing, we realized that
it might be too tricky for us to provide easy-to-use dev scripts that
work in all environments and setups out of the box.

We could still add such dev scripts at a later point. For now, this PR
updates and extends our documentation. I think that’s also a good way to
share tips and workflows (although it’s prose), and to align ones own
workflows with best practices that others are using. I tried to cover
all topics that I could think of, and that appeared useful or important
to me. The structure is more or less loose, but I thought it makes sense
to group things into sections.

I also removed the section on SSH agent forwarding. This should be
obsolete since we abandoned the git-based update workflow.

If there is anything else that we can add, please let me know.
<a data-ca-tag
href="https://codeapprove.com/pr/tiny-pilot/tinypilot/1414"><img
src="https://codeapprove.com/external/github-tag-allbg.png" alt="Review
on CodeApprove" /></a>
2023-06-03 20:14:16 +02:00
Michael Lynch
0f241f384b Set up TinyPilot virtual environment from Debian package (#1352)
This change integrates the
[dh-virtualenv](https://github.com/spotify/dh-virtualenv) extension to
debhelper to install TinyPilot's Python virtual environment as part of
the Debian package install.

This seemed like it would be easy, but it turned out to be fairly
complicated. Putting the virtualenv into the Debian package makes the
Debian package architecture-specific, so we have to spin up QEMU and
manage architecture-specific bits throughout the build process.

## What this PR does

### Reduces disk writes on customer devices

The advantage of this change is that on customer devices, this reduces
disk writes. Instead of installing/compiling Python packages on the
device, most of that work is done ahead of time, so we're putting less
wear on the customer's microSD.

### Speeds up installs/updates

Similarly to the reduction in disk writes, it should speed up installs.
We don't have to go through the install process for the virtualenv on
the end-user's device because the packages are pre-provisioned in the
Debian package.

### Reduces Ansible code

This change continues our "war on Ansible," reimplementing Ansible logic
as Debian package logic.

### Makes TinyPilot's Debian package architecture-dependent

Previously, the TinyPilot Debian package could declare an architecture
of `all` because it didn't contain any native binaries. Using
`dh-virtualenv` means that TinyPilot's third-party libraries are now
packaged inside the Debian package, and some of the dependencies are
architecture-dependent, which means the package as a whole is
architecture dependent.

### Only builds AMD64 in PRs

Because we have to emulate ARMv7 from CI, this change slows down Debian
package building significantly. It's about a 20x slowdown, increasing
build time for the Debian package from ~30s to ~6m.

I considered building in ARM on CircleCI, but we need 32-bit ARM, and
CircleCI only supports 64-bit.

>We currently do not provide support for 32-bit Arm architectures. Only
64-bit arm64 architectures are supported at this time.

https://circleci.com/docs/using-arm/#limitations

With that in mind, we now only build AMD64 in PRs and ARMv7+AMD64 in
master/releases.

## Notes

### Lintian Override Syntax

I find the documentation for [Lintian
overrides](https://lintian.debian.org/manual/index.html#overrides)
really confusing. I got the overrides by copying errors from Lintian and
pasting them into the overrides. What I put in doesn't seem to match
Lintian's documented syntax, but when I try to adjust the overrides to
match my understanding of the documentation, the overrides fail.

### Debian package hardening

In an effort to resolve a [`hardening-no-relro` lintian
issue](https://app.circleci.com/pipelines/github/tiny-pilot/tinypilot/3386/workflows/aaa8762f-0791-4805-b2aa-14663ece04dd/jobs/18387?invite=true#step-106-19),
I enabled [Debian package
"hardening"](https://wiki.debian.org/Hardening#Using_Hardening_Options):

79fe3e6a37/debian-pkg/debian/rules (L3-L6)
But to be honest, I don't know what it really does for our package. It
didn't resolve the lintian issue, but it seems to be something to do
with package security, so I kept it in.

### `install-from-source` script

To get the `install-from-source` script working again, I mostly just
needed to [clean out previous ansible
roles](4ebe94a86b/bundler/create-bundle (L75-L77))
before creating the bundle.

<a data-ca-tag
href="https://codeapprove.com/pr/tiny-pilot/tinypilot/1352"><img
src="https://codeapprove.com/external/github-tag-allbg.png" alt="Review
on CodeApprove" /></a>

---------

Co-authored-by: Jan Heuermann <github-jotaen4tinypilot@reg.jotaen.net>
Co-authored-by: Jason Wallace <jdeanwallace@gmail.com>
2023-06-02 16:12:50 +02:00
jotaen4tinypilot
6582b394b4 Abandon remote scripts (for dev workflow) (#1388)
Part of https://github.com/tiny-pilot/tinypilot/issues/1073.

We had only one “remote script”, `pull`, which doesn’t work anymore
since it’s based on the now sunsetted git-based update mechanism. It
seems we haven’t really used it anyway, so however our dev workflow will
be, it should be safe to delete the “remote scripts”.
<a data-ca-tag
href="https://codeapprove.com/pr/tiny-pilot/tinypilot/1388"><img
src="https://codeapprove.com/external/github-tag-allbg.png" alt="Review
on CodeApprove" /></a>
2023-05-11 16:39:06 +02:00
Michael Lynch
d1522cca99 Move style guide documentation to dedicated repo (#1309)
Corresponds with: https://github.com/tiny-pilot/style-guides/pull/1
<a data-ca-tag
href="https://codeapprove.com/pr/tiny-pilot/tinypilot/1309"><img
src="https://codeapprove.com/external/github-tag-allbg.png" alt="Review
on CodeApprove" /></a>
2023-02-13 09:00:21 -05:00
Michael Lynch
efe00c1cf8 Adjust dev instructions so they work on Python >= 3.7 (#1301)
Our dev instructions hardcoded the Python version to 3.7. Let's just
make it Python 3 and trust that the user followed the instructions to
install 3.7 or higher.
<a data-ca-tag
href="https://codeapprove.com/pr/tiny-pilot/tinypilot/1301"><img
src="https://codeapprove.com/external/github-tag-allbg.png" alt="Review
on CodeApprove" /></a>
2023-02-08 11:32:25 -05:00
Jason Wallace
70d2dd5888 Create bundle using local ansible-role directory. (#1286)
Resolves https://github.com/tiny-pilot/tinypilot/issues/1174

This PR bundles the local `ansible-role` directory into the TinyPilot
bundle file and corrects the documentation that previously referenced
the [`ansible-role-tinypilot`
repo](70321141a8).

### Notes

* After merging this PR, we can safely archive the
[`ansible-role-tinypilot`
repo](70321141a8)
(as readonly)
* I have successfully tested the [build
bundle](https://app.circleci.com/pipelines/github/tiny-pilot/tinypilot/2964/workflows/e69ad101-634a-48b1-a345-6c4bced166e5/jobs/13760/artifacts)
on a device running Raspberry Pi OS Lite Buster

<a data-ca-tag
href="https://codeapprove.com/pr/tiny-pilot/tinypilot/1286"><img
src="https://codeapprove.com/external/github-tag-allbg.png" alt="Review
on CodeApprove" /></a>
2023-02-03 17:38:08 +02:00
Michael Lynch
9c45a76b8c Add convenience script for installing TinyPilot from local code (#1242)
I've found during development, it's sometimes convenient to clone the
repo and make changes directly on the device and then install those
changes. This script automates the process of installing TinyPilot from
the local repo.

This also makes it a little easier for newcomers to the project to make
changes and then test the changes on a real device. Before the update
overhaul, `quick-install` let users do that, but then the update
overhaul brought Gatekeeper into the install path, which prevents users
from installing their own code. This allows users to easily install
their own code again.

Related: #1246

<a data-ca-tag
href="https://codeapprove.com/pr/tiny-pilot/tinypilot/1242"><img
src="https://codeapprove.com/external/github-tag-allbg.png" alt="Review
on CodeApprove" /></a>
2023-01-04 17:37:40 -05:00
jotaen4tinypilot
2a8eef7d5b Clarify coding conventions on underscore prefix (#1101)
Co-authored-by: Jan Heuermann <jan@jotaen.net>
2022-09-19 17:39:44 +02:00
Michael Lynch
7adddf0a53 Use Prettier to format all non-Python files (#1041)
* Use Prettier to format all non-Python files

* Update fix instructions

* Add comment for check-style script
2022-06-30 13:04:28 -04:00
Jason Wallace
183eaf2e1a Add element naming conventions to CONTRIBUTING.md. (#895)
* Add element naming conventions to CONTRIBUTING.md.

* Fix whitespace.

* Add review changes.
2022-01-28 12:53:11 +02:00
rw4nn
8cb498af1b Add the states pattern to contributing guidelines + update style guide (#804) 2021-10-21 14:13:43 +02:00
Michael Lynch
7ec5e87c6b Document TinyPilot's conventions for web components (#791)
* Document TinyPilot's conventions for web components

* Revise text

* Fix quotation marks

* Clarify wording

* Add section on parameterizing style rules

* Fix code snippet termination

* Add a link for shadow DOM and clarify wording
2021-09-16 10:15:44 -04:00
Jan Heuermann
7e8731d778 Setup unit tests for the frontend (#772)
* Keep track of FE dependencies in `package.json` file

* Setup unit tests with Mocha

* Fix Circle config

* Pin dependencies to the exact version

* Upgrade NodeJS to the latest available LTS

* Add FE test script to `build` script

* Replace dummy test with real one
2021-08-25 16:03:08 +02:00
Jason Wallace
19d18448cf Load keyboard and mouse paths from Flask config file (#754)
* Add app settings file.

* Remove helper functions.

* Remove references to the KEYBOARD_PATH & MOUSE_PATH env vars.

* Add app_settings.cfg to gitignore.
2021-08-18 14:11:15 +02:00
Jan Heuermann
d3d15d5cbb Proposal: reduce build/test feedback loop through remote procedures (#725)
* Setup remote script for pulling and running a specific revision

* Execute git operations with root user (to make use of ssh agent forwarding)

* Make sure we don’t overwrite non-commited changes

* Describe basic SSH setup for testing on real device

* Correct paht

* Improve instructions

* Always fetch from all remotes

* Don’t rely on the root user, but support all users with passwordless sudo permissions
2021-06-24 18:43:13 +02:00
Michael Lynch
40a66870f1 Update URLs for new TinyPilot org (#724)
* Update URLs for new TinyPilot org

I've moved tinypilot from mtlynch/tinypilot to tiny-pilot/tinypilot, so this makes all the URLs match the new location.

* Fix spelling of tiny
2021-06-08 08:16:10 -04:00
Michael Lynch
19ba09589f Update URL for ansible-role-tinypilot (#719)
The role has moved from mtlynch/ansible-role-tinypilot to tiny-pilot/ansible-role-tinypilot, and we're no longer using Ansible Galaxy.

Related: https://github.com/mtlynch/ansible-role-tinypilot/pull/137
2021-06-02 17:30:11 -04:00
Michael Lynch
5ad43ceea1 Move documentation of environment variables to CONTRIBUTING.md (#621)
They aren't really something an end-user should change. They are more useful to developers working on the code.

For end-users, the preferred way to change options is through the settings.yml file and advanced installation (linked to in the README).
2021-03-24 16:51:30 -04:00
Michael Lynch
a3806db374 Move pull request template to CONTRIBUTING.md (#617)
The PR template is meant for new contributors, but it pops up for every PR, even from regular contributors. It's creating too much of a cost for regular developers and buying too little with newcomers, so I'm getting rid of the PR template.
2021-03-24 13:58:41 -04:00
Jason Wallace
c803358913 Add ShellCheck to Circle CI config. (#569)
* Add shellcheck.

* Fix circleci config.

* Apply shellcheck recommendations.

* Fix check-bash.

* Globally ignore SC1091.

* Cleanup.
2021-03-13 00:55:06 +02:00
Michael Lynch
c799b89c9b Add mock scripts for development (#566)
* Add mock scripts for development

This enables TinyPilot developers to mock out two privileged functions during development:

* Change hostname
* Collect debug logs

Once the developer enables mock scripts on their system, they can use these two features and have it work (sort of) like it works on a real device.

This still leaves a few functions unmocked:

* Shutdown/restart (because we call those by absolute path to system scripts, we can't mock them out)
* Update: The update logic is pretty complex and involves launching a systemd process, so it's non-trivial to mock this out.

Related: #501

* Handle case where /opt/tinypilot-privileged is a real directory
2021-03-10 15:05:39 -05:00
Michael Lynch
86ecd3b16c Clarify CONTRIBUTING.md to say we no longer obey Google JS style (#542)
Fixes #537
2021-03-02 17:20:55 -05:00
Michael Lynch
51c14265be Add more developer documentation (#476)
Add CONTRIBUTING.md and ARCHITECTURE.md docs to the repo.

Credit to this blog post for inspiration: https://matklad.github.io//2021/02/06/ARCHITECTURE.md.html

Fixes #440
2021-02-09 09:16:53 -05:00