Your project should include the following:
README.md
– external description and documentation, as defined above.
notes/
folder). Don’t make ‘README-[subcomponent].md, or
path/to/[subcomponent]/README.md`.LICENSE.md
– we usually use the Apache 2.0 license. If the project is internal, it should state ‘all rights reserved’.
CHANGELOG.md
– update with changes before pushing a new version
TODO.md
– known issues and nitpicks.
notes/
– a git submodule
d version of the project’s wiki
examples/
data/
Guardfile
, Procfile
notes/
directoryThe notes/
a git submodule
d version of the project’s wiki. If the sections outlined in the README README become lengthy, separate them into files named as follows:
notes/INSTALL.md
notes/design-goals.md
notes/examples.md
notes/configuration.md
notes/code-components.md
notes/code-layout.md
notes/known-issues.md
notes/performance.md
notes/references.md
Rakefile
for simple scriptsGuardfile
automates iterative developmentProcfile
shows how to launch support daemons and longrunning appsSupply a procfile that will start
Include the following in the header block:
# Procfile -- supporting daemons
#
# * Ensure you've done a `bundle install`
# * run `foreman start [process name]`
List each daemon, with no path (if it’s typically a system-wide dependency) or a path relative to the top of the repo. Here’s an example goliath Procfile:
listener: ./app/listener.rb -sv -p 9000 -c $PWD/config/app.rb
mongod: mongod
Gemfile
is a manifest for ruby gem dependenciesGemfiles for appllications should be precise about their direct dependencies. Gemfiles and gemspecs for libraries should not be strict with version dependencies. For example:
gem 'gorillib', "~> 0.1.8"
group :development do
gem 'yard', ">= 0.7"
gem 'pry'
end
As written, any version of pry
will work – it’s included in the Gemfile so that we debug with binding.pry
, but there are no code dependencies in the library. The documentation uses some modern features of yard
, so we ask for a version newer than 0.7; but if other libraries specify some future "~> 1.0"
version we would rather break our docs than your app.
A library with a strict Gemfile leads to conflicts that are nearly impossible to work around in current versions of bundler. A library with a too-generous Gemfile might break on an upgrade of some dependency, but it’s straightforward to correct by pinning a version in my app.
If the repo is a standalone-deployable application (web app, wukong job) you should include the Gemfile.lock file: it says “I don’t care what’s on the machine, use this precise gemset”.
If the repo is not a standalone-deployable application (most things) you should not include the Gemfile.lock file. Add it to your .gitignore
.
.yardopts
, .rspec
, {reponame}.gemspec
(yes), .rvmrc
(hell no).yardopts
and .rspec
filesYou should not version the following:
.rvmrc
: I shouldn’t have to install a crazy ruby version to read through some source files.TAGS
.project
files, emacs autosaves, or any other editor droppings.doc
(documentation from yarddoc or otherwise)pkg
(generated gems)build
(compiled products for java, c, etc)specs
holds RSpec test scriptsput test helpers in specs/support/whatever_test_helper.rb
. The spec_helper.rb
file should add specs/support
to the load path, but it should not load the contents of that directory.
put custom rspec matchers in specs/support/matchers
. The spec_helper.rb
should load the contents of that directory: Dir['spec/support/matchers/*.rb'].each{|f| require f}
place files in parallel with lib
:
lib/gorillib/record.rb
goes in spec/gorillib/record_spec.rb
.examples/simple.rb
goes in spec/examples/simple_spec.rb
Don’t make separate directories for ‘integration’ and ‘unit’ and other test-jargon soup. I don’t care about your test methodology, I care about seeing the fully-expressed API of a library component. You should mostly be writing integration tests anyway.
It’s fine to make integration tests that don’t correspond with a single library file: spec/gorillib/structures_spec.rb
tests various combined uses of record
, bucket
, etc.
If the tests for a library component are quite too large for one file, pause to consider whether you’re over-testing, over-thinking, under-helpering, or if you should be splitting the library component. If your muse concurs that this is necessary, preserve core tests in a file named for the component (spec/whatever/foo_spec.rb
), along with files named with an underscore-delimited decoration: spec/whatever/foo_in_space_spec.rb
, spec/whatever/foo_underwater_spec.rb
).
examples/
holds example apps or scriptsYour best be is to include
You should write tests for the examples, though they’re typically as simple as ‘its ran successfully and its output was what I expected’.
data/
holds example data (keep it small and interesting)Place data files in data/
with helpful, descriptive names. Use something fun and domain-interesting. For structured data, use YAML if possible, JSON if necessary (YAML is more readable). Do not use any of the fancy features of YAML (anchors, references, baked-in types). For tabular data, use the TSV (tab-separated values) format. TSV files must not use any quoting or escaping; unless it’s as simple as ‘one line per record, split on tabs for fields’ fall back to JSON. If at all reasonable, run TSV files through wukong’s wulign
script – it pads with spaces to make the data readable.
Don’t put anything larger than a few dozen KB in the directory – if a larger payload is necessary, make a {reponame}-data
repo and submodule it into the data directory.
The subdirectory data/expected_output
should
Have your examples output to tmp/actual_output
; its contents should exactly mirror that of the expected output directory (letting me diff -ruw data/expected_output tmp/actual_output
to detect differences). You should .gitignore the contents of the actual_output
directory, but .gitkeep
the presence of that directory.