老舊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

相關文章
相關標籤/搜索