老旧Java Web应用实现增量自动化部署的一个方案

    若是你也有一个老旧的Java Web应用,由于各类缘由,代码库中的代码是不完整的,因此每次上线只能增量部署,或者研发规范里就要求增量部署,在这种状况下如何实现自动化的编译和部署呢?下面给出一个可行的方案:java

    一、部署前,将须要部署的代码合并到deliver分支git

    二、比较deliver分支和master分支的差别,获得差别列表以后,用于后续的编译maven

    三、编译差别文件时,须要将应用所依赖的jar,已经部署的class文件等加入到CLASSPATHide

    四、若是各测试环境也使用这一套自动部署的方案,可能还须要考虑剥离环境相关的配置到配置文件中,并根据环境分目录存放,具体能够参考maven的profile机制测试

    核心代码(代码结构请自行优化 :D):fetch

    一、比较两个分支的差别(忽略whitespace带来的差别):优化

try (Git git = Git.open(gitRepoFile);
                ByteArrayOutputStream out = new ByteArrayOutputStream();
                DiffFormatter df = new DiffFormatter(out);) {

            Repository repository = git.getRepository();
            ObjectReader reader = repository.newObjectReader();

            String branchName = repository.getBranch();

            ObjectId masterId = repository.resolve("remotes/origin/master^{tree}");
            ObjectId branchId = repository.resolve(branchName + "^{tree}");

            CanonicalTreeParser masterTreeParser = new CanonicalTreeParser();
            masterTreeParser.reset(reader, masterId);

            CanonicalTreeParser branchTreeParser = new CanonicalTreeParser();
            branchTreeParser.reset(reader, branchId);

            List<DiffEntry> diffs = git.diff()
                    .setNewTree(branchTreeParser)
                    .setOldTree(masterTreeParser)
                    .call();

            Map<String, List<String>> diffFileMap = new HashMap<>();
            List<String> changeFileList = new ArrayList<>();
            List<String> deleteFileList = new ArrayList<>();

            df.setDiffComparator(RawTextComparator.WS_IGNORE_ALL);
            df.setRepository(git.getRepository());

            for (DiffEntry diffEntry : diffs) {
                df.format(diffEntry);
                FileHeader fileHeader = df.toFileHeader(diffEntry);

                @SuppressWarnings("unchecked")
                List<HunkHeader> hunks = (List<HunkHeader>) fileHeader.getHunks();
                int changedSize = 0;
                for (HunkHeader hunkHeader : hunks) {
                    EditList editList = hunkHeader.toEditList();
                    for (Edit edit : editList) {
                        changedSize += edit.getLengthA() + edit.getLengthB();
                    }
                }

                if (changedSize > 0) {
                    ChangeType changeType = diffEntry.getChangeType();
                    if (ChangeType.DELETE.equals(changeType)) {
                        String oldFilePath = diffEntry.getOldPath();
                        log.info("{}|{}", changeType.name(), oldFilePath);
                        deleteFileList.add(oldFilePath);
                    } else {
                        String newFilePath = diffEntry.getNewPath();
                        log.info("{}|{}", changeType.name(), newFilePath);
                        changeFileList.add(newFilePath);
                    }
                }
            }
            diffFileMap.put("change", changeFileList);
            diffFileMap.put("delete", deleteFileList);

            return diffFileMap;
        }

    二、编译:ui

Iterable<String> options = Arrays.asList(
                "-classpath", classpath,
                "-encoding", encoding,
                "-source", jdkVersion,
                "-target", jdkVersion,
                "-d", targetPath);

        JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
        log.info("classpath:{}", classpath);
        log.info("targetPath:{}", targetPath);

        try (StandardJavaFileManager fileManager = compiler.getStandardFileManager(null, null, null);) {

            Iterable<? extends JavaFileObject> compilationUnits = fileManager.getJavaFileObjectsFromFiles(fileList);

            DiagnosticCollector<JavaFileObject> diagnostics = new DiagnosticCollector<>();

            CompilationTask compilationTask = compiler
                    .getTask(null, fileManager, diagnostics, options, null, compilationUnits);

            if (!compilationTask.call()) {
                log.error("JavaCompiler Build failed:");

                for (Diagnostic<?> diagnostic : diagnostics.getDiagnostics()) {
                    long line = diagnostic.getLineNumber();
                    String source = diagnostic.getSource() != null ? diagnostic.getSource().toString() : "";
                    String kind = diagnostic.getKind().name();
                    String message = diagnostic.getMessage(null);
                    log.info("{} on line:{} in {}.", kind, line, source);
                    log.info("message:{}", message);
                }
                return false;
            }
        }

    要实现完整的功能,还须要根据应用的具体状况完善,好比:从运行环境同步删除代码库中删除的文件;从代码库拉取文件时,用fetch,reset的方式;还能够借助Marathon、Mesos、Docker运行应用等。spa

相关文章
相关标签/搜索