Skip to content

Commit 2ca6598

Browse files
Automatically generate contracts documentation
We are creating GH Actions workflows which automatically generates the contracts documentation in Markdown, based on the functions and the NatSpec-format comments in the Solidity files stored in the `contracts` folders in `keep-network/keep-core/solidity/random-beacon` and `keep-network/keep-core/solidity/ecdsa`. For certain workflow triggers, the generated documentation will be pushed to the `threshold-network/threshold` repository, under `./docs/app-development/random-beacon/random-beacon-api` / `./docs/app-development/ecdsa/ecdsa-api`. As the `.docs` folder is synched with Threshold docs GitBook space, the pushed docs will be displayed in HTML under `docs.threshold.network` domain. There are two main jobs in the workflows: * `contracts-docs-publish-preview` * `contracts-docs-publish` Both call a reusable workflow `reusable-solidity-docs.yml` which resides in the `keep-network/ci` repository under `.github/workflows`. The jobs differ in parameters with witch the reusable action is called. The common part of the jobs is the beginning stage, where the Solidity files are being prepared for Markdown generation. During that stage the jobs will remove the spaces chars between the NatSpec comments markers (`///`) and the text of the comment. This is done to ensure proper rendering of the lists in the output docs and is a default action made by `reusable-solidity-docs.yml`. Another pre-processing is running a `sed` command on a `./contracts/bridge/BitcoinTx.sol` that removes incorrectly used line with `//` blank comment in the middle of section with NatSpec's `///` comments (which was breaking the formatting of that comment in Markdown). Once files are ready, the jobs use Docgen tool to generate the Markdown docs. The tool needs to be installed in the project and configured in the `hardhat.config.ts`. The configuration that we use specifies that the docs should be generated to the `geerated-docs` subfolder, to one single `index.md` file. The `.sol` files in the `./solidity/contracts/test` folder will be ignored during generation (those are test/stub contracts which are not used on Mainnet). A custom template will be used during docs generations. The template was created based on the default `https://github.com/OpenZeppelin/solidity-docgen/blob/master/src/themes/markdown/common.hbs` template, but it removes the cursive from the `@dev` type comments (because the cursive didn't work well with formatting of the lists). Once the Docgen is run and the `index.md` file is generated, the jobs will add a Table of Contents to the file, to improve the navigation. The TOC will be added by the `markdown-toc` tool and will be generated using `--maxdepth 2` param, which results in listing all the contract names, but not the functions. Once the TOC is added, we'll start to see the difference in the behavior of the jobs. The `contracts-docs-publish-preview` job is triggered for: * `pull_request` events, if the PR modifies either files if `./solidity/<project>/contracts` or the workflow files itself, * `push` events, when the push is made to a branch which name starts with `releases/mainnet/solidity/` and project's files are modified, * `workflow_dispatch` events. The job publishes the generated artifacts as artifacts of the GH Actions workflow run. For PRs, link to the run with the artifacts will be posted as a PR comment. The `contracts-docs-publish` job is triggered for: * published releases, which names start with `refs/tags/solidity/`. The job pushes the generated file to the `./docs/app-development/random-beacon/random-beacon-api` / `./docs/app-development/ecdsa/ecdsa-api`folder in the `threshold-network/threshold` repo, to the `main` branch. The `.docs` folder is synched with the GitBook Threshold documentation, so thanks to the job, the changes in the contracts should be reflected on the docs.threshold.network. In order for the job to work, we need to configure a user which will create the commit The user needs to have right to commit to the `threshold-network/threshold` repo. We also need to configure following secrets: - [ ] `THRESHOLD_DOCS_GITHUB_TOKEN` - [ ] `GPG_PRIVATE_KEY` - [ ] `GPG_PASSPHRASE` We're using a GPG key to be able to do verified commits.
1 parent 0484ddb commit 2ca6598

12 files changed

+316
-2
lines changed
+75
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
name: Solidity ECDSA docs
2+
3+
on:
4+
pull_request:
5+
push:
6+
branches:
7+
- releases/mainnet/solidity/**
8+
paths:
9+
- "solidity/ecdsa/**"
10+
release:
11+
types:
12+
- "published"
13+
workflow_dispatch:
14+
15+
jobs:
16+
docs-detect-changes:
17+
runs-on: ubuntu-latest
18+
outputs:
19+
path-filter: ${{ steps.filter.outputs.path-filter }}
20+
steps:
21+
- uses: actions/checkout@v3
22+
if: github.event_name == 'pull_request'
23+
- uses: dorny/paths-filter@v2
24+
if: github.event_name == 'pull_request'
25+
id: filter
26+
with:
27+
filters: |
28+
path-filter:
29+
- './solidity/ecdsa/contracts/**'
30+
- './.github/workflows/contracts-ecdsa-docs.yml'
31+
32+
# This job will be triggered for PRs which modify contracts. It will generate
33+
# the archive with contracts documentation in Markdown and attatch it to the
34+
# workflow run results. Link to the archive will be posted in a PR comment.
35+
# The job will also be run after manual triggering and after pushes to the
36+
# `releases/mainnet/solidity/**` branches if there were changes to the
37+
# `ecdsa` project.
38+
contracts-docs-publish-preview:
39+
name: Publish preview of contracts documentation
40+
needs: docs-detect-changes
41+
if: |
42+
github.event_name == 'pull_request'
43+
|| github.event_name == 'push'
44+
|| github.event_name == 'workflow_dispatch'
45+
uses: keep-network/ci/.github/workflows/reusable-solidity-docs.yml@main
46+
with:
47+
projectSubfolder: /solidity/ecdsa
48+
publish: false
49+
commentPR: true
50+
exportAsGHArtifacts: true
51+
52+
# This job will be triggered for releases which name starts with
53+
# `refs/tags/solidity/`. It will generate contracts documentation in
54+
# Markdown and sync it with a specific path of
55+
# `threshold-network/threshold` repository. If changes will be detected,
56+
# the destination repository will be updated. The commit pushing the
57+
# changes will be verified using GPG key.
58+
contracts-docs-publish:
59+
name: Publish contracts documentation
60+
needs: docs-detect-changes
61+
if: github.event_name == 'release' && startsWith(github.ref, 'refs/tags/solidity/')
62+
uses: keep-network/ci/.github/workflows/reusable-solidity-docs.yml@main
63+
with:
64+
projectSubfolder: /solidity/ecdsa
65+
publish: true
66+
verifyCommits: true
67+
destinationRepo: threshold-network/threshold
68+
destinationFolder: ./docs/app-development/tbtc-v2/ecdsa-api
69+
destinationBranch: main
70+
userEmail: [email protected]
71+
userName: Valkyrie
72+
secrets:
73+
githubToken: ${{ secrets.THRESHOLD_DOCS_GITHUB_TOKEN }}
74+
gpgPrivateKey: ${{ secrets.GPG_PRIVATE_KEY }}
75+
gpgPassphrase: ${{ secrets.GPG_PASSPHRASE }}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
name: Solidity Random Beacon docs
2+
3+
on:
4+
pull_request:
5+
push:
6+
branches:
7+
- releases/mainnet/solidity/**
8+
paths:
9+
- "solidity/random-beacon/**"
10+
release:
11+
types:
12+
- "published"
13+
workflow_dispatch:
14+
15+
jobs:
16+
docs-detect-changes:
17+
runs-on: ubuntu-latest
18+
outputs:
19+
path-filter: ${{ steps.filter.outputs.path-filter }}
20+
steps:
21+
- uses: actions/checkout@v3
22+
if: github.event_name == 'pull_request'
23+
- uses: dorny/paths-filter@v2
24+
if: github.event_name == 'pull_request'
25+
id: filter
26+
with:
27+
filters: |
28+
path-filter:
29+
- './solidity/random-beacon/contracts/**'
30+
- './.github/workflows/contracts-random-beacon-docs.yml'
31+
32+
# This job will be triggered for PRs which modify contracts. It will generate
33+
# the archive with contracts documentation in Markdown and attatch it to the
34+
# workflow run results. Link to the archive will be posted in a PR comment.
35+
# The job will also be run after manual triggering and after pushes to the
36+
# `releases/mainnet/solidity/**` branches if there were changes to the
37+
# `random-beacon` project.
38+
contracts-docs-publish-preview:
39+
name: Publish preview of contracts documentation
40+
needs: docs-detect-changes
41+
if: |
42+
github.event_name == 'pull_request'
43+
|| github.event_name == 'push'
44+
|| github.event_name == 'workflow_dispatch'
45+
uses: keep-network/ci/.github/workflows/reusable-solidity-docs.yml@main
46+
with:
47+
projectSubfolder: /solidity/random-beacon
48+
publish: false
49+
commentPR: true
50+
exportAsGHArtifacts: true
51+
52+
# This job will be triggered for releases which name starts with
53+
# `refs/tags/solidity/`. It will generate contracts documentation in
54+
# Markdown and sync it with a specific path of
55+
# `threshold-network/threshold` repository. If changes will be detected,
56+
# the destination repository will be updated. The commit pushing the
57+
# changes will be verified using GPG key.
58+
contracts-docs-publish:
59+
name: Publish contracts documentation
60+
needs: docs-detect-changes
61+
if: github.event_name == 'release' && startsWith(github.ref, 'refs/tags/solidity/')
62+
uses: keep-network/ci/.github/workflows/reusable-solidity-docs.yml@main
63+
with:
64+
projectSubfolder: /solidity/random-beacon
65+
publish: true
66+
verifyCommits: true
67+
destinationRepo: threshold-network/threshold
68+
destinationFolder: ./docs/app-development/random-beacon/random-beacon-api
69+
destinationBranch: main
70+
userEmail: [email protected]
71+
userName: Valkyrie
72+
secrets:
73+
githubToken: ${{ secrets.THRESHOLD_DOCS_GITHUB_TOKEN }}
74+
gpgPrivateKey: ${{ secrets.GPG_PRIVATE_KEY }}
75+
gpgPassphrase: ${{ secrets.GPG_PASSPHRASE }}

solidity/ecdsa/.prettierignore

+1
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,5 @@ export/
66
external/
77
hardhat-dependency-compiler/
88
typechain/
9+
docgen-templates/
910
export.json
+33
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
{{h}} {{name}}
2+
3+
{{#if signature}}
4+
```solidity
5+
{{{signature}}}
6+
```
7+
{{/if}}
8+
9+
{{{natspec.notice}}}
10+
11+
{{#if natspec.dev}}
12+
{{{natspec.dev}}}
13+
{{/if}}
14+
15+
{{#if natspec.params}}
16+
{{h 2}} Parameters
17+
18+
| Name | Type | Description |
19+
| ---- | ---- | ----------- |
20+
{{#each params}}
21+
| {{name}} | {{type}} | {{{joinLines natspec}}} |
22+
{{/each}}
23+
{{/if}}
24+
25+
{{#if natspec.returns}}
26+
{{h 2}} Return Values
27+
28+
| Name | Type | Description |
29+
| ---- | ---- | ----------- |
30+
{{#each returns}}
31+
| {{#if name}}{{name}}{{else}}[{{@index}}]{{/if}} | {{type}} | {{{joinLines natspec}}} |
32+
{{/each}}
33+
{{/if}}

solidity/ecdsa/hardhat.config.ts

+7
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import "@tenderly/hardhat-tenderly"
99
import "hardhat-contract-sizer"
1010
import "hardhat-dependency-compiler"
1111
import "hardhat-gas-reporter"
12+
import "solidity-docgen"
1213

1314
import "./tasks"
1415
import { task } from "hardhat/config"
@@ -221,6 +222,12 @@ const config: HardhatUserConfig = {
221222
typechain: {
222223
outDir: "typechain",
223224
},
225+
docgen: {
226+
outputDir: "generated-docs",
227+
templates: "docgen-templates",
228+
pages: "single", // `single`, `items` or `files`
229+
exclude: ["./test"],
230+
},
224231
}
225232

226233
task(TASK_TEST, "Runs mocha tests").setAction(async (args, hre, runSuper) => {

solidity/ecdsa/package.json

+1
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@
6464
"prettier-plugin-solidity": "^1.0.0-beta.19",
6565
"solhint": "^3.3.6",
6666
"solhint-config-keep": "github:keep-network/solhint-config-keep",
67+
"solidity-docgen": "^0.6.0-beta.35",
6768
"ts-node": "^10.4.0",
6869
"typechain": "^6.1.0",
6970
"typescript": "^4.5.4"

solidity/ecdsa/yarn.lock

+41-1
Original file line numberDiff line numberDiff line change
@@ -6087,6 +6087,18 @@ [email protected]:
60876087
resolved "https://registry.yarnpkg.com/growl/-/growl-1.10.5.tgz#f2735dc2283674fa67478b10181059355c369e5e"
60886088
integrity sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==
60896089

6090+
handlebars@^4.7.7:
6091+
version "4.7.7"
6092+
resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.7.7.tgz#9ce33416aad02dbd6c8fafa8240d5d98004945a1"
6093+
integrity sha512-aAcXm5OAfE/8IXkcZvCepKU3VzW1/39Fb5ZuqMtgI/hT8X2YgoMvBY5dLhq/cpOvw7Lk1nK/UF71aLG/ZnVYRA==
6094+
dependencies:
6095+
minimist "^1.2.5"
6096+
neo-async "^2.6.0"
6097+
source-map "^0.6.1"
6098+
wordwrap "^1.0.0"
6099+
optionalDependencies:
6100+
uglify-js "^3.1.4"
6101+
60906102
har-schema@^2.0.0:
60916103
version "2.0.0"
60926104
resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-2.0.0.tgz#a94c2224ebcac04782a0d9035521f24735b7ec92"
@@ -8084,6 +8096,11 @@ [email protected]:
80848096
resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.3.tgz#58e323a72fedc0d6f9cd4d31fe49f51479590ccd"
80858097
integrity sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==
80868098

8099+
neo-async@^2.6.0:
8100+
version "2.6.2"
8101+
resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.2.tgz#b4aafb93e3aeb2d8174ca53cf163ab7d7308305f"
8102+
integrity sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==
8103+
80878104
next-tick@^1.1.0:
80888105
version "1.1.0"
80898106
resolved "https://registry.yarnpkg.com/next-tick/-/next-tick-1.1.0.tgz#1836ee30ad56d67ef281b22bd199f709449b35eb"
@@ -9820,11 +9837,24 @@ solidity-ast@^0.4.15:
98209837
resolved "https://registry.yarnpkg.com/solidity-ast/-/solidity-ast-0.4.31.tgz#c63e42f894cd047826a05dbb8d1e1dfc17282d39"
98219838
integrity sha512-kX6o4XE4ihaqENuRRTMJfwQNHoqWusPENZUlX4oVb19gQdfi7IswFWnThONHSW/61umgfWdKtCBgW45iuOTryQ==
98229839

9840+
solidity-ast@^0.4.38:
9841+
version "0.4.46"
9842+
resolved "https://registry.yarnpkg.com/solidity-ast/-/solidity-ast-0.4.46.tgz#d0745172dced937741d07464043564e35b147c59"
9843+
integrity sha512-MlPZQfPhjWXqh7YxWcBGDXaPZIfMYCOHYoLEhGDWulNwEPIQQZuB7mA9eP17CU0jY/bGR4avCEUVVpvHtT2gbA==
9844+
98239845
solidity-comments-extractor@^0.0.7:
98249846
version "0.0.7"
98259847
resolved "https://registry.yarnpkg.com/solidity-comments-extractor/-/solidity-comments-extractor-0.0.7.tgz#99d8f1361438f84019795d928b931f4e5c39ca19"
98269848
integrity sha512-wciNMLg/Irp8OKGrh3S2tfvZiZ0NEyILfcRCXCD4mp7SgK/i9gzLfhY2hY7VMCQJ3kH9UB9BzNdibIVMchzyYw==
98279849

9850+
solidity-docgen@^0.6.0-beta.35:
9851+
version "0.6.0-beta.35"
9852+
resolved "https://registry.yarnpkg.com/solidity-docgen/-/solidity-docgen-0.6.0-beta.35.tgz#174d7fe54efa8b10f7d3cbe0dfc40e52e11bf867"
9853+
integrity sha512-9QdwK1THk/MWIdq1PEW/6dvtND0pUqpFTsbKwwU9YQIMYuRhH1lek9SsgnsGGYtdJ0VTrXXcVT30q20a8Y610A==
9854+
dependencies:
9855+
handlebars "^4.7.7"
9856+
solidity-ast "^0.4.38"
9857+
98289858
source-map-resolve@^0.5.0:
98299859
version "0.5.3"
98309860
resolved "https://registry.yarnpkg.com/source-map-resolve/-/source-map-resolve-0.5.3.tgz#190866bece7553e1f8f267a2ee82c606b5509a1a"
@@ -9869,7 +9899,7 @@ source-map@^0.5.6, source-map@^0.5.7:
98699899
resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc"
98709900
integrity sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=
98719901

9872-
source-map@^0.6.0:
9902+
source-map@^0.6.0, source-map@^0.6.1:
98739903
version "0.6.1"
98749904
resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263"
98759905
integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==
@@ -10708,6 +10738,11 @@ typical@^5.2.0:
1070810738
resolved "https://registry.yarnpkg.com/typical/-/typical-5.2.0.tgz#4daaac4f2b5315460804f0acf6cb69c52bb93066"
1070910739
integrity sha512-dvdQgNDNJo+8B2uBQoqdb11eUCE1JQXhvjC/CZtgvZseVd5TYMXnq0+vuUemXbd/Se29cTaUuPX3YIc2xgbvIg==
1071010740

10741+
uglify-js@^3.1.4:
10742+
version "3.17.4"
10743+
resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.17.4.tgz#61678cf5fa3f5b7eb789bb345df29afb8257c22c"
10744+
integrity sha512-T9q82TJI9e/C1TAxYvfb16xO120tMVFZrGA3f9/P4424DNu6ypK103y0GPFVa17yotwSyZW5iYXgjYHkGrJW/g==
10745+
1071110746
ultron@~1.1.0:
1071210747
version "1.1.1"
1071310748
resolved "https://registry.yarnpkg.com/ultron/-/ultron-1.1.1.tgz#9fe1536a10a664a65266a1e3ccf85fd36302bc9c"
@@ -11540,6 +11575,11 @@ word-wrap@^1.2.3, word-wrap@~1.2.3:
1154011575
resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.3.tgz#610636f6b1f703891bd34771ccb17fb93b47079c"
1154111576
integrity sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==
1154211577

11578+
wordwrap@^1.0.0:
11579+
version "1.0.0"
11580+
resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-1.0.0.tgz#27584810891456a4171c8d0226441ade90cbcaeb"
11581+
integrity sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==
11582+
1154311583
wordwrapjs@^4.0.0:
1154411584
version "4.0.1"
1154511585
resolved "https://registry.yarnpkg.com/wordwrapjs/-/wordwrapjs-4.0.1.tgz#d9790bccfb110a0fc7836b5ebce0937b37a8b98f"

solidity/random-beacon/.prettierignore

+1
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,5 @@ deployments/
55
external/
66
hardhat-dependency-compiler/
77
typechain/
8+
docgen-templates/
89
export.json
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
{{h}} {{name}}
2+
3+
{{#if signature}}
4+
```solidity
5+
{{{signature}}}
6+
```
7+
{{/if}}
8+
9+
{{{natspec.notice}}}
10+
11+
{{#if natspec.dev}}
12+
{{{natspec.dev}}}
13+
{{/if}}
14+
15+
{{#if natspec.params}}
16+
{{h 2}} Parameters
17+
18+
| Name | Type | Description |
19+
| ---- | ---- | ----------- |
20+
{{#each params}}
21+
| {{name}} | {{type}} | {{{joinLines natspec}}} |
22+
{{/each}}
23+
{{/if}}
24+
25+
{{#if natspec.returns}}
26+
{{h 2}} Return Values
27+
28+
| Name | Type | Description |
29+
| ---- | ---- | ----------- |
30+
{{#each returns}}
31+
| {{#if name}}{{name}}{{else}}[{{@index}}]{{/if}} | {{type}} | {{{joinLines natspec}}} |
32+
{{/each}}
33+
{{/if}}

solidity/random-beacon/hardhat.config.ts

+7
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import "hardhat-contract-sizer"
1010
import "@typechain/hardhat"
1111
import "hardhat-dependency-compiler"
1212
import "./tasks"
13+
import "solidity-docgen"
1314

1415
import { task } from "hardhat/config"
1516

@@ -192,6 +193,12 @@ const config: HardhatUserConfig = {
192193
currency: "USD",
193194
coinmarketcap: process.env.COINMARKETCAP_API_KEY,
194195
},
196+
docgen: {
197+
outputDir: "generated-docs",
198+
templates: "docgen-templates",
199+
pages: "single", // `single`, `items` or `files`
200+
exclude: ["./test"],
201+
},
195202
}
196203

197204
task("check-accounts-count", "Checks accounts count").setAction(async () => {

solidity/random-beacon/package.json

+1
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@
6666
"prettier-plugin-solidity": "^1.0.0-beta.18",
6767
"solhint": "^3.3.6",
6868
"solhint-config-keep": "github:keep-network/solhint-config-keep",
69+
"solidity-docgen": "^0.6.0-beta.35",
6970
"ts-node": "^10.2.1",
7071
"typechain": "^7.0.0",
7172
"typescript": "^4.4.3"

0 commit comments

Comments
 (0)