https://github.com/brian-mcnamara/plugin_uploader
Gradle plugin to automate uploading JetBrains IDE plugins to a private repository and maintaining the plugin entry in updatePlugins.xml
https://github.com/brian-mcnamara/plugin_uploader
gradle-plugin intellij intellij-plugin
Last synced: 13 days ago
JSON representation
Gradle plugin to automate uploading JetBrains IDE plugins to a private repository and maintaining the plugin entry in updatePlugins.xml
- Host: GitHub
- URL: https://github.com/brian-mcnamara/plugin_uploader
- Owner: brian-mcnamara
- License: mit
- Created: 2020-01-31T18:33:05.000Z (about 5 years ago)
- Default Branch: master
- Last Pushed: 2024-05-10T20:46:38.000Z (12 months ago)
- Last Synced: 2025-03-24T18:11:13.597Z (about 1 month ago)
- Topics: gradle-plugin, intellij, intellij-plugin
- Language: Java
- Homepage:
- Size: 163 KB
- Stars: 45
- Watchers: 4
- Forks: 7
- Open Issues: 2
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGES.MD
- License: LICENSE
Awesome Lists containing this project
README
[](https://plugins.gradle.org/plugin/dev.bmac.intellij.plugin-uploader)
# IntelliJ plugin uploader
A gradle plugin to automate uploading an IntelliJ plugin and updating updatePlugins.xml hosted on a private repository,
including S3-compatible stores.## Usage
```groovy
buildscript {
repositories {
gradlePluginPortal()
}
}plugins {
id "dev.bmac.intellij.plugin-uploader" version "1.3.5"
}generateBlockMap {
// Depend on either signPlugin or buildPlugin, depending on which task provides the file in the uploadPlugin
dependsOn(project.tasks.named("signPlugin"))
}uploadPlugin {
def signPluginTask = project.tasks.named("signPlugin").get() as SignPluginTask
// Get the plugin distribution file from the signPlugin task provided from the gradle-intellij-plugin
def archive = signPluginTask.outputArchiveFile.asFile
// If you do not wish to sign the plugin, you can use the buildPlugin output instead and specify `archive.archivePath` for the file argument
// def archive = project.tasks.buildPlugin.get().archiveFile
// For security, do not hard code usernames or passwords in source control, instead load them through the gradle properties:
//findProperty('some.gradle.property') as String
// or through Environment variables:
//System.getenv('SOME_ENVIRONMENT_VARIABLE')
def username = "exampleUsername"
def password = "examplePassword"
url.set('https://repo.example.com/intellij/plugins/')
pluginName.set('PluginName')
file.set(archive.get())
pluginId.set(project.group)
version.set(project.version)
pluginDescription.set(file('description.txt').text)
changeNotes.set(file('change-notes.txt').text)
sinceBuild.set("211")
// Example for Basic type authentication
authentication.set('Basic ' + new String(Base64.encoder.encode(("$username:$password").bytes)))
}
```## Configuration
| Attributes | Values |
|:---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|:-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| url - The url plus path of the repository to post the plugin to | **Required:** true
**Acceptable Values:** Any URL, for example:
- `https://repo.example.com/intellij/plugins`
- `http://repo.example.com:4443`
| pluginName - The plugin name to be used in the upload path such that url + pluginName is the folder the plugin will be uploaded to
**Note:** Name will be escaped when used as the upload path | **Required:** true
**Acceptable Values:** Any String |
| file - The file to be uploaded to the repo under url + pluginName + file.getName() | **Required:** true
**Acceptable Values:** A existing file path, ideally should be set via `project.tasks.buildPlugin as Zip` which grabs the file from the IntelliJ gradle plugin |
| pluginId - Plugin Id used to match in the updatePlugins.xml | **Required:** true
**Acceptable Values:** Any String |
| version - Plugin version used to update updatePlugins.xml | **Required:** true
**Acceptable Values:** Any String |
| pluginDescription - Plugins description to be used in updatePlugins.xml | **Required:** false
**Default:** *none*
**Acceptable Values:** Any String |
| changeNotes - Plugins change notes to be used in updatePlugins.xml | **Required:** false
**Default:** *none*
**Acceptable Values:** Any String |
| sinceBuild - Plugins minimum required IDE version.
See [Multi-versioning](#Multi-versioning) for more info.
Note: This should match the version specified in plugin.xml. The IDE will still validate the version in plugin.xml if this is excluded, but will not be until its been downloaded. | **Required:** false (required if using multi-versioning)
**Default:** *none*
**Acceptable Values:** A valid build number. See [Build Number Ranges](https://plugins.jetbrains.com/docs/intellij/build-number-ranges.html) for more info. |
| untilBuild - Plugins max allowed IDE version.
Note: This should match the version specified in plugin.xml. The IDE will still validate the version in plugin.xml if this is excluded, but will not be until its been downloaded. | **Required:** false
**Default:** *none*
**Acceptable Values:** A valid build number. See [Build Number Ranges](https://plugins.jetbrains.com/docs/intellij/build-number-ranges.html) for more info. |
| authentication - Authentication string used to publish files to the private repo. Will be used as the authorization header | **Required:** false
**Default:** *none*
**Acceptable Values:**
- `Basic [authenticationString]`
- `Bearer [bearerToken] `
| updateFile - Overrides the default updatePlugins.xml file name.
Note: See [Publishing a Plugin to a Custom Plugin Repository](https://jetbrains.org/intellij/sdk/docs/basics/getting_started/update_plugins_format.html#describing-your-plugins-in-updatepluginsxml-file) for more information about updatePlugins.xml | **Required:** false
**Default:** updatePlugins.xml
**Acceptable Values:** Any String |
| updatePluginXml - Gates whether updatePlugins.xml is updated. | **Required:** false
**Default:** true
**Acceptable Values:** `true` / `false` |
| repoType - Sets the type of repository operations to use. | **Required:** false
**Default:** REST_POST
**Acceptable Values:**
- REST_POST
- REST_PUT
- S3
| absoluteDownloadUrls - **deprecated**: see downloadUrlPrefix
Use absolute url to the plugin download in update plugins xml over relative paths. | **Required:** false
**Default:** false
**Acceptable Values:** `true` / `false` |
| downloadUrlPrefix - Allows specifying the download url prefix to use over the default relative path. | **Required:** false
**Default:** *none*
**Acceptable Values:** A URL prefix, for example:
- `https://repo.example.com/intellij/plugins`
- `/intellij/plugins`
- |
## Supported repo types
This plugin supports standard REST style repositories (Nexus, artifactory, etc) which accept uploads
via POST/PUT requests. As of version 1.3.0, the plugin now supports Amazon S3 compatible stores as well.
### S3
S3 compatible repositories are supported with the repoType set to `S3`. Some requirements should be noted:
* AWS S3 should use [virtual-hosted-style endpoints](https://docs.aws.amazon.com/AmazonS3/latest/userguide/access-bucket-intro.html)
as the url, for example `https://bucket-name.s3.Region.amazonaws.com/folder`
* non-AWS S3 endpoints need to specify the bucket name as the userinfo in the url, for example
`https://[email protected]/folder`
* Any path added to the url will be the directory structure under the bucket
* Authentication can be specified by any means accepted by the [aws sdk](https://docs.aws.amazon.com/sdk-for-java/v1/developer-guide/credentials.html)
or can be passed into the authentication as a colon (`:`) separated list of access key, secret key, or access key, secret key, session token.
## Multi-versioning
As of version 1.2.0, multiple plugin entries with the same ID can be added to the updateFile file
as long as the since-build and until-build don't overlap. This is available since IDEA version 193.2956.37 (2019.3)
which added entry-filtering using since and until build on each entry.
The gradle plugin will check if the current upload, or an existing entry on the repository, has a since-build set before 193.2956.37 (or is not set),
which prevents multiple entries from being added to ensure compatibility for the older IDEA versions.
Otherwise, multi-versioning is enabled which will update an existing entry if the since-build matches otherwise
a new entry is created and existing entries until-build are updated ensuring no overlap occurs.
For best experience, it is recommended to always provide a valid build version to the sinceBuild parameter
and to exclude the untilBuild parameter as this plugin will take care of adding until-build when new entries are uploaded.
It should be noted, specifying untilBuild is possible while using multi-version, however the until-build version may be changed
at a later time to a lower build version (for example, if a new entry specifies a since-build which is before the current entries
until-build, the until-build will be updated to a build before the new entries since-build)
## Updating a local file-based updatePlugins.xml
A task is registered as part of this plugin which can be used to update a file based updatePlugins.xml
This can be useful when hosting plugins in source control over a dedicated repository.
### Usage
```groovy
task updateLocalPluginXml(type:dev.bmac.gradle.intellij.UpdateXmlTask) {
updateFile.set(file('updatePlugins.xml'))
downloadUrl.set('http://example.com/plugins/pluginFile.zip')
pluginName.set('PluginName')
pluginId.set(project.group)
version.set(project.version)
pluginDescription.set(file('description.txt').text)
changeNotes.set(file('change-notes.txt').text)
sinceBuild.set("211")
}
```
## Notes
This plugin uses a lock file to prevent concurrent modifications to the updatePlugins.xml file.
While the lock file will be cleaned up, it could be left behind if the process is forcefully interrupted
requiring the lock to be deleted manually. The lock can be found in the url root and is named `updatePlugins.xml.lock`
(lock file name depends on updateFile)
As of 1.3.0, a check will be performed to prevent replacing an existing release. This only checks updatePlugins.xml
versions, so any versions not in this file will be allowed to be replaced. This can be disabled using
`dev.bmac.pluginUploader.skipReleaseCheck` system property set to `true`
### Plugin Signing
As of 2021.2 plugin signature are being checked during install. Private plugin can use plugin signing but require the `signPlugin`
task be implemented and public/private keys be used to sign. While not required to use this plugin, it is recommended.
## License
Most of this project is covered under the MIT license - located in the LICENSE file, with certain portions covered by
Apache 2 license; all of which are clearly marked in a comment at the top of the file(s).