docs.etherisc.com

How we organize the Etherisc documentation.

Basic idea:

  • Generally, we follow the documentation guidelines of OpenZeppelin. This means:

  • In the repo github.com/etherisc/docs.etherisc.com we put all the general docs which are not specific for a certain code repository.

    • General information

    • Tutorials

    • Architecture…

  • In each code repo (e.g. github.com/etherisc/gif-contracts etc) we create a folder <project>/docs.

  • The basic, manually created documentation which is specific for this code repo is put under <project>/docs/modules/ROOT/pages

  • All solidity code is documented with NatSpec and documentation is generated with solidity-docgen and (automagically) put in <project>/docs/modules/api/…

  • On each commit, the docs are automatically preprocessed and published.

Documentation Structure

Documentation Structure

Using solidity-docgen

solidity-docgen automagically generates perfectly formatted AsciiDoc files for each smart contract, with each contract, function etc. nicely formatted. However, some prerequisites need to be made.

solidity-docgen works with hardhat so both solidity-docgen and hardhat needs to be installed. Openzeppelin provides some necessary scripts and templates which enable AsciiDoc-formatted output, and which need to be copied in the docs folder of the repo. To make it work, we need a README.adoc file in every source directory under /contracts. All output generated by solidity-docgen needs to be included in these README.adoc files via {{…​}} directive. Typically, the README.adoc will start with some general documentation of the smart contracts, formatted in AsciiDoc. Then you can include the generated AsciiDoc for each Xyz.sol contract simply via the {{Xyz}} directive.

Example README.adoc

Lets assume we have a contracts folder with the following structure:

/contracts
 ├── Migrations.sol
 ├── main.sol
 ├── module1
 │   ├── Part1.sol
 │   ├── Part2.sol
 │   └── Part3.sol
 └── module2
     ├── Part4.sol
     └── Part5.adoc

We add README.adoc in each folder:

/contracts
 ├── Migrations.sol
 ├── main.sol
 ├── module1
 │   ├── Part1.sol
 │   ├── Part2.sol
 │   ├── Part3.sol
 │   └── README.adoc
 └── module2
     ├── Part3.sol
     ├── Part4.sol
     └── README.adoc

The file /contracts/module1/README.adoc would then look like this:

= Documentation of `module1`

== General considerations

...

== Contracts

{{Part1}}

{{Part2}}

{{Part3}}
Put an empty line between each two contracts.

Generation of asciidoc files

In each source repo (e.g. gif-contracts, gif-interface etc.), AsciiDoc files are generated by

$ npx hardhat docgen

In addition, a table of contents is generated by

$ node scripts/gen-nav.js "$OUTDIR" > "$OUTDIR/../nav.adoc"

Both actions can be combined by calling

$ npm run prepare-docs

The scripts are executed automatically by github actions on push to a release branch.

Git Branches

Documentation is maintained together with the source code in the main development branch.

Release branches adhere to the following regex:

releaseBranchRegex = /^release-v(?<version>(?<major>\d+)\.(?<minor>\d+)(?:\.(?<patch>\d+))?)$/

Examples:

release-v3
release-v3.0
release-v3.0.1

For each major release, a separate docs-v{major}.x branch is automatically generated by the update-docs-branch.js script. The script is invoked by a github action each time a release branch is pushed and checks for conflicting branches and other conditions.

The docs-v{major}.x branch should never be manually edited.

Cross-linking between docs

Antora offers the capability to cross-link between doc sources with the xref macro. For details, see here

Tech stack

  • We use AsciiDoc

  • Here’s a nice cheatsheet with most of the basic commands

  • We use Antora to publish the docs to docs.etherisc.com

  • docs.etherisc.com is hosted at netlify

  • Netlify is integrated in our CI/CD workflow. Each code repo has a webhook which is triggered on push and which will notify Netlify to re-generate the doc site.

  • We use the Openzeppelin docs template.