mirror of https://github.com/halo-dev/halo
feat: support deploy static page in netlify.
parent
83e87553b7
commit
c37f36f61e
|
@ -35,6 +35,7 @@ public class Application extends SpringBootServletInitializer {
|
|||
|
||||
// Run application
|
||||
context = SpringApplication.run(Application.class, args);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -1,26 +1,55 @@
|
|||
package run.halo.app.controller.admin.api;
|
||||
|
||||
import cn.hutool.core.io.FileUtil;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import org.springframework.http.HttpEntity;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
import run.halo.app.model.properties.NetlifyStaticDeployProperties;
|
||||
import run.halo.app.model.support.StaticPageFile;
|
||||
import run.halo.app.service.OptionService;
|
||||
import run.halo.app.service.StaticPageService;
|
||||
|
||||
import java.io.FileNotFoundException;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author ryan0up
|
||||
* @date 2019/12/25
|
||||
* Static page controller.
|
||||
*
|
||||
* @author ryanwang
|
||||
* @date 2019-12-25
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/api/admin/static_page")
|
||||
public class StaticPageController {
|
||||
|
||||
private final static String DEPLOY_API = "https://api.netlify.com/api/v1/sites/%s/deploys";
|
||||
|
||||
private final OptionService optionService;
|
||||
|
||||
private final RestTemplate httpsRestTemplate;
|
||||
|
||||
private final StaticPageService staticPageService;
|
||||
|
||||
public StaticPageController(StaticPageService staticPageService) {
|
||||
public StaticPageController(StaticPageService staticPageService,
|
||||
OptionService optionService,
|
||||
RestTemplate httpsRestTemplate) {
|
||||
this.staticPageService = staticPageService;
|
||||
this.optionService = optionService;
|
||||
this.httpsRestTemplate = httpsRestTemplate;
|
||||
|
||||
MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter = new MappingJackson2HttpMessageConverter();
|
||||
mappingJackson2HttpMessageConverter.setSupportedMediaTypes(Collections.singletonList(MediaType.ALL));
|
||||
this.httpsRestTemplate.getMessageConverters().add(mappingJackson2HttpMessageConverter);
|
||||
}
|
||||
|
||||
@GetMapping
|
||||
|
@ -35,9 +64,29 @@ public class StaticPageController {
|
|||
staticPageService.generate();
|
||||
}
|
||||
|
||||
@GetMapping("deploy")
|
||||
@PostMapping("deploy")
|
||||
@ApiOperation("Deploy static page to remove platform")
|
||||
public void deploy() {
|
||||
staticPageService.deploy();
|
||||
}
|
||||
|
||||
@GetMapping("netlify")
|
||||
public void testNetlify() throws FileNotFoundException {
|
||||
String domain = optionService.getByPropertyOfNonNull(NetlifyStaticDeployProperties.NETLIFY_DOMAIN).toString();
|
||||
String siteId = optionService.getByPropertyOfNonNull(NetlifyStaticDeployProperties.NETLIFY_SITE_ID).toString();
|
||||
String token = optionService.getByPropertyOfNonNull(NetlifyStaticDeployProperties.NETLIFY_TOKEN).toString();
|
||||
|
||||
HttpHeaders headers = new HttpHeaders();
|
||||
|
||||
headers.set("Content-Type", "application/zip");
|
||||
headers.set(HttpHeaders.AUTHORIZATION, "Bearer " + token);
|
||||
|
||||
Path path = staticPageService.zipStaticPagesDirectory();
|
||||
|
||||
byte[] bytes = FileUtil.readBytes(path.toFile());
|
||||
|
||||
HttpEntity<byte[]> httpEntity = new HttpEntity<>(bytes, headers);
|
||||
|
||||
ResponseEntity<Object> responseEntity = httpsRestTemplate.postForEntity(String.format(DEPLOY_API, siteId), httpEntity, Object.class);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
package run.halo.app.handler.migrate;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
import run.halo.app.model.enums.MigrateType;
|
||||
|
||||
|
@ -9,6 +11,8 @@ import run.halo.app.model.enums.MigrateType;
|
|||
* @author ryanwang
|
||||
* @date 2019-10-30
|
||||
*/
|
||||
@Slf4j
|
||||
@Component
|
||||
public class CnBlogsMigrateHandler implements MigrateHandler {
|
||||
|
||||
@Override
|
||||
|
|
|
@ -31,7 +31,7 @@ public class MigrateHandlers {
|
|||
|
||||
public MigrateHandlers(ApplicationContext applicationContext) {
|
||||
// Add all migrate handler
|
||||
addFileHandlers(applicationContext.getBeansOfType(MigrateHandler.class).values());
|
||||
addMigrateHandlers(applicationContext.getBeansOfType(MigrateHandler.class).values());
|
||||
}
|
||||
|
||||
@NonNull
|
||||
|
@ -56,7 +56,7 @@ public class MigrateHandlers {
|
|||
* @return current migrate handlers
|
||||
*/
|
||||
@NonNull
|
||||
private MigrateHandlers addFileHandlers(@Nullable Collection<MigrateHandler> migrateHandlers) {
|
||||
private MigrateHandlers addMigrateHandlers(@Nullable Collection<MigrateHandler> migrateHandlers) {
|
||||
if (!CollectionUtils.isEmpty(migrateHandlers)) {
|
||||
this.migrateHandlers.addAll(migrateHandlers);
|
||||
}
|
||||
|
|
|
@ -1,9 +1,18 @@
|
|||
package run.halo.app.handler.staticdeploy;
|
||||
|
||||
import cn.hutool.core.io.FileUtil;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.http.HttpEntity;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
import run.halo.app.model.enums.StaticDeployType;
|
||||
import run.halo.app.model.properties.NetlifyStaticDeployProperties;
|
||||
import run.halo.app.service.OptionService;
|
||||
import run.halo.app.service.StaticPageService;
|
||||
|
||||
import java.nio.file.Path;
|
||||
|
||||
/**
|
||||
* Netlify deploy handler.
|
||||
|
@ -15,15 +24,40 @@ import run.halo.app.service.OptionService;
|
|||
@Component
|
||||
public class NetlifyStaticDeployHandler implements StaticDeployHandler {
|
||||
|
||||
private final static String DEPLOY_API = "https://api.netlify.com/api/v1/sites/%s/deploys";
|
||||
|
||||
private final OptionService optionService;
|
||||
|
||||
public NetlifyStaticDeployHandler(OptionService optionService) {
|
||||
private final RestTemplate httpsRestTemplate;
|
||||
|
||||
private final StaticPageService staticPageService;
|
||||
|
||||
public NetlifyStaticDeployHandler(OptionService optionService,
|
||||
RestTemplate httpsRestTemplate,
|
||||
StaticPageService staticPageService) {
|
||||
this.optionService = optionService;
|
||||
this.httpsRestTemplate = httpsRestTemplate;
|
||||
this.staticPageService = staticPageService;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deploy() {
|
||||
String domain = optionService.getByPropertyOfNonNull(NetlifyStaticDeployProperties.NETLIFY_DOMAIN).toString();
|
||||
String siteId = optionService.getByPropertyOfNonNull(NetlifyStaticDeployProperties.NETLIFY_SITE_ID).toString();
|
||||
String token = optionService.getByPropertyOfNonNull(NetlifyStaticDeployProperties.NETLIFY_TOKEN).toString();
|
||||
|
||||
HttpHeaders headers = new HttpHeaders();
|
||||
|
||||
headers.set("Content-Type", "application/zip");
|
||||
headers.set(HttpHeaders.AUTHORIZATION, "Bearer " + token);
|
||||
|
||||
Path path = staticPageService.zipStaticPagesDirectory();
|
||||
|
||||
byte[] bytes = FileUtil.readBytes(path.toFile());
|
||||
|
||||
HttpEntity<byte[]> httpEntity = new HttpEntity<>(bytes, headers);
|
||||
|
||||
ResponseEntity<Object> responseEntity = httpsRestTemplate.postForEntity(String.format(DEPLOY_API, siteId), httpEntity, Object.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -26,8 +26,8 @@ public class StaticDeployHandlers {
|
|||
private final Collection<StaticDeployHandler> staticDeployHandlers = new LinkedList<>();
|
||||
|
||||
public StaticDeployHandlers(ApplicationContext applicationContext) {
|
||||
// Add all file handler
|
||||
addFileHandlers(applicationContext.getBeansOfType(StaticDeployHandler.class).values());
|
||||
// Add all static deploy handler
|
||||
addStaticDeployHandlers(applicationContext.getBeansOfType(StaticDeployHandler.class).values());
|
||||
}
|
||||
|
||||
|
||||
|
@ -42,6 +42,7 @@ public class StaticDeployHandlers {
|
|||
for (StaticDeployHandler staticDeployHandler : staticDeployHandlers) {
|
||||
if (staticDeployHandler.supportType(staticDeployType)) {
|
||||
staticDeployHandler.deploy();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -55,7 +56,7 @@ public class StaticDeployHandlers {
|
|||
* @return current file handlers
|
||||
*/
|
||||
@NonNull
|
||||
public StaticDeployHandlers addFileHandlers(@Nullable Collection<StaticDeployHandler> staticDeployHandlers) {
|
||||
public StaticDeployHandlers addStaticDeployHandlers(@Nullable Collection<StaticDeployHandler> staticDeployHandlers) {
|
||||
if (!CollectionUtils.isEmpty(staticDeployHandlers)) {
|
||||
this.staticDeployHandlers.addAll(staticDeployHandlers);
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@ package run.halo.app.model.enums;
|
|||
* Migrate type.
|
||||
*
|
||||
* @author ryanwang
|
||||
* @date : 2019-03-12
|
||||
* @date 2019-03-12
|
||||
*/
|
||||
public enum MigrateType implements ValueEnum<Integer> {
|
||||
|
||||
|
|
|
@ -11,12 +11,12 @@ public enum StaticDeployType implements ValueEnum<Integer> {
|
|||
/**
|
||||
* Deploy static pages in remote git repository, such as github pages,gitee pages,coding pages.etc.
|
||||
*/
|
||||
GIT(1),
|
||||
GIT(0),
|
||||
|
||||
/**
|
||||
* Deploy static pages in netlify.
|
||||
*/
|
||||
NETLIFY(2);
|
||||
NETLIFY(1);
|
||||
|
||||
private Integer value;
|
||||
|
||||
|
|
|
@ -30,6 +30,11 @@ public class HaloConst {
|
|||
*/
|
||||
public final static String HALO_BACKUP_PREFIX = "halo-backup-";
|
||||
|
||||
/**
|
||||
* Static pages pack prefix.
|
||||
*/
|
||||
public final static String STATIC_PAGE_PACK_PREFIX = "static-pages-";
|
||||
|
||||
/**
|
||||
* Default theme name.
|
||||
*/
|
||||
|
|
|
@ -16,6 +16,8 @@ import java.util.List;
|
|||
@ToString
|
||||
public class StaticFile implements Comparator<StaticFile> {
|
||||
|
||||
private String id;
|
||||
|
||||
private String name;
|
||||
|
||||
private String path;
|
||||
|
|
|
@ -14,6 +14,8 @@ import java.util.List;
|
|||
@Data
|
||||
public class StaticPageFile implements Comparator<StaticPageFile> {
|
||||
|
||||
private String id;
|
||||
|
||||
private String name;
|
||||
|
||||
private Boolean isFile;
|
||||
|
|
|
@ -2,8 +2,13 @@ package run.halo.app.service;
|
|||
|
||||
import run.halo.app.model.support.StaticPageFile;
|
||||
|
||||
import java.nio.file.Path;
|
||||
import java.util.List;
|
||||
|
||||
import static run.halo.app.model.support.HaloConst.FILE_SEPARATOR;
|
||||
import static run.halo.app.model.support.HaloConst.TEMP_DIR;
|
||||
import static run.halo.app.utils.HaloUtils.ensureSuffix;
|
||||
|
||||
/**
|
||||
* Static Page service interface.
|
||||
*
|
||||
|
@ -17,6 +22,11 @@ public interface StaticPageService {
|
|||
*/
|
||||
String PAGES_FOLDER = "static_pages";
|
||||
|
||||
|
||||
String STATIC_PAGE_PACK_DIR = ensureSuffix(TEMP_DIR, FILE_SEPARATOR) + "static-pages-pack" + FILE_SEPARATOR;
|
||||
|
||||
String[] USELESS_FILE_SUFFIX = {"ftl", "md", "yaml", "yml", "gitignore"};
|
||||
|
||||
/**
|
||||
* Generate pages.
|
||||
*/
|
||||
|
@ -27,6 +37,13 @@ public interface StaticPageService {
|
|||
*/
|
||||
void deploy();
|
||||
|
||||
/**
|
||||
* Zip static pages directory.
|
||||
*
|
||||
* @return zip path
|
||||
*/
|
||||
Path zipStaticPagesDirectory();
|
||||
|
||||
/**
|
||||
* List file of generated static page.
|
||||
*
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
package run.halo.app.service.impl;
|
||||
|
||||
import cn.hutool.core.io.FileUtil;
|
||||
import cn.hutool.core.io.file.FileWriter;
|
||||
import cn.hutool.core.util.IdUtil;
|
||||
import cn.hutool.core.util.PageUtil;
|
||||
import freemarker.template.Template;
|
||||
import freemarker.template.TemplateException;
|
||||
|
@ -42,6 +44,8 @@ import java.nio.charset.StandardCharsets;
|
|||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.stream.Stream;
|
||||
|
@ -123,6 +127,7 @@ public class StaticPageServiceImpl implements StaticPageService {
|
|||
|
||||
pagesDir = Paths.get(haloProperties.getWorkDir(), PAGES_FOLDER);
|
||||
FileUtils.createIfAbsent(pagesDir);
|
||||
Files.createDirectories(Paths.get(STATIC_PAGE_PACK_DIR));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -158,6 +163,22 @@ public class StaticPageServiceImpl implements StaticPageService {
|
|||
staticDeployHandlers.deploy(type);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Path zipStaticPagesDirectory() {
|
||||
try {
|
||||
String staticPagePackName = HaloConst.STATIC_PAGE_PACK_PREFIX +
|
||||
LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd-HH-mm-ss-")) +
|
||||
IdUtil.simpleUUID().hashCode() + ".zip";
|
||||
Path staticPageZipPath = Files.createFile(Paths.get(STATIC_PAGE_PACK_DIR, staticPagePackName));
|
||||
|
||||
FileUtils.zip(pagesDir, staticPageZipPath);
|
||||
|
||||
return staticPageZipPath;
|
||||
} catch (IOException e) {
|
||||
throw new ServiceException("Failed to zip static pages directory", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<StaticPageFile> listFile() {
|
||||
return listStaticPageFileTree(pagesDir);
|
||||
|
@ -176,6 +197,7 @@ public class StaticPageServiceImpl implements StaticPageService {
|
|||
|
||||
pathStream.forEach(path -> {
|
||||
StaticPageFile staticPageFile = new StaticPageFile();
|
||||
staticPageFile.setId(IdUtil.fastSimpleUUID());
|
||||
staticPageFile.setName(path.getFileName().toString());
|
||||
staticPageFile.setIsFile(Files.isRegularFile(path));
|
||||
if (Files.isDirectory(path)) {
|
||||
|
@ -708,9 +730,41 @@ public class StaticPageServiceImpl implements StaticPageService {
|
|||
*/
|
||||
private void copyThemeFolder() throws IOException {
|
||||
ThemeProperty activatedTheme = themeService.getActivatedTheme();
|
||||
Path path = Paths.get(pagesDir.toString(), activatedTheme.getId());
|
||||
Path path = Paths.get(pagesDir.toString(), activatedTheme.getFolderName());
|
||||
FileUtils.createIfAbsent(path);
|
||||
FileUtils.copyFolder(Paths.get(activatedTheme.getThemePath()), path);
|
||||
cleanThemeFolder(Paths.get(pagesDir.toString(), activatedTheme.getFolderName()));
|
||||
}
|
||||
|
||||
private void cleanThemeFolder(Path themePath) {
|
||||
if (!Files.isDirectory(themePath)) {
|
||||
return;
|
||||
}
|
||||
|
||||
try (Stream<Path> pathStream = Files.list(themePath)) {
|
||||
|
||||
pathStream.forEach(path -> {
|
||||
if (!Files.isDirectory(path)) {
|
||||
for (String suffix : USELESS_FILE_SUFFIX) {
|
||||
if (suffix.contains(FileUtil.extName(path.toFile()))) {
|
||||
try {
|
||||
Files.delete(path);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (path.getFileName().toString().contains(".git")) {
|
||||
FileUtils.deleteFolderQuietly(path);
|
||||
} else {
|
||||
cleanThemeFolder(path);
|
||||
}
|
||||
}
|
||||
});
|
||||
} catch (IOException e) {
|
||||
throw new ServiceException("Failed to list sub files", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package run.halo.app.service.impl;
|
||||
|
||||
import cn.hutool.core.util.IdUtil;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.lang.NonNull;
|
||||
import org.springframework.lang.Nullable;
|
||||
|
@ -59,6 +60,7 @@ public class StaticStorageServiceImpl implements StaticStorageService {
|
|||
|
||||
pathStream.forEach(path -> {
|
||||
StaticFile staticFile = new StaticFile();
|
||||
staticFile.setId(IdUtil.fastSimpleUUID());
|
||||
staticFile.setName(path.getFileName().toString());
|
||||
staticFile.setPath(path.toString());
|
||||
staticFile.setRelativePath(StringUtils.removeStart(path.toString(), staticDir.toString()));
|
||||
|
|
Loading…
Reference in New Issue