Skip to content

Latest commit

 

History

History
816 lines (590 loc) · 21.7 KB

CONTRIBUTING.md

File metadata and controls

816 lines (590 loc) · 21.7 KB

Contributing guide

Table of Contents

The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in BCP 14, RFC2119, and RFC8174 when, and only when, they appear in all capitals, as shown here.

Introduction

  • Make sure to follow the naming guidelines.
  • Refer to the common fields example for a good starting point for a new package.
  • Refer to the different examples and/or existing package definitions for further guidance.
  • Testing a package MUST be done locally prior to creating a PR. See testing for more information.

Tip

Use the YAML language server combined with the schemastore schema to get diagnostics and autocompletion (see Schema).

Schema

Package definitions are validated against a well-defined JSON schema. The full schema is hosted on http://schemastore.org/.

Tip

Use b0o/SchemaStore.nvim and the YAML language server to integrate these schemas in Neovim. This gives you diagnostics and autocompletion inside the editor when editing package definitions:

Testing

Testing a package locally can be achieved by configuring the mason.nvim client to source package definitions locally from your filesystem.

Important

In order for mason.nvim to be able to parse the YAML files you must have yq installed on your system. Tip: install yq (:MasonInstall yq) from the core registry before testing.

Take note of the path where you have mason-org/mason-registry cloned on your file system. To configure mason.nvim to source packages from there you'll use the file: protocol, like so:

require("mason").setup {
  registries = {
    "file:~/dev/mason-registry"
  }
}

Before continuing, make sure Mason has been properly configured to source packages locally by opening the :Mason window and pressing g? to open the help view:

Tip

You can emulate different platforms ("targets") by providing the --target= option to :MasonInstall. For example:

:MasonInstall --target=linux_arm64 my-package

Note that this is only a soft emulation and only impacts how the package definition is parsed.

The anatomy of a package

Packages are defined following a well-defined specification. Package definitions are hosted as separate YAML files that MUST be located at packages/<package-name>/package.yaml.

Package sources are identified via a purl identifier. Each package source (purl) MUST contain a version component specifying the latest available version, e.g pkg:github/rust-lang/rust-analyzer@2023-04-04.

Package versions are automatically kept up-to-date via Renovate.

Package specification

The following is a rough outline of the package definition schema:

name: string
description: string
homepage: URL
licenses: SPDXLicense[]
languages: string[]
categories: Category[]

source:
    id: string
    [key: string]: any

bin?:
    [executable: string]: string
share?:
    [share_location: string]: string
opt?:
    [opt_location: string]: string

name

The package name MUST be unique. The name of a package MUST follow the following naming scheme:

  1. If the upstream package name is sufficiently unambiguous, or otherwise widely recognized, that name MUST be used.
  2. If the upstream package provides a single executable with a name that is sufficiently unambiguous, or otherwise widely recognized, the name of the executable MUST be used.
  3. If either the package or executable name is ambiguous, a name where a clarifying prefix or suffix is added SHOULD be used.
  4. As a last resort, the name of the package should be constructed to best convey its target language and scope, e.g. json-language-server for a JSON language server.

description

Short description of the package. The description SHOULD be sourced from the upstream package directly.

Longer descriptions MUST be split on multiple lines, as to not exceed the max line length (120).

Example:

description: |
  Lorem ipsum dolor sit amet, officia excepteur ex fugiat reprehenderit enim labore culpa sint ad nisi Lorem pariatur
  mollit ex esse exercitation amet. Nisi anim cupidatat excepteur officia.

Tip

To automatically format the description across multiple lines, run :setlocal textwidth=120, visually select the description and press gw (:help gw).

homepage

The homepage of the package. The homepage SHOULD be a public website if available, otherwise it MUST be a URL to the source code.

The URL MUST be a well-formed URL. The URL scheme MUST be either http or https.

licenses

List of licenses associated with this package. MUST contain at least one entry.

The license MUST be a SPDX-compatible license identifier. Should the package use a license not available as a SPDX identifier, the license "proprietary" (all lower case) MUST be used.

Examples:

  • MIT
  • Apache-2.0
  • GPL-3.0-only

languages

The languages the package targets. MAY be empty. A language is an arbitrary string (e.g., "Rust"). The casing of the string MUST be the same as other references to the same language in other package definitions, i.e. it's an error if package A specifies Javascript and package B specifies JavaScript.

categories

The categories the package belongs to. MAY be empty. If not empty, each entry MUST be one of:

  • Compiler
  • DAP
  • Formatter
  • LSP
  • Linter
  • Runtime

source

The source of the package. The source entry contains all necessary information to properly install the package. At the very minimum it MUST contain an id property. The id property MUST be a purl-compatible package identifier. The purl identifier MUST contain a version component.

The source object MAY contain additional properties to support installation.

Examples:

source:
    id: pkg:npm/[email protected]
source:
    id: pkg:github/rust-lang/rust-analyzer@2022-12-05

bin

The executables the package provides. The key is the canonical name of the executable, and the value is either (i) a relative path to the executable from the package directory, or (ii) an expression that delegates path resolution (e.g., npm:typescript-language-server or cargo:rust-analyzer), or (iii) an expression.

On Unix systems, a symlink is created. On Windows, a wrapper batch .cmd executable is always created.

Example:

bin:
    typescript-language-server: npm:typescript-language-server
    rust-analyzer: bin/rust-analyzer

share

The architecture independent files the package provides.

The mapping MUST either (i) link a single target file to a single source file, or (ii) link a target directory to a source directory, or (iii) an expression.

This creates symlinks (uv_fs_symlink) on all platforms.

Example:

share:
    # Links $MASON/share/jdtls/lombok.jar -> <package>/lombok.jar
    jdtls/lombok.jar: lombok.jar
    # Links $MASON/share/jdtls/plugins/ -> <package>/plugins/**/* (i.e. all files within the target directory)
    jdtls/plugins/: plugins/

Important

The contents of linked files MUST be compatible with all machines, regardless of hardware architecture.

opt

The optional, add-on, contents of a package. This is for example useful in situations when a package provides auxiliary binaries that should not be linked to the "global" Mason bin/ directory.

The mapping MUST either (i) link a single target file to a single source file, or (ii) link a target directory to a source directory, or (iii) an expression.

This creates symlinks (uv_fs_symlink) on all platforms.

Example:

opt:
    # Links $MASON/opt/solang/llvm15.0/LICENSE -> <package>/doc/LICENSE
    solang/llvm15.0/LICENSE: doc/LICENSE
    # Links $MASON/opt/solang/llvm15.0/ -> <package>/llvm15.0/**/* (i.e. all files within the target directory)
    solang/llvm15.0/: llvm15.0/

Expressions

When specified, a component of a package definition may include expressions. These expressions can only be used in string values, and are denoted by {{expr}}. This allows for dynamically evaluating values, when needed.

Example:

# ...
source:
    id: pkg:github/rust-lang/[email protected]
    asset:
        - target: darwin_x64
          file: rust-analyzer-darwin_x64_{{ version | strip_prefix "v" }}.tar.gz
          bin: rust-analyzer-darwin_x64
          some_other_bin: rust-fmt-darwin_x64
        - target: linux_x64
          file: rust-analyzer-linux_x64_{{ version | strip_prefix "v" }}.tar.gz
          bin: rust-analyzer-linux_x64
          some_other_bin: rust-fmt-linux_x64

bin:
    # This will be evaluated to either "rust-analyzer-darwin_x64" or "rust-analyzer-linux_x64", depending on which
    # platform the package is being installed on.
    rust-analyzer: "{{source.asset.bin}}"
    rustfmt: "{{source.asset.some_other_bin}}"

Expressions use basic Lua syntax with the additional ability to pipe values to a limited set of transformation functions. All expressions are evaluated in a context, where values are accessed through normal variable access.

Examples

Common fields

The following fields are common for all packages and are subject to the same requirements.

Refer to the following sections for a detailed description:

Example:

---
name: lua-language-server
description: A language server that offers Lua language support - programmed in Lua.
homepage: https://github.com/LuaLS/lua-language-server
licenses:
  - MIT
languages:
  - Lua
categories:
  - LSP

Important

The document MUST start with a YAML header notation (---).


Cargo

Example:

source:
  id: pkg:cargo/[email protected]

bin:
  rnix-lsp: cargo:rnix-lsp
Example: Specify features

To specify the features to install, use the features qualifier.

Example:

source:
  id: pkg:cargo/[email protected]?features=lsp,cli
Example: Git source

To install a cargo package from a git source you may specify the repository_url qualifier. This will by default target tags in the provided git repository (i.e. cargo install --tag <TAG>). To target commits instead (i.e. cargo install --rev <REV>), provide an additional &rev=true qualifier.

Example:

source:
  id: pkg:cargo/[email protected]?repository_url=https://github.com/influxdata/flux-lsp
Example: Specify supported platforms

You MUST provide the supported_platforms field if the package is only supported on certain platforms.

Example:

source:
  id: pkg:cargo/[email protected]
  supported_platforms:
    - linux_x64_gnu
    - linux_arm64_gnu

Composer

Example:

source:
  id: pkg:composer/vimeo/[email protected]

bin:
  psalm: composer:psalm
  psalm-language-server: composer:psalm-language-server

Gem

Example:

source:
  id: pkg:gem/[email protected]

bin:
  standardrb: gem:standardrb
Example: Specify supported platforms

You MUST provide the supported_platforms field if the package is only supported on certain platforms.

Example:

source:
  id: pkg:gem/[email protected]
  supported_platforms:
    - linux_x64_gnu
    - linux_arm64_gnu

GitHub release assets

Note: Downloaded release assets are automatically unpacked (e.g. if it's a .tar file it's unpacked in its download location).

Example: Platform dependent release assets

When multiple, platform dependent, release assets are provided you MUST register an entry for each applicable platform. This is done by providing a list of assets. The ordering of this list is important as clients may be target to more than one platform and entries appearing first in the list have precedence.

When this source is parsed by the client, the list is "unwrapped" to the very first entry whose target applies to the current system.

Example:

source:
  id: pkg:github/LuaLS/[email protected]
  asset:
    - target: darwin_arm64
      file: lua-language-server-{{version}}-darwin-arm64.tar.gz
    - target: darwin_x64
      file: lua-language-server-{{version}}-darwin-x64.tar.gz
    - target: linux_arm64_gnu
      file: lua-language-server-{{version}}-linux-arm64.tar.gz
    - target: linux_x64_gnu
      file: lua-language-server-{{version}}-linux-x64.tar.gz
    - target: win_x86
      file: lua-language-server-{{version}}-win32-ia32.zip
    - target: win_x64
      file: lua-language-server-{{version}}-win32-x64.zip

It's common that platform-dependent assets contain different files and different folder structures. In order to facilitate linking executables at a later stage you may provide additional, arbitrary, fields. The following example adds a bin field to each entry, which is later used in a expression to link the executable.

Example:

source:
  id: pkg:github/LuaLS/[email protected]
  asset:
    - target: darwin_arm64
      file: lua-language-server-{{version}}-darwin-arm64.tar.gz
      bin: lua-language-server
    - target: win_x64
      file: lua-language-server-{{version}}-win32-x64.zip
      bin: lua-language-server.exe

bin:
  lua-language-server: "{{source.asset.bin}}"
Example: Single, platform independent, release asset

Example:

source:
  id: pkg:github/Dart-Code/[email protected]
  asset:
    file: dart-code-{{ version | strip_prefix "v" }}.vsix
Example: Downloading multiple assets

Example:

source:
  id: pkg:github/LuaLS/[email protected]
  asset:
    file:
      - lua-language-server-{{version}}
      - lua-language-server-{{version}}.sha256
      - LICENSE
Example: Change asset download location

By default, assets are downloaded in the root directory of the package directory. You MAY change the download location by appending it to the file name itself with a : prefix.

If the download location ends with a / the file will be downloaded in that directory, otherwise it's a filename.

Example:

source:
  id: pkg:github/lua/[email protected]
  asset:
    file:
      # download "lua-language-server-{{version}}" to "bin/lua-language-server-{{version}}"
      - lua-language-server-{{version}}:bin/

      # download "lua-formatter-{{version}}" to "bin/lua-format"
      - lua-formatter-{{version}}:bin/lua-format

      # download "license" to "LICENSE.txt"
      - license:LICENSE.txt

Important

Linux binaries are commonly compiled for GNU systems. These binaries MUST be associated with a _gnu target, e.g. linux_x64_gnu.


GitHub build from source

Note: Build scripts run on the platform's default shell. On Unix this is bash, on Windows it's pwsh.

Note: By default, Renovate is configured to look for new releases for pkg:github sources. However, when building from source, the repository most likely doesn't provide GitHub releases, but instead uses normal git tags. To ensure that Renovate picks up new versions, you MUST provide a datasource override via a comment (see example below).

Example:

source:
  # renovate:datasource=github-tags
  id: pkg:github/stoplightio/[email protected]
  build:
    run: |
      npm exec yarn@1 install
      npm exec --package=yarn@1 'node make package'

bin:
  spectral-language-server: node:dist/server/index.js
Example: Platform-dependent build scripts

Sometimes the build script cannot be expressed in a shell-agnostic way. You MUST then provide a list of entries with the appropriate targets. The ordering of this list is important as clients may be target to more than one platform and entries appearing first in the list have precedence.

When this source is parsed by the client, the list is "unwrapped" to the very first entry whose target applies to the current system.

Example:

source:
  id: pkg:github/vala-lang/[email protected]
  build:
    - target: unix
      run: |
        meson -Dprefix="$PWD" build
        ninja -C build install
    - target: win
      run: |
        meson -Dprefix="($pwd).path" build
        ninja -C build install

Golang

Example:

source:
  id: pkg:golang/golang.org/x/tools/[email protected]

bin:
  gopls: golang:gopls
Example: Specifying additional package path

Use the subpath component to specify a sub-path of a golang package.

Example:

source:
  id: pkg:golang/golang.org/x/[email protected]#cmd/goimports

LuaRocks

Example:

source:
  id: pkg:luarocks/[email protected]

bin:
  luacheck: luarocks:luacheck
Example: Specifying a server

Use the repository_url qualifier to specify a different server (i.e. luarocks install --server).

Example:

source:
  id: pkg:luarocks/luaformatter@scm-1?repository_url=https://luarocks.org/dev
Example: dev target

Use the dev qualifier to specify a dev target (i.e. luarocks install --dev).

Example:

source:
  id: pkg:luarocks/teal-language-server@dev-1?dev=true

npm

Example:

source:
  id: pkg:npm/[email protected]

bin:
  typescript-language-server: npm:typescript-language-server
Example: Additional npm dependencies

Some packages may require additional npm dependencies to be installed in the same location. This can be achieved by providing the extra_packages field.

Example:

source:
  id: pkg:npm/[email protected]
  extra_packages:
    - typescript

Packages provided in extra_packages are passed as-is to npm, so they may require version constraints such as typescript@4.


Nuget

Example:

source:
  id: pkg:nuget/[email protected]

bin:
  fsautocomplete: nuget:fsautocomplete

opam

Example:

source:
  id: pkg:opam/[email protected]

bin:
  ocamllsp: opam:ocamllsp

PyPI

Example:

source:
  id: pkg:pypi/[email protected]

bin:
  yamllint: pypi:yamllint
Example: Adding extra specifiers

To add "extra" specifiers to a pypi package (i.e. pip install python-lsp-server[all]), use the extra qualifier.

Example:

source:
  id: pkg:pypi/[email protected]?extra=all
Example: Additional pypi dependencies

Some packages may require additional pypi dependencies to be installed in the same location. This can be achieved by providing the extra_packages field.

Example:

source:
  id: pkg:pypi/[email protected]
  extra_packages:
    - toml

Packages provided in extra_packages are passed as-is, so they may require version constraints such as toml==4.


Open VSX

Open VSX is an open-source registry for VS Code extensions.

Example:

source:
  id: pkg:openvsx/vscjava/[email protected]
  download:
    file: vscjava.vscode-java-debug-{{version}}.vsix
Example: Platform-dependent file

If the Open VSX package provides platform-dependent files they need to be registered explicitly. In addition to target and file, the target_platform field must be defined and correspond to an OpenVSX platform identifier (e.g. linux-x64).

source:
  id: pkg:openvsx/BroadcomMFD/[email protected]
  download:
    - target: linux_x64
      file: BroadcomMFD.cobol-language-support-{{ version }}@linux-x64.vsix
      target_platform: linux-x64
    - target: darwin_arm64
      file: BroadcomMFD.cobol-language-support-{{ version }}@darwin-arm64.vsix
      target_platform: darwin-arm64