solidarity
solidarity copied to clipboard
Support Other Backend Languages
I recently wrote a similar project for Elixir. If we want to use solidarity
for Elixir backend (or other) projects, there are some changes we would need to make.
As I see it, solidarity
's core concept can be divided into three parts:
- Rule file
- Plugins
- Validator
Rule File
The config file format must be able to specify the following kinds of checks for backend projects:
- [x] Existence of
binary
in$PATH
- [x] Version of
binary
in$PATH
- [x] Existence of
ENV
variable - [x] Existence of file at filesystem path
- [ ] Conditional on ENV. Web environments require different checks in each environment. Checks must be able to be made conditional on ENV values.
- For example,
elasticsearch
and Postgres are on separate hardware in production - The existing
platform
option is not a good fit for this, because we can't assume that dev environments will not be Linux.
- For example,
Plugins
Plugins that generate configuration files (snapshots) for a given language or framework should be written in that language. There are several reasons for this.
-
They can easily read their own, proprietary configuration.
For example, if my
solidarity-elixir
plugin were written in Elixir, I could reliably determine which Elixir version to require in the.solidarity
file.Mix.Project.get().project()[:elixir] "~> 1.5"
If my
solidarity-elixir
plugin were not written in Elixir, I'd have to a) assume where the project config files are, (not always in the same place) and b) use an unreliable regex scan on the files, since I could not interpret them. In contrast, the Elixir app already knows all of this stuff when it boots. -
Idiomatic, tight integration. If my plugin is written in my target language, I can provide idiomatic features and interfaces for it that my target audience expect. (For example,
mix
orrake
tasks for Elixir or Ruby developers) This will boost adoption.- This also allows plugins to provide native functions which users can call at runtime or when their app boots
-
Easier plugin maintenance. The author of an Elixir or Ruby on Rails plugin already knows those languages and can most easily maintain a plugin in those languages. This will lead to higher adoption because you don't have to maintain javascript code in order to maintain a plugin.
Validator
Backend projects must run the validator at the following times:
- [ ] Compile-time. Backend apps must fail to compile/deploy if the production server has invalid configuration. This prevents broken code from making it to production and embarrassing bugs.
- [ ] Run-time. Configuration values can be removed at will from a backend server, without recompiling the code. Therefore, the validator must also run when the app boots. The app should still boot if configuration is invalid, but an error should be reported to Honeybadger, etc.
The validator must also have:
- [ ] Zero runtime dependencies. We cannot assume the presence of the Node runtime for Elixir (or other) backend apps, because:
- Not all Elixir apps use Node. Many are backend-only.
- When Node is used, it is only used at compile-time, not run-time. (This is also true for Ruby on Rails)
- Elixir (and other language devs) will resist adding the entire Node runtime to their dev/prod stack just so they can use
solidarity
. This will result in low-to-no adoption outside the javascript community.
Proposal
- [ ] Rewrite the validator binary in a language that has zero runtime dependencies, with the following API:
-
solidarity [optional file]
- Loads
.solidarity
file at designated location, if provided. Otherwise, assumes project root. - Parse file
- Validate each configuration rule with a system command
- Returns 0 if all successful
- Returns 1 if one or more checks failed, printing a list of all failed checks
- Loads
-
solidarity [optional file] --dry-run
- Prints a list of the exact system commands that solidarity will use to validate configuration.
- This will be useful for debugging.
- Returns 0
-
solidarity merge [file a] [file b]
- Merges
file a
, a solidarity config file, withfile b
, another solidarity config file. - Returns 0 if successful, removes
file b
- Returns 1 if failed, prints reason, leaves files in place
- This allows plugins to generate their own solidarity file, which will then be merged into the main file for the project. Plugins only care about their own rules, and don't have to worry about merging them with the existing file.
- Plugin runs, creates
.solidarity-plugin-name
file - Plugin calls
solidarity merge
, which merges changes and removes the plugin file.
- Plugin runs, creates
- Merges
-
solidarity --help
- Displays help
- Returns 0
-
solidarity --version
- Returns the current version of
solidarity
- Returns 0
- Returns the current version of
- This API is very limited and simple, and should be easy to achieve in Go or Rust despite our team's limited familiarity with them.
-
- [ ] Move existing
snapshot
and javascript-specific plugin functionality to a plugin:solidarity-javascript
- [ ] Document how to make a plugin
- When installed, each plugin would download the zero-dependencies
solidarity
binary from the mainsolidarity
repo's releases - Each language would get to define its own
snapshot
extraction logic and functionality in its plugin, as described above. - Each plugin would be responsible to build its snapshot to
.solidarity-plugin-name
, and then callsolidarity merge .solidarity .solidarity-plugin-name
- When installed, each plugin would download the zero-dependencies
@GantMan and I talked about it, and a cause for some hesitation was that in rewriting the validator, we would lose access to the features provided by Gluegun. But I suggested that we could sacrifice those features in order to get the benefits of adoption and features of the target-language, as you mentioned above, @danielberkompas.
We would also be able to keep the Gluegun features for any JavaScript-based plugins by keeping the JS validator. It could either be included in the general validator, or moved to its own project and repo; I don't know which would make more sense.
I'm interested in helping out with this. Gant mentioned that GO would be an appropriate language for the validator, so I might go learn that after any further soon discussion.
@danielberkompas Please, take a look https://github.com/iegik/solidarity-bash