feat: add static deploy handlers.

pull/471/head^2
ruibaby 2019-12-26 14:21:49 +08:00
parent 0f59e2fe04
commit 83e87553b7
13 changed files with 505 additions and 1 deletions

View File

@ -1,10 +1,14 @@
package run.halo.app.controller.admin.api;
import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import run.halo.app.model.support.StaticPageFile;
import run.halo.app.service.StaticPageService;
import java.util.List;
/**
* @author ryan0up
* @date 2019/12/25
@ -19,8 +23,21 @@ public class StaticPageController {
this.staticPageService = staticPageService;
}
@GetMapping
@ApiOperation("List static page files.")
public List<StaticPageFile> list() {
return staticPageService.listFile();
}
@GetMapping("generate")
@ApiOperation("Generate static page files.")
public void generate() {
staticPageService.generate();
}
@GetMapping("deploy")
@ApiOperation("Deploy static page to remove platform")
public void deploy() {
staticPageService.deploy();
}
}

View File

@ -0,0 +1,33 @@
package run.halo.app.handler.staticdeploy;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import run.halo.app.model.enums.StaticDeployType;
import run.halo.app.service.OptionService;
/**
* Git deploy handler.
*
* @author ryanwang
* @date 2019-12-26
*/
@Slf4j
@Component
public class GitStaticDeployHandler implements StaticDeployHandler {
private final OptionService optionService;
public GitStaticDeployHandler(OptionService optionService) {
this.optionService = optionService;
}
@Override
public void deploy() {
}
@Override
public boolean supportType(StaticDeployType type) {
return StaticDeployType.GIT.equals(type);
}
}

View File

@ -0,0 +1,33 @@
package run.halo.app.handler.staticdeploy;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import run.halo.app.model.enums.StaticDeployType;
import run.halo.app.service.OptionService;
/**
* Netlify deploy handler.
*
* @author ryanwang
* @date 2019-12-26
*/
@Slf4j
@Component
public class NetlifyStaticDeployHandler implements StaticDeployHandler {
private final OptionService optionService;
public NetlifyStaticDeployHandler(OptionService optionService) {
this.optionService = optionService;
}
@Override
public void deploy() {
}
@Override
public boolean supportType(StaticDeployType type) {
return StaticDeployType.NETLIFY.equals(type);
}
}

View File

@ -0,0 +1,26 @@
package run.halo.app.handler.staticdeploy;
import org.springframework.lang.Nullable;
import run.halo.app.model.enums.StaticDeployType;
/**
* Static deploy handler interface class.
*
* @author ryanwang
* @date 2019-12-26
*/
public interface StaticDeployHandler {
/**
* do deploy.
*/
void deploy();
/**
* Checks if the given type is supported.
*
* @param type deploy type
* @return true if supported; false or else
*/
boolean supportType(@Nullable StaticDeployType type);
}

View File

@ -0,0 +1,64 @@
package run.halo.app.handler.staticdeploy;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.ApplicationContext;
import org.springframework.lang.NonNull;
import org.springframework.lang.Nullable;
import org.springframework.stereotype.Component;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;
import run.halo.app.exception.FileOperationException;
import run.halo.app.model.enums.StaticDeployType;
import java.util.Collection;
import java.util.LinkedList;
/**
* Static deploy handlers.
*
* @author ryanwang
* @date 2019-12-26
*/
@Slf4j
@Component
public class StaticDeployHandlers {
private final Collection<StaticDeployHandler> staticDeployHandlers = new LinkedList<>();
public StaticDeployHandlers(ApplicationContext applicationContext) {
// Add all file handler
addFileHandlers(applicationContext.getBeansOfType(StaticDeployHandler.class).values());
}
/**
* do deploy.
*
* @param staticDeployType static deploy type
*/
public void deploy(@NonNull StaticDeployType staticDeployType) {
Assert.notNull(staticDeployType, "Static deploy type must not be null");
for (StaticDeployHandler staticDeployHandler : staticDeployHandlers) {
if (staticDeployHandler.supportType(staticDeployType)) {
staticDeployHandler.deploy();
}
}
throw new FileOperationException("No available static deploy handler to deploy static pages").setErrorData(staticDeployType);
}
/**
* Adds static deploy handlers.
*
* @param staticDeployHandlers static deploy handler collection
* @return current file handlers
*/
@NonNull
public StaticDeployHandlers addFileHandlers(@Nullable Collection<StaticDeployHandler> staticDeployHandlers) {
if (!CollectionUtils.isEmpty(staticDeployHandlers)) {
this.staticDeployHandlers.addAll(staticDeployHandlers);
}
return this;
}
}

View File

@ -0,0 +1,36 @@
package run.halo.app.model.enums;
/**
* Static deploy type.
*
* @author ryanwang
* @date 2019-12-26
*/
public enum StaticDeployType implements ValueEnum<Integer> {
/**
* Deploy static pages in remote git repository, such as github pages,gitee pages,coding pages.etc.
*/
GIT(1),
/**
* Deploy static pages in netlify.
*/
NETLIFY(2);
private Integer value;
StaticDeployType(Integer value) {
this.value = value;
}
/**
* Get enum value.
*
* @return enum value
*/
@Override
public Integer getValue() {
return value;
}
}

View File

@ -0,0 +1,76 @@
package run.halo.app.model.properties;
/**
* Git static deploy properties.
*
* @author ryanwang
* @date 2019-12-26
*/
public enum GitStaticDeployProperties implements PropertyEnum {
/**
* Git static deploy domain.
*/
GIT_DOMAIN("git_static_deploy_domain", String.class, ""),
/**
* Git static deploy repository.
*/
GIT_REPOSITORY("git_static_deploy_repository", String.class, ""),
/**
* Git static deploy branch.
*/
GIT_BRANCH("git_static_deploy_branch", String.class, "master"),
/**
* Git static deploy username.
*/
GIT_USERNAME("git_static_deploy_username", String.class, ""),
/**
* Git static deploy email.
*/
GIT_EMAIL("git_static_deploy_email", String.class, ""),
/**
* Git static deploy token.
*/
GIT_TOKEN("git_static_deploy_token", String.class, ""),
/**
* Git static deploy cname.
*/
GIT_CNAME("git_static_deploy_cname", String.class, "");
private final String value;
private final Class<?> type;
private final String defaultValue;
GitStaticDeployProperties(String value, Class<?> type, String defaultValue) {
this.defaultValue = defaultValue;
if (!PropertyEnum.isSupportedType(type)) {
throw new IllegalArgumentException("Unsupported blog property type: " + type);
}
this.value = value;
this.type = type;
}
@Override
public Class<?> getType() {
return type;
}
@Override
public String defaultValue() {
return defaultValue;
}
@Override
public String getValue() {
return value;
}
}

View File

@ -0,0 +1,56 @@
package run.halo.app.model.properties;
/**
* Netlify static deploy properties.
*
* @author ryanwang
* @date 2019-12-26
*/
public enum NetlifyStaticDeployProperties implements PropertyEnum {
/**
* Netlify static deploy domain.
*/
NETLIFY_DOMAIN("netlify_static_deploy_domain", String.class, ""),
/**
* Netlify static deploy site id.
*/
NETLIFY_SITE_ID("netlify_static_deploy_site_id", String.class, ""),
/**
* Netlify static deploy token.
*/
NETLIFY_TOKEN("netlify_static_deploy_token", String.class, "");
private final String value;
private final Class<?> type;
private final String defaultValue;
NetlifyStaticDeployProperties(String value, Class<?> type, String defaultValue) {
this.defaultValue = defaultValue;
if (!PropertyEnum.isSupportedType(type)) {
throw new IllegalArgumentException("Unsupported blog property type: " + type);
}
this.value = value;
this.type = type;
}
@Override
public Class<?> getType() {
return type;
}
@Override
public String defaultValue() {
return defaultValue;
}
@Override
public String getValue() {
return value;
}
}

View File

@ -155,6 +155,9 @@ public interface PropertyEnum extends ValueEnum<String> {
propertyEnumClasses.add(SeoProperties.class);
propertyEnumClasses.add(UpOssProperties.class);
propertyEnumClasses.add(ApiProperties.class);
propertyEnumClasses.add(StaticDeployProperties.class);
propertyEnumClasses.add(GitStaticDeployProperties.class);
propertyEnumClasses.add(NetlifyStaticDeployProperties.class);
Map<String, PropertyEnum> result = new HashMap<>();

View File

@ -0,0 +1,45 @@
package run.halo.app.model.properties;
import run.halo.app.model.enums.StaticDeployType;
/**
* Static deploy properties.
*
* @author ryanwang
* @date 2019-12-26
*/
public enum StaticDeployProperties implements PropertyEnum {
/**
* static deploy type
*/
DEPLOY_TYPE("static_deploy_type", StaticDeployType.class, StaticDeployType.GIT.name());
private final String value;
private final Class<?> type;
private final String defaultValue;
StaticDeployProperties(String value, Class<?> type, String defaultValue) {
this.value = value;
this.type = type;
this.defaultValue = defaultValue;
}
@Override
public Class<?> getType() {
return type;
}
@Override
public String defaultValue() {
return defaultValue;
}
@Override
public String getValue() {
return value;
}
}

View File

@ -0,0 +1,35 @@
package run.halo.app.model.support;
import lombok.Data;
import java.util.Comparator;
import java.util.List;
/**
* Static page dto.
*
* @author ryanwang
* @date 2019-12-26
*/
@Data
public class StaticPageFile implements Comparator<StaticPageFile> {
private String name;
private Boolean isFile;
private List<StaticPageFile> children;
@Override
public int compare(StaticPageFile leftFile, StaticPageFile rightFile) {
if (leftFile.isFile && !rightFile.isFile) {
return 1;
}
if (!leftFile.isFile && rightFile.isFile) {
return -1;
}
return leftFile.getName().compareTo(rightFile.getName());
}
}

View File

@ -1,5 +1,9 @@
package run.halo.app.service;
import run.halo.app.model.support.StaticPageFile;
import java.util.List;
/**
* Static Page service interface.
*
@ -17,4 +21,16 @@ public interface StaticPageService {
* Generate pages.
*/
void generate();
/**
* Deploy static pages.
*/
void deploy();
/**
* List file of generated static page.
*
* @return a list of generated static page.
*/
List<StaticPageFile> listFile();
}

View File

@ -10,18 +10,24 @@ import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.lang.NonNull;
import org.springframework.lang.Nullable;
import org.springframework.stereotype.Service;
import org.springframework.ui.ModelMap;
import org.springframework.ui.freemarker.FreeMarkerTemplateUtils;
import org.springframework.util.Assert;
import org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer;
import run.halo.app.config.properties.HaloProperties;
import run.halo.app.exception.ServiceException;
import run.halo.app.handler.staticdeploy.StaticDeployHandlers;
import run.halo.app.handler.theme.config.support.ThemeProperty;
import run.halo.app.model.dto.PhotoDTO;
import run.halo.app.model.entity.*;
import run.halo.app.model.enums.PostStatus;
import run.halo.app.model.enums.StaticDeployType;
import run.halo.app.model.properties.PostProperties;
import run.halo.app.model.properties.StaticDeployProperties;
import run.halo.app.model.support.HaloConst;
import run.halo.app.model.support.StaticPageFile;
import run.halo.app.model.vo.PostDetailVO;
import run.halo.app.model.vo.PostListVO;
import run.halo.app.model.vo.SheetDetailVO;
@ -33,9 +39,12 @@ import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.LinkedList;
import java.util.List;
import java.util.stream.Stream;
import static org.springframework.data.domain.Sort.Direction.DESC;
@ -79,6 +88,8 @@ public class StaticPageServiceImpl implements StaticPageService {
private final FreeMarkerConfigurer freeMarkerConfigurer;
private final StaticDeployHandlers staticDeployHandlers;
public StaticPageServiceImpl(PostService postService,
PostCategoryService postCategoryService,
PostTagService postTagService,
@ -92,7 +103,8 @@ public class StaticPageServiceImpl implements StaticPageService {
ThemeService themeService,
HaloProperties haloProperties,
OptionService optionService,
FreeMarkerConfigurer freeMarkerConfigurer) throws IOException {
FreeMarkerConfigurer freeMarkerConfigurer,
StaticDeployHandlers staticDeployHandlers) throws IOException {
this.postService = postService;
this.postCategoryService = postCategoryService;
this.postTagService = postTagService;
@ -107,6 +119,7 @@ public class StaticPageServiceImpl implements StaticPageService {
this.haloProperties = haloProperties;
this.optionService = optionService;
this.freeMarkerConfigurer = freeMarkerConfigurer;
this.staticDeployHandlers = staticDeployHandlers;
pagesDir = Paths.get(haloProperties.getWorkDir(), PAGES_FOLDER);
FileUtils.createIfAbsent(pagesDir);
@ -138,6 +151,47 @@ public class StaticPageServiceImpl implements StaticPageService {
}
}
@Override
public void deploy() {
StaticDeployType type = getStaticDeployType();
staticDeployHandlers.deploy(type);
}
@Override
public List<StaticPageFile> listFile() {
return listStaticPageFileTree(pagesDir);
}
@Nullable
private List<StaticPageFile> listStaticPageFileTree(@NonNull Path topPath) {
Assert.notNull(topPath, "Top path must not be null");
if (!Files.isDirectory(topPath)) {
return null;
}
try (Stream<Path> pathStream = Files.list(topPath)) {
List<StaticPageFile> staticPageFiles = new LinkedList<>();
pathStream.forEach(path -> {
StaticPageFile staticPageFile = new StaticPageFile();
staticPageFile.setName(path.getFileName().toString());
staticPageFile.setIsFile(Files.isRegularFile(path));
if (Files.isDirectory(path)) {
staticPageFile.setChildren(listStaticPageFileTree(path));
}
staticPageFiles.add(staticPageFile);
});
staticPageFiles.sort(new StaticPageFile());
return staticPageFiles;
} catch (IOException e) {
throw new ServiceException("Failed to list sub files", e);
}
}
/**
* Clean static pages folder
*/
@ -714,4 +768,14 @@ public class StaticPageServiceImpl implements StaticPageService {
Path path = Paths.get(pagesDir.toString(), subPath);
return path.toFile();
}
/**
* Get static deploy type from options.
*
* @return static deploy type
*/
@NonNull
private StaticDeployType getStaticDeployType() {
return optionService.getEnumByPropertyOrDefault(StaticDeployProperties.DEPLOY_TYPE, StaticDeployType.class, StaticDeployType.GIT);
}
}