diff --git a/core/src/main/resources/org/wildfly/blocklist/v1.0.0/schema.json b/core/src/main/resources/org/wildfly/blocklist/v1.0.0/schema.json new file mode 100644 index 00000000..cc4cf755 --- /dev/null +++ b/core/src/main/resources/org/wildfly/blocklist/v1.0.0/schema.json @@ -0,0 +1,43 @@ +{ + "$id": "https://wildfly.org/channels/blocklist/v1.0.0/schema.json", + "$schema": "http://json-schema.org/draft/2019-09/schema#", + "type": "object", + "required": ["schemaVersion"], + "properties": { + "schemaVersion": { + "description": "The version of the schema defining a blocklist resource.", + "type": "string", + "pattern": "^[0-9]+.[0-9]+.[0-9]+$" + }, + "blocks":{ + "description": "Streams of blocked components", + "type": "array", + "minItems": 1, + "items": { + "type": "object", + "properties": { + "groupId": { + "description": "GroupId of the blocklisted artifact. It must be a valid groupId (corresponding to a G of a Maven GAV)", + "type": "string" + }, + "artifactId": { + "description": "ArtifactId of the blocklisted artifact. It must be either a valid artifactId (corresponding to a A of a Maven GAV) or the * character to represent any artifactId", + "type": "string" + }, + "versions": { + "description": "List of blocklisted versions of the artifact.", + "type": "array", + "items": { + "type": "string" + } + } + }, + "required": [ + "groupId", + "artifactId", + "versions" + ] + } + } + } +} diff --git a/core/src/main/resources/org/wildfly/channel/v2.0.0/schema.json b/core/src/main/resources/org/wildfly/channel/v2.0.0/schema.json new file mode 100644 index 00000000..50b917f3 --- /dev/null +++ b/core/src/main/resources/org/wildfly/channel/v2.0.0/schema.json @@ -0,0 +1,151 @@ +{ + "$id": "https://wildfly.org/channels/v2.0.0/schema.json", + "$schema": "http://json-schema.org/draft/2019-09/schema#", + "type": "object", + "required": ["schemaVersion", "repositories"], + "properties": { + "schemaVersion": { + "description": "The version of the schema defining a channel resource.", + "type": "string", + "pattern": "^[0-9]+.[0-9]+.[0-9]+$" + }, + "name": { + "description": "Name of the channel. This is a one-line human-readable description of the channel", + "type": "string" + }, + "description": { + "description": "Description of the channel. This is a multi-lines human-readable description of the channel", + "type": "string" + }, + "vendor": { + "description": "Vendor of the channel.", + "type": "object", + "properties": { + "name": { + "description": "Name of the vendor", + "type": "string" + }, + "support": { + "description": "Support level provided by the vendor", + "type": "string", + "enum": [ + "supported", + "tech-preview", + "community" + ] + } + }, + "required": ["name", "support"] + }, + "repositories": { + "description": "Repositories the channel uses to resolve its streams.", + "type": "array", + "minItems": 1, + "items": { + "type": "object", + "properties": { + "id": { + "description": "Id of the repository", + "type": "string" + }, + "url": { + "description": "URL of the repository", + "type": "string" + } + }, + "required": ["id", "url"] + } + }, + "manifest": { + "description": "Location of the channel's manifest", + "type": "object", + "properties": { + "maven": { + "type": "object", + "properties": { + "groupId": { + "description": "GroupID Maven coordinate of the manifest", + "type": "string" + }, + "artifactId": { + "description": "ArtifactID Maven coordinate of the manifest", + "type": "string" + }, + "version": { + "description": "Version Maven coordinate of the manifest", + "type": "string" + } + }, + "required": ["groupId", "artifactId"] + }, + "url": { + "description": "URL of the manifest file.", + "type": "string" + } + }, + "oneOf": [ + { + "required": [ + "maven" + ] + }, + { + "required": [ + "url" + ] + } + ] + }, + "blocklist": { + "description": "Location of the channel's blocklist", + "type": "object", + "properties": { + "maven": { + "type": "object", + "properties": { + "groupId": { + "description": "GroupID Maven coordinate of the blocklist", + "type": "string" + }, + "artifactId": { + "description": "ArtifactID Maven coordinate of the blocklist", + "type": "string" + }, + "version": { + "description": "Version Maven coordinate of the blocklist", + "type": "string" + } + }, + "required": ["groupId", "artifactId"] + }, + "url": { + "description": "URL of the blocklist file.", + "type": "string" + } + }, + "oneOf": [ + { + "required": [ + "maven" + ] + }, + { + "required": [ + "url" + ] + } + ] + }, + "resolve-if-no-stream": { + "description": "Strategy for resolving artifact versions if it is not listed in streams. If not specified, 'original' strategy is used.", + "type": "string", + "enum": [ + "latest", + "maven-latest", + "maven-release", + "none", + "original" + ] + } + } +} diff --git a/core/src/main/resources/org/wildfly/manifest/v1.0.0/schema.json b/core/src/main/resources/org/wildfly/manifest/v1.0.0/schema.json new file mode 100644 index 00000000..89680abd --- /dev/null +++ b/core/src/main/resources/org/wildfly/manifest/v1.0.0/schema.json @@ -0,0 +1,92 @@ +{ + "$id": "https://wildfly.org/manifests/v1.0.0/schema.json", + "$schema": "http://json-schema.org/draft/2019-09/schema#", + "type": "object", + "required": ["schemaVersion"], + "properties": { + "schemaVersion": { + "description": "The version of the schema defining a manifest resource.", + "type": "string", + "pattern": "^[0-9]+.[0-9]+.[0-9]+$" + }, + "id": { + "description": "ID of the manifest. Used to resolved inter-channel requirements." + }, + "name": { + "description": "Name of the manifest. This is a one-line human-readable description of the manifest", + "type": "string" + }, + "description": { + "description": "Description of the manifest. This is a multi-lines human-readable description of the manifest", + "type": "string" + }, + "requires": { + "description": "Manifests that are required by this manifest.", + "type": "array", + "items": { + "type": "object", + "minItems": 1, + "properties": { + "id": { + "description": "ID of the required manifest.", + "type": "string" + }, + "maven": { + "type": "object", + "properties": { + "groupId": { + "description": "GroupID Maven coordinate of the required manifest", + "type": "string" + }, + "artifactId": { + "description": "ArtifactID Maven coordinate of the required manifest", + "type": "string" + }, + "version": { + "description": "Version Maven coordinate of the required manifest", + "type": "string" + } + }, + "required": ["groupId", "artifactId"] + } + }, + "required": ["id"] + } + }, + "streams":{ + "description": "Streams of components that are provided by this channel", + "type": "array", + "minItems": 1, + "items": { + "type": "object", + "properties": { + "groupId": { + "description": "GroupId of the stream. It must be a valid groupId (corresponding to a G of a Maven GAV)", + "type": "string" + }, + "artifactId": { + "description": "ArtifactId of the stream. It must be either a valid artifactId (corresponding to a A of a Maven GAV) or the * character to represent any artifactId", + "type": "string" + }, + "version" : { + "description": "Version of the stream. This must be either a single version. Only one of version, versionPattern must be set.", + "type": "string" + }, + "versionPattern" : { + "description": "VersionPattern of the stream. This is a regular expression that matches any version from this stream. Only one of version, versionPattern must be set.", + "type": "string" + } + }, + "required": ["groupId", "artifactId"], + "oneOf": [ + { + "required": ["version"] + }, + { + "required": ["versionPattern"] + } + ] + } + } + } +} diff --git a/doc/examples/channel.adoc b/doc/examples/channel.adoc new file mode 100644 index 00000000..47f0d07e --- /dev/null +++ b/doc/examples/channel.adoc @@ -0,0 +1,161 @@ +# Example channels + +## Simple channel definition + +Open channel uses streams with version patterns and resolve-if-no-stream to define content. + +The first step to create a channel is the definition file: + +[source, yaml, title="test-channel.yaml"] +---- +schemaVersion: "2.0.0" +name: "test-channel" #<1> +resolve-if-no-stream: latest #<2> +repositories: #<3> + - id: "central" + url: "https://repo1.maven.org/maven2/" +---- +<1> human readable channel name +<2> `latest` strategy means that if channel cannot find a stream matching the requested artifact, it will attempt to find the latest version in its repositories +<3> the repository channel is allowed to use to resolve requested artifacts. + +In this form channel will be able to resolve any artifact in `central` repository. It will always return the "latest" available version according to rules defined in spec. + +## Limiting available versions + +In most channels, the version resolution will need to be limited in some way. Channels provide a number of mechanism to achieve that. + +### Streams with concrete versions + +If the channel should only allow one, specific version of artifact to be resolved, a new stream can be added to the manifest: + +[source, yaml, title="test-manifest.yaml"] +---- +schemaVersion: "1.0.0" +name: "test-manifest" +streams: #<1> +- groupId: "org.test" + artifactId: "artifact-one" + version: "1.2.3.Final" +---- +<1> a list of curated artifact streams + +This manifest needs to referenced in the Channel. Let's say that to make it available, we publish it in an internal Maven repository with classifier `manifest` - e.g. as `org.test.channel:test:manifest:yaml:1.0.0.Final`. The channel definition will have to modified as follows: + +[source, yaml, title="test-channel.yaml"] +---- +schemaVersion: "2.0.0" +name: "test-channel" +resolve-if-no-stream: latest +manifest: + maven: #<1> + groupId: "org.test.channel" + artifactId: "test" +repositories: + - id: "central" + url: "https://repo1.maven.org/maven2/" + - id: "internal" #<2> + url: "https://internal.org/repository" +---- +<1> Instruct the channel to resolve the latest available version of `org.test.channel:test:manifest:yaml` +<2> Add an internal maven repository to the channel + +Now, when resolving artifact `org.test:artifact-one`, the channel will always return version `1.2.3.Final`. + +For anny other artifact, the latest available version will still be resolved. Note that since a new repository was added to the channel, the artifacts will be resolved in both `central` and `internal` repository. + +### Streams with version patterns + +Sometimes the artifact version needs to be limited to a certain version range - e.g. based on a minor or a version suffix. In such cases, it might be possible to utilize streams with `versionPattern`: + +[source, yaml, title="test-manifest.yaml"] +---- +schemaVersion: "1.0.0" +name: "test-manifest" +streams: + - groupId: "org.test" + artifactId: "artifact-one" + version: "1.2.3.Final" + - groupId: "org.test" + artifactId: "artifact-two" + versionPattern: "1.2.*" #<1> +... +---- +<1> allow only versions starting with "1.2" for "artifact-two" + +The modified `test-manifest.yaml` needs to be published with a new version - e.g. as `org.test.channel:test:manifest:yaml:1.0.1.Final`. The channel will automatically resolve the latest available version of the manifest. + +Assuming the Maven repositories contain two versions of the `artifact-two` - `1.2.1.Final` and `1.3.0.Final`. Because the stream allows only versions matching `1.2.*` pattern, the former version will return, even though `1.3.0.Final` would normally be considered "later". + +If a new version `1.2.2.Final` is added to the repository, the Channel will resolve it instead as it's considered "later" then `1.2.1.Final` and matches the version pattern. + +### Block versions + +Blocklist allows to exclude a concrete version of an artifact from resolution while maintaining the "latest" resolution strategy. To block an artifact version we need to create a new file called `test-blocklist.yaml`: + +[source, yaml, title="test-blocklist.yaml"] +---- +schemaVersion: "1.0.0" +name: "test-blocklist" +blocks: + - groupId: "org.test" + artifactId: "artifact-three" #<1> + version: #<1> + - "1.0.1.Final" +... +---- +<1> if the block rules should apply to all artifact without a `groupId` a wildcard `*` can be used +<2> the blocks list can include multiple versions of artifact + +Again the new file needs to published in a Maven repository, this time with classifier `blocklist` - e.g. as `org.test.channel:test:blocklist:yaml:1.0.1.Final`, and included in the channel definition: + +[source, yaml, title="test-channel.yaml"] +---- +schemaVersion: "2.0.0" +name: "test-channel" +resolve-if-no-stream: latest +manifest: + maven: + groupId: "org.test.channel" + artifactId: "test" +blocklist: + maven: #<1> + groupId: "org.test.channel" + artifactId: "test" +repositories: + - id: "central" + url: "https://repo1.maven.org/maven2/" + - id: "internal" + url: "https://internal.org/repository" +---- +<1> added blocklist definition + +Let's say the Maven repositories currently contain versions 1.0.0.Final and 1.0.1.Final of `org.test.artifact-three`. When `artifact-three` is resolved from the Channel, the `1.0.1.Final` version will be blocked, and instead `1.0.0.Final` will be used. + +When a new version, `1.0.3.Final`, is made available, the channel will instead resolve that version and the blocklist will have no effect. + +## Fix manifest and blocklist versions + +So far the channel has been using the latest available versions of manifest and blocklist. If required this can be changed to either use a specific Maven version or a file URL: + +[source, yaml, title="test-channel.yaml"] +---- +schemaVersion: "2.0.0" +name: "test-channel" +resolve-if-no-stream: latest +manifest: + maven: + groupId: "org.test.channel" + artifactId: "test" + version: "1.0.1.Final" #<1> +blocklist: + url: "http://internal.org/test-blocklist.yaml" #<2> +repositories: + - id: "central" + url: "https://repo1.maven.org/maven2/" + - id: "internal" + url: "https://internal.org/repository" +---- +<1> The channel will always use version `1.0.1.Final` of the manifest, even if newer verisons are available. +<2> The channel will download the blocklist from `http://internal.org/test-blocklist.yaml` instead of resolving it from Maven repositories. + diff --git a/doc/spec.adoc b/doc/spec.adoc index 52215855..3ebfaba9 100644 --- a/doc/spec.adoc +++ b/doc/spec.adoc @@ -5,7 +5,9 @@ [cols="1,1"] |=== -| Schema Version | 1.0.0 | +| Channel schema Version | 2.0.0 +| Manifest schema Version | 1.0.0 +| Blocklist schema Version | 1.0.0 |=== ### Summary @@ -40,6 +42,10 @@ Backwards compatibility is only guaranteed inside a single channel. If an instal ## Channel Model +Channel combines a Channel Manifest defining content of channel, one or more Repositories from which the content can be resolved and an optional Blocklist Manifest. + + +### Channel definition A channel is composed of several fields: * An optional `name` that is a human-readable one-line description of the channel (`Channel for WildFly 27`) @@ -50,11 +56,41 @@ A channel is composed of several fields: *** `supported` - Components provided by this channel are supported by the vendor. Some features provided by this channel can still be considered as tech-preview. *** `tech-preview` - Feature provided by this channel are Tech Preview by the vendor *** `community` - Components provided by this channel are a community effort from the vendor +* A collection of `repositories` that defines repositories associated with the channel. Only listed repositories are used to resolve channel's components. Each repository is composed of: +** A required `id` that defines the repository name used in Maven cache +** A required `url` pointing to a default Maven repository +* Optional `manifest` corresponding to the Channel Manifest artifact. Channel Manifest is used to define streams available in the channel. +** One of the following, mutually exclusive fields, used to resolve the Channel Manifest: +*** `maven` corresponds to Maven coordinates of the Manifest. It's composed of: +**** Mandatory `groupId` and `artifactId` elements that are the Maven coordinates of the manifest. +**** Optional `version` to stick to a given manifest version (instead of requiring the latest version of that manifest). In the absence of this `version`, the latest version of the manifest will be determined based on the Maven repository metadata (see <>). +*** `url` corresponding to a URL where the manifest file can be found. +* Optional `blocklist` corresponding to the Blocklist artifact. Blocklist is used to define versions of artifacts excluded from a channel. +** One of the following, mutually exclusive fields, used to resolve the Blocklist: +*** `maven` corresponds to Maven coordinates of the Blocklist. It's composed of: +**** Mandatory `groupId` and `artifactId` elements that are the Maven coordinates of the blocklist. +**** Optional `version` to stick to a given blocklist version (instead of requiring the latest version of that blocklist). In the absence of this `version`, the latest version of the blocklist will be determined based on the Maven repository metadata (see <>). +*** `url` corresponding to a URL where the blocklist file can be found. +* An optional `resolve-if-no-stream` that defines strategy for version resolution if the artifact has not been found in the `streams` collection or if the channel didn't declare a manifest. Allowed values are: +** `original` - fallback to the `baseVersion` provided when querying the channel. Default value if no strategy is provided. +** `latest` - use the latest version found in the Maven repositories (using mechanism described in <>) +** `maven-latest` - a version marked as `latest` in the Maven metadata +** `maven-release` - a version marked as `release` in the Maven metadata +** `none` - do not attempt to resolve versions of artifact not listed in the `streams` collection + +### Manifest definition +A Channel Manifest is composed of following fields: + +* An optional `name` that is a human-readable one-line description of the channel (`manifest for WildFly 27`) +* An optional `id` element that is used to identify channel. +* An optional `description` that provides human-readable description of the channel * A collection of `requires`. Each element of that list corresponds to another channel that is required to provision components from this channel. This field can be used for layered products to enforce their dependencies so that the installation only need to update the top level channel to get updates from all required channels. Each element is composed of: -** Mandatory `groupId` and `artifactId` elements that are the Maven coordinates of the required channel. -** Optional `version` to stick to a given channel version (instead of requiring the latest version of that channel). In the absence of this `version`, the latest version of the channel will be determined based on the Maven repository metadata. +** Mandatory `id` element corresponding to the ID of required manifest. +** Optional `maven` element representing Maven coordinates the required manifest is published at. +*** Mandatory `groupId` and `artifactId` elements. +*** Optional `version` to stick to a given manifest version (instead of requiring the latest version of that manifest). In the absence of this `version`, the latest version of the manifest will be determined based on the Maven repository metadata. * A collection of `streams` that defines all the components installable from this channel. Each stream is composed of: ** A required `groupId` that corresponds to Maven GroupId to pull artifacts (it is not allowed to specify `*` for the groupId). ** A required `artifactId` that corresponds to Maven ArtifactId to pull artifacts. Special syntax `*` can be used to match _any_ artifactId. @@ -62,44 +98,78 @@ Each element is composed of: *** `versionPattern` corresponds to a Pattern through which the available versions are matched (e.g. `2\.2\..*`) *** `version` corresponds to a single version (e.g. `2.2.Final`) -A channel does not define the Maven repositories that contain the resolved Maven artifacts from any of its streams. -It is up to the provisioning tooling to properly configure the required Maven repositories. - -A channel does not provide any default streams. +### Blocklist definition +* A collection of `blocks` that defines all the component versions excluded from version resolution. Each exclusion is composed of: +** A required `groupId` that corresponds to Maven GroupId of the excluded artifacts (it is not allowed to specify `*` for the groupId). +** A required `artifactId` that corresponds to Maven ArtifactId of the excluded artifacts. Special syntax `*` can be used to match _any_ artifactId. +** A required list of `versions` corresponding to excluded version (e.g. `[2.2.Final, 2.2.1.Final]`) ## Channel Schema -A JSON Schema is provided to validate that channels comply with the model described above. +JSON Schemas are provided to validate that channels and manifests comply with the model described above. ## Channel Representation -A channel is specified in the YAML language with a link:../core/src/main/resources/org/wildfly/channel/v1.0.0./schema.json[corresponding JSON schema] to validate its structure. +A channel is specified in the YAML language with a link:../core/src/main/resources/org/wildfly/channel/v2.0.0./schema.json[corresponding JSON schema] to validate its structure. + +A manifest is specified in the YAML language with a link:../core/src/main/resources/org/wildfly/manifest/v1.0.0./schema.json[corresponding JSON schema] to validate its structure. + +A blocklist is specified in the YAML language with a link:. +./core/src/main/resources/org/wildfly/blocklist/v1.0.0./schema.json[corresponding JSON schema] to validate its structure. ### Channel Actions and Responsibilities #### Create a channel -A Channel is a single file that complies with the channel YAML representation. -Creating a channel corresponds to the creation of such a file. +A minimal Channel definition is a single file that complies with the channel YAML representation. The Channel definition may reference two additional resources: a Manifest file and a Blocklist file. + +Creating a channel corresponds to the creation of the above files. #### Publish a channel -A channel must be “published” so that it can be read (or downloaded) by WildFly provisioning tooling. -Channels are published as a Maven artifact with the the classifier `channel` and extension/type `yaml`. +A channel may be “published” so that it can be read (or downloaded) by WildFly provisioning tooling. +Channels are published as a Maven artifact with the classifier `channel` and extension/type `yaml`. + +If the Channel uses maven coordinates to reference Manifest and/or Blocklist, those files must be "published" in one of the repositories defined in the Channel so that the Channel is able to resolve them. Otherwise, those files must be made available at the URLs defined by the Channel. + +When manifests are published as Maven artifacts, they must use the classifier `manifest` and extension/type `yaml`. + +When blocklists are published as Maven artifacts, they must use the classifier `blocklist` and extension/type `yaml`. #### Update a channel -A channel definition can be updated to add or modify streams, change its requirements, etc. -A new version of the channel must be published before it can be consumed. +A channel definition and manifest can be updated to add or modify streams, change its requirements, etc. Each of the channel files can be updated independently of each other. + +To update a channel file, it needs to be published with a new version. #### Consume a channel The main consumers of WildFly Channels are the provisioning tooling provided by the WildFly project. They consume channels by pulling the channel artifact corresponding to the `groupId`/`artifactId` of a channel. If a `version` is specified, the channel corresponding to that version is pulled. Otherwise, the latest version of the channel is determined based on the Maven metadata from the repository that hosts the channel artifacts. +#### Resolving channel manifest + +The manifest is resolved when a channel is initialized. The channel can omit the manifest definition in which case the `resolve-if-no-stream` strategy will be used to resolve artifacts. + +If the channel defines a manifest using URL, the manifest will be read from that location. If instead maven coordinates are used, the specified version of manifest is resolved from the channel's repositories. If only `groupId` and `artifactId` is provided, the latest available version of the channel manifest (as defined in <>) will be used. + +If the chanel defines a manifest, but no manifest can be resolved (using either URL or GA[V]), an error will be thrown. + +#### Resolving required channels + +Required channels are identified by their manifests' ID. When a channel is initialized, required channels' IDs are collected from the channel's manifest. If multiple channels are defined, the IDs are first resolved from the list of channels. + +If an ID cannot be resolved in this way, and the requirement provides `maven` element, a resolution will be attempted using provided maven coordinates. The parent channel's repositories will be used to resolve the new manifest and the created channel will inherit repository settings from the parent channel. + +If the resolution cannot be achieved, an error will be thrown. + +If the required channels form a cycle, an error will be thrown. + +If the set of channels contains non-unique manifest IDs, an error will be thrown. + ### Maven Artifact resolution A Maven artifact can be resolved through a channel. -Such a resolution will use the Maven repositories configured by the provisioning tool. +Such a resolution will use the Maven repositories defined within the channel. If a channel `requires` a different channel, the required channel will use the repositories from its own definition. The channels will be searched for a stream that matches the `groupId`/`artifactId` of the artifact. @@ -107,17 +177,72 @@ If a channel directly defines a stream that matches the groupId/artifactId of th If channel does not directly define a stream, required channels will be searched. The latest version of the stream found in the required channels will be used. -If multiple channels are defined, the latest version from any channel that defines the stream (directly or through required channels) is used. +If multiple channels are defined, the latest version from any channel that defines the stream (directly or through required channels) is used. Channel which manifests are `required` by another channel, are excluded from a direct search. -If no stream that matches the artifact have been found, an error is returned to the caller. +If no stream that matches the artifact have been found, version is resolved using fallback strategy defined in `resolve-if-no-stream` for the channel. +An error is returned to the caller if + +* the fallback strategy is `none` +* the fallback strategy is `latest`, `maven-latest` or `maven-release` but underlying Maven repository contains no metadata for artifacts with required `groupId` and `artifactId` If the stream defines a `version`, the artifact will be resolved based on this version. If that version of the artifact can not be pulled from the Maven repositories, an error is returned to the caller. If the stream defines a `versionPattern`, the version will be determined by querying the version of the artifacts from the Maven repositories and use the latest version that matches the pattern. If no version matches the pattern, an error is returned to the caller. +#### Maven repository proxies + +A channel defines repositories using their `id` and a default `url`. When creating the channel from definition the provisioning tool can replace the provided `url` with URL of a proxy server or an alternative repository. The `id` of the repository must not be changed. + +### Blocking artifact versions +When using an open channel, a situation may arise where certain artifacts are promoted to the channel and later discovered to be invalid. As it’s impossible to remove artifacts already deployed into a repository, those versions have to blocklisted. + +#### Format +The blocklist file contains a list of stream Maven coordinates with multiple versions: +``` +--- +blocks: +- groupId: io.undertow + artifactId: undertow-core + versions: + - 2.2.18.Final + - 2.2.17.Final +… +``` +The artifactId can use a wildcard syntax to refer to all the artifacts with the same groupId +``` +--- +blocks: +- groupId: io.undertow + artifactId: “*” + versions: + - 2.2.18.Final + - 2.2.17.Final +``` + +#### Resolving channel blocklist + +The blocklist is resolved when a channel is initialized. + +If the channel defines a blocklist using URL, the blocklist will be read from that location. If instead maven coordinates are used, the specified version of manifest is resolved from the channel's repositories. If only `groupId` and `artifactId` is provided, the latest available version of the blocklist (as defined in <>) will be used. + +If no blocklist artifact can be resolved with supplied Maven coordinates, the channel treats it as an empty blocklist. + +A blocklist applies only to the channel that defined it, not its required channels. + +#### Resolving artifact version + +During artifact version resolution, a stream matching artifact GA is located in the channel. If the stream uses concrete versions, that version of the artifact is resolved and returned to the user. +If the stream uses `versionPattern`, the blocklist is checked for excluded versions. The excluded versions are removed from the set of available artifact versions before the latest remaining version matching the stream’s pattern is used to resolve the artifact. +If the blocklist excludes all available artifact versions, `UnresolvedMavenArtifactException` is thrown. +The blocklist is ignored when using `resolveDirectMavenArtifact` method. + ### Changelog +### Version 2.0.0 + +* Introduction of the Channel Manifest and Blocklist + ### Version 1.0.0 * Initial release of the Channel specification