From 27aa8d84db80da1262d0356939c2848ec58817ee Mon Sep 17 00:00:00 2001 From: Oleh Prypin Date: Tue, 2 Mar 2021 01:35:25 +0100 Subject: [PATCH] Migrate/add an API documentation site based on MkDocs Includes version selector and auto-deployment to GitHub Pages --- .github/workflows/deploy-docs.yml | 33 +++++++++++ .gitignore | 2 +- docs/SUMMARY.md | 50 ++++++++++++++++ docs/css/mkdocstrings.css | 7 +++ docs/gen_doc_stubs.py | 18 ++++++ docs/requirements.in | 6 ++ docs/requirements.txt | 97 +++++++++++++++++++++++++++++++ mkdocs.yml | 42 +++++++++++++ src/db.cr | 3 +- src/db/serializable.cr | 1 + src/spec.cr | 7 ++- 11 files changed, 261 insertions(+), 5 deletions(-) create mode 100644 .github/workflows/deploy-docs.yml create mode 100644 docs/SUMMARY.md create mode 100644 docs/css/mkdocstrings.css create mode 100644 docs/gen_doc_stubs.py create mode 100644 docs/requirements.in create mode 100644 docs/requirements.txt create mode 100644 mkdocs.yml diff --git a/.github/workflows/deploy-docs.yml b/.github/workflows/deploy-docs.yml new file mode 100644 index 0000000..0dad161 --- /dev/null +++ b/.github/workflows/deploy-docs.yml @@ -0,0 +1,33 @@ +name: Deploy docs +on: + push: + pull_request: + branches: [master] +jobs: + build: + name: Deploy docs + runs-on: ubuntu-latest + steps: + - name: Download source + uses: actions/checkout@v2 + with: + fetch-depth: 0 # Prevent shallow clone + - name: Install Crystal + uses: oprypin/install-crystal@v1 + - name: Install Python + uses: actions/setup-python@v2 + - name: Install Python libs + run: | + pip install --no-deps -r docs/requirements.txt + - name: Configure Git + run: | + git config user.name 'github-actions[bot]' + git config user.email 'github-actions[bot]@users.noreply.github.com' + - name: Build site + run: | + mkdocs build --strict + - name: Deploy to gh-pages + if: startsWith(github.ref, 'refs/tags/v') + run: | + mike deploy --push --update-aliases --prefix=api "${GITHUB_REF#refs/tags/v}" latest + mike set-default --push --prefix=api "${GITHUB_REF#refs/tags/v}" diff --git a/.gitignore b/.gitignore index e978b32..614e5ff 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,3 @@ -/docs/ /lib/ /bin/ /.shards/ @@ -8,3 +7,4 @@ # Dependencies will be locked in application that uses them /shard.lock +/site/ diff --git a/docs/SUMMARY.md b/docs/SUMMARY.md new file mode 100644 index 0000000..42c229a --- /dev/null +++ b/docs/SUMMARY.md @@ -0,0 +1,50 @@ +* [Home](README.md) + * [DB module](DB.md) +* Connection & session + * [Database](DB/Database.md) + * [ConnectionContext](DB/ConnectionContext.md) + * [Connection](DB/Connection.md) + * [Pool](DB/Pool.md) + * [Stats](DB/Pool/Stats.md) + * [SessionMethods](DB/SessionMethods.md) + * [PreparedQuery](DB/SessionMethods/PreparedQuery.md) + * [UnpreparedQuery](DB/SessionMethods/UnpreparedQuery.md) +* Transaction + * [Transaction](DB/Transaction.md) + * [TopLevelTransaction](DB/TopLevelTransaction.md) + * [SavePointTransaction](DB/SavePointTransaction.md) + * [BeginTransaction](DB/BeginTransaction.md) + * [QueryMethods](DB/QueryMethods.md) + * [ExecResult](DB/ExecResult.md) + * [ResultSet](DB/ResultSet.md) +* Statement + * [Statement](DB/Statement.md) + * [PoolStatement](DB/PoolStatement.md) + * [PoolUnpreparedStatement](DB/PoolUnpreparedStatement.md) + * [PoolPreparedStatement](DB/PoolPreparedStatement.md) + * [StatementMethods](DB/StatementMethods.md) +* Driver + * [Driver](DB/Driver.md) + * [DriverSpecs](DB/DriverSpecs.md) + * [ColumnDef](DB/DriverSpecs/ColumnDef.md) + * [MetadataValueConverter](DB/MetadataValueConverter.md) +* Serialization + * [Serializable](DB/Serializable.md) + * [NonStrict](DB/Serializable/NonStrict.md) + * [Field](DB/Field.md) + * [Mappable](DB/Mappable.md) +* Miscellaneous + * [Any](DB/Any.md) + * [StringKeyCache](DB/StringKeyCache.md) + * [Disposable](DB/Disposable.md) +* Errors + * [Error](DB/Error.md) + * [NoResultsError](DB/NoResultsError.md) + * [Rollback](DB/Rollback.md) + * [MappingException](DB/MappingException.md) + * [PoolResourceLost](DB/PoolResourceLost.md) + * [ConnectionLost](DB/ConnectionLost.md) + * [PoolResourceRefused](DB/PoolResourceRefused.md) + * [ConnectionRefused](DB/ConnectionRefused.md) + * [PoolRetryAttemptsExceeded](DB/PoolRetryAttemptsExceeded.md) + * [PoolTimeout](DB/PoolTimeout.md) diff --git a/docs/css/mkdocstrings.css b/docs/css/mkdocstrings.css new file mode 100644 index 0000000..5ae79d9 --- /dev/null +++ b/docs/css/mkdocstrings.css @@ -0,0 +1,7 @@ +/* https://mkdocstrings.github.io/crystal/styling.html#recommended-styles */ + +/* Indent and distinguish sub-items */ +div.doc-contents:not(.first) { + padding-left: 15px; + border-left: 4px solid rgba(230, 230, 230); +} diff --git a/docs/gen_doc_stubs.py b/docs/gen_doc_stubs.py new file mode 100644 index 0000000..e6223e1 --- /dev/null +++ b/docs/gen_doc_stubs.py @@ -0,0 +1,18 @@ +# Generate virtual doc files for the mkdocs site. +# You can also run this script directly to actually write out those files, as a preview. + +import mkdocs_gen_files + +# Get the documentation root object +root = mkdocs_gen_files.config['plugins']['mkdocstrings'].get_handler('crystal').collector.root + +# For each type (e.g. "Foo::Bar") +for typ in root.walk_types(): + # Use the file name "Foo/Bar.md" + filename = '/'.join(typ.abs_id.split('::')) + '.md' + # Make a file with the content "# ::: Foo::Bar\n" + with mkdocs_gen_files.open(filename, 'w') as f: + print(f'# ::: {typ.abs_id}', file=f) + +with mkdocs_gen_files.open('README.md', 'w') as f, open('README.md') as in_f: + f.write(in_f.read()) diff --git a/docs/requirements.in b/docs/requirements.in new file mode 100644 index 0000000..f95ccc4 --- /dev/null +++ b/docs/requirements.in @@ -0,0 +1,6 @@ +mkdocs-material +mkdocstrings-crystal +mkdocs-gen-files +mkdocs-literate-nav +mkdocs-section-index +git+https://github.com/jimporter/mike.git@7cff0cc9bd434ff2db8d7c8c945d2a6befcba85f diff --git a/docs/requirements.txt b/docs/requirements.txt new file mode 100644 index 0000000..a15996d --- /dev/null +++ b/docs/requirements.txt @@ -0,0 +1,97 @@ +# +# This file is autogenerated by pip-compile +# To update, run: +# +# pip-compile requirements.in +# +cached-property==1.5.2 + # via mkdocstrings-crystal +click==7.1.2 + # via + # mkdocs + # nltk +future==0.18.2 + # via lunr +glob2==0.7 + # via mkdocs-literate-nav +jinja2==2.11.3 + # via + # mike + # mkdocs + # mkdocstrings + # mkdocstrings-crystal +joblib==1.0.1 + # via nltk +livereload==2.6.3 + # via mkdocs +lunr[languages]==0.5.8 + # via mkdocs +markdown==3.3.4 + # via + # mkdocs + # mkdocs-autorefs + # mkdocs-material + # mkdocstrings + # pymdown-extensions +markupsafe==1.1.1 + # via + # jinja2 + # mkdocstrings + # mkdocstrings-crystal +git+https://github.com/jimporter/mike.git@7cff0cc9bd434ff2db8d7c8c945d2a6befcba85f + # via -r requirements.in +mkdocs-autorefs==0.1.1 + # via mkdocstrings +mkdocs-gen-files==0.3.1 + # via -r requirements.in +mkdocs-literate-nav==0.3.0 + # via -r requirements.in +mkdocs-material-extensions==1.0.1 + # via mkdocs-material +mkdocs-material==7.0.3 + # via + # -r requirements.in + # mkdocs-material-extensions +mkdocs-section-index==0.2.3 + # via -r requirements.in +mkdocs==1.1.2 + # via + # mike + # mkdocs-autorefs + # mkdocs-gen-files + # mkdocs-literate-nav + # mkdocs-material + # mkdocs-section-index + # mkdocstrings +mkdocstrings-crystal==0.3.1 + # via -r requirements.in +mkdocstrings==0.15.0 + # via mkdocstrings-crystal +nltk==3.5 + # via lunr +pygments==2.8.0 + # via mkdocs-material +pymdown-extensions==8.1.1 + # via + # mkdocs-material + # mkdocstrings +pytkdocs==0.11.0 + # via mkdocstrings +pyyaml==5.4.1 + # via + # mike + # mkdocs +regex==2020.11.13 + # via nltk +six==1.15.0 + # via + # livereload + # lunr +tornado==6.1 + # via + # livereload + # mkdocs +tqdm==4.58.0 + # via nltk +verspec==0.1.0 + # via mike diff --git a/mkdocs.yml b/mkdocs.yml new file mode 100644 index 0000000..938c1be --- /dev/null +++ b/mkdocs.yml @@ -0,0 +1,42 @@ +site_name: crystal-db +site_url: https://oprypin.github.io/crystal-db/api/ +repo_url: https://github.com/oprypin/crystal-db +edit_uri: blob/master/docs/ +use_directory_urls: false + +theme: + name: material + icon: + repo: fontawesome/brands/github + features: + - navigation.sections +extra: + version: + provider: mike + +extra_css: + - css/mkdocstrings.css + +plugins: + - search + - gen-files: + scripts: + - docs/gen_doc_stubs.py + - mkdocstrings: + default_handler: crystal + watch: [src] + - literate-nav: + nav_file: SUMMARY.md + - section-index + - mike: + canonical_version: latest + +markdown_extensions: + - pymdownx.highlight + - pymdownx.magiclink + - pymdownx.saneheaders + - pymdownx.superfences + - pymdownx.tasklist + - deduplicate-toc + - toc: + permalink: "#" diff --git a/src/db.cr b/src/db.cr index b715cfd..befb313 100644 --- a/src/db.cr +++ b/src/db.cr @@ -5,6 +5,7 @@ require "log" # Individual database systems are supported by specific database driver shards. # # Available drivers include: +# # * [crystal-lang/crystal-sqlite3](https://github.com/crystal-lang/crystal-sqlite3) for SQLite # * [crystal-lang/crystal-mysql](https://github.com/crystal-lang/crystal-mysql) for MySQL and MariaDB # * [will/crystal-pg](https://github.com/will/crystal-pg) for PostgreSQL @@ -88,7 +89,7 @@ module DB alias Any = Union({{*TYPES}}) {% end %} - # Result of a `#exec` statement. + # Result of a `QueryMethods#exec` statement. record ExecResult, rows_affected : Int64, last_insert_id : Int64 # :nodoc: diff --git a/src/db/serializable.cr b/src/db/serializable.cr index 63b6579..c058a6a 100644 --- a/src/db/serializable.cr +++ b/src/db/serializable.cr @@ -44,6 +44,7 @@ module DB # ``` # # `DB::Field` properties: + # # * **ignore**: if `true`, skip this field in serialization and deserialization (`false` by default) # * **key**: defines which column to read from a `ResultSet` (name of the instance variable by default) # * **converter**: defines an alternate type for parsing results. The given type must define `#from_rs(DB::ResultSet)` and return an instance of the included type. diff --git a/src/spec.cr b/src/spec.cr index 225a419..35ed5b8 100644 --- a/src/spec.cr +++ b/src/spec.cr @@ -132,9 +132,10 @@ module DB @values = [] of ValueDef(DBAnyType) # Use *value* as sample value that should be stored in columns of type *sql_type*. - # *value_encoded* is driver specific expression that should generate that value in the database. - # *type_safe_value* indicates whether *value_encoded* is expected to generate the *value* even without - # been stored in a table (default `true`). + # + # * *value_encoded* is driver specific expression that should generate that value in the database. + # * *type_safe_value* indicates whether *value_encoded* is expected to generate the *value* even without + # been stored in a table (default `true`). def sample_value(value, sql_type, value_encoded, *, type_safe_value = true) @values << ValueDef(DBAnyType).new(value, sql_type, value_encoded)