This is an automated email from the ASF dual-hosted git repository. asorokoumov pushed a commit to branch website-poc-from-asf-template in repository https://gitbox.apache.org/repos/asf/hunter-website.git
commit a00241183b269eb98a1d1efed9196ca1772edf15 Author: Alex Sorokoumov <aleksandr.sorokou...@gmail.com> AuthorDate: Mon Feb 17 22:25:32 2025 -0800 Initial commit --- .gitignore | 20 + LICENSE | 201 ++++ NOTICE | 5 + README.md | 36 + babel.config.js | 22 + docs/basics.md | 179 ++++ docs/big-query.md | 24 + docs/contributing.md | 46 + docs/csv.md | 46 + docs/getting-started.md | 132 +++ docs/grafana.md | 66 ++ docs/graphite.md | 107 +++ docs/install.md | 19 + docs/overview.md | 21 + docs/postgresql.md | 120 +++ docs/sidebars.ts | 71 ++ docusaurus.config.ts | 156 +++ licenserc.toml | 32 + package.json | 47 + src/components/HomepageFeatures/index.tsx | 53 + src/components/HomepageFeatures/styles.module.css | 36 + src/css/custom.css | 59 ++ src/pages/index.module.css | 42 + src/pages/index.tsx | 38 + static/.nojekyll | 0 static/img/apache-incubator.svg | 1 + static/img/favicon.ico | Bin 0 -> 1595 bytes static/img/logo.svg | 1063 +++++++++++++++++++++ static/img/social-card.png | Bin 0 -> 219253 bytes tsconfig.json | 7 + 30 files changed, 2649 insertions(+) diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..b2d6de3 --- /dev/null +++ b/.gitignore @@ -0,0 +1,20 @@ +# Dependencies +/node_modules + +# Production +/build + +# Generated files +.docusaurus +.cache-loader + +# Misc +.DS_Store +.env.local +.env.development.local +.env.test.local +.env.production.local + +npm-debug.log* +yarn-debug.log* +yarn-error.log* diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..8dada3e --- /dev/null +++ b/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright {yyyy} {name of copyright owner} + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/NOTICE b/NOTICE new file mode 100644 index 0000000..e163d63 --- /dev/null +++ b/NOTICE @@ -0,0 +1,5 @@ +Apache Website Template +Copyright 2024 The Apache Software Foundation + +This product includes software developed at +The Apache Software Foundation (http://www.apache.org/). diff --git a/README.md b/README.md new file mode 100644 index 0000000..b413907 --- /dev/null +++ b/README.md @@ -0,0 +1,36 @@ +# Apache Website Template + +This project contains a template website that aims to follow all the various required Apache Website Policies. + +This template was generated using [Docusaurus](https://docusaurus.io/). + +## Usage + +You can directly copy from the root path of this template repository to your website repository. + +> [!NOTE] +> TODO: Integrate it with [template support of Docusaurus](https://docusaurus.io/docs/api/misc/create-docusaurus#git-strategy). + +Most of the configurations are inherited from Docusaurus https://docusaurus.io/docs/configuration. + +Specificly, our template defines a few metadata fields to customize for every project: + +```typescript +const projectName = "Template"; +const mainRepoName = "apache-website-template"; +const siteRepoName = "apache-website-template"; +``` + +For example, Apache Fury can customize these fields as: + +```typescript +const projectName = "Fury"; +const mainRepoName = "incubator-fury"; +const siteRepoName = "incubator-fury-site"; +``` + +More placeholders and preset are under developed. + +## Deploy + +This template contains [a GitHub Actions workflow](.github/workflows/deploy.yml) to deploy the generated website content to the `asf-site` branch. It would work automatically, without any other ections required. diff --git a/babel.config.js b/babel.config.js new file mode 100644 index 0000000..5c94bb7 --- /dev/null +++ b/babel.config.js @@ -0,0 +1,22 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +module.exports = { + presets: [require.resolve('@docusaurus/core/lib/babel/preset')], +}; diff --git a/docs/basics.md b/docs/basics.md new file mode 100644 index 0000000..2c179f2 --- /dev/null +++ b/docs/basics.md @@ -0,0 +1,179 @@ +# Basics + +## Listing Available Tests + +``` +otava list-groups +``` + +Lists all available test groups - high-level categories of tests. + +``` +otava list-tests [group name] +``` + +Lists all tests or the tests within a given group, if the group name is provided. + +## Listing Available Metrics for Tests + +To list all available metrics defined for the test: + +``` +otava list-metrics <test> +``` + +### Example + +:::tip +See [otava.yaml](https://github.com/apache/otava/tree/master/examples/csv/otava.yaml) for the full example configuration. +::: + +``` +$ otava list-metrics local.sample +metric1 +metric2 +``` + +## Finding Change Points + +``` +otava analyze <test>... +otava analyze <group>... +``` + +This command prints interesting results of all +runs of the test and a list of change-points. +A change-point is a moment when a metric value starts to differ significantly +from the values of the earlier runs and when the difference +is persistent and statistically significant that it is unlikely to happen by chance. +Otava calculates the probability (P-value) that the change point was caused +by chance - the closer to zero, the more "sure" it is about the regression or +performance improvement. The smaller is the actual magnitude of the change, +the more data points are needed to confirm the change, therefore Otava may +not notice the regression immediately after the first run that regressed. +However, it will eventually identify the specific commit that caused the regression, +as it analyzes the history of changes rather than just the HEAD of a branch. + +The `analyze` command accepts multiple tests or test groups. +The results are simply concatenated. + +### Example + +:::tip +See [otava.yaml](https://github.com/apache/otava/tree/master/examples/csv/otava.yaml) for the full +example configuration and [local_samples.csv](https://github.com/apache/otava/tree/master/examples/csv/data/local_samples.csv) +for the data. +::: + +``` +$ otava analyze local.sample --since=2024-01-01 +INFO: Computing change points for test sample.csv... +sample: +time metric1 metric2 +------------------------- --------- --------- +2021-01-01 02:00:00 +0000 154023 10.43 +2021-01-02 02:00:00 +0000 138455 10.23 +2021-01-03 02:00:00 +0000 143112 10.29 +2021-01-04 02:00:00 +0000 149190 10.91 +2021-01-05 02:00:00 +0000 132098 10.34 +2021-01-06 02:00:00 +0000 151344 10.69 + ········· + -12.9% + ········· +2021-01-07 02:00:00 +0000 155145 9.23 +2021-01-08 02:00:00 +0000 148889 9.11 +2021-01-09 02:00:00 +0000 149466 9.13 +2021-01-10 02:00:00 +0000 148209 9.03 +``` + +## Avoiding test definition duplication + +You may find that your test definitions are very similar to each other, e.g. they all have the same metrics. Instead +of copy-pasting the definitions you can use templating capability built-in otava to define the common bits of configs +separately. + +First, extract the common pieces to the `templates` section: +```yaml +templates: + common-metrics: + throughput: + suffix: client.throughput + response-time: + suffix: client.p50 + direction: -1 # lower is better + cpu-load: + suffix: server.cpu + direction: -1 # lower is better +``` + +Next you can recall a template in the `inherit` property of the test: + +```yaml +my-product.test-1: + type: graphite + tags: [perf-test, daily, my-product, test-1] + prefix: performance-tests.daily.my-product.test-1 + inherit: common-metrics +my-product.test-2: + type: graphite + tags: [perf-test, daily, my-product, test-2] + prefix: performance-tests.daily.my-product.test-2 + inherit: common-metrics +``` + +You can inherit more than one template. + +## Example + +The `otava regressions` command can work with feature branches. + +First you need to tell Otava how to fetch the data of the tests run against a feature branch. +The `prefix` property of the graphite test definition accepts `%{BRANCH}` variable, +which is substituted at the data import time by the branch name passed to `--branch` +command argument. Alternatively, if the prefix for the main branch of your product is different +from the prefix used for feature branches, you can define an additional `branch_prefix` property. + +```yaml +my-product.test-1: + type: graphite + tags: [perf-test, daily, my-product, test-1] + prefix: performance-tests.daily.%{BRANCH}.my-product.test-1 + inherit: common-metrics + +my-product.test-2: + type: graphite + tags: [perf-test, daily, my-product, test-2] + prefix: performance-tests.daily.master.my-product.test-2 + branch_prefix: performance-tests.feature.%{BRANCH}.my-product.test-2 + inherit: common-metrics +``` + +Now you can verify if correct data are imported by running +`otava analyze <test> --branch <branch>`. + +The `--branch` argument also works with `otava regressions`. In this case a comparison will be made +between the tail of the specified branch and the tail of the main branch (or a point of the +main branch specified by one of the `--since` selectors). + +``` +$ otava regressions <test or group> --branch <branch> +$ otava regressions <test or group> --branch <branch> --since <date> +$ otava regressions <test or group> --branch <branch> --since-version <version> +$ otava regressions <test or group> --branch <branch> --since-commit <commit> +``` + +Sometimes when working on a feature branch, you may run the tests multiple times, +creating more than one data point. To ignore the previous test results, and compare +only the last few points on the branch with the tail of the main branch, +use the `--last <n>` selector. E.g. to check regressions on the last run of the tests +on the feature branch: + +``` +$ otava regressions <test or group> --branch <branch> --last 1 +``` + +Please beware that performance validation based on a single data point is quite weak +and Otava might miss a regression if the point is not too much different from +the baseline. However, accuracy improves as more data points accumulate, and it is +a normal way of using Otava to just merge a feature and then revert if it is +flagged later. diff --git a/docs/big-query.md b/docs/big-query.md new file mode 100644 index 0000000..9dd8ecd --- /dev/null +++ b/docs/big-query.md @@ -0,0 +1,24 @@ +# Importing results from BigQuery + +## Schema + +See [schema.sql](https://github.com/apache/hunter/tree/master/examples/bigquery/schema.sql) for the example schema. + +## Usage + +Define BigQuery connection details via environment variables: + +```bash +export BIGQUERY_PROJECT_ID=... +export BIGQUERY_DATASET=... +export BIGQUERY_VAULT_SECRET=... +``` +or in `hunter.yaml`. + +Also configure the credentials. See [config_credentials.sh](https://github.com/apache/hunter/tree/master/examples/bigquery/config_credentials.sh) for an example. + +The following command shows results for a single test `aggregate_mem` and updates the database with newly found change points: + +```bash +$ BRANCH=trunk HUNTER_CONFIG=hunter.yaml hunter analyze aggregate_mem --update-bigquery +``` diff --git a/docs/contributing.md b/docs/contributing.md new file mode 100644 index 0000000..f195ef6 --- /dev/null +++ b/docs/contributing.md @@ -0,0 +1,46 @@ +# Setting up for development + +* Ensure that `python3` points to a version of python >= 3.8 (`python3 --version` will tell you). If it does not, use [pyenv](https://github.com/pyenv/pyenv) to both install a recent python version and make it your current python. + +* There are two wrappers (`poetryw` and `toxw`) that install and run the correct versions of [poetry](https://python-poetry.org) and [tox](https://tox.wiki) for you. + +* Run poetry to install dependencies: + +``` +./poetryw install +``` + +* Run the development version of hunter using poetry: + +``` +./poetryw run hunter ... +``` + +See the [poetry docs](https://python-poetry.org/docs) for more. + +# Running tests + +``` +./poetryw run pytest +``` + +...or using [tox](https://tox.readthedocs.io/): + +``` +./toxw +``` + +# Linting and formatting + +Code-style is enforced using [ruff](https://docs.astral.sh/ruff/) and [flake8](https://flake8.pycqa.org/); import optimisation is handled by [isort](https://pycqa.github.io/isort/) and [autoflake](https://pypi.org/project/autoflake/). Linting is automatically applied when tox runs tests; if linting fails, you can fix trivial problems with: + +``` +./toxw -e format +``` + + +# Build a docker image + +``` +./toxw -e docker-build +``` diff --git a/docs/csv.md b/docs/csv.md new file mode 100644 index 0000000..c813ba4 --- /dev/null +++ b/docs/csv.md @@ -0,0 +1,46 @@ +# Importing results from CSV + +:::tip +See [hunter.yaml](https://github.com/apache/hunter/tree/master/examples/csv/hunter.yaml) for the full example configuration. +::: + +## Tests + +```yaml +tests: + local.sample: + type: csv + file: tests/local_sample.csv + time_column: time + attributes: [commit] + metrics: [metric1, metric2] + csv_options: + delimiter: ',' + quotechar: "'" +``` + +## Example + +```bash +docker-compose -f examples/csv/docker-compose.yaml run --build hunter bin/hunter analyze local.sample +``` + +Expected output: + +```bash +time commit metric1 metric2 +------------------------- -------- --------- --------- +2024-01-01 02:00:00 +0000 aaa0 154023 10.43 +2024-01-02 02:00:00 +0000 aaa1 138455 10.23 +2024-01-03 02:00:00 +0000 aaa2 143112 10.29 +2024-01-04 02:00:00 +0000 aaa3 149190 10.91 +2024-01-05 02:00:00 +0000 aaa4 132098 10.34 +2024-01-06 02:00:00 +0000 aaa5 151344 10.69 + ········· + -12.9% + ········· +2024-01-07 02:00:00 +0000 aaa6 155145 9.23 +2024-01-08 02:00:00 +0000 aaa7 148889 9.11 +2024-01-09 02:00:00 +0000 aaa8 149466 9.13 +2024-01-10 02:00:00 +0000 aaa9 148209 9.03 +``` diff --git a/docs/getting-started.md b/docs/getting-started.md new file mode 100644 index 0000000..15d5250 --- /dev/null +++ b/docs/getting-started.md @@ -0,0 +1,132 @@ +# Getting Started + +## Installation + +Otava requires Python 3.8. If you don't have Python 3.8, use pyenv to install it. + +Use pipx to install otava: + +``` +pipx install git+ssh://g...@github.com/apache/otava +``` + +## Setup + +Copy the main configuration file `resources/otava.yaml` to `~/.otava/otava.yaml` and adjust data source configuration. + +:::tip +See docs on specific data sources to learn more about their configuration - [CSV](csv.md), [Graphite](graphite.md), +[PostgreSQL](postgresql.md), or [BigQuery](big-query.md). +::: + +Alternatively, it is possible to leave the config file as is, and provide credentials in the environment +by setting appropriate environment variables. +Environment variables are interpolated before interpreting the configuration file. + +## Defining tests + +All test configurations are defined in the main configuration file. +Otava supports reading data from and publishing results to a CSV file, [Graphite](https://graphiteapp.org/), +[PostgreSQL](https://www.postgresql.org/), and [BigQuery](https://cloud.google.com/bigquery). + +Tests are defined in the `tests` section. For example, the following definition will import results of the test from a CSV file: + +```yaml +tests: + local.sample: + type: csv + file: tests/resources/sample.csv + time_column: time + metrics: [metric1, metric2] + attributes: [commit] + csv_options: + delimiter: "," + quote_char: "'" +``` + +The `time_column` property points to the name of the column storing the timestamp +of each test-run. The data points will be ordered by that column. + +The `metrics` property selects the columns tha hold the values to be analyzed. These values must +be numbers convertible to floats. The `metrics` property can be not only a simple list of column +names, but it can also be a dictionary configuring other properties of each metric, +the column name or direction: + +```yaml +metrics: + resp_time_p99: + direction: -1 + column: p99 +``` + +Direction can be 1 or -1. If direction is set to 1, this means that the higher the metric, the +better the performance is. If it is set to -1, higher values mean worse performance. + +The `attributes` property describes any other columns that should be attached to the final +report. Special attribute `version` and `commit` can be used to query for a given time-range. + +:::tip +To learn how to avoid repeating the same configuration in multiple tests, see [Avoiding test definition duplication](basics.md#avoiding-test-definition-duplication). +::: + +## Listing Available Tests + +``` +otava list-groups +otava list-tests [group name] +``` + +## Listing Available Metrics for Tests + +To list all available metrics defined for the test: +``` +otava list-metrics <test> +``` + +## Finding Change Points + +:::tip +For more details, see [Finding Change Points](basics.md#finding-change-points) and +[Validating Performance of a Feature Branch](basics.md#validating-performance-of-a-feature-branch). +::: + +``` +otava analyze <test>... +otava analyze <group>... +``` + +This command prints interesting results of all runs of the test and a list of change-points. + +A change-point is a moment when a metric value starts to differ significantly from the values of the earlier runs and +when the difference is statistically significant. + +Otava calculates the probability (P-value) that the change point was caused by chance - the closer to zero, the more +"sure" it is about the regression or performance improvement. The smaller is the actual magnitude of the change, the +more data points are needed to confirm the change, therefore Otava may not notice the regression immediately after the first run +that regressed. + +The `analyze` command accepts multiple tests or test groups. +The results are simply concatenated. + +## Example + +``` +$ otava analyze local.sample +INFO: Computing change points for test sample.csv... +sample: +time metric1 metric2 +------------------------- --------- --------- +2021-01-01 02:00:00 +0000 154023 10.43 +2021-01-02 02:00:00 +0000 138455 10.23 +2021-01-03 02:00:00 +0000 143112 10.29 +2021-01-04 02:00:00 +0000 149190 10.91 +2021-01-05 02:00:00 +0000 132098 10.34 +2021-01-06 02:00:00 +0000 151344 10.69 + ········· + -12.9% + ········· +2021-01-07 02:00:00 +0000 155145 9.23 +2021-01-08 02:00:00 +0000 148889 9.11 +2021-01-09 02:00:00 +0000 149466 9.13 +2021-01-10 02:00:00 +0000 148209 9.03 +``` diff --git a/docs/grafana.md b/docs/grafana.md new file mode 100644 index 0000000..b25ed4b --- /dev/null +++ b/docs/grafana.md @@ -0,0 +1,66 @@ +# Annotating Change Points in Grafana + +Change points found by `analyze` can be exported +as Grafana annotations using the `--update-grafana` flag: + +``` +$ otava analyze <test or group> --update-grafana +``` + +The annotations generated by Otava get the following tags: +- `otava` +- `change-point` +- `test:<test name>` +- `metric:<metric name>` +- tags configured in the `tags` property of the test +- tags configured in the `annotate` property of the test +- tags configured in the `annotate` property of the metric + +Additionally, the `annotate` property supports variable tags: +- `%{TEST_NAME}` - name of the test +- `%{METRIC_NAME}` - name of the metric +- `%{GRAPHITE_PATH}` - resolves to the path to the data in Graphite +- `%{GRAPHITE_PATH_COMPONENTS}` - splits the path of the data in Graphite into separate components + and each path component is exported as a separate tag +- `%{GRAPHITE_PREFIX}` - resolves to the prefix of the path to the data in Graphite + (the part of the path up to the metric suffix) +- `%{GRAPHITE_PREFIX_COMPONENTS}` - similar as `%{GRAPHITE_PATH_COMPONENTS}` but splits the prefix +of the path instead of the path + +## Example + +:::tip +See [otava.yaml](https://github.com/apache/otava/tree/master/examples/graphite/otava.yaml) for the full Graphite & Grafana example. +::: + +Start docker-compose with Graphite in one tab: + +```bash +docker-compose -f examples/graphite/docker-compose.yaml up --force-recreate --always-recreate-deps --renew-anon-volumes --build +```` + + +Run otava in another tab: + +```bash +docker-compose -f examples/graphite/docker-compose.yaml run otava otava analyze my-product.test --since=-10m --update-grafana +``` + +Expected output: + +```bash +time run branch version commit throughput response_time cpu_usage +------------------------- ----- -------- --------- -------- ------------ --------------- ----------- +2024-12-14 22:45:10 +0000 61160 87 0.2 +2024-12-14 22:46:10 +0000 60160 85 0.3 +2024-12-14 22:47:10 +0000 60960 89 0.1 + ············ ··········· + -5.6% +300.0% + ············ ··········· +2024-12-14 22:48:10 +0000 57123 88 0.8 +2024-12-14 22:49:10 +0000 57980 87 0.9 +2024-12-14 22:50:10 +0000 56950 85 0.7 +``` + +Open local [Grafana](http://localhost:3000) in your browser (use default `admin/admin` credentials), open +`Benchmarks` dashboard, and see your data points and annotations on both charts.: diff --git a/docs/graphite.md b/docs/graphite.md new file mode 100644 index 0000000..51937cd --- /dev/null +++ b/docs/graphite.md @@ -0,0 +1,107 @@ +# Importing results from Graphite + +:::tip +See [otava.yaml](https://github.com/apache/otava/tree/master/examples/graphite/otava.yaml) for the full example configuration. +::: + +## Graphite and Grafana Connection + +The following block contains Graphite and Grafana connection details: + +```yaml +graphite: + url: ... + +grafana: + url: ... + user: ... + password: ... +``` + +These variables can be specified directly in `otava.yaml` or passed as environment variables: + +```yaml +graphite: + url: ${GRAPHITE_ADDRESS} + +grafana: + url: ${GRAFANA_ADDRESS} + user: ${GRAFANA_USER} + password: ${GRAFANA_PASSWORD} +``` + + +## Tests + +### Importing results from Graphite + +Test configuration contains queries selecting experiment data from Graphite. This is done by specifying the Graphite +path prefix common for all the test's metrics and suffixes for each of the metrics recorded by the test run. + +```yaml +tests: + my-product.test: + type: graphite + prefix: performance-tests.daily.my-product + metrics: + throughput: + suffix: client.throughput + response-time: + suffix: client.p50 + direction: -1 # lower is better + cpu-load: + suffix: server.cpu + direction: -1 # lower is better +``` + +### Tags + +> [!WARNING] +> Tags do not work as expected in the current version. See https://github.com/apache/otava/issues/24 for more details + +The optional `tags` property contains the tags that are used to query for Graphite events that store +additional test run metadata such as run identifier, commit, branch and product version information. + +The following command will post an event with the test run metadata: +```shell +$ curl -X POST "http://graphite_address/events/" \ + -d '{ + "what": "Performance Test", + "tags": ["perf-test", "daily", "my-product"], + "when": 1537884100, + "data": {"commit": "fe6583ab", "branch": "new-feature", "version": "0.0.1"} + }' +``` + +Posting those events is not mandatory, but when they are available, Otava is able to +filter data by commit or version using `--since-commit` or `--since-version` selectors. + +## Example + +Start docker-compose with Graphite in one tab: + +```bash +docker-compose -f examples/graphite/docker-compose.yaml up --force-recreate --always-recreate-deps --renew-anon-volumes --build +```` + +Run otava in another tab: + +```bash +docker-compose -f examples/graphite/docker-compose.yaml run otava otava analyze my-product.test --since=-10m +``` + +Expected output: + +```bash +time run branch version commit throughput response_time cpu_usage +------------------------- ----- -------- --------- -------- ------------ --------------- ----------- +2024-12-14 22:45:10 +0000 61160 87 0.2 +2024-12-14 22:46:10 +0000 60160 85 0.3 +2024-12-14 22:47:10 +0000 60960 89 0.1 + ············ ··········· + -5.6% +300.0% + ············ ··········· +2024-12-14 22:48:10 +0000 57123 88 0.8 +2024-12-14 22:49:10 +0000 57980 87 0.9 +2024-12-14 22:50:10 +0000 56950 85 0.7 +``` diff --git a/docs/install.md b/docs/install.md new file mode 100644 index 0000000..470f808 --- /dev/null +++ b/docs/install.md @@ -0,0 +1,19 @@ +# Installation + +## Install using pipx + +Otava requires Python 3.8. If you don't have python 3.8, use pyenv to install it. + +Use pipx to install otava: + +``` +pipx install git+ssh://g...@github.com/apache/otava +``` + +## Build Docker container + +To build the Docker container, run the following command: + +```bash +docker build -t otava . +``` diff --git a/docs/overview.md b/docs/overview.md new file mode 100644 index 0000000..f5a18db --- /dev/null +++ b/docs/overview.md @@ -0,0 +1,21 @@ +--- +sidebar_label: About +sidebar_position: 1 +--- + +# Welcome to Apache Otava® + +## Getting Started +- [Installation](install.md) +- [Getting Started](getting-started.md) +- [Contributing](contributing.md) +- [Basics](basics.md) + +## Data Sources +- [Graphite](graphite.md) +- [PostgreSQL](postgresql.md) +- [BigQuery](big-query.md) +- [CSV](csv.md) +- [Annotating Change Points in Grafana](grafana.md) + +This is a demo page for the portal page of documentation. Remember to follow the trademark [policy](https://www.apache.org/foundation/marks/) and [guide](https://www.apache.org/foundation/marks/guide) to provide your content. diff --git a/docs/postgresql.md b/docs/postgresql.md new file mode 100644 index 0000000..63ede39 --- /dev/null +++ b/docs/postgresql.md @@ -0,0 +1,120 @@ +# Importing results from PostgreSQL + +:::tip +See [otava.yaml](https://github.com/apache/otava/tree/master/examples/postgresql/otava.yaml) for the full example configuration. +::: + +## PostgreSQL Connection +The following block contains PostgreSQL connection details: + +```yaml +postgres: + hostname: ... + port: ... + username: ... + password: ... + database: ... +``` + +These variables can be specified directly in `otava.yaml` or passed as environment variables: + +```yaml +postgres: + hostname: ${POSTGRES_HOSTNAME} + port: ${POSTGRES_PORT} + username: ${POSTGRES_USERNAME} + password: ${POSTGRES_PASSWORD} + database: ${POSTGRES_DATABASE} +``` + +## Tests + +Test configuration contains queries selecting experiment data, a time column, and a list of columns to analyze: + +```yaml +tests: + aggregate_mem: + type: postgres + time_column: commit_ts + attributes: [experiment_id, config_id, commit] + metrics: + process_cumulative_rate_mean: + direction: 1 + scale: 1 + process_cumulative_rate_stderr: + direction: -1 + scale: 1 + process_cumulative_rate_diff: + direction: -1 + scale: 1 + query: | + SELECT e.commit, + e.commit_ts, + r.process_cumulative_rate_mean, + r.process_cumulative_rate_stderr, + r.process_cumulative_rate_diff, + r.experiment_id, + r.config_id + FROM results r + INNER JOIN configs c ON r.config_id = c.id + INNER JOIN experiments e ON r.experiment_id = e.id + WHERE e.exclude_from_analysis = false AND + e.branch = 'trunk' AND + e.username = 'ci' AND + c.store = 'MEM' AND + c.cache = true AND + c.benchmark = 'aggregate' AND + c.instance_type = 'ec2i3.large' + ORDER BY e.commit_ts ASC; +``` + +## Example + +### Usage + +Start docker-compose with PostgreSQL in one tab: + +```bash +docker-compose -f examples/postgresql/docker-compose.yaml up --force-recreate --always-recreate-deps --renew-anon-volumes +```` + +Run Otava in the other tab to show results for a single test `aggregate_mem` and update the database with newly found change points: + +```bash +docker-compose -f examples/postgresql/docker-compose.yaml run --build otava bin/otava analyze aggregate_mem --update-postgres +``` + +Expected output: + +```bash 0.0s +time experiment_id commit process_cumulative_rate_mean process_cumulative_rate_stderr process_cumulative_rate_diff +------------------------- ------------------ -------- ------------------------------ -------------------------------- ------------------------------ +2024-03-13 10:03:02 +0000 aggregate-36e5ccd2 36e5ccd2 61160 2052 13558 +2024-03-25 10:03:02 +0000 aggregate-d5460f38 d5460f38 60160 2142 13454 +2024-04-02 10:03:02 +0000 aggregate-bc9425cb bc9425cb 60960 2052 13053 + ······························ + -5.6% + ······························ +2024-04-06 10:03:02 +0000 aggregate-14df1b11 14df1b11 57123 2052 14052 +2024-04-13 10:03:02 +0000 aggregate-ac40c0d8 ac40c0d8 57980 2052 13521 +2024-04-27 10:03:02 +0000 aggregate-0af4ccbc 0af4ccbc 56950 2052 13532 +``` + +### Configuration + +See [otava.yaml](../examples/postgresql/otava.yaml) for the example configuration: +* Block `postgres` contains connection details to the PostgreSQL database. +* Block `templates` contains common pieces of configuration used by all tests - time column and a list of attributes and metrics. +* Block `tests` contains configuration for the individual tests, specifically a query that fetches analyzed columns sorted by commit timestamp. + +[schema.sql](../examples/postgresql/init-db/schema.sql) contains the schema used in this example. + +[docker-compose.yaml](../examples/postgresql/docker-compose.yaml) contains example config required to connect to PosgreSQL: +1. `POSTGRES_*` environment variables are used to pass connection details to the container. +2. `HUNTER_CONFIG` is the path to the configuration file described above. +3. `BRANCH` variable is used within `HUNTER_CONFIG` to analyze experiment results only for a specific branch. + + +### CLI arguments + +* `--update-postgres` - updates the database with newly found change points. diff --git a/docs/sidebars.ts b/docs/sidebars.ts new file mode 100644 index 0000000..dddd05e --- /dev/null +++ b/docs/sidebars.ts @@ -0,0 +1,71 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import type { SidebarsConfig } from "@docusaurus/plugin-content-docs"; + +// Check https://docusaurus.io/docs/sidebar/ for more information. +const sidebars: SidebarsConfig = { + docs: [ + { + type: "doc", + id: "overview", + label: "About", + }, + { + type: "category", + label: "Getting Started", + items: ["install", "getting-started", "contributing", "basics"], + collapsed: false, + }, + { + type: "category", + label: "Data Sources", + items: [ + { + type: "doc", + id: "graphite", + label: "Graphite", + }, + { + type: "doc", + id: "postgresql", + label: "PostgreSQL", + }, + { + type: "doc", + id: "big-query", + label: "BigQuery", + }, + { + type: "doc", + id: "csv", + label: "CSV", + }, + { + type: "doc", + id: "grafana", + label: "Grafana", + }, + ], + collapsed: false, + }, + ], +}; + +export default sidebars; diff --git a/docusaurus.config.ts b/docusaurus.config.ts new file mode 100644 index 0000000..b5d58ef --- /dev/null +++ b/docusaurus.config.ts @@ -0,0 +1,156 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { themes as prismThemes } from "prism-react-renderer"; +import type { Config } from "@docusaurus/types"; +import type * as Preset from "@docusaurus/preset-classic"; + +const projectName = "Otava"; +const mainRepoName = "otava"; +const siteRepoName = "otava-website"; + +const config: Config = { + title: `Apache ${projectName}`, + tagline: `Welcome to Apache ${projectName}!`, + favicon: "img/favicon.ico", + + url: `https://${projectName.toLowerCase()}.apache.org/`, + baseUrl: "/", + + onBrokenLinks: "throw", + onBrokenMarkdownLinks: "throw", + + // Even if you don't use internationalization, you can use this field to set + // useful metadata like html lang. For example, if your site is Chinese, you + // may want to replace "en" with "zh-Hans". + i18n: { + defaultLocale: "en", + locales: ["en"], + }, + + presets: [ + [ + "classic", + { + docs: { + sidebarPath: "./docs/sidebars.ts", + editUrl: `https://github.com/apache/${siteRepoName}/tree/main/`, + }, + blog: { + blogSidebarCount: "ALL", + blogSidebarTitle: "All our posts", + showReadingTime: true, + editUrl: `https://github.com/apache/${siteRepoName}/tree/main/`, + }, + theme: { + customCss: "./src/css/custom.css", + }, + } satisfies Preset.Options, + ], + ], + + themeConfig: { + // TODO: Replace with your project's social card + image: "img/social-card.png", + navbar: { + logo: { + alt: "Logo", + src: "img/logo.svg", + }, + items: [ + { + type: "docSidebar", + sidebarId: "docs", + position: "right", + label: "Docs", + }, + { + type: "dropdown", + label: "ASF", + position: "right", + items: [ + { + label: "Foundation", + to: "https://www.apache.org/", + }, + { + label: "License", + to: "https://www.apache.org/licenses/", + }, + { + label: "Events", + to: "https://www.apache.org/events/current-event.html", + }, + { + label: "Privacy", + to: "https://privacy.apache.org/policies/privacy-policy-public.html", + }, + { + label: "Security", + to: "https://www.apache.org/security/", + }, + { + label: "Sponsorship", + to: "https://www.apache.org/foundation/sponsorship.html", + }, + { + label: "Thanks", + to: "https://www.apache.org/foundation/thanks.html", + }, + { + label: "Code of Conduct", + to: "https://www.apache.org/foundation/policies/conduct.html", + }, + ], + }, + { + href: `https://github.com/apache/${mainRepoName}`, + position: "right", + className: "header-github-link", + "aria-label": "GitHub repository", + }, + ], + }, + footer: { + style: "dark", + links: [], + logo: { + width: 200, + src: "/img/apache-incubator.svg", + href: "https://incubator.apache.org/", + alt: "Apache Incubator logo", + }, + copyright: `<div> + <p> + Apache ${projectName} is an effort undergoing incubation at The Apache Software Foundation (ASF), sponsored by the Apache Incubator. Incubation is required of all newly accepted projects until a further review indicates that the infrastructure, communications, and decision making process have stabilized in a manner consistent with other successful ASF projects. While incubation status is not necessarily a reflection of the completeness or stability of the code, it does indicate t [...] + </p> + <p> + Copyright © ${new Date().getFullYear()} The Apache Software Foundation, Licensed under the Apache License, Version 2.0. <br/> + Apache, the names of Apache projects, and the feather logo are either registered trademarks or trademarks of the Apache Software Foundation in the United States and/or other countries. + </p> + </div>`, + }, + prism: { + theme: prismThemes.github, + darkTheme: prismThemes.dracula, + }, + } satisfies Preset.ThemeConfig, +}; + +export default config; diff --git a/licenserc.toml b/licenserc.toml new file mode 100644 index 0000000..dda7ce0 --- /dev/null +++ b/licenserc.toml @@ -0,0 +1,32 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +headerPath = "Apache-2.0-ASF.txt" + +excludes = [ + # Website generated files + "build", + ".docusaurus", + + # Documents + "**/*.md", + "**/*.mdx", + + # Meta files + "NOTICE", + ".nojekyll", +] diff --git a/package.json b/package.json new file mode 100644 index 0000000..90628fe --- /dev/null +++ b/package.json @@ -0,0 +1,47 @@ +{ + "name": "apache-website-template", + "version": "0.0.0", + "private": true, + "scripts": { + "docusaurus": "docusaurus", + "start": "docusaurus start", + "build": "docusaurus build", + "swizzle": "docusaurus swizzle", + "deploy": "docusaurus deploy", + "clear": "docusaurus clear", + "serve": "docusaurus serve", + "write-translations": "docusaurus write-translations", + "write-heading-ids": "docusaurus write-heading-ids", + "typecheck": "tsc" + }, + "dependencies": { + "@docusaurus/core": "3.6.3", + "@docusaurus/preset-classic": "3.6.3", + "@mdx-js/react": "^3.1.0", + "clsx": "^2.1.1", + "prism-react-renderer": "^2.4.0", + "react": "^19.0.0", + "react-dom": "^19.0.0" + }, + "devDependencies": { + "@docusaurus/module-type-aliases": "3.6.3", + "@docusaurus/tsconfig": "3.6.3", + "@docusaurus/types": "3.6.3", + "typescript": "5.7.2" + }, + "browserslist": { + "production": [ + ">0.5%", + "not dead", + "not op_mini all" + ], + "development": [ + "last 3 chrome version", + "last 3 firefox version", + "last 5 safari version" + ] + }, + "engines": { + "node": ">=18.0" + } +} \ No newline at end of file diff --git a/src/components/HomepageFeatures/index.tsx b/src/components/HomepageFeatures/index.tsx new file mode 100644 index 0000000..879b597 --- /dev/null +++ b/src/components/HomepageFeatures/index.tsx @@ -0,0 +1,53 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import clsx from "clsx"; +import styles from "./styles.module.css"; + +export default function HomepageFeatures(): JSX.Element { + return ( + <section className={styles.features}> + <div className="container"> + <div className={clsx("text--center", "padding-horiz--md")}> + <h2>Otava - Mapping Performance Changes</h2> + <p className={styles.description}> + Otava performs statistical analysis of performance test results + stored in CSV files, PostgreSQL, BigQuery, or Graphite database. It + finds change-points and notifies about possible performance + regressions. + </p> + <div className={styles.buttons}> + <a + href="/docs/getting-started" + className="button button--primary button--lg" + > + Get Started + </a> + <a + href="https://github.com/apache/otava" + className="button button--secondary button--lg" + > + Source Code + </a> + </div> + </div> + </div> + </section> + ); +} diff --git a/src/components/HomepageFeatures/styles.module.css b/src/components/HomepageFeatures/styles.module.css new file mode 100644 index 0000000..9657b9e --- /dev/null +++ b/src/components/HomepageFeatures/styles.module.css @@ -0,0 +1,36 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +.features { + padding: 2rem 0; + width: 100%; +} +.description { + max-width: 800px; + margin: 0 auto 2rem; + font-size: 1.2rem; + line-height: 1.6; +} + +.buttons { + display: flex; + align-items: center; + justify-content: center; + gap: 1rem; +} diff --git a/src/css/custom.css b/src/css/custom.css new file mode 100644 index 0000000..d1ef6c4 --- /dev/null +++ b/src/css/custom.css @@ -0,0 +1,59 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +:root { + --ifm-color-primary: #3071a9; + --ifm-code-font-size: 95%; + --docusaurus-highlighted-code-line-bg: rgba(0, 0, 0, 0.1); + --ifm-footer-background-color:rgba(115, 150, 233, 0.61); +} + +[data-theme='dark'] { + --docusaurus-highlighted-code-line-bg: rgba(0, 0, 0, 0.3); +} + +.navbar__logo img { + width: 80%; +} + +.header-github-link:hover { + opacity: 0.6; +} + +.header-github-link::before { + content: ''; + width: 24px; + height: 24px; + display: flex; + background: url("data:image/svg+xml,%3Csvg viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.52 [...] + no-repeat; +} + +[data-theme='dark'] .header-github-link::before { + background: url("data:image/svg+xml,%3Csvg viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath fill='white' d='M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135- [...] + no-repeat; +} + +.footer__copyright { + font-size: .7em; +} + +.footer__links { + text-align: center; +} diff --git a/src/pages/index.module.css b/src/pages/index.module.css new file mode 100644 index 0000000..55ce941 --- /dev/null +++ b/src/pages/index.module.css @@ -0,0 +1,42 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +/** + * CSS files with the .module.css suffix will be treated as CSS modules + * and scoped locally. + */ + +.heroBanner { + padding: 4rem 0; + text-align: center; + position: relative; + overflow: hidden; +} + +@media screen and (max-width: 996px) { + .heroBanner { + padding: 2rem; + } +} + +.buttons { + display: flex; + align-items: center; + justify-content: center; +} diff --git a/src/pages/index.tsx b/src/pages/index.tsx new file mode 100644 index 0000000..9e51bc6 --- /dev/null +++ b/src/pages/index.tsx @@ -0,0 +1,38 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import clsx from "clsx"; +import Layout from "@theme/Layout"; +import styles from "./index.module.css"; +import HomepageFeatures from "../components/HomepageFeatures"; + +export default function Home(): JSX.Element { + return ( + <Layout title="Welcome"> + <header className={clsx("hero", styles.heroBanner)}> + <div className="container"> + <h1 className="hero__title">Apache Otava®</h1> + </div> + </header> + <main> + <HomepageFeatures /> + </main> + </Layout> + ); +} diff --git a/static/.nojekyll b/static/.nojekyll new file mode 100644 index 0000000..e69de29 diff --git a/static/img/apache-incubator.svg b/static/img/apache-incubator.svg new file mode 100644 index 0000000..1b4c364 --- /dev/null +++ b/static/img/apache-incubator.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 473.26 110.22"><defs><style>.cls-1,.cls-2{fill:#fff;}.cls-1{fill-rule:evenodd;}</style></defs><g id="Layer_2" data-name="Layer 2"><g id="Layer_1-2" data-name="Layer 1"><polygon class="cls-1" points="445.81 13.29 467.03 13.29 467.03 15.29 448.03 15.29 448.03 27.09 465.11 27.09 465.11 29.09 448.03 29.09 448.03 41.1 467.24 41.1 467.24 43.11 445.81 43.11 445.81 13.29"/><polygon class="cls-1" points="377.65 13.29 379.86 13.29 379.86 27.13 3 [...] \ No newline at end of file diff --git a/static/img/favicon.ico b/static/img/favicon.ico new file mode 100644 index 0000000..b6b6c2c Binary files /dev/null and b/static/img/favicon.ico differ diff --git a/static/img/logo.svg b/static/img/logo.svg new file mode 100644 index 0000000..33c174e --- /dev/null +++ b/static/img/logo.svg @@ -0,0 +1,1063 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> + +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + width="11.699139in" + height="4.7441311in" + viewBox="0 0 1052.9225 426.9718" + id="svg4398" + version="1.1" + inkscape:version="0.92.3 (2405546, 2018-03-11)" + sodipodi:docname="foundation.svg"> + <defs + id="defs4400"> + <linearGradient + id="SVGID_1_" + gradientUnits="userSpaceOnUse" + x1="-6873.6479" + y1="2774.2998" + x2="-6636.2373" + y2="2496.6895" + gradientTransform="matrix(0.4345,-0.9318,-0.9318,-0.4345,6223.4761,-5052.7427)"> + <stop + offset="0" + style="stop-color:#F59723" + id="stop3172" /> + <stop + offset="0.3123" + style="stop-color:#F69822" + id="stop3174" /> + <stop + offset="0.8383" + style="stop-color:#E87726" + id="stop3176" /> + </linearGradient> + <linearGradient + id="SVGID_2_" + gradientUnits="userSpaceOnUse" + x1="-8630.7197" + y1="2804.9607" + x2="-6936.9253" + y2="2804.9607" + gradientTransform="matrix(0.4345,-0.9318,-0.9318,-0.4345,6223.4761,-5052.7427)"> + <stop + offset="0.3233" + style="stop-color:#9C2063" + id="stop3197" /> + <stop + offset="0.6302" + style="stop-color:#C82037" + id="stop3199" /> + <stop + offset="0.7514" + style="stop-color:#CC2135" + id="stop3201" /> + <stop + offset="1" + style="stop-color:#E87726" + id="stop3203" /> + </linearGradient> + <linearGradient + id="SVGID_3_" + gradientUnits="userSpaceOnUse" + x1="-8426.2559" + y1="2635.2839" + x2="-7416.9194" + y2="2635.2839" + gradientTransform="matrix(0.4345,-0.9318,-0.9318,-0.4345,6223.4761,-5052.7427)"> + <stop + offset="0" + style="stop-color:#282661" + id="stop3208" /> + <stop + offset="9.548389e-02" + style="stop-color:#662E8C" + id="stop3210" /> + <stop + offset="0.7882" + style="stop-color:#9E2064" + id="stop3212" /> + <stop + offset="0.9487" + style="stop-color:#CC2032" + id="stop3214" /> + </linearGradient> + <linearGradient + id="SVGID_4_" + gradientUnits="userSpaceOnUse" + x1="-8535.5879" + y1="2820.8604" + x2="-6841.793" + y2="2820.8604" + gradientTransform="matrix(0.4345,-0.9318,-0.9318,-0.4345,6223.4761,-5052.7427)"> + <stop + offset="0.3233" + style="stop-color:#9C2063" + id="stop3219" /> + <stop + offset="0.6302" + style="stop-color:#C82037" + id="stop3221" /> + <stop + offset="0.7514" + style="stop-color:#CC2135" + id="stop3223" /> + <stop + offset="1" + style="stop-color:#E87726" + id="stop3225" /> + </linearGradient> + <linearGradient + id="SVGID_5_" + gradientUnits="userSpaceOnUse" + x1="-8412.0576" + y1="2797.8789" + x2="-7521.9175" + y2="2797.8789" + gradientTransform="matrix(0.4345,-0.9318,-0.9318,-0.4345,6223.4761,-5052.7427)"> + <stop + offset="0" + style="stop-color:#282661" + id="stop3230" /> + <stop + offset="9.548389e-02" + style="stop-color:#662E8C" + id="stop3232" /> + <stop + offset="0.7882" + style="stop-color:#9E2064" + id="stop3234" /> + <stop + offset="0.9487" + style="stop-color:#CC2032" + id="stop3236" /> + </linearGradient> + <linearGradient + id="SVGID_6_" + gradientUnits="userSpaceOnUse" + x1="-8535.5879" + y1="2645.4897" + x2="-6841.793" + y2="2645.4897" + gradientTransform="matrix(0.4345,-0.9318,-0.9318,-0.4345,6223.4761,-5052.7427)"> + <stop + offset="0.3233" + style="stop-color:#9C2063" + id="stop3241" /> + <stop + offset="0.6302" + style="stop-color:#C82037" + id="stop3243" /> + <stop + offset="0.7514" + style="stop-color:#CC2135" + id="stop3245" /> + <stop + offset="1" + style="stop-color:#E87726" + id="stop3247" /> + </linearGradient> + <linearGradient + id="SVGID_7_" + gradientUnits="userSpaceOnUse" + x1="-8640.6592" + y1="2654.2649" + x2="-6946.8647" + y2="2654.2649" + gradientTransform="matrix(0.4345,-0.9318,-0.9318,-0.4345,6223.4761,-5052.7427)"> + <stop + offset="0.3233" + style="stop-color:#9C2063" + id="stop3252" /> + <stop + offset="0.6302" + style="stop-color:#C82037" + id="stop3254" /> + <stop + offset="0.7514" + style="stop-color:#CC2135" + id="stop3256" /> + <stop + offset="1" + style="stop-color:#E87726" + id="stop3258" /> + </linearGradient> + <linearGradient + id="SVGID_8_" + gradientUnits="userSpaceOnUse" + x1="-8535.5889" + y1="2593.446" + x2="-6841.7925" + y2="2593.446" + gradientTransform="matrix(0.4345,-0.9318,-0.9318,-0.4345,6223.4761,-5052.7427)"> + <stop + offset="0.3233" + style="stop-color:#9C2063" + id="stop3267" /> + <stop + offset="0.6302" + style="stop-color:#C82037" + id="stop3269" /> + <stop + offset="0.7514" + style="stop-color:#CC2135" + id="stop3271" /> + <stop + offset="1" + style="stop-color:#E87726" + id="stop3273" /> + </linearGradient> + <linearGradient + id="SVGID_9_" + gradientUnits="userSpaceOnUse" + x1="-8535.5889" + y1="2599.3242" + x2="-6841.7925" + y2="2599.3242" + gradientTransform="matrix(0.4345,-0.9318,-0.9318,-0.4345,6223.4761,-5052.7427)"> + <stop + offset="0.3233" + style="stop-color:#9C2063" + id="stop3282" /> + <stop + offset="0.6302" + style="stop-color:#C82037" + id="stop3284" /> + <stop + offset="0.7514" + style="stop-color:#CC2135" + id="stop3286" /> + <stop + offset="1" + style="stop-color:#E87726" + id="stop3288" /> + </linearGradient> + <linearGradient + id="SVGID_10_" + gradientUnits="userSpaceOnUse" + x1="-7584.0386" + y1="2600.5515" + x2="-7209.6543" + y2="2600.5515" + gradientTransform="matrix(0.4345,-0.9318,-0.9318,-0.4345,6223.4761,-5052.7427)"> + <stop + offset="0.3233" + style="stop-color:#9C2063" + id="stop3297" /> + <stop + offset="0.6302" + style="stop-color:#C82037" + id="stop3299" /> + <stop + offset="0.7514" + style="stop-color:#CC2135" + id="stop3301" /> + <stop + offset="1" + style="stop-color:#E87726" + id="stop3303" /> + </linearGradient> + <linearGradient + id="SVGID_1_-7" + gradientUnits="userSpaceOnUse" + x1="-6873.6479" + y1="2774.2998" + x2="-6636.2373" + y2="2496.6895" + gradientTransform="matrix(0.4345,-0.9318,-0.9318,-0.4345,6223.4761,-5052.7427)"> + <stop + offset="0" + style="stop-color:#F59723" + id="stop3172-5" /> + <stop + offset="0.3123" + style="stop-color:#F69822" + id="stop3174-3" /> + <stop + offset="0.8383" + style="stop-color:#E87726" + id="stop3176-5" /> + </linearGradient> + <linearGradient + id="SVGID_2_-6" + gradientUnits="userSpaceOnUse" + x1="-8630.7197" + y1="2804.9607" + x2="-6936.9253" + y2="2804.9607" + gradientTransform="matrix(0.4345,-0.9318,-0.9318,-0.4345,6223.4761,-5052.7427)"> + <stop + offset="0.3233" + style="stop-color:#9C2063" + id="stop3197-2" /> + <stop + offset="0.6302" + style="stop-color:#C82037" + id="stop3199-9" /> + <stop + offset="0.7514" + style="stop-color:#CC2135" + id="stop3201-1" /> + <stop + offset="1" + style="stop-color:#E87726" + id="stop3203-2" /> + </linearGradient> + <linearGradient + id="SVGID_3_-7" + gradientUnits="userSpaceOnUse" + x1="-8426.2559" + y1="2635.2839" + x2="-7416.9194" + y2="2635.2839" + gradientTransform="matrix(0.4345,-0.9318,-0.9318,-0.4345,6223.4761,-5052.7427)"> + <stop + offset="0" + style="stop-color:#282661" + id="stop3208-0" /> + <stop + offset="9.548389e-02" + style="stop-color:#662E8C" + id="stop3210-9" /> + <stop + offset="0.7882" + style="stop-color:#9E2064" + id="stop3212-3" /> + <stop + offset="0.9487" + style="stop-color:#CC2032" + id="stop3214-6" /> + </linearGradient> + <linearGradient + id="SVGID_4_-0" + gradientUnits="userSpaceOnUse" + x1="-8535.5879" + y1="2820.8604" + x2="-6841.793" + y2="2820.8604" + gradientTransform="matrix(0.4345,-0.9318,-0.9318,-0.4345,6223.4761,-5052.7427)"> + <stop + offset="0.3233" + style="stop-color:#9C2063" + id="stop3219-6" /> + <stop + offset="0.6302" + style="stop-color:#C82037" + id="stop3221-2" /> + <stop + offset="0.7514" + style="stop-color:#CC2135" + id="stop3223-6" /> + <stop + offset="1" + style="stop-color:#E87726" + id="stop3225-1" /> + </linearGradient> + <linearGradient + id="SVGID_5_-8" + gradientUnits="userSpaceOnUse" + x1="-8412.0576" + y1="2797.8789" + x2="-7521.9175" + y2="2797.8789" + gradientTransform="matrix(0.4345,-0.9318,-0.9318,-0.4345,6223.4761,-5052.7427)"> + <stop + offset="0" + style="stop-color:#282661" + id="stop3230-7" /> + <stop + offset="9.548389e-02" + style="stop-color:#662E8C" + id="stop3232-9" /> + <stop + offset="0.7882" + style="stop-color:#9E2064" + id="stop3234-2" /> + <stop + offset="0.9487" + style="stop-color:#CC2032" + id="stop3236-0" /> + </linearGradient> + <linearGradient + id="SVGID_6_-2" + gradientUnits="userSpaceOnUse" + x1="-8535.5879" + y1="2645.4897" + x2="-6841.793" + y2="2645.4897" + gradientTransform="matrix(0.4345,-0.9318,-0.9318,-0.4345,6223.4761,-5052.7427)"> + <stop + offset="0.3233" + style="stop-color:#9C2063" + id="stop3241-3" /> + <stop + offset="0.6302" + style="stop-color:#C82037" + id="stop3243-7" /> + <stop + offset="0.7514" + style="stop-color:#CC2135" + id="stop3245-5" /> + <stop + offset="1" + style="stop-color:#E87726" + id="stop3247-9" /> + </linearGradient> + <linearGradient + id="SVGID_7_-2" + gradientUnits="userSpaceOnUse" + x1="-8640.6592" + y1="2654.2649" + x2="-6946.8647" + y2="2654.2649" + gradientTransform="matrix(0.4345,-0.9318,-0.9318,-0.4345,6223.4761,-5052.7427)"> + <stop + offset="0.3233" + style="stop-color:#9C2063" + id="stop3252-2" /> + <stop + offset="0.6302" + style="stop-color:#C82037" + id="stop3254-8" /> + <stop + offset="0.7514" + style="stop-color:#CC2135" + id="stop3256-9" /> + <stop + offset="1" + style="stop-color:#E87726" + id="stop3258-7" /> + </linearGradient> + <linearGradient + id="SVGID_8_-3" + gradientUnits="userSpaceOnUse" + x1="-8535.5889" + y1="2593.446" + x2="-6841.7925" + y2="2593.446" + gradientTransform="matrix(0.4345,-0.9318,-0.9318,-0.4345,6223.4761,-5052.7427)"> + <stop + offset="0.3233" + style="stop-color:#9C2063" + id="stop3267-6" /> + <stop + offset="0.6302" + style="stop-color:#C82037" + id="stop3269-1" /> + <stop + offset="0.7514" + style="stop-color:#CC2135" + id="stop3271-2" /> + <stop + offset="1" + style="stop-color:#E87726" + id="stop3273-9" /> + </linearGradient> + <linearGradient + id="SVGID_9_-3" + gradientUnits="userSpaceOnUse" + x1="-8535.5889" + y1="2599.3242" + x2="-6841.7925" + y2="2599.3242" + gradientTransform="matrix(0.4345,-0.9318,-0.9318,-0.4345,6223.4761,-5052.7427)"> + <stop + offset="0.3233" + style="stop-color:#9C2063" + id="stop3282-1" /> + <stop + offset="0.6302" + style="stop-color:#C82037" + id="stop3284-9" /> + <stop + offset="0.7514" + style="stop-color:#CC2135" + id="stop3286-4" /> + <stop + offset="1" + style="stop-color:#E87726" + id="stop3288-7" /> + </linearGradient> + <linearGradient + id="SVGID_10_-8" + gradientUnits="userSpaceOnUse" + x1="-7584.0386" + y1="2600.5515" + x2="-7209.6543" + y2="2600.5515" + gradientTransform="matrix(0.4345,-0.9318,-0.9318,-0.4345,6223.4761,-5052.7427)"> + <stop + offset="0.3233" + style="stop-color:#9C2063" + id="stop3297-4" /> + <stop + offset="0.6302" + style="stop-color:#C82037" + id="stop3299-5" /> + <stop + offset="0.7514" + style="stop-color:#CC2135" + id="stop3301-0" /> + <stop + offset="1" + style="stop-color:#E87726" + id="stop3303-3" /> + </linearGradient> + </defs> + <sodipodi:namedview + id="base" + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1.0" + inkscape:pageopacity="0.0" + inkscape:pageshadow="2" + inkscape:zoom="0.98994949" + inkscape:cx="705.0122" + inkscape:cy="399.14686" + inkscape:document-units="px" + inkscape:current-layer="layer1" + showgrid="false" + units="in" + inkscape:window-width="3726" + inkscape:window-height="2049" + inkscape:window-x="114" + inkscape:window-y="55" + inkscape:window-maximized="1" + fit-margin-top="0" + fit-margin-left="0" + fit-margin-right="0" + fit-margin-bottom="0" /> + <metadata + id="metadata4403"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + <dc:title></dc:title> + </cc:Work> + </rdf:RDF> + </metadata> + <g + inkscape:label="Layer 1" + inkscape:groupmode="layer" + id="layer1" + transform="translate(-84.941252,-512.09059)"> + <g + id="g3169" + transform="matrix(0.2470791,0,0,0.2470791,84.768297,512.1097)"> + <linearGradient + id="linearGradient4274" + gradientUnits="userSpaceOnUse" + x1="-6873.6479" + y1="2774.2998" + x2="-6636.2373" + y2="2496.6895" + gradientTransform="matrix(0.4345,-0.9318,-0.9318,-0.4345,6223.4761,-5052.7427)"> + <stop + offset="0" + style="stop-color:#F59723" + id="stop4276" /> + <stop + offset="0.3123" + style="stop-color:#F69822" + id="stop4278" /> + <stop + offset="0.8383" + style="stop-color:#E87726" + id="stop4280" /> + </linearGradient> + <path + d="m 736.1,8.1 c -27.1,16 -72.2,61.3 -125.8,127 l 49.3,93.2 C 694.3,178.8 729.5,134.1 765,96 c 2.8,-3 4.1,-4.4 4.1,-4.4 -1.3,1.4 -2.8,3 -4.1,4.4 -11.5,12.6 -46.4,53.4 -99,134.2 50.7,-2.5 128.5,-12.9 192,-23.7 19,-105.9 -18.5,-154.3 -18.5,-154.3 0,0 -47.6,-77 -103.4,-44.1 z" + id="path3178" + inkscape:connector-curvature="0" + style="fill:url(#SVGID_1_-7)" /> + <path + d="m 652.5,539.9 c 0.3,-0.1 0.7,-0.1 1.1,-0.2 l -7.1,0.8 c -0.4,0.2 -0.8,0.4 -1.2,0.6 2.3,-0.5 4.8,-0.9 7.2,-1.2 z" + id="path3180" + inkscape:connector-curvature="0" + style="fill:none" /> + <path + d="m 602,706.9 c -4,0.9 -8.1,1.6 -12.3,2.3 4.2,-0.7 8.3,-1.5 12.3,-2.3 z" + id="path3182" + inkscape:connector-curvature="0" + style="fill:none" /> + <path + d="m 259.4,1081.4 c 0.5,-1.3 1,-2.8 1.5,-4.1 10.9,-28.7 21.7,-56.6 32.3,-83.8 11.9,-30.5 23.7,-60 35.5,-88.6 12.3,-30.1 24.5,-59.3 36.4,-87.5 12.5,-29.5 24.9,-58 37.1,-85.4 9.9,-22.3 19.6,-43.9 29.2,-64.8 3.2,-7 6.4,-13.9 9.6,-20.7 6.3,-13.6 12.5,-26.8 18.7,-39.8 5.7,-11.9 11.3,-23.6 17,-35.2 1.9,-3.8 3.7,-7.6 5.6,-11.4 0.3,-0.6 0.6,-1.2 0.9,-1.9 l -6.1,0.6 -4.8,-9.5 c -0.5,0.9 -0.9,1.9 -1.4,2.8 -8.6,17.3 -17.3,34.6 -25.8,52.1 -4.9,10.2 -9.8,20.4 -14.7,30.5 -13.5,28.3 -26.7,57 - [...] + id="path3184" + inkscape:connector-curvature="0" + style="fill:none" /> + <path + d="M 586.6,709.6 Z" + id="path3186" + inkscape:connector-curvature="0" + style="fill:none" /> + <path + d="m 570.2,791 c -6.3,1.1 -12.7,2.3 -19.4,3.4 0,0 -0.1,0 -0.1,0.1 3.4,-0.5 6.7,-1 10,-1.5 3.1,-0.7 6.3,-1.3 9.5,-2 z" + id="path3188" + inkscape:connector-curvature="0" + style="fill:#bd202e" /> + <path + enable-background="new " + d="m 570.2,791 c -6.3,1.1 -12.7,2.3 -19.4,3.4 0,0 -0.1,0 -0.1,0.1 3.4,-0.5 6.7,-1 10,-1.5 3.1,-0.7 6.3,-1.3 9.5,-2 z" + id="path3190" + inkscape:connector-curvature="0" + style="opacity:0.35;fill:#bd202e" /> + <path + d="m 586.7,709.5 c 0,0 0,0.1 0,0 -0.1,0 -0.1,0 -0.1,0.1 1,-0.1 2.1,-0.3 3.1,-0.5 4.2,-0.6 8.3,-1.3 12.3,-2.3 -5,0.9 -10,1.8 -15.3,2.7 z" + id="path3192" + inkscape:connector-curvature="0" + style="fill:#bd202e" /> + <path + enable-background="new " + d="m 586.7,709.5 c 0,0 0,0.1 0,0 -0.1,0 -0.1,0 -0.1,0.1 1,-0.1 2.1,-0.3 3.1,-0.5 4.2,-0.6 8.3,-1.3 12.3,-2.3 -5,0.9 -10,1.8 -15.3,2.7 z" + id="path3194" + inkscape:connector-curvature="0" + style="opacity:0.35;fill:#bd202e" /> + <linearGradient + id="linearGradient4291" + gradientUnits="userSpaceOnUse" + x1="-8630.7197" + y1="2804.9607" + x2="-6936.9253" + y2="2804.9607" + gradientTransform="matrix(0.4345,-0.9318,-0.9318,-0.4345,6223.4761,-5052.7427)"> + <stop + offset="0.3233" + style="stop-color:#9C2063" + id="stop4293" /> + <stop + offset="0.6302" + style="stop-color:#C82037" + id="stop4295" /> + <stop + offset="0.7514" + style="stop-color:#CC2135" + id="stop4297" /> + <stop + offset="1" + style="stop-color:#E87726" + id="stop4299" /> + </linearGradient> + <path + d="m 514,469.2 c 15,-28.1 30.2,-55.5 45.5,-82.1 15.9,-27.8 32.1,-54.6 48.4,-80.6 0.9,-1.5 2,-3.1 2.9,-4.6 16.1,-25.5 32.4,-50.1 48.7,-73.5 l -49.3,-93.2 c -3.7,4.5 -7.4,9.1 -11.2,13.9 -14.3,17.8 -29,36.8 -44.2,57.1 -17.1,22.8 -34.6,47.2 -52.5,72.8 -16.4,23.6 -33.2,48.3 -50,74 -14.3,21.8 -28.5,44.2 -42.7,67.2 -0.5,0.8 -1,1.7 -1.5,2.6 l 64.3,127 C 486,522.3 500,495.4 514,469.2 Z" + id="path3205" + inkscape:connector-curvature="0" + style="fill:url(#SVGID_2_-6)" /> + <linearGradient + id="linearGradient4302" + gradientUnits="userSpaceOnUse" + x1="-8426.2559" + y1="2635.2839" + x2="-7416.9194" + y2="2635.2839" + gradientTransform="matrix(0.4345,-0.9318,-0.9318,-0.4345,6223.4761,-5052.7427)"> + <stop + offset="0" + style="stop-color:#282661" + id="stop4304" /> + <stop + offset="9.548389e-02" + style="stop-color:#662E8C" + id="stop4306" /> + <stop + offset="0.7882" + style="stop-color:#9E2064" + id="stop4308" /> + <stop + offset="0.9487" + style="stop-color:#CC2032" + id="stop4310" /> + </linearGradient> + <path + d="m 221.2,1184.4 c -8.5,23.3 -17.1,47.2 -25.6,71.5 -0.1,0.3 -0.2,0.7 -0.4,1 -1.2,3.4 -2.5,6.9 -3.6,10.3 -5.8,16.4 -10.8,31.2 -22.3,64.7 18.9,8.6 34.1,31.4 48.5,57.2 -1.5,-26.7 -12.5,-51.8 -33.6,-71.2 93.3,4.2 173.7,-19.4 215.3,-87.6 3.7,-6.1 7.1,-12.4 10.2,-19.3 -18.9,24 -42.4,34.1 -86.5,31.7 -0.1,0 -0.2,0.1 -0.3,0.1 0.1,0 0.2,-0.1 0.3,-0.1 65,-29.1 97.5,-57 126.4,-103.2 6.8,-11 13.5,-22.9 20.3,-36.2 -56.8,58.3 -122.5,74.9 -191.8,62.3 l -52,5.7 c -1.7,4.4 -3.2,8.7 -4.9,13.1 z" + id="path3216" + inkscape:connector-curvature="0" + style="fill:url(#SVGID_3_-7)" /> + <linearGradient + id="linearGradient4313" + gradientUnits="userSpaceOnUse" + x1="-8535.5879" + y1="2820.8604" + x2="-6841.793" + y2="2820.8604" + gradientTransform="matrix(0.4345,-0.9318,-0.9318,-0.4345,6223.4761,-5052.7427)"> + <stop + offset="0.3233" + style="stop-color:#9C2063" + id="stop4315" /> + <stop + offset="0.6302" + style="stop-color:#C82037" + id="stop4317" /> + <stop + offset="0.7514" + style="stop-color:#CC2135" + id="stop4319" /> + <stop + offset="1" + style="stop-color:#E87726" + id="stop4321" /> + </linearGradient> + <path + d="m 245.5,1068.1 c 11.2,-29 22.8,-58.4 34.6,-88 11.4,-28.4 23,-57 35,-85.6 12,-28.6 24.2,-57.5 36.6,-86.3 12.6,-29.3 25.6,-58.5 38.9,-87.6 13.1,-28.8 26.3,-57.4 39.8,-85.6 4.8,-10.2 9.8,-20.4 14.7,-30.5 8.5,-17.5 17.1,-34.9 25.8,-52.1 0.5,-0.9 0.9,-1.9 1.4,-2.8 L 408,422.6 c -1,1.7 -2.1,3.5 -3.2,5.1 -15,24.5 -29.9,49.5 -44.5,75 -14.8,25.8 -29.3,52.1 -43.5,78.8 -11.9,22.5 -23.6,45.1 -35.1,68.1 -2.3,4.6 -4.5,9.3 -6.8,13.9 -14,28.9 -26.6,56.6 -38.1,83.5 -13,30.3 -24.4,59.3 -34.3,8 [...] + id="path3227" + inkscape:connector-curvature="0" + style="fill:url(#SVGID_4_-0)" /> + <linearGradient + id="linearGradient4324" + gradientUnits="userSpaceOnUse" + x1="-8412.0576" + y1="2797.8789" + x2="-7521.9175" + y2="2797.8789" + gradientTransform="matrix(0.4345,-0.9318,-0.9318,-0.4345,6223.4761,-5052.7427)"> + <stop + offset="0" + style="stop-color:#282661" + id="stop4326" /> + <stop + offset="9.548389e-02" + style="stop-color:#662E8C" + id="stop4328" /> + <stop + offset="0.7882" + style="stop-color:#9E2064" + id="stop4330" /> + <stop + offset="0.9487" + style="stop-color:#CC2032" + id="stop4332" /> + </linearGradient> + <path + d="m 146.2,1034 c -8.1,40.8 -13.9,81.4 -16.8,121.8 -0.1,1.4 -0.2,2.8 -0.3,4.2 -20.2,-32.3 -74.1,-63.8 -74,-63.5 38.7,56 68,111.6 72.3,166.2 -20.7,4.2 -49,-1.9 -81.7,-13.9 34.1,31.4 59.7,40 69.8,42.4 -31.4,2 -64,23.5 -96.9,48.3 48.1,-19.6 87,-27.4 114.8,-21.1 -44.2,125 -88.4,263 -132.7,409.6 13.6,-4 21.7,-13.2 26.2,-25.5 7.9,-26.5 60.2,-200.7 142.3,-429.4 2.4,-6.5 4.7,-13.1 7.1,-19.6 0.6,-1.9 1.3,-3.7 2,-5.4 8.6,-24 17.7,-48.5 26.9,-73.5 2.1,-5.7 4.2,-11.4 6.4,-17.1 0,-0.1 0.1,-0 [...] + id="path3238" + inkscape:connector-curvature="0" + style="fill:url(#SVGID_5_-8)" /> + <linearGradient + id="linearGradient4335" + gradientUnits="userSpaceOnUse" + x1="-8535.5879" + y1="2645.4897" + x2="-6841.793" + y2="2645.4897" + gradientTransform="matrix(0.4345,-0.9318,-0.9318,-0.4345,6223.4761,-5052.7427)"> + <stop + offset="0.3233" + style="stop-color:#9C2063" + id="stop4337" /> + <stop + offset="0.6302" + style="stop-color:#C82037" + id="stop4339" /> + <stop + offset="0.7514" + style="stop-color:#CC2135" + id="stop4341" /> + <stop + offset="1" + style="stop-color:#E87726" + id="stop4343" /> + </linearGradient> + <path + d="m 482.3,560.2 c -1.9,3.8 -3.7,7.6 -5.6,11.4 -5.6,11.5 -11.2,23.2 -17,35.2 -6.2,13 -12.4,26.2 -18.7,39.8 -3.2,6.8 -6.4,13.7 -9.6,20.7 -9.6,20.9 -19.3,42.5 -29.2,64.8 -12.1,27.3 -24.6,55.8 -37.1,85.4 -11.9,28.2 -24.2,57.3 -36.4,87.5 -11.7,28.6 -23.5,58.2 -35.5,88.6 -10.7,27.1 -21.5,55.1 -32.3,83.8 -0.5,1.3 -1,2.8 -1.5,4.1 -10.8,28.5 -21.7,57.8 -32.6,87.8 -0.2,0.7 -0.5,1.3 -0.7,2.1 l 52,-5.7 c -1,-0.2 -2.1,-0.3 -3.1,-0.5 62.1,-7.7 144.8,-54.2 198.1,-111.5 24.6,-26.4 46.9,-57.6 6 [...] + id="path3249" + inkscape:connector-curvature="0" + style="fill:url(#SVGID_6_-2)" /> + <linearGradient + id="linearGradient4346" + gradientUnits="userSpaceOnUse" + x1="-8640.6592" + y1="2654.2649" + x2="-6946.8647" + y2="2654.2649" + gradientTransform="matrix(0.4345,-0.9318,-0.9318,-0.4345,6223.4761,-5052.7427)"> + <stop + offset="0.3233" + style="stop-color:#9C2063" + id="stop4348" /> + <stop + offset="0.6302" + style="stop-color:#C82037" + id="stop4350" /> + <stop + offset="0.7514" + style="stop-color:#CC2135" + id="stop4352" /> + <stop + offset="1" + style="stop-color:#E87726" + id="stop4354" /> + </linearGradient> + <path + d="m 666.1,230.2 c -14.5,22.3 -30.3,47.6 -47.5,76.3 -0.9,1.4 -1.9,3.1 -2.7,4.5 -14.7,24.8 -30.3,52 -46.9,81.9 -14.2,25.8 -29,53.4 -44.4,83.1 -13.4,25.9 -27.2,53.4 -41.5,82.5 l 163.3,-17.9 c 47.6,-21.9 68.8,-41.6 89.4,-70.3 5.4,-7.9 11,-16.1 16.4,-24.7 16.8,-26.2 33.2,-55 47.9,-83.7 14.2,-27.7 26.7,-55.1 36.3,-79.9 6.1,-15.7 11,-30.3 14.4,-43.2 3,-11.3 5.3,-22.1 7.1,-32.4 -63.3,10.9 -141.2,21.3 -191.8,23.8 z" + id="path3260" + inkscape:connector-curvature="0" + style="fill:url(#SVGID_7_-2)" /> + <path + d="m 560.5,792.8 c -3.3,0.6 -6.6,1.1 -10,1.5 v 0 c 3.4,-0.3 6.8,-0.9 10,-1.5 z" + id="path3262" + inkscape:connector-curvature="0" + style="fill:#bd202e" /> + <path + enable-background="new " + d="m 560.5,792.8 c -3.3,0.6 -6.6,1.1 -10,1.5 v 0 c 3.4,-0.3 6.8,-0.9 10,-1.5 z" + id="path3264" + inkscape:connector-curvature="0" + style="opacity:0.35;fill:#bd202e" /> + <linearGradient + id="linearGradient4359" + gradientUnits="userSpaceOnUse" + x1="-8535.5889" + y1="2593.446" + x2="-6841.7925" + y2="2593.446" + gradientTransform="matrix(0.4345,-0.9318,-0.9318,-0.4345,6223.4761,-5052.7427)"> + <stop + offset="0.3233" + style="stop-color:#9C2063" + id="stop4361" /> + <stop + offset="0.6302" + style="stop-color:#C82037" + id="stop4363" /> + <stop + offset="0.7514" + style="stop-color:#CC2135" + id="stop4365" /> + <stop + offset="1" + style="stop-color:#E87726" + id="stop4367" /> + </linearGradient> + <path + d="m 560.5,792.8 c -3.3,0.6 -6.6,1.1 -10,1.5 v 0 c 3.4,-0.3 6.8,-0.9 10,-1.5 z" + id="path3275" + inkscape:connector-curvature="0" + style="fill:url(#SVGID_8_-3)" /> + <path + d="m 586.6,709.6 c 1,-0.1 2.1,-0.3 3.1,-0.5 -1,0.1 -2,0.4 -3.1,0.5 z" + id="path3277" + inkscape:connector-curvature="0" + style="fill:#bd202e" /> + <path + enable-background="new " + d="m 586.6,709.6 c 1,-0.1 2.1,-0.3 3.1,-0.5 -1,0.1 -2,0.4 -3.1,0.5 z" + id="path3279" + inkscape:connector-curvature="0" + style="opacity:0.35;fill:#bd202e" /> + <linearGradient + id="linearGradient4372" + gradientUnits="userSpaceOnUse" + x1="-8535.5889" + y1="2599.3242" + x2="-6841.7925" + y2="2599.3242" + gradientTransform="matrix(0.4345,-0.9318,-0.9318,-0.4345,6223.4761,-5052.7427)"> + <stop + offset="0.3233" + style="stop-color:#9C2063" + id="stop4374" /> + <stop + offset="0.6302" + style="stop-color:#C82037" + id="stop4376" /> + <stop + offset="0.7514" + style="stop-color:#CC2135" + id="stop4378" /> + <stop + offset="1" + style="stop-color:#E87726" + id="stop4380" /> + </linearGradient> + <path + d="m 586.6,709.6 c 1,-0.1 2.1,-0.3 3.1,-0.5 -1,0.1 -2,0.4 -3.1,0.5 z" + id="path3290" + inkscape:connector-curvature="0" + style="fill:url(#SVGID_9_-3)" /> + <path + d="m 586.6,709.6 c 0.1,0 0.1,-0.1 0,0 v 0 0 0 c 0.1,-0.1 0.1,0 0,0 z" + id="path3292" + inkscape:connector-curvature="0" + style="fill:#bd202e" /> + <path + enable-background="new " + d="m 586.6,709.6 c 0.1,0 0.1,-0.1 0,0 v 0 0 0 c 0.1,-0.1 0.1,0 0,0 z" + id="path3294" + inkscape:connector-curvature="0" + style="opacity:0.35;fill:#bd202e" /> + <linearGradient + id="linearGradient4385" + gradientUnits="userSpaceOnUse" + x1="-7584.0386" + y1="2600.5515" + x2="-7209.6543" + y2="2600.5515" + gradientTransform="matrix(0.4345,-0.9318,-0.9318,-0.4345,6223.4761,-5052.7427)"> + <stop + offset="0.3233" + style="stop-color:#9C2063" + id="stop4387" /> + <stop + offset="0.6302" + style="stop-color:#C82037" + id="stop4389" /> + <stop + offset="0.7514" + style="stop-color:#CC2135" + id="stop4391" /> + <stop + offset="1" + style="stop-color:#E87726" + id="stop4393" /> + </linearGradient> + <path + d="m 586.6,709.6 c 0.1,0 0.1,-0.1 0,0 v 0 0 0 c 0.1,-0.1 0.1,0 0,0 z" + id="path3305" + inkscape:connector-curvature="0" + style="fill:url(#SVGID_10_-8)" /> + </g> + <g + aria-label="APACHE" + transform="scale(0.95669208,1.0452684)" + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:195.62255859px;line-height:125%;font-family:Montserrat;-inkscape-font-specification:Montserrat;letter-spacing:0px;word-spacing:0px;fill:#cb2533;fill-opacity:1;stroke:none;stroke-width:7.1135478px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + id="text5526"> + <path + d="M 452.0268,750.44354 436.57262,715.4271 h -74.53219 l -15.25856,35.01644 h -16.62792 l 61.42548,-136.93579 h 16.23668 l 61.22986,136.93579 z m -83.53083,-49.4925 h 61.81673 l -31.10399,-70.42413 z" + style="font-style:normal;font-variant:normal;font-weight:300;font-stretch:normal;font-family:Montserrat;-inkscape-font-specification:'Montserrat Light';fill:#cb2533;fill-opacity:1;stroke-width:7.1135478px" + id="path6019" /> + <path + d="m 542.1599,613.50775 q 25.43093,0 39.32013,12.1286 14.08483,11.93298 14.08483,33.8427 0,22.4966 -14.08483,35.01644 -13.8892,12.51984 -39.32013,12.51984 h -35.79893 v 43.42821 h -15.6498 V 613.50775 Z m -0.58687,79.03152 q 18.58414,0 28.75652,-8.21615 10.17237,-8.41177 10.17237,-24.45282 0,-15.64981 -10.17237,-23.67033 -10.17238,-8.21615 -28.75652,-8.21615 h -35.21206 v 64.55545 z" + style="font-style:normal;font-variant:normal;font-weight:300;font-stretch:normal;font-family:Montserrat;-inkscape-font-specification:'Montserrat Light';fill:#cb2533;fill-opacity:1;stroke-width:7.1135478px" + id="path6021" /> + <path + d="M 716.04084,750.44354 700.58666,715.4271 h -74.53219 l -15.25856,35.01644 h -16.62792 l 61.42548,-136.93579 h 16.23667 L 733.06,750.44354 Z m -83.53083,-49.4925 h 61.81673 l -31.10399,-70.42413 z" + style="font-style:normal;font-variant:normal;font-weight:300;font-stretch:normal;font-family:Montserrat;-inkscape-font-specification:'Montserrat Light';fill:#cb2533;fill-opacity:1;stroke-width:7.1135478px" + id="path6023" /> + <path + d="m 850.46717,643.82925 q -8.02053,-8.02053 -18.77977,-12.51985 -10.56362,-4.69494 -21.7141,-4.69494 -15.25856,0 -28.16965,7.43366 -12.71547,7.23803 -20.14913,19.9535 -7.43365,12.71547 -7.43365,27.7784 0,14.86732 7.43365,27.58279 7.43366,12.71546 20.14913,20.14912 12.91109,7.43366 28.16965,7.43366 11.15048,0 21.7141,-4.3037 10.56362,-4.49932 18.77977,-12.32422 l 9.5855,10.36799 q -10.36799,9.78113 -23.67033,15.45419 -13.10671,5.47743 -27.19153,5.47743 -19.36664,0 -35.60331,-9.1 [...] + style="font-style:normal;font-variant:normal;font-weight:300;font-stretch:normal;font-family:Montserrat;-inkscape-font-specification:'Montserrat Light';fill:#cb2533;fill-opacity:1;stroke-width:7.1135478px" + id="path6025" /> + <path + d="m 888.06949,613.50775 h 15.6498 v 62.01235 h 82.55272 v -62.01235 h 15.64979 v 136.93579 h -15.64979 v -60.64299 h -82.55272 v 60.64299 h -15.6498 z" + style="font-style:normal;font-variant:normal;font-weight:300;font-stretch:normal;font-family:Montserrat;-inkscape-font-specification:'Montserrat Light';fill:#cb2533;fill-opacity:1;stroke-width:7.1135478px" + id="path6027" /> + <path + d="m 1043.5741,613.50775 h 92.9207 v 14.47607 h -77.2709 v 45.9713 h 69.0548 v 14.28045 h -69.0548 v 47.7319 h 79.814 v 14.47607 h -95.4638 z" + style="font-style:normal;font-variant:normal;font-weight:300;font-stretch:normal;font-family:Montserrat;-inkscape-font-specification:'Montserrat Light';fill:#cb2533;fill-opacity:1;stroke-width:7.1135478px" + id="path6029" /> + </g> + <g + aria-label="THE" + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:37.29720688px;line-height:125%;font-family:Montserrat;-inkscape-font-specification:Montserrat;letter-spacing:0px;word-spacing:0px;fill:#6c6c70;fill-opacity:0.83137255;stroke:none;stroke-width:1.35626209px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + id="text5530"> + <path + d="m 352.73715,585.27138 v 22.04265 h -4.40107 v -22.04265 h -7.90701 v -4.0281 h 20.21509 v 4.0281 z" + style="letter-spacing:8.86995506px;fill:#6c6c70;fill-opacity:0.83137255;stroke-width:1.35626209px" + id="path6012" /> + <path + d="m 374.27009,607.31403 v -26.07075 h 4.40107 v 11.30105 h 12.94213 v -11.30105 h 4.40107 v 26.07075 h -4.40107 v -10.66701 h -12.94213 v 10.66701 z" + style="letter-spacing:8.86995506px;fill:#6c6c70;fill-opacity:0.83137255;stroke-width:1.35626209px" + id="path6014" /> + <path + d="m 430.44573,581.24328 v 4.13999 h -13.91186 v 6.89998 h 12.49456 v 3.91621 h -12.49456 v 6.97458 h 14.35942 v 4.13999 H 412.1328 v -26.07075 z" + style="letter-spacing:8.86995506px;fill:#6c6c70;fill-opacity:0.83137255;stroke-width:1.35626209px" + id="path6016" /> + </g> + <g + aria-label="SOFTWARE FOUNDATION" + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:45.40566254px;line-height:125%;font-family:Montserrat;-inkscape-font-specification:Montserrat;letter-spacing:0px;word-spacing:0px;fill:#6c6c70;fill-opacity:0.83137255;stroke:none;stroke-width:1.65111506px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + id="text5530-3"> + <path + d="m 323.68517,818.45323 q -2.31569,0 -3.81408,0.95352 -1.49838,0.95352 -1.49838,2.90596 0,1.90704 1.49838,2.95137 1.49839,0.99892 6.3568,2.17947 4.90381,1.18055 7.35571,3.31461 2.49732,2.13407 2.49732,6.31139 0,4.13192 -3.13299,6.72004 -3.133,2.58812 -8.21843,2.58812 -7.44653,0 -13.21305,-5.13084 l 3.36002,-4.0411 q 4.813,4.17732 9.98925,4.17732 2.58812,0 4.08651,-1.08974 1.54379,-1.13514 1.54379,-2.95137 0,-1.86163 -1.45298,-2.86055 -1.40758,-1.04433 -4.90381,-1.86164 -3.49624 [...] + style="letter-spacing:10.79829407px;fill:#6c6c70;fill-opacity:0.83137255;stroke-width:1.65111506px" + id="path5975" /> + <path + d="m 376.15948,821.76784 q -3.2238,-3.36002 -7.94599,-3.36002 -4.72219,0 -7.9914,3.36002 -3.2238,3.36002 -3.2238,8.17302 0,4.7676 3.2238,8.12761 3.26921,3.36002 7.9914,3.36002 4.72219,0 7.94599,-3.36002 3.26921,-3.36001 3.26921,-8.12761 0,-4.813 -3.26921,-8.17302 z m 3.95029,19.88768 q -4.813,4.67678 -11.89628,4.67678 -7.08329,0 -11.89629,-4.67678 -4.813,-4.72219 -4.813,-11.71466 0,-7.03788 4.813,-11.71466 4.813,-4.72219 11.89629,-4.72219 7.08328,0 11.89628,4.72219 4.813,4.67678 [...] + style="letter-spacing:10.79829407px;fill:#6c6c70;fill-opacity:0.83137255;stroke-width:1.65111506px" + id="path5977" /> + <path + d="m 407.83728,819.27053 v 8.71789 h 14.07576 v 4.94921 h -14.07576 v 13.07684 h -5.35787 v -31.73856 h 21.15904 l -0.0454,4.99462 z" + style="letter-spacing:10.79829407px;fill:#6c6c70;fill-opacity:0.83137255;stroke-width:1.65111506px" + id="path5979" /> + <path + d="m 452.66783,819.17972 v 26.83475 h -5.35787 v -26.83475 h -9.626 v -4.90381 h 24.60987 v 4.90381 z" + style="letter-spacing:10.79829407px;fill:#6c6c70;fill-opacity:0.83137255;stroke-width:1.65111506px" + id="path5981" /> + <path + d="m 488.78049,837.11496 7.08328,-22.83905 h 4.813 l 7.08329,22.83905 7.99139,-22.83905 h 5.76652 l -11.07898,31.73856 h -5.31246 l -6.67463,-21.74932 h -0.36325 l -6.67463,21.74932 h -5.31246 l -11.07899,-31.73856 h 5.76652 z" + style="letter-spacing:10.79829407px;fill:#6c6c70;fill-opacity:0.83137255;stroke-width:1.65111506px" + id="path5983" /> + <path + d="m 540.29064,838.79496 -3.1784,7.21951 h -5.72111 l 13.98494,-31.73856 h 5.72112 l 13.98494,31.73856 h -5.72111 l -3.1784,-7.21951 z m 13.71251,-4.94921 -5.76652,-13.07683 -5.76652,13.07683 z" + style="letter-spacing:10.79829407px;fill:#6c6c70;fill-opacity:0.83137255;stroke-width:1.65111506px" + id="path5985" /> + <path + d="m 605.62966,824.58299 q 0,7.85518 -6.85626,9.89844 l 8.30924,11.53304 h -6.81085 l -7.58275,-10.67034 h -7.03788 v 10.67034 h -5.35786 v -31.73856 h 11.80547 q 7.2649,0 10.39789,2.4519 3.133,2.45191 3.133,7.85518 z m -13.30386,5.90274 q 4.54056,0 6.17517,-1.40758 1.6346,-1.40757 1.6346,-4.49516 0,-3.13299 -1.68001,-4.26813 -1.68001,-1.18055 -5.99355,-1.18055 h -6.81085 v 11.35142 z" + style="letter-spacing:10.79829407px;fill:#6c6c70;fill-opacity:0.83137255;stroke-width:1.65111506px" + id="path5987" /> + <path + d="m 646.46449,814.27591 v 5.04003 h -16.93631 v 8.40004 h 15.2109 v 4.7676 h -15.2109 v 8.49086 h 17.48118 v 5.04003 h -22.83905 v -31.73856 z" + style="letter-spacing:10.79829407px;fill:#6c6c70;fill-opacity:0.83137255;stroke-width:1.65111506px" + id="path5989" /> + <path + d="m 693.24916,819.27053 v 8.71789 h 14.07575 v 4.94921 h -14.07575 v 13.07684 h -5.35787 v -31.73856 h 21.15904 l -0.0454,4.99462 z" + style="letter-spacing:10.79829407px;fill:#6c6c70;fill-opacity:0.83137255;stroke-width:1.65111506px" + id="path5991" /> + <path + d="m 748.70463,821.76784 q -3.2238,-3.36002 -7.94599,-3.36002 -4.72219,0 -7.9914,3.36002 -3.2238,3.36002 -3.2238,8.17302 0,4.7676 3.2238,8.12761 3.26921,3.36002 7.9914,3.36002 4.72219,0 7.94599,-3.36002 3.26921,-3.36001 3.26921,-8.12761 0,-4.813 -3.26921,-8.17302 z m 3.95029,19.88768 q -4.813,4.67678 -11.89628,4.67678 -7.08328,0 -11.89628,-4.67678 -4.813,-4.72219 -4.813,-11.71466 0,-7.03788 4.813,-11.71466 4.813,-4.72219 11.89628,-4.72219 7.08328,0 11.89628,4.72219 4.81301,4.676 [...] + style="letter-spacing:10.79829407px;fill:#6c6c70;fill-opacity:0.83137255;stroke-width:1.65111506px" + id="path5993" /> + <path + d="m 782.15328,838.74956 q 2.17947,2.54272 5.90273,2.54272 3.72327,0 5.90274,-2.54272 2.17947,-2.54272 2.17947,-6.90166 v -17.57199 h 5.35787 v 17.79902 q 0,6.85625 -3.76867,10.57952 -3.76867,3.67785 -9.67141,3.67785 -5.90273,0 -9.6714,-3.67785 -3.76867,-3.72327 -3.76867,-10.57952 v -17.79902 h 5.35787 v 17.57199 q 0,4.35894 2.17947,6.90166 z" + style="letter-spacing:10.79829407px;fill:#6c6c70;fill-opacity:0.83137255;stroke-width:1.65111506px" + id="path5995" /> + <path + d="m 844.46782,814.27591 h 5.35787 v 31.73856 h -5.81193 l -17.98064,-23.15689 v 23.15689 h -5.35787 v -31.73856 h 5.35787 l 18.4347,23.70175 z" + style="letter-spacing:10.79829407px;fill:#6c6c70;fill-opacity:0.83137255;stroke-width:1.65111506px" + id="path5997" /> + <path + d="m 880.32719,814.27591 q 8.53627,0 13.12224,4.17732 4.58597,4.13191 4.58597,11.53304 0,7.40112 -4.44976,11.71466 -4.44975,4.31354 -13.62169,4.31354 h -10.53412 v -31.73856 z m 12.30493,15.84657 q 0,-10.89736 -12.48655,-10.89736 h -5.35787 v 21.74932 h 5.94814 q 5.76652,0 8.8087,-2.72434 3.08758,-2.76975 3.08758,-8.12762 z" + style="letter-spacing:10.79829407px;fill:#6c6c70;fill-opacity:0.83137255;stroke-width:1.65111506px" + id="path5999" /> + <path + d="m 920.19648,838.79496 -3.1784,7.21951 h -5.72111 l 13.98494,-31.73856 h 5.72111 l 13.98495,31.73856 h -5.72112 l -3.17839,-7.21951 z m 13.71251,-4.94921 -5.76652,-13.07683 -5.76652,13.07683 z" + style="letter-spacing:10.79829407px;fill:#6c6c70;fill-opacity:0.83137255;stroke-width:1.65111506px" + id="path6001" /> + <path + d="m 969.70312,819.17972 v 26.83475 h -5.35787 v -26.83475 h -9.626 v -4.90381 h 24.60987 v 4.90381 z" + style="letter-spacing:10.79829407px;fill:#6c6c70;fill-opacity:0.83137255;stroke-width:1.65111506px" + id="path6003" /> + <path + d="m 995.91732,814.27591 h 5.35788 v 31.73856 h -5.35788 z" + style="letter-spacing:10.79829407px;fill:#6c6c70;fill-opacity:0.83137255;stroke-width:1.65111506px" + id="path6005" /> + <path + d="m 1043.5169,821.76784 q -3.2238,-3.36002 -7.946,-3.36002 -4.7222,0 -7.9914,3.36002 -3.2238,3.36002 -3.2238,8.17302 0,4.7676 3.2238,8.12761 3.2692,3.36002 7.9914,3.36002 4.7222,0 7.946,-3.36002 3.2692,-3.36001 3.2692,-8.12761 0,-4.813 -3.2692,-8.17302 z m 3.9503,19.88768 q -4.813,4.67678 -11.8963,4.67678 -7.0833,0 -11.8963,-4.67678 -4.813,-4.72219 -4.813,-11.71466 0,-7.03788 4.813,-11.71466 4.813,-4.72219 11.8963,-4.72219 7.0833,0 11.8963,4.72219 4.813,4.67678 4.813,11.71466 0 [...] + style="letter-spacing:10.79829407px;fill:#6c6c70;fill-opacity:0.83137255;stroke-width:1.65111506px" + id="path6007" /> + <path + d="m 1093.6294,814.27591 h 5.3579 v 31.73856 h -5.8119 l -17.9807,-23.15689 v 23.15689 h -5.3578 v -31.73856 h 5.3578 l 18.4347,23.70175 z" + style="letter-spacing:10.79829407px;fill:#6c6c70;fill-opacity:0.83137255;stroke-width:1.65111506px" + id="path6009" /> + </g> + <g + aria-label="®" + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:39.51562881px;line-height:125%;font-family:Montserrat;-inkscape-font-specification:Montserrat;letter-spacing:0px;word-spacing:0px;fill:#6c6c70;fill-opacity:0.83137255;stroke:none;stroke-width:1.43693185px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + id="text5951"> + <path + d="m 1133.6751,638.00586 q 4.1887,4.18866 4.1887,10.07649 0,5.88782 -4.1887,10.116 -4.1886,4.22817 -10.1555,4.22817 -5.9669,0 -10.116,-4.18866 -4.1492,-4.18865 -4.1492,-10.07648 0,-5.88783 4.1887,-10.116 4.1887,-4.22818 10.116,-4.22818 5.9274,0 10.116,4.18866 z m -1.225,19.00702 q 3.675,-3.71447 3.675,-8.89102 0,-5.17655 -3.6355,-8.8515 -3.5959,-3.67495 -8.8515,-3.67495 -5.2555,0 -8.891,3.71447 -3.6354,3.67495 -3.6354,8.89101 0,5.17655 3.5959,8.8515 3.5959,3.67496 8.8515,3.67496 [...] + style="fill:#6c6c70;fill-opacity:0.83137255;stroke-width:1.43693185px" + id="path5972" /> + </g> + </g> +</svg> diff --git a/static/img/social-card.png b/static/img/social-card.png new file mode 100644 index 0000000..81eebc3 Binary files /dev/null and b/static/img/social-card.png differ diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..314eab8 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,7 @@ +{ + // This file is not used in compilation. It is here just for a nice editor experience. + "extends": "@docusaurus/tsconfig", + "compilerOptions": { + "baseUrl": "." + } +}