refactor: plugin author to an object (#2806)

#### What type of PR is this?
/kind improvement
/area core
/kind api-change

#### What this PR does / why we need it:
将 Plugin 的 author 改为 Author 对象与主题保持一致。
移除了测试类中使用的 jar 文件,改为使用时压缩

⚠️ 此为破坏性更新,需要修改 Console 插件列表的展示,以及所有官方插件的 plugin.yaml

#### Special notes for your reviewer:
/cc @halo-dev/sig-halo 
#### Does this PR introduce a user-facing change?

```release-note
Require-user-change:将 Plugin 的 author 类型从 String 为 Author
```
pull/2807/head
guqing 2022-11-30 23:45:50 +08:00 committed by GitHub
parent 9f3c7ae378
commit 68ccbb098b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 146 additions and 31 deletions

View File

@ -1,5 +1,7 @@
package run.halo.app.core.extension;
import static io.swagger.v3.oas.annotations.media.Schema.RequiredMode.REQUIRED;
import com.fasterxml.jackson.annotation.JsonIgnore;
import io.swagger.v3.oas.annotations.media.Schema;
import java.time.Instant;
@ -29,7 +31,7 @@ import run.halo.app.extension.GVK;
@EqualsAndHashCode(callSuper = true)
public class Plugin extends AbstractExtension {
@Schema(required = true)
@Schema(requiredMode = REQUIRED)
private PluginSpec spec;
private PluginStatus status;
@ -54,6 +56,8 @@ public class Plugin extends AbstractExtension {
private String displayName;
/**
* plugin version.
*
* @see <a href="semver.org">semantic version</a>
*/
@Schema(required = true, pattern = "^(0|[1-9]\\d*)\\.(0|[1-9]\\d*)\\.(0|[1-9]\\d*)(?:-("
@ -62,7 +66,7 @@ public class Plugin extends AbstractExtension {
+ ".[0-9a-zA-Z-]+)*))?$")
private String version;
private String author;
private PluginAuthor author;
private String logo;
@ -116,6 +120,16 @@ public class Plugin extends AbstractExtension {
private String logo;
}
@Data
@ToString
public static class PluginAuthor {
@Schema(requiredMode = REQUIRED, minLength = 1)
private String name;
private String website;
}
@JsonIgnore
public String generateFileName() {
return String.format("%s-%s.jar", getMetadata().getName(), spec.getVersion());

View File

@ -46,6 +46,8 @@ public class YamlPluginDescriptorFinder implements PluginDescriptorFinder {
private DefaultPluginDescriptor convert(Plugin plugin) {
String pluginId = plugin.getMetadata().getName();
Plugin.PluginSpec spec = plugin.getSpec();
Plugin.PluginAuthor author = spec.getAuthor();
String provider = (author == null ? StringUtils.EMPTY : author.getName());
DefaultPluginDescriptor defaultPluginDescriptor =
new DefaultPluginDescriptor(pluginId,
@ -53,7 +55,7 @@ public class YamlPluginDescriptorFinder implements PluginDescriptorFinder {
BasePlugin.class.getName(),
spec.getVersion(),
spec.getRequires(),
spec.getAuthor(),
provider,
joinLicense(spec.getLicense()));
// add dependencies
spec.getPluginDependencies().forEach((pluginDepName, versionRequire) -> {

View File

@ -1,16 +1,18 @@
package run.halo.app.plugin;
import static java.util.Objects.requireNonNull;
import static org.assertj.core.api.Assertions.assertThat;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Set;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
import org.springframework.util.FileSystemUtils;
import org.springframework.util.ResourceUtils;
import run.halo.app.infra.utils.FileUtils;
/**
* Tests for {@link PluginStartedListener}.
@ -39,14 +41,22 @@ class PluginStartedListenerTest {
}
@Test
void lookupFromJar() throws FileNotFoundException {
File file =
ResourceUtils.getFile("classpath:plugin/test-unstructured-resource-loader.jar");
void lookupFromJar() throws IOException {
Path tempDirectory = Files.createTempDirectory("halo-plugin");
try {
var plugin001Uri = requireNonNull(
ResourceUtils.getFile("classpath:plugin/plugin-0.0.1")).toURI();
Path targetJarPath = tempDirectory.resolve("plugin-0.0.1.jar");
FileUtils.jar(Paths.get(plugin001Uri), targetJarPath);
Set<String> unstructuredFilePathFromJar =
PluginStartedListener.PluginExtensionLoaderUtils.lookupFromJar(file.toPath());
PluginStartedListener.PluginExtensionLoaderUtils.lookupFromJar(targetJarPath);
assertThat(unstructuredFilePathFromJar).hasSize(3);
assertThat(unstructuredFilePathFromJar).containsAll(Set.of("extensions/roles.yaml",
"extensions/reverseProxy.yaml", "extensions/test.yml"));
} finally {
FileSystemUtils.deleteRecursively(tempDirectory);
}
}
}
}

View File

@ -1,18 +1,22 @@
package run.halo.app.plugin;
import static java.util.Objects.requireNonNull;
import static org.assertj.core.api.AssertionsForInterfaceTypes.assertThat;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import org.json.JSONException;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.pf4j.PluginDescriptor;
import org.skyscreamer.jsonassert.JSONAssert;
import org.springframework.util.FileSystemUtils;
import org.springframework.util.ResourceUtils;
import run.halo.app.infra.utils.FileUtils;
import run.halo.app.infra.utils.JsonUtils;
/**
@ -26,11 +30,23 @@ class YamlPluginDescriptorFinderTest {
private YamlPluginDescriptorFinder yamlPluginDescriptorFinder;
private File testFile;
private Path tempDirectory;
@BeforeEach
void setUp() throws FileNotFoundException {
void setUp() throws IOException {
yamlPluginDescriptorFinder = new YamlPluginDescriptorFinder();
testFile = ResourceUtils.getFile("classpath:plugin/test-unstructured-resource-loader.jar");
tempDirectory = Files.createTempDirectory("halo-plugin");
var plugin002Uri = requireNonNull(
ResourceUtils.getFile("classpath:plugin/plugin-0.0.2")).toURI();
Path targetJarPath = tempDirectory.resolve("plugin-0.0.2.jar");
FileUtils.jar(Paths.get(plugin002Uri), targetJarPath);
testFile = targetJarPath.toFile();
}
@AfterEach
void tearDown() throws IOException {
FileSystemUtils.deleteRecursively(tempDirectory);
}
@Test
@ -64,14 +80,14 @@ class YamlPluginDescriptorFinderTest {
String actual = JsonUtils.objectToJson(pluginDescriptor);
JSONAssert.assertEquals("""
{
"pluginId": "io.github.guqing.apples",
"pluginDescription": "这是一个用来测试的插件",
"pluginId": "fake-plugin",
"pluginDescription": "Fake description",
"pluginClass": "run.halo.app.plugin.BasePlugin",
"version": "0.0.1",
"requires": "*",
"provider": "guqing",
"version": "0.0.2",
"requires": ">=2.0.0",
"provider": "johnniang",
"dependencies": [],
"license": "MIT"
"license": "GPLv3"
}
""",
actual,

View File

@ -1,5 +1,6 @@
package run.halo.app.plugin;
import static java.util.Objects.requireNonNull;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
@ -7,6 +8,7 @@ import com.fasterxml.jackson.core.JsonProcessingException;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.net.URISyntaxException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
@ -19,9 +21,11 @@ import org.springframework.core.io.FileSystemResource;
import org.springframework.core.io.Resource;
import org.springframework.security.util.InMemoryResource;
import org.springframework.util.FileCopyUtils;
import org.springframework.util.FileSystemUtils;
import org.springframework.util.ResourceUtils;
import run.halo.app.core.extension.Plugin;
import run.halo.app.extension.Unstructured;
import run.halo.app.infra.utils.FileUtils;
import run.halo.app.infra.utils.JsonUtils;
/**
@ -60,12 +64,20 @@ class YamlPluginFinderTest {
}
@Test
void findFromJar() throws FileNotFoundException {
File file =
ResourceUtils.getFile("classpath:plugin/test-unstructured-resource-loader.jar");
Plugin plugin = pluginFinder.find(file.toPath());
void findFromJar() throws IOException, URISyntaxException {
Path tempDirectory = Files.createTempDirectory("halo-plugin");
try {
var plugin002Uri = requireNonNull(
getClass().getClassLoader().getResource("plugin/plugin-0.0.2")).toURI();
Path targetJarPath = tempDirectory.resolve("plugin-0.0.2.jar");
FileUtils.jar(Paths.get(plugin002Uri), targetJarPath);
Plugin plugin = pluginFinder.find(targetJarPath);
assertThat(plugin).isNotNull();
assertThat(plugin.getMetadata().getName()).isEqualTo("io.github.guqing.apples");
assertThat(plugin.getMetadata().getName()).isEqualTo("fake-plugin");
} finally {
FileSystemUtils.deleteRecursively(tempDirectory);
}
}
@Test
@ -77,7 +89,9 @@ class YamlPluginFinderTest {
"spec": {
"displayName": "a name to show",
"version": "0.0.1",
"author": "guqing",
"author": {
"name": "guqing"
},
"logo": "https://guqing.xyz/avatar",
"pluginDependencies": {
"banana": "0.0.1"

View File

@ -0,0 +1,13 @@
apiVersion: plugin.halo.run/v1alpha1
kind: ReverseProxy
metadata:
name: reverse-proxy-template
labels:
plugin.halo.run/pluginName: io.github.guqing.apples
rules:
- path: /static/**
file:
directory: static
- path: /admin/**
file:
directory: admin

View File

@ -0,0 +1,13 @@
apiVersion: v1alpha1
kind: Role
metadata:
name: role-template-view-apples
labels:
halo.run/role-template: "true"
annotations:
halo.run/module: "Apples Management"
halo.run/alias-name: "Apples View"
rules:
- apiGroups: [ "apples.guqing.github.com" ]
resources: [ "apples" ]
verbs: [ "get", "list" ]

View File

@ -0,0 +1,13 @@
apiVersion: plugin.halo.run/v1alpha1
kind: ReverseProxy
metadata:
name: reverse-proxy-template
labels:
plugin.halo.run/pluginName: io.github.guqing.apples
rules:
- path: /static/**
file:
directory: static
- path: /admin/**
file:
directory: admin

View File

@ -0,0 +1,18 @@
apiVersion: v1
kind: Plugin
metadata:
name: plugin-1
spec:
# 'version' is a valid semantic version string (see semver.org).
version: 0.0.1
requires: ">=2.0.0"
author:
name: guqing
logo: https://guqing.xyz/avatar
pluginDependencies:
"banana": "0.0.1"
homepage: https://github.com/guqing/halo-plugin-1
displayName: "a name to show"
description: "Tell me more about this plugin."
license:
- name: MIT

View File

@ -6,7 +6,8 @@ spec:
# 'version' is a valid semantic version string (see semver.org).
version: 0.0.2
requires: ">=2.0.0"
author: johnniang
author:
name: johnniang
logo: https://halo.run/avatar
homepage: https://github.com/halo-sigs/halo-plugin-1
displayName: "Fake Display Name"

View File

@ -6,7 +6,8 @@ spec:
# 'version' is a valid semantic version string (see semver.org).
version: 0.0.1
requires: ">=2.0.0"
author: guqing
author:
name: guqing
logo: https://guqing.xyz/avatar
pluginDependencies:
"banana": "0.0.1"