From 1cadb6312d1962e76bacb1df2c6db6e90483c6ee Mon Sep 17 00:00:00 2001 From: Sean Budd Date: Wed, 8 Mar 2023 08:17:59 +1100 Subject: [PATCH] Improve and refactor documentation (#109) Closes #95 Issues fixed in this PR: convertAddonManifest.py has been deleted as the issue form replaces this process. This python script was also an unintentional less polished duplicate of a script in the validation repo. documentation is split into design/development docs, metadata schema information, and an add-on submission guide, documentation is added on the latest and legacy end points the submission process has been given a lot more detail, and largely rewritten this is to add information on all the fields in the template, derived from the schema file --- README.md | 220 +++-------------------------- convertAddonManifest.py | 218 ---------------------------- docs/design/designOverview.md | 142 +++++++++++++++++++ docs/submitters/jsonMetadata.md | 133 +++++++++++++++++ docs/submitters/submissionGuide.md | 36 +++++ 5 files changed, 327 insertions(+), 422 deletions(-) delete mode 100644 convertAddonManifest.py create mode 100644 docs/design/designOverview.md create mode 100644 docs/submitters/jsonMetadata.md create mode 100644 docs/submitters/submissionGuide.md diff --git a/README.md b/README.md index 7f716d08db4..5d5288d14ae 100644 --- a/README.md +++ b/README.md @@ -1,220 +1,32 @@ -# Add on Store +# Add-on Store -The intention the add-on store is to improve the end-to-end process and supporting infrastructure for hosting add-ons. -This is the current plan from NV Access, work is ongoing. -Inspiration has been taken from [Windows Package Manager Community repo](https://github.com/microsoft/winget-pkgs) -A highly automated process would be ideal, and we can keep the ideas in mind to work in that direction. +The addon-datastore repository is a data pipeline of submitting, validating and transforming add-on data to views. +These views are hosted on the NV Access server and will become available in the NVDA add-on store. -Goal: enable an "NVDA add-on store" accessible from within NVDA itself. -In this proposal the word "store" is used to refer to the system used to store metadata about add-on releases and APIs to access this data. -Aims: -- Enable any necessary, API, process, or infrastructure to support users to browse, search, install and update add-ons for NVDA. -- A secure and robust provision of addon-metadata. -- No intention of supporting paid add-ons at this stage. -- Transparent process, to make it simple (for developers) to understand the current state of the - Add-on Store, or the state of a submission of a new / updated add-on. -- Faster release process for add-ons, by-passing human review. -- Non-subjective review process for add-ons. +The add-on store is a planned NVDA feature, which allows browsing, installing and updating add-ons from within NVDA. +The current work in progress can be tracked in this pull request: https://github.com/nvaccess/nvda/pull/13985 + +### Guide for submitters +Add-on authors who wish to have their add-on distributed through the add-on store should refer to [the submission guide](./docs/submitters/submissionGuide.md). + +### Design overview +For an overview of the whole add-on store, read [the design overview](./docs/submitters/designOverview.md). ### About security Ensuring that an add-on is safe to run is a difficult challenge that isn't addressed here. However, the metadata for a new submission (add-on release) can be confirmed to match its manifest description. -Additionally, add-on file integrity can be enforced via a Sha256 checksum. +Additionally, add-on file integrity can be enforced via a SHA256 checksum. The checksum allows NVDA to ensure that add-on releases are immutable. ### Human review process / code audit -- NV Access doesn't require a manual review of the add-on (code or user experience) itself - before the add-on submission. -- Source code reviews or audits could exist outside the store. - The Sha256 checksum of the `nvda-addon` prevents undetected changes. +- NV Access doesn't require a manual review of the add-on (code or user experience) itself before the add-on submission. +- You are welcome to review code / UX of add-ons and provide that feedback directly to add-on authors. +- The SHA256 checksum of the `.nvda-addon` prevents undetected changes. - User reviews/rating of add-ons are currently out of scope. ### Non-exclusivity -This proposal does not intend to restrict add-on authors from developing, publishing, and distributing an add-on outside this store. +This system does not restrict add-on authors from developing, publishing, and distributing an add-on outside this store. NVDA will still allow local installation from a `*.nvda-addon` file. The data hosted here is distributed under the [ODC-PDDL](https://opendatacommons.org/licenses/pddl/1-0/) license. A plain language summary can be found [here](https://opendatacommons.org/licenses/pddl/summary/). - -## Too Long; Didn't Read for add-on authors -With this proposal if an add-on author wishes to submit their add-on to be visible in this add-on store they will need to: -- Copy and fill out the metadata template -- Create a pull request to merge the branch to master of this repository. - -## Too Long; Didn't Read for add-on reviewers -Reviews of metadata will be automated. -You are welcome to review code / UX of add-ons and provide that feedback directly to add-on authors. - -## Considerations - -- Submissions and automated checks should be easy to find and get the status of. -- Make it possible to automate many steps in the process. -- The `.nvda-addon` file accessible via the download URL must continue to match the SHA. - NVDA will verify the file has not changed by comparing the checksum (SHA256). - This gives users certainty when installing a "known version" of an add-on. - To update or make changes to an add-on, a new unique URL should be used, and a new add-on - submission made to the Add-on Store. -- Allow add-on authors to easily revoke a version if it is buggy / no longer supported. - Removed releases are no longer presented in the store, halting new installations. -- Enable support in the store for multiple versions of an add-on, based on NVDA API version. - - EG add-on version 1.2.5 for NVDA 2019.3 and add-on version 1.3.2 for NVDA 2020.1 -- Enable support in the store for 'beta' and 'dev' add-ons, for instance: - - 'dev' add-ons are being developed against alpha / beta / rc NVDA, these would only be offered to alpha / beta / rc NVDA users. - - 'beta' add-ons are from authors who want early feedback from end users, signaling that not all edge cases are handled. - - End users of NVDA can select "show pre-release add-ons" - -## Overview - -[Addon store system design diagram](./docs/design/designOverview.svg) ([PlantUML markup](./docs/design/designOverview.puml)) - -- Use GitHub pull requests for store submissions. -- Use GitHub for storage of meta-data for add-ons available from the store. -- Use GitHub actions (or other integrations) to automate construction of the data store, and as many of the metadata checks as possible. - This will all be open source and extensible by the community. - -### Why GitHub Pull Requests? -- GitHub is where much of the NVDA development ecosystem is already based. -- Handles all the of the CRUD ([create, read, update, delete](https://en.wikipedia.org/wiki/CRUD)) - for users, authentication is handled, and we can determine how a user relates to an add-on - repository and what their permissions are for that repository. -- GitHub PR's keep a record of the outcomes of automated checks. - They also facilitate discussion should there be any confusion or disagreement with the outcome. -- GitHub PR's provided an atomic view of a store submission. -- The status (open / merged / closed) of the PR is clear. - -## Infrastructure - -- `addon-datastore` GitHub Repository - - Authors submit new add-on versions. - - The "source of truth" for add-on releases. - - This repository acts as a back-end database, it is open and easy to inspect. - - Since our needs are simple, preconfigured "views" of the data will suffice. -- `nvaccess/addon-datastore-validation` GitHub Repository - - Metadata / submission schema. - - Tools used to validate the submission. -- NV Access server - To provide the endpoint for "available add-ons" meta-data - - While this is technically not necessary, it provides a good separation from implementation. - If we wished to change our storage mechanism, we would not be breaking old versions of NVDA. - -## `addon-datastore` GitHub Repository - -Essentially this repository holds metadata about all the accepted versions of add-ons which are included in the store. -Metadata about old versions of an add-on remains until it is explicitly removed or becomes invalid. -This allows delivery to older versions of NVDA. -If a newer add-on release is removed (in response to a critical bug being found) NVDA can fall back -on a prior add-on release. -Add-ons versions are submitted by submitting a pull request, adding a file for that version of the add-on. - -### Layout - -Root directory of repository: - - `readme.md` - A guide for submission - - `addons/addon1/majorVersion.minorVersion.patch.json` - - `addons/addon2/majorVersion.minorVersion.patch.json` - - `addons/addon3/majorVersion.minorVersion.patch.json` - -Note: `addonName` is the add-on ID, and must be unique and match the add-on ID from the add-on manifest. - -Example for the NV Access add-on, 'NVDA - OCR': -- Filename: `addons/nvda-ocr/1.6.0.json` -- add-on ID `nvda-ocr` - -### Metadata format -For a full description of the schema see the -[_validate/addonVersion_schema.json file](https://github.com/nvaccess/addon-datastore-validation/blob/main/_validate/addonVersion_schema.json). -It includes an example of the file contents. - -### Submitting an add-on version - -#### Pre-requisites: -- Familiarity with GitHub -- Familiarity with Git, including working with branches. - -Process to add a new NVDA add-on version: -1. Fork the `addon-datastore` repository -1. On a new branch, copy the `_template_addon_release.json` file. - - Rename / move the file to `addons//.json` - - `` is the ID of the add-on. This should match the `name` field in the add-on manifest, E.G. "nv-speech-player" - - `` is the add-on version in the form: `Major.Minor.Patch` E.G. "2.4.1" -1. Fill out the template. -1. Create a PR to merge your branch into master on the `addon-datastore` repository -1. Automated checks for common issues will complete. Either giving feedback or merging the PR. -1. When the PR is merged the add-on becomes available in the store. - -### Converting an add-on manifest to a valid submission: -1. Fork the `addon-datastore` repository -1. Install requirements to python environment: -`pip install requests configobj` -1. Convert an add-on hosted at `addonUrl` to a json file: -`python convertAddonManifest.py [addonId] [stable|beta|dev] [addonUrl]` -1. Edit the auto-generated json file as required. -1. Create a PR to merge your branch into master on the `addon-datastore` repository -1. Automated checks for common issues will complete. Either giving feedback or merging the PR. -1. When the PR is merged the add-on becomes available in the store. - - -### Automated checks -See https://github.com/nvaccess/addon-datastore-validation - -### Other notes -- By using a git repository and PR process, `git blame` and `git log` can be used to get more - context about add-ons listed in the store. - For instance: - - When was the add-on accepted? - - What did the review look like? - - How often is the add-on updated? -- GitHub allows assigning reviews to reviewers - -## API data generation details - -Triggered by a new commit to the `master` branch, [a GitHub workflow](./.github/workflows/transformDataToViews.yml), [addon-datastore-transform](https://github.com/nvaccess/addon-datastore-transform), transforms the data into the required views. - -For each NVDA API version and channel, the add-on metadata with the highest version number is written. - -These views are then committed by the GitHub Action to the [views branch](https://github.com/nvaccess/addon-datastore/tree/views). - -### Data views -The following views will only be available on the [views branch](https://github.com/nvaccess/addon-datastore/tree/views) and located in a `views` folder. -Required transformations of the data: -- `/NVDA API Version/addon-1-ID/stable.json` -- `/NVDA API Version/addon-1-ID/beta.json` -- `/NVDA API Version/addon-2-ID/stable.json` - -Notes: -- 'NVDA API Version' will be something like '2019.3', there will be one folder for each NVDA API Version. -- The `beta.json` and `stable.json` contain the information necessary for a store entry. -- The contents for each add-on will include all the technical details required for NVDA to download, verify file integrity, and install. -- The file will include translations (if available) for the displayable metadata. - -This simplifies the processing on the hosting (E.G NV Access) server. - -## NV Access Add-on Store endpoints - -Using the NV Access server as the endpoint for this is important in case the implementation has to change or be migrated away from GitHub for some reason. - -### `GET` All -Get a complete list of the latest add-on releases. -Includes both stable and beta versions - -- Format: `https://www.nvaccess.org/addonStore//all/.json` -- Example: - -### `GET` All stable -Get a complete list of the latest stable add-on releases. -Includes only stable versions - -- Format: `https://www.nvaccess.org/addonStore//stable/.json` -- Example: - -### `GET` All beta -Get a complete list of the latest beta add-on releases. -Includes only beta versions - -- Format: `https://www.nvaccess.org/addonStore//beta/.json` -- Example: - -## Suffix - -### Terminology: add-on version vs add-on release - -Since this proposal supports beta addons, I have tried to avoid using the term "add-on release", instead favouring "add-on version". diff --git a/convertAddonManifest.py b/convertAddonManifest.py deleted file mode 100644 index 8798269b40e..00000000000 --- a/convertAddonManifest.py +++ /dev/null @@ -1,218 +0,0 @@ -""" -Setup: -pip install requests configobj - -Usage: -python convertAddonManifest.py [addonId] [stable|beta|dev] [addonUrl] -""" - -import hashlib -from io import StringIO -import json -import os -import pathlib -import sys -import tempfile -from time import sleep -import traceback -from typing import ( - Any, - Dict, - NamedTuple, - Tuple, -) -from zipfile import ZipFile, BadZipFile - -import configobj -from requests import get - - -manifestSpec = configobj.ConfigObj(StringIO( -""" -# NVDA Add-on Manifest configuration specification -# Add-on unique name -name = string() - -# short summary (label) of the add-on to show to users. -summary = string() - -# Long description with further information and instructions -description = string(default=None) - -# Name of the author or entity that created the add-on -author = string() - -# Version of the add-on. Should preferably in some standard format such as x.y.z -version = string() - -# The minimum required NVDA version for this add-on to work correctly. -# Should be less than or equal to lastTestedNVDAVersion -minimumNVDAVersion = apiVersion(default="0.0.0") - -# Must be greater than or equal to minimumNVDAVersion -lastTestedNVDAVersion = apiVersion(default="0.0.0") - -# URL for more information about the add-on. New versions and such. -url= string(default=None) - -# Name of default documentation file for the add-on. -docFileName = string(default=None) - -# NOTE: apiVersion: -# EG: 2019.1.0 or 0.0.0 -# Must have 3 integers separated by dots. -# The first integer must be a Year (4 characters) -# "0.0.0" is also valid. -# The final integer can be left out, and in that case will default to 0. E.g. 2019.1 - -""")) - - -class MajorMinorPatch(NamedTuple): - major: int - minor: int - patch: int = 0 - - def __str__(self) -> str: - return f"{self.major}.{self.minor}.{self.patch}" - - -def createNewAddonJSON(addonId: str, channel: str, url: str, sha256: str, manifest: Dict[str, str]) -> Dict[str, Any]: - if "minimumNVDAVersion" in manifest and not manifest["minimumNVDAVersion"] == "None": - minimumNVDAVersionInts = [int(x) for x in manifest["minimumNVDAVersion"].split(".")] - minimumNVDAVersion = MajorMinorPatch(*minimumNVDAVersionInts) - else: - minimumNVDAVersion = MajorMinorPatch(0, 0, 0) - - if "lastTestedNVDAVersion" in manifest: - lastTestedNVDAVersionInts = [int(x) for x in manifest["lastTestedNVDAVersion"].split(".")] - lastTestedNVDAVersion = MajorMinorPatch(*lastTestedNVDAVersionInts) - else: - lastTestedNVDAVersion = MajorMinorPatch(0, 0, 0) - - if lastTestedNVDAVersion > MajorMinorPatch(2023, 1, 0): - print("Setting lastTestedNVDAVersion version to 2023.1.0") - lastTestedNVDAVersion = MajorMinorPatch(2023, 1, 0) - elif lastTestedNVDAVersion < MajorMinorPatch(2019, 3, 0): - print("Setting lastTestedNVDAVersion version to 0.0.0") - lastTestedNVDAVersion = MajorMinorPatch(0, 0, 0) - - if minimumNVDAVersion > MajorMinorPatch(2023, 1, 0): - print("Setting minimumNVDAVersion version to 2023.1.0") - minimumNVDAVersion = MajorMinorPatch(2023, 1, 0) - elif minimumNVDAVersion < MajorMinorPatch(2019, 3, 0): - print("Setting minimumNVDAVersion version to 0.0.0") - minimumNVDAVersion = MajorMinorPatch(0, 0, 0) - - try: - addonVersionStr = manifest["version"] - if "-dev" in addonVersionStr: - addonVersionStr = addonVersionStr.replace("-dev", "") - if channel != "dev": - print(f"addon version str for {addonId} contains dev but channel is not dev") - - if "dev" in addonVersionStr: - addonVersionStr = addonVersionStr.replace("dev", "") - if channel != "dev": - print(f"addon version str for {addonId} contains dev but channel is not dev") - - if ":" in addonVersionStr: - addonVersionStr = addonVersionStr.split(":")[0] - - addonVersionInts = [int(x) for x in addonVersionStr.split(".")] - if len(addonVersionInts) == 1: - addonVersionInts.append(0) - addonVersionNumber = MajorMinorPatch(*addonVersionInts) - except: - print(f"Error parsing version: {manifest['version']}") - addonVersionNumber = MajorMinorPatch(0, 0, 0) - - - return { - "displayName": manifest['summary'], - "publisher": manifest["author"], - "description": manifest["description"], - "homepage": manifest.get("url"), - "addonId": addonId, - "addonVersionName": manifest["version"], - "addonVersionNumber": addonVersionNumber._asdict(), - "minNVDAVersion": minimumNVDAVersion._asdict(), - "lastTestedVersion": lastTestedNVDAVersion._asdict(), - "channel": channel, - "URL": url, - "sha256": sha256, - "sourceURL": manifest.get("url", default=""), - "license": "unknown", - "licenseURL": None, - } - - -def downloadAddonManifest(url: str) -> Tuple[configobj.ConfigObj, str]: - response = get(url, headers={ - "Accept": "*/*", - "User-Agent": f"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/110.0.0.0 Safari/537.36" - } - ) - - with tempfile.TemporaryFile() as outfile: - outfile.write(response.content) - - try: - with ZipFile(outfile, 'r') as zipFile: - with zipFile.open("manifest.ini", "r") as manifestFile: - config = configobj.ConfigObj(manifestFile, configspec=manifestSpec) - except BadZipFile: - sleep(1) - print(f"failed get {url}, trying again") - return downloadAddonManifest(url) - - sha256Hash = hashlib.sha256(outfile.read()).hexdigest() - - return config, sha256Hash - - -def fetchAndTransformLegacyAddons(addonId: str, channel: str, url: str): - newAddonPaths = set() - addonManifest = None - try: - addonManifest, sha256 = downloadAddonManifest(url) - newAddonJson = createNewAddonJSON(addonId, channel, url, sha256, addonManifest) - print("Fetched: ", addonId, newAddonJson['addonVersionName'], newAddonJson["channel"]) - newAddonFolder = os.path.join(".", "addons", addonId.replace("-dev", "")) - pathlib.Path(newAddonFolder).mkdir(parents=True, exist_ok=True) - - while True: - # handle when a dev and stable version collide with the same version number - addonVersionNumber = MajorMinorPatch(**newAddonJson['addonVersionNumber']) - newAddonPath = os.path.join(newAddonFolder, f"{str(addonVersionNumber)}.json") - if newAddonPath in newAddonPaths: - print(f"Collision with version path {addonId} {newAddonPath}") - with open(newAddonPath, "r") as newAddonFile: - existingCopyOfAddon = json.load(newAddonFile) - - if existingCopyOfAddon["channel"] != newAddonJson["channel"]: - newAddonJson["addonVersionNumber"]["patch"] += 1 - print( - f"Channels are different, increasing patch version number for {addonId} {newAddonJson['channel']}" - f" from {str(MajorMinorPatch(**newAddonJson['addonVersionNumber']))} to {str(addonVersionNumber)}" - ) - else: - break - - try: - pathlib.Path(newAddonPath).touch(exist_ok=False) - newAddonPaths.add(newAddonPath) - except OSError as e: - print(f"Error: {e} file exists {newAddonPath}") - raise - with open(newAddonPath, "w") as newAddonFile: - json.dump(newAddonJson, newAddonFile, indent="\t") - - except Exception as error: - print(f"Error {error}: {url} {addonManifest}") - print(traceback.format_exc()) - - -if __name__ == "__main__": - fetchAndTransformLegacyAddons(*sys.argv[1:]) - diff --git a/docs/design/designOverview.md b/docs/design/designOverview.md new file mode 100644 index 00000000000..aef7d104187 --- /dev/null +++ b/docs/design/designOverview.md @@ -0,0 +1,142 @@ + +# Design Overview + +## Background + +Inspiration has been taken from [Windows Package Manager Community repo](https://github.com/microsoft/winget-pkgs) +A highly automated process would be ideal, and we can keep the ideas in mind to work in that direction. + +Goal: enable an "NVDA add-on store" accessible from within NVDA itself. +"store" is used to refer to the system used to store metadata about add-on releases and APIs to access this data. +Aims: +- Enable any necessary, API, process, or infrastructure to support users to browse, search, install and update add-ons for NVDA. +- A secure and robust provision of addon-metadata. +- No intention of supporting paid add-ons at this stage. +- Transparent process, to make it simple (for developers) to understand the current state of the + Add-on Store, or the state of a submission of a new / updated add-on. +- Faster release process for add-ons, by-passing human review. +- Non-subjective review process for add-ons. + +## Considerations + +- Submissions and automated checks should be easy to find and get the status of. +- Make it possible to automate many steps in the process. +- The `.nvda-addon` file accessible via the download URL must continue to match the SHA. + NVDA will verify the file has not changed by comparing the checksum (SHA256). + This gives users certainty when installing a "known version" of an add-on. + To update or make changes to an add-on, a new unique URL should be used, and a new add-on + submission made to the Add-on Store. +- Allow add-on authors to easily revoke a version if it is buggy / no longer supported. + Removed releases are no longer presented in the store, halting new installations. +- Enable support in the store for multiple versions of an add-on, based on NVDA API version. + - EG add-on version 1.2.5 for NVDA 2019.3 and add-on version 1.3.2 for NVDA 2020.1 +- Enable support in the store for 'beta' and 'dev' add-ons, for instance: + - 'dev' add-ons are being developed against alpha / beta / rc NVDA, these would only be offered to alpha / beta / rc NVDA users. + - 'beta' add-ons are from authors who want early feedback from end users, signaling that not all edge cases are handled. + - End users of NVDA can select "show pre-release add-ons" + +## Overview + +[Addon store system design diagram](./designOverview.svg) ([PlantUML markup](./designOverview.puml)) + +### Why GitHub Pull Requests? +- GitHub is where much of the NVDA development ecosystem is already based. +- Handles all the of the CRUD ([create, read, update, delete](https://en.wikipedia.org/wiki/CRUD)) + for users, authentication is handled, and we can determine how a user relates to an add-on + repository and what their permissions are for that repository. +- GitHub PRs keep a record of the outcomes of automated checks. + They also facilitate discussion should there be any confusion or disagreement with the outcome. +- GitHub PRs provided an atomic view of a store submission. +- The status (open / merged / closed) of the PR is clear. + +## Infrastructure + +- `addon-datastore` GitHub Repository + - Authors submit new add-on versions. + - The "source of truth" for add-on releases. + - This repository acts as a back-end database, it is open and easy to inspect. + - Since our needs are simple, preconfigured "views" of the data will suffice. +- `nvaccess/addon-datastore-validation` GitHub Repository + - Metadata / submission schema. + - Tools used to validate the submission. +- NV Access server - To provide the endpoint for "available add-ons" meta-data + - While this is technically not necessary, it provides a good separation from implementation. + If we wished to change our storage mechanism, we would not be breaking old versions of NVDA. + + +## API data generation details + +Triggered by a new commit to the `master` branch, [a GitHub workflow](../../.github/workflows/transformDataToViews.yml), [addon-datastore-transform](https://github.com/nvaccess/addon-datastore-transform), transforms the data into the required views. + +For each NVDA API version and channel, the add-on metadata with the highest version number is written. + +These views are then committed by the GitHub Action to the [views branch](https://github.com/nvaccess/addon-datastore/tree/views). + +### Data views +The following views will only be available on the [views branch](https://github.com/nvaccess/addon-datastore/tree/views) and located in a `views` folder. +Required transformations of the data: +- `/NVDA API Version/addon-1-ID/stable.json` +- `/NVDA API Version/addon-1-ID/beta.json` +- `/NVDA API Version/addon-2-ID/stable.json` + +Notes: +- 'NVDA API Version' will be something like '2019.3', there will be one folder for each NVDA API Version. +- The `beta.json` and `stable.json` contain the information necessary for a store entry. +- The contents for each add-on will include all the technical details required for NVDA to download, verify file integrity, and install. +- The file will include translations (if available) for the displayable metadata. + +This simplifies the processing on the hosting (E.G NV Access) server. + +## `addon-datastore` GitHub Repository + +Essentially this repository holds metadata about all the accepted versions of add-ons which are included in the store. +Metadata about old versions of an add-on remains until it is explicitly removed or becomes invalid. +This allows delivery to older versions of NVDA. +If a newer add-on release is removed (in response to a critical bug being found) NVDA can fall back +on a prior add-on release. +Add-ons versions are submitted by submitting a pull request, adding a file for that version of the add-on. + +## NV Access Add-on Store endpoints + +Using the NV Access server as the endpoint for this is important in case the implementation has to change or be migrated away from GitHub for some reason. + +### `GET` +Get a complete list of the latest add-on releases given an NVDA API version, channel and language. +Channel can be: all, dev, stable or beta. + +- Format: `https://www.nvaccess.org/addonStore///.json` +- Example: + + +### `GET` latest +Get a complete list of the latest add-on releases for any NVDA API version, given a channel and language. +Channel can be: all, dev, stable or beta. + +- Format: `https://www.nvaccess.org/addonStore///latest.json` +- Example: + +### Legacy +This endpoint mirrors the legacy [get.php, from the addonFiles repository](https://github.com/nvaccess/addonFiles/blob/master/get.php). + +#### `addonslist` end-point + +The `addonslist` parameter generates a list of list of add-ons using the same logic as the [latest end-point](#get-latest) for all channels. +The addonIds are generated to match the legacy naming schema. +For example, dev channel add-ons are named `addonId-dev` in the `addonslist`. + +- Link: + +#### `file` end-point +The addonId supplied to the file parameter is fetched from the `addonslist`, returning the latest add-on version for that addonId. +`addonId` is case insensitive. + +- Format: `https://www.nvaccess.org/addonStore/legacy?file=` + +### Other notes +- By using a git repository and PR process, `git blame` and `git log` can be used to get more + context about add-ons listed in the store. + For instance: + - When was the add-on accepted? + - What did the review look like? + - How often is the add-on updated? +- GitHub allows assigning reviews to reviewers diff --git a/docs/submitters/jsonMetadata.md b/docs/submitters/jsonMetadata.md new file mode 100644 index 00000000000..c3c857cb122 --- /dev/null +++ b/docs/submitters/jsonMetadata.md @@ -0,0 +1,133 @@ +## JSON Metadata Schema details +For a full description of the schema see the +[_validate/addonVersion_schema.json file](https://github.com/nvaccess/addon-datastore-validation/blob/main/_validate/addonVersion_schema.json). +It includes an example of the file contents. + +### addonId +The ID for the addon. +This should match the name field in the addon manifest and the folder name for the submission. +The suggested convention is a camelCaseName. + +Example: `easyAddonTech` + +### channel +Should be `"stable", "beta" or "dev"`. + +**Stable:** Suggested for add-on versions which are stable, and have been tested with a stable version of NVDA. + +**Beta**: Suggested for getting add-on feedback from early adopter users before publishing an add-on as stable. +Suggested for testing with stable, beta or rc NVDA releases. + +**Dev**: This channel is suggested to be used with any preview or pre-release version of NVDA. +This is useful for testing compatibility breaking changes in an API breaking release cycle, and unreleased additions to the NVDA API. + +### addonVersionNumber +The version of the add-on, as a major-minor-patch dictionary. +Add-on versions are expected to be unique for the addonId, +meaning that a beta, stable and dev add-on version cannot share a version number. +This is so there can be a unique ordering of newest to oldest. +Add-on versions should be released in order, newer versions will encourage an update. +Users may be able to upgrade across channels in future. + +The suggested convention is to increment the patch version number for dev versions, +increment the minor version number for beta versions, +and increment the major version number for stable versions. + +Example: +```json +{ + "major": 21, + "minor": 6, + "patch": 0 +} +``` + +### addonVersionName +The addon version being released. +Must match the version in the addon manifest and the file name for the submission. + +Example: `21.6.0`. + +### displayName +The name that will be displayed in English for the addon. +Must match the summary in the addon manifest. + +Example: `"Easy Addon"` + +### publisher +The name of the individual, group, or company responsible for the addon. + +Example: `"NV Access"` + +### description +The English description of the addon that will be displayed for the addon. + +Example: `"Makes doing XYZ easier"` + +### homepage +Optional. +If the addon has a homepage where users can get more information about the addon, you can specify it here. +Must match the url in the addon manifest and the file name for the submission. + +Example: `"https://github.com/nvaccess/addon-datastore"` + +### minNVDAVersion +The add-on will not work with versions of NVDA prior to this version. +Must be a valid NVDA API version. +Valid NVDA API versions are listed in [nvdaAPIVersions.json](https://github.com/nvaccess/addon-datastore-transform/blob/main/nvdaAPIVersions.json). + +Example: +```json +{ + "major": 2021, + "minor": 1, + "patch": 0 +} +``` + +### lastTestedVersion +The add-on has been tested up to and including this version of NVDA. +Must be a valid NVDA API version. +Valid NVDA API versions are listed in [nvdaAPIVersions.json](https://github.com/nvaccess/addon-datastore-transform/blob/main/nvdaAPIVersions.json). + +Example: +```json +{ + "major": 2020, + "minor": 4, + "patch": 0 +} +``` + +### URL +To allow directly downloading the *.nvda-addon file. +The URL should remain valid indefinitely. +GitHub release URLs are recommended. + +Example: `"https://github.com/nvaccess/addon-datastore/releases/download/v0.1.0/myAddon.nvda-addon"` + +### sha256 +The SHA256 checksum for the *.nvda-addon file. +To calculate a SHA256 sum on Windows, run the following from command prompt: + +```cmd +certutil -hashfile SHA256 +``` + +Example: `"69D84CA8899800A5575CE31798293CD4FEBAB1D734A07C2E51E56A28E0DF8C82"` + +### sourceURL +Allows reviewers to inspect the source code for common issues. + +Example: `"https://github.com/nvaccess/addon-datastore/"` + +### license +The short name of the license + +Example: `"GPL v2"` + +### licenseURL +Optional. +A URL to the full license for the addon. + +Example: `"https://github.com/nvaccess/addon-datastore/license.MD"` \ No newline at end of file diff --git a/docs/submitters/submissionGuide.md b/docs/submitters/submissionGuide.md new file mode 100644 index 00000000000..339f1d3b008 --- /dev/null +++ b/docs/submitters/submissionGuide.md @@ -0,0 +1,36 @@ +# Submission Guide + +If an add-on author wishes to submit their add-on to be visible in this add-on store they will need to: +- Copy and fill out the metadata template +- Create a pull request to merge the branch to master of this repository. + +## Pre-requisites: +- Familiarity with GitHub +- Familiarity with Git, including working with branches. + +## Create an add-on version file for submission +You can create this manually, or generate this by submitting an issue. + +### Submit from an issue form +1. Select ["Add-on registration" from the new issue options](https://github.com/nvaccess/addon-datastore/issues/new/choose). +1. Fill out and submit the issue form. +1. A PR should automatically open. +1. If the PR fails to auto-merge, re-submit the auto-generated JSON file by following the "Manual file creation" steps. + +### Manual file creation +1. Fork the `addon-datastore` repository +1. On a new branch, copy the `_template_addon_release.json` file. + - Rename and move the file to `addons//.json` + - `` is the ID of the add-on. This should match the `name` field in the add-on manifest, e.g. "speechPlayer" + - `` is the add-on version in the form: `Major.Minor.Patch` e.g. "2.4.1" +1. Fill out the template. +Descriptions for the fields of JSON schema can be found in [jsonMetadata.md](./jsonMetadata.md). +1. Create a PR to merge your branch into master on the `addon-datastore` repository. + +## After submitting your add-on version file +1. Automated checks to validate the submission will complete. +Refer to [addon-datastore-validation](https://github.com/nvaccess/addon-datastore-validation) for more information on automated checks. +GitHub requires manual approval for the automated checks to run on an author's first submission to the repository. +1. If the checks pass, the PR should be merged automatically. +However, a human review process may be required. +1. When the PR is merged the add-on becomes available in the store.