From e5bde6cd7f7b6d6e409d704f1332c6b32672fcb3 Mon Sep 17 00:00:00 2001 From: "Joshua A. Anderson" Date: Mon, 20 May 2024 06:59:02 -0400 Subject: [PATCH] Configure CI. --- .github/ISSUE_TEMPLATE/bug_report.yml | 42 +++++ .github/ISSUE_TEMPLATE/config.yml | 8 + .github/ISSUE_TEMPLATE/feature_request.yml | 25 +++ .github/ISSUE_TEMPLATE/task.yml | 16 ++ .github/PULL_REQUEST_TEMPLATE.md | 27 +++ .github/dependabot.yml | 77 ++++++++ .github/workflows/pre-commit-requirements.in | 2 +- .github/workflows/pre-commit.yaml | 17 +- .github/workflows/release.yaml | 142 ++++++++++++++ .github/workflows/test.yaml | 43 +++-- .pre-commit-config.yaml | 19 +- .readthedocs.yaml | 9 + Cargo.toml | 1 + DESIGN.md | 6 +- doc/book.toml | 8 +- doc/rtd.css | 187 +++++++++++++++++++ doc/src/release-notes.md | 2 + doc/theme/index.hbs | 10 +- src/cli/submit.rs | 2 +- src/launcher.rs | 2 +- src/lib.rs | 1 + src/workflow.rs | 28 +-- 22 files changed, 628 insertions(+), 46 deletions(-) create mode 100644 .github/ISSUE_TEMPLATE/bug_report.yml create mode 100644 .github/ISSUE_TEMPLATE/config.yml create mode 100644 .github/ISSUE_TEMPLATE/feature_request.yml create mode 100644 .github/ISSUE_TEMPLATE/task.yml create mode 100644 .github/PULL_REQUEST_TEMPLATE.md create mode 100644 .github/dependabot.yml create mode 100644 .github/workflows/release.yaml create mode 100644 .readthedocs.yaml create mode 100644 doc/rtd.css diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml new file mode 100644 index 0000000..aa011c1 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -0,0 +1,42 @@ +name: Bug report +description: Report a problem with row. +labels: ['bug'] +body: + - type: textarea + attributes: + label: Description + description: Describe the problem. + validations: + required: true + - type: textarea + attributes: + label: Steps to reproduce + description: | + What specific commands do you execute to trigger the problem? + placeholder: | + row show status + ... + render: shell + - type: textarea + attributes: + label: Input files + description: Attach any input files needed to execute the above steps. + - type: textarea + attributes: + label: Output + description: | + What output did you get? + render: shell + - type: textarea + attributes: + label: Expected output + description: What output do you expect? + - type: input + attributes: + label: Row version + description: What version of **row** are you using? + placeholder: 0.1.0 + - type: markdown + attributes: + value: | + Execute `row --version` to find your **row** version. diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 0000000..4a6256a --- /dev/null +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1,8 @@ +blank_issues_enabled: true +contact_links: + - name: Row discussion board + url: https://github.com/glotzerlab/row/discussions/ + about: Ask the Row user community for help. + - name: Row documentation + url: https://row.readthedocs.io/ + about: User documentation. diff --git a/.github/ISSUE_TEMPLATE/feature_request.yml b/.github/ISSUE_TEMPLATE/feature_request.yml new file mode 100644 index 0000000..eb5334a --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.yml @@ -0,0 +1,25 @@ +name: Feature request +description: Suggest a new **row** feature +labels: ['enhancement'] +body: + - type: textarea + attributes: + label: Description + description: What new capability would you like in **row**? + validations: + required: true + - type: textarea + attributes: + label: Proposed solution + description: How should this capability be implemented? What might user interface look like? + - type: textarea + attributes: + label: Additional context + description: What additional information is helpful to understand this request? + - type: markdown + attributes: + value: | + We would welcome your contribution! + + If you plan to implement this functionality, the **row** developers will discuss the + proposed design and API with you **before** you begin work. diff --git a/.github/ISSUE_TEMPLATE/task.yml b/.github/ISSUE_TEMPLATE/task.yml new file mode 100644 index 0000000..e6a4e6b --- /dev/null +++ b/.github/ISSUE_TEMPLATE/task.yml @@ -0,0 +1,16 @@ +name: Task +description: A task that needs to be completed +labels: ['task'] +body: + - type: textarea + attributes: + label: Description + description: What needs to be done? + validations: + required: true + - type: textarea + attributes: + label: Motivation and context + description: What additional information is helpful to understand this task? + validations: + required: true diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 0000000..305157f --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,27 @@ +## Description + + + +## Motivation and context + + + + +Resolves #??? + +## How has this been tested? + + + +## Change log + + +``` + +``` + +## Checklist: + +- [ ] I have reviewed the [**Contributor Guidelines**](https://github.com/glotzerlab/row/blob/trunk/doc/src/developers/contributing.md). +- [ ] I agree with the terms of the [**Row Contributor Agreement**](https://github.com/glotzerlab/row/blob/trunk/ContributorAgreement.md). +- [ ] My name is on the list of contributors (`doc/src/contributors.md`) in the pull request source branch. diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..a5d365f --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,77 @@ +version: 2 +updates: +- package-ecosystem: "github-actions" + directory: "/" + target-branch: trunk + schedule: + interval: "monthly" + time: "07:00" + timezone: "EST5EDT" + pull-request-branch-name: + separator: "-" + open-pull-requests-limit: 2 + reviewers: + - joaander + groups: + actions-version: + applies-to: version-updates + patterns: + - '*' + actions-security: + applies-to: security-updates + patterns: + - '*' +- package-ecosystem: "pip" + directory: "/" + target-branch: trunk + schedule: + interval: "monthly" + time: "07:00" + timezone: "EST5EDT" + pull-request-branch-name: + separator: "-" + open-pull-requests-limit: 2 + reviewers: + - joaander + groups: + pip-version: + applies-to: version-updates + patterns: + - '*' + update-types: + - minor + - patch + pip-security: + applies-to: security-updates + patterns: + - '*' + update-types: + - minor + - patch +- package-ecosystem: "cargo" + directory: "/" + target-branch: trunk + schedule: + interval: "monthly" + time: "07:00" + timezone: "EST5EDT" + pull-request-branch-name: + separator: "-" + open-pull-requests-limit: 2 + reviewers: + - joaander + groups: + pip-version: + applies-to: version-updates + patterns: + - '*' + update-types: + - minor + - patch + pip-security: + applies-to: security-updates + patterns: + - '*' + update-types: + - minor + - patch diff --git a/.github/workflows/pre-commit-requirements.in b/.github/workflows/pre-commit-requirements.in index 6837283..a93b8c1 100644 --- a/.github/workflows/pre-commit-requirements.in +++ b/.github/workflows/pre-commit-requirements.in @@ -1 +1 @@ -pre-commit==3.7.0 +pre-commit==3.7.1 diff --git a/.github/workflows/pre-commit.yaml b/.github/workflows/pre-commit.yaml index 83b5148..9b65964 100644 --- a/.github/workflows/pre-commit.yaml +++ b/.github/workflows/pre-commit.yaml @@ -12,11 +12,22 @@ on: workflow_dispatch: +env: + RUST_VERSION: 1.78.0 + jobs: pre-commit: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4.1.3 + # For unknown reasons, pre-commit fails with error: component download failed for cargo-x86_64-unknown-linux-gnu: could not rename downloaded file ... + # unless we install with rustup first manually. + - name: Update rust + run: rustup install "$RUST_VERSION" --no-self-update && rustup default "${RUST_VERSION}" + - name: Install rustfmt + run: rustup component add rustfmt + - name: Install clippy + run: rustup component add clippy - uses: actions/cache@v4.0.2 with: path: | @@ -25,5 +36,7 @@ jobs: - uses: actions/setup-python@v5.0.0 with: python-version: '3.12' - - run: pip install -r .github/workflows/pre-commit-requirements.txt - - run: pre-commit run --all-files + - name: Install pre-commit + run: pip install -r .github/workflows/pre-commit-requirements.txt + - name: Run pre-commit + run: pre-commit run --all-files diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml new file mode 100644 index 0000000..1d5e084 --- /dev/null +++ b/.github/workflows/release.yaml @@ -0,0 +1,142 @@ +name: release + +permissions: + contents: write + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +on: + pull_request: + + push: + branches: + - "*" + tags: + - "*" + + workflow_dispatch: + +defaults: + run: + shell: bash + +env: + name: row + CARGO_TERM_COLOR: always + CLICOLOR: 1 + RUST_VERSION: 1.78.0 + +jobs: + source: + name: Build source tarball + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4.1.4 + with: + path: code + + - name: Determine filename-safe ref from GITHUB_REF_NAME + run: echo ref="$(echo "${GITHUB_REF_NAME}" | sed -e 's/\//-/g')" >> "$GITHUB_ENV" + + - name: Copy source + run: cp -R code "${name}-${ref}" + + - name: Remove .git + run: rm -rf "${name}-${ref}/.git" && ls -laR "${name}-${ref}" + + - name: Tar/xz source + run: tar -cvJf "${name}-${ref}.tar.xz" "${name}-${ref}" + + - uses: actions/upload-artifact@v4.3.3 + with: + name: source + path: | + *.tar.* + + release-notes: + name: Extract release notes + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4.1.4 + with: + path: code + + - name: Write release-notes.md + run: grep -P -m 2 -B 10000 "^## v*\d*\.\d*\.\d*" doc/src/release-notes.md | sed '$d' | tee "${GITHUB_WORKSPACE}/release-notes.md" + working-directory: code + + - uses: actions/upload-artifact@v4.3.3 + with: + name: release-notes + path: | + release-notes.md + + binary: + name: Build [${{ matrix.target }}] + runs-on: ${{ matrix.runner }} + strategy: + matrix: + target: + - x86_64-unknown-linux-gnu + # - aarch64-apple-darwin + include: + - target: x86_64-unknown-linux-gnu + runner: ubuntu-20.04 + # - target: aarch64-apple-darwin + # runner: macos-14 + + steps: + - uses: actions/checkout@v4.1.4 + - name: Determine filename-safe ref from GITHUB_REF_NAME + run: echo ref="$(echo "${GITHUB_REF_NAME}" | sed -e 's/\//-/g')" >> "$GITHUB_ENV" + - name: Update rust + run: rustup install "$RUST_VERSION" --no-self-update && rustup default "$RUST_VERSION" + - name: Check rust installation + run: rustc -vV + - uses: actions/cache@v4.0.2 + with: + path: | + ~/.cargo/registry/index/ + ~/.cargo/registry/cache/ + ~/.cargo/git/db/ + target/ + key: ${{ runner.os }}-rust-${{ env.RUST_VERSION }}-cargo-release-binary-${{ matrix.target }}-${{ hashFiles('**/Cargo.lock') }} + - name: Build + run: cargo build --locked --bin "${name}" --release --target ${{ matrix.target }} + - name: Check output + run: file "target/${{ matrix.target }}/release/${name}" + - name: Compress + run: cp "target/${{ matrix.target }}/release/${name}" . && tar -cvJf "${name}-${ref}-${{ matrix.target }}.tar.xz" "${name}" + - uses: actions/upload-artifact@v4.3.3 + with: + name: ${{ matrix.target }} + path: "${{ env.name }}-${{ env.ref }}-${{ matrix.target }}.tar.xz" + + publish: + name: Publish [GitHub] + needs: [binary, source, release-notes] + runs-on: ubuntu-latest + + steps: + - name: Download artifacts + uses: actions/download-artifact@v4.1.7 + with: + merge-multiple: true + + - name: List files + run: ls -lR + + - name: Create release + uses: softprops/action-gh-release@v2.0.5 + if: startsWith(github.ref, 'refs/tags/v') + with: + files: | + *.xz + body_path: release-notes.md + make_latest: true + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index 0974f6d..5b3feaf 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -22,24 +22,36 @@ env: CLICOLOR: 1 MDBOOK_VERSION: 0.4.37 LINKCHECK_VERSION: 0.7.7 + RUST_LATEST_VERSION: 1.78.0 jobs: unit_test: - name: Unit test on ${{ matrix.os }} [${{ matrix.mode }}] + name: Unit test [${{ matrix.mode }}-rust-${{ matrix.rust }}-${{ matrix.os }}] runs-on: ${{ matrix.os }} strategy: matrix: - os: [ubuntu-22.04] - mode: [debug, release] + os: + - ubuntu-22.04 + - macos-14 + rust: + # Oldest supported version of rust + - 1.77.2 + - 1.78.0 + mode: + - debug include: - - mode: 'debug' - mode_option: '' - - mode: 'release' - mode_option: '--release' + # Add a release build on linux with the latest version of rust + - os: ubuntu-22.04 + rust: 1.78.0 + mode: release steps: - uses: actions/checkout@v4.1.3 + - name: Update rust + run: rustup install ${{ matrix.rust }} --no-self-update && rustup default ${{ matrix.rust }} + - name: Check rust installation + run: rustc -vV - uses: actions/cache@v4.0.2 with: path: | @@ -47,17 +59,21 @@ jobs: ~/.cargo/registry/cache/ ~/.cargo/git/db/ target/ - key: ${{ runner.os }}-cargo-unit-test-${{ matrix.mode }}-${{ hashFiles('**/Cargo.lock') }} + key: ${{ runner.os }}-rust-${{ matrix.rust }}-cargo-unit-test-${{ matrix.mode }}-${{ hashFiles('**/Cargo.lock') }} - name: Build - run: cargo build ${{ matrix.mode_option }} --verbose + run: cargo build ${{ matrix.mode == 'release' && '--release' || '' }} --verbose - name: Run tests - run: cargo test ${{ matrix.mode_option }} --verbose + run: cargo test ${{ matrix.mode == 'release' && '--release' || '' }} --verbose execute_tutorials: name: Execute tutorials runs-on: ubuntu-22.04 steps: - uses: actions/checkout@v4.1.3 + - name: Update rust + run: rustup install "$RUST_LATEST_VERSION" --no-self-update && rustup default "$RUST_LATEST_VERSION" + - name: Check rust installation + run: rustc -vV - uses: actions/cache@v4.0.2 with: path: | @@ -65,7 +81,7 @@ jobs: ~/.cargo/registry/cache/ ~/.cargo/git/db/ target/ - key: ${{ runner.os }}-cargo-execute-tutorials-${{ hashFiles('**/Cargo.lock') }} + key: ${{ runner.os }}-rust-${{ env.RUST_LATEST_VERSION }}-cargo-execute-tutorials-${{ hashFiles('**/Cargo.lock') }} - name: Install run: cargo install --path . --locked --verbose - name: Run hello.sh @@ -116,8 +132,11 @@ jobs: tests_complete: name: All tests + if: always() needs: [unit_test, execute_tutorials, build_documentation] runs-on: ubuntu-latest steps: - - run: echo "Done!" + - run: jq --exit-status 'all(.result == "success")' <<< '${{ toJson(needs) }}' + - name: Done + run: exit 0 diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index fdcd5dd..3b37310 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -3,12 +3,15 @@ ci: autoupdate_branch: 'trunk' autofix_prs: false +default_language_version: + rust: 1.78.0 + repos: -- repo: https://github.com/backplane/pre-commit-rust-hooks - rev: v1.1.0 +- repo: https://github.com/Young-Naive-Simple/pre-commit-rust/ + rev: 3a8de64acc969112746489e5ec1f0b13e00d871e hooks: - id: fmt - - id: check + - id: cargo-check - id: clippy args: - --all-targets @@ -25,10 +28,11 @@ repos: - id: check-yaml - id: check-case-conflict - id: mixed-line-ending -- repo: https://github.com/rhysd/actionlint - rev: v1.6.27 - hooks: - - id: actionlint +# fails with _cgo_export.c:3:10: fatal error: 'stdlib.h' file not found on Mac. +# - repo: https://github.com/rhysd/actionlint +# rev: v1.6.27 +# hooks: +# - id: actionlint - repo: https://github.com/astral-sh/ruff-pre-commit rev: 'v0.3.4' hooks: @@ -48,3 +52,4 @@ repos: rev: v1.21.0 hooks: - id: typos + exclude_types: [css] diff --git a/.readthedocs.yaml b/.readthedocs.yaml new file mode 100644 index 0000000..87ca7a4 --- /dev/null +++ b/.readthedocs.yaml @@ -0,0 +1,9 @@ +version: 2 +build: + os: "ubuntu-22.04" + commands: + - mkdir -p bin + - curl -sSL "https://github.com/rust-lang/mdBook/releases/download/v0.4.37/mdbook-v0.4.37-x86_64-unknown-linux-gnu.tar.gz" | tar -xvz --directory "bin" + - mkdir -p $READTHEDOCS_OUTPUT/html + - echo "site-url = \"/$READTHEDOCS_LANGUAGE/$READTHEDOCS_VERSION/\"" >> doc/book.toml + - bin/mdbook build doc --dest-dir=$READTHEDOCS_OUTPUT/html diff --git a/Cargo.toml b/Cargo.toml index ac112b9..3ebc5bb 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,6 +2,7 @@ name = "row" version = "0.1.0" edition = "2021" +rust-version = "1.77" [dependencies] clap = { version = "4.5.3", features = ["derive", "env"] } diff --git a/DESIGN.md b/DESIGN.md index 4d3e55b..f5a4605 100644 --- a/DESIGN.md +++ b/DESIGN.md @@ -294,9 +294,5 @@ status may take a long time, so it should display a progress bar. without applying the additional submission filters. - **workspace**: The location on the file system that contains **directories**. -# TODO: Pull request template -# TODO: Issue templates? -# TODO: Dependabot configuration -# TODO: readthedocs builds # TODO: logo -# TODO: release CI +# TODO: Expand include to apply any to the array and allow condition or all elements. diff --git a/doc/book.toml b/doc/book.toml index 33da2a9..7975267 100644 --- a/doc/book.toml +++ b/doc/book.toml @@ -4,9 +4,6 @@ multilingual = false src = "src" title = "Row documentation" -[output.html] -git-repository-url = "https://github.com/glotzerlab/row" - [build] create-missing = false @@ -14,3 +11,8 @@ create-missing = false # You also need to install https://github.com/Michael-F-Bryan/mdbook-linkcheck. # [output.linkcheck] # follow-web-links = true + +# [output.html] must be the last table so that .readthedocs.yaml can easily add a key to it +[output.html] +git-repository-url = "https://github.com/glotzerlab/row" +additional-css = ["rtd.css"] diff --git a/doc/rtd.css b/doc/rtd.css new file mode 100644 index 0000000..467c4d5 --- /dev/null +++ b/doc/rtd.css @@ -0,0 +1,187 @@ +/* Read the Docs promotional block, only applicable to RTD.org + +To support sphinx_rtd_theme, a `wy-menu` element is added. Other themes are +targeted using the theme identifier and use custom elements instead of a CSS +framework html structure. + +*/ + +div.ethical-sidebar, +div.ethical-footer { + display: block !important; +} +.ethical-sidebar, +.ethical-footer { + padding: 0.5em; + margin: 1em 0; +} +.ethical-sidebar img, +.ethical-footer img { + width: 120px; + height: 90px; + display: inline-block; +} +.ethical-sidebar .ethical-callout, +.ethical-footer .ethical-callout { + padding-top: 1em; + clear: both; +} +.ethical-sidebar .ethical-pixel, +.ethical-footer .ethical-pixel, +.ethical-fixedfooter .ethical-pixel { + display: none !important; +} +.ethical-sidebar .ethical-text, +.ethical-footer .ethical-text { + margin-top: 1em; +} +.ethical-sidebar .ethical-image-link, +.ethical-footer .ethical-image-link { + border: 0; +} + +.ethical-sidebar, +.ethical-footer { + background-color: #eee; + border: 1px solid #ccc; + border-radius: 5px; + color: #0a0a0a; + font-size: 14px; + line-height: 20px; +} + +/* Techstack badging */ +.ethical-sidebar ul { + margin: 0 !important; + padding-left: 0; + list-style: none; +} +.ethical-sidebar ul li { + display: inline-block; + background-color: lightskyblue; + color: black; + padding: 0.25em 0.4em; + font-size: 75%; + font-weight: 700; + margin: 0.25em; + border-radius: 0.25rem; + text-align: center; + vertical-align: baseline; + white-space: nowrap; + line-height: 1.41; +} +.ethical-sidebar ul li:not(:last-child) { + margin-right: .25rem; +} + +.ethical-sidebar a, +.ethical-sidebar a:visited, +.ethical-sidebar a:hover, +.ethical-sidebar a:active, +.ethical-footer a, +.ethical-footer a:visited, +.ethical-footer a:hover, +.ethical-footer a:active { + color: #0a0a0a; + text-decoration: none !important; + border-bottom: 0 !important; +} + +.ethical-callout a { + color: #707070 !important; + text-decoration: none !important; +} + +/* Sidebar promotions */ +.ethical-sidebar { + text-align: center; + max-width: 300px; + margin-left: auto; + margin-right: auto; +} + +/* Footer promotions */ +.ethical-footer { + text-align: left; + + font-size: 14px; + line-height: 20px; +} +.ethical-footer img { + float: right; + margin-left: 25px; +} +.ethical-footer .ethical-callout { + text-align: center; +} +.ethical-footer small { + font-size: 10px; +} + +/* Fixed footer promotions */ +.ethical-fixedfooter { + box-sizing: border-box; + position: fixed; + bottom: 0; + left: 0; + z-index: 100; + background-color: #eee; + border-top: 1px solid #bfbfbf; + font-size: 12px; + line-height: 1.5; + padding: 0.5em 1.5em; + text-align: center; + color: #404040; + width: 100%; /* Fallback for Opera Mini */ + width: 100vw; +} +@media (min-width: 769px) { + /* Improve viewing on non-mobile */ + .ethical-fixedfooter { + font-size: 13px; + padding: 1em 1.5em; + } +} +.ethical-fixedfooter .ethical-text:before { + margin-right: 4px; + padding: 2px 6px; + border-radius: 3px; + background-color: #4caf50; + color: #fff; + content: "Sponsored"; +} +.ethical-fixedfooter .ethical-callout { + color: #999; + padding-left: 6px; + white-space: nowrap; +} +.ethical-fixedfooter a, +.ethical-fixedfooter a:hover, +.ethical-fixedfooter a:active, +.ethical-fixedfooter a:visited { + color: #404040; + text-decoration: none; +} +.ethical-fixedfooter .ethical-close { + position: absolute; + top: 0; + right: 5px; + font-size: 20px; + line-height: 20px; +} + +/* Use mdbook theme colors. */ + +.ethical-sidebar { + border: none; + box-shadow: none; + background: var(--sidebar-bg); +} + +.ethical-sidebar:hover { + background: var(--sidebar-non-existant); +} + +.ethical-sidebar a { + color: var(--sidebar-fg); +} diff --git a/doc/src/release-notes.md b/doc/src/release-notes.md index 864a062..ec15972 100644 --- a/doc/src/release-notes.md +++ b/doc/src/release-notes.md @@ -3,3 +3,5 @@ ## 0.1.0 (not yet released) * Initial release. + +## 0.0.0 diff --git a/doc/theme/index.hbs b/doc/theme/index.hbs index f86b1c2..cb44889 100644 --- a/doc/theme/index.hbs +++ b/doc/theme/index.hbs @@ -111,6 +111,14 @@