CCS项目持续集成

这篇具有很好参考价值的文章主要介绍了CCS项目持续集成。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

​ 因工作需要,用户提出希望可以做ccs项目的持续集成,及代码提交后能够自动编译并提交到svn。调研过jenkins之后发现重新手写更有性价比,所以肝了几晚终于搞出来了,现在分享出来。

​ 先交代背景:

	1.	代码分两部分,一部分在git上,一部分在svn上
	2.	希望git上提交的代码时和svn上提交代码时都触发持续集成。

​ 实现功能:

  1. git上提交代码时自动触发持续集成

  2. svn上提交代码时,并在备注中以“编译”开头时触发持续集成

  3. 持续集成功能:

    a. 将git上的代码复制到 svn的 编译目录(记为 X)中

    b. 将svn的源码目录(记为S)复制到svn的编译目录X的子目录(X1)中

    c. 执行ccs的编译命令,编译ccs项目,

    d. 将编译出的结果文件分别复制到 svn的多个目录中,

    e. 将编译结果文件提交到svn,备注日志中包括git上的版本信息、svn源码目录(S)的版本信息。

实现说明:

  1. 使用springboot 搭建一个web项目,并提供一个接口用户触发持续集成,记为接口X

  2. 在git配置webhook,在代码检入时调用接口X (下面的配置需要使用管理员的账号)

    CCS项目持续集成,工具,ci/cd,c++

  3. 在svn中编写钩子函数,在备注信息以”编译“开头时,调用接口x

    # 构造函数代码片段,此代码在svn的仓库目录下的hooks目中,文件名称为 post-commit  对的,没有后缀
    COMMENT=$(svnlook log -r $REV $REPOS)
    
    if echo "$COMMENT" | grep -qE '^编译'; then
      echo "提交日志以'编译'开头。"  >> ${SVN_LOG_FILE_PATH}
      curl -X post -v http://xxxx/cicd/xxx #这个就是接口x的地址了
    
  4. 接口X的具体逻辑如下:

    整体逻辑是:

    a. 将git 和svn上的代码更新到本地

    b. 将文件复制到指定目录中

    c. 执行编译命令: 编译命令使用的是ccs的编译命令

    d. 判断编译是否成功,成功的话则将编译结果复制到指定目录中

    e. 获取源码目录的最新版本号及备注信息,并拼接成备注信息,将结果文件提交到svn上。

    先将其关键代码展示:文章来源地址https://www.toymoban.com/news/detail-859521.html

    // 操作git,使用的是org.eclipse.jgit  5.13.3.202401111512-r
    /**
         * 克隆仓库
         *
         * @throws Exception
         */
        public void cloneRep(boolean force) throws Exception {
            File targetDirectory = new File(getLocalPath());
            boolean exists = targetDirectory.exists();
            if (exists && force) {
                FileUtil.del(targetDirectory);
            } else if (exists) {
                return;
            }
            Git.cloneRepository()
                    .setURI(getRepUrl())
                    .setBranch(getBranch())
                    .setDirectory(targetDirectory)
                    .setCredentialsProvider(new UsernamePasswordCredentialsProvider(getUsername(), getPassword()))
                    .call();
        }
    
    
        /** 获取仓库版本 */
        public String getRepVersion(){
            File localFile = new File(getLocalPath());
            boolean exists = localFile.exists();
            if (!exists) {
                return "";
            }
            try (Git git = Git.open(localFile)) {
                final Iterable<RevCommit> revCommits = git.log().setMaxCount(1).call();
                final RevCommit revCommit = revCommits.iterator().next();
                final String commitDate = DateUtil.format(revCommit.getAuthorIdent().getWhen(), "yyyy-MM-dd HH:mm:ss");
                final String commitName = revCommit.getAuthorIdent().getName();
                return String.format("%s(%s)", commitName,commitDate);
            } catch (Exception e) {
                log.error(e.getMessage(), e);
            }
            return "";
        }
    
        /** 更新仓库 */
        public void updateRep(boolean force) throws Exception {
            File localFile = new File(getLocalPath());
            boolean exists = localFile.exists();
            if (!exists) {
                cloneRep(force);
                return;
            }
            try (Git git = Git.open(localFile)) {
                if (force) {
                    // 撤销所有未提交的本地修改
                    git.reset()
                            .setMode(ResetCommand.ResetType.HARD)
                            .call();
                    // 删除未跟踪的文件和目录
                    git.clean()
                            .setCleanDirectories(true) // 递归清理子目录
                            .call();
                }
                // 设置凭据
                CredentialsProvider cp = new UsernamePasswordCredentialsProvider(getUsername(), getPassword());
                git.fetch()
                        .setCredentialsProvider(cp)
                        .call();
                git.pull()
                        .setRebase(true) // 默认情况下合并(merge),这里改为变基(rebase)
                        .setCredentialsProvider(cp)
                        .call();
            } catch (RepositoryNotFoundException e) {
                // 未找到仓库
                cloneRep(true);
            }
        }
    
// 操作 svn
static {
        DAVRepositoryFactory.setup();
        SVNRepositoryFactoryImpl.setup();
        FSRepositoryFactory.setup();
    }

    public void updateRep() throws Exception {
        updateRep(true);
    }

    public void updateRep(boolean force) throws Exception {
        log.info("updateRep");
        BasicAuthenticationManager authManager = new BasicAuthenticationManager(getUsername(), getPassword());
        SVNRepository repository = SVNRepositoryFactory.create(SVNURL.parseURIEncoded(getRepUrl()));
        repository.setAuthenticationManager(authManager);
        File targetFile = new File(getLocalPath(), "\\");
        if (force && targetFile.exists()) {
            // 撤销本地修改
            SVNWCClient wcClient = SVNClientManager.newInstance(null, authManager).getWCClient();
            wcClient.doRevert(new File[]{targetFile}, SVNDepth.INFINITY, null);
        }
        // 检出
        SVNUpdateClient updateClient = SVNClientManager.newInstance(null, authManager).getUpdateClient();
        updateClient.doCheckout(repository.getLocation(), targetFile, SVNRevision.HEAD, SVNRevision.HEAD, SVNDepth.INFINITY, false);
    }

    public void commit(List<File> delFileList) throws Exception {
        commit("", delFileList);
    }

    public void commit(String commitMsg, List<File> delFileList) throws Exception {
        if (!isNeedCommit()) {
            log.info("不需要提交,直接跳过!");
            return;
        }
        BasicAuthenticationManager authManager = new BasicAuthenticationManager(getUsername(), getPassword());
        SVNRepository repository = SVNRepositoryFactory.create(SVNURL.parseURIEncoded(getRepUrl()));
        repository.setAuthenticationManager(authManager);
        SVNCommitClient client = SVNClientManager.newInstance(null, authManager).getCommitClient();
        File[] pathsToCommit = {new File(getLocalPath())};
        List<SVNURL> delSvnUrlList = new ArrayList<>();
        if (delFileList != null && !delFileList.isEmpty()) {
            for (File file : delFileList) {
                SVNURL svnUrl = getSvnUrl(file);
                if (isURLExist(svnUrl)) {
                    delSvnUrlList.add(svnUrl);
                } else {
                    file.delete();
                }
            }
        }
        if (!delSvnUrlList.isEmpty()) {
            SVNURL[] array = delSvnUrlList.toArray(new SVNURL[0]);
          // 先把老的旧文件删除掉。
            client.doDelete(array, StrUtil.isBlank(commitMsg) ? getCommitMsg() : commitMsg);
        }
      // 添加新增加的文件
        SVNClientManager.newInstance(null, authManager).getWCClient()
                .doAdd(pathsToCommit, true, true, true, SVNDepth.INFINITY, true, false, true);
        SVNCommitInfo commitInfo = client.doCommit(pathsToCommit, false,
                StrUtil.isBlank(commitMsg) ? getCommitMsg() : commitMsg, false, true);
        log.info("Committed revision: {}", commitInfo.getNewRevision());
    }

    private boolean isURLExist(SVNURL url) {
        try {
            BasicAuthenticationManager authManager = new BasicAuthenticationManager(getUsername(), getPassword());
            SVNRepository svnRepository = SVNRepositoryFactory.create(url);
            svnRepository.setAuthenticationManager(authManager);
            SVNNodeKind nodeKind = svnRepository.checkPath("", -1);
            return nodeKind == SVNNodeKind.NONE ? false : true;
        } catch (SVNException e) {
            log.error("isURLExist error", e);
        }
        return false;
    }

    private SVNURL getSvnUrl(File file) throws SVNException {
        String svnUrl = StrUtil.replace(file.getAbsolutePath(), getRepLocalBasePath(), getRepUrl());
        svnUrl = svnUrl.replace("\\", "/");
        log.info("getSvnUrl: {}", svnUrl);
        return SVNURL.parseURIEncoded(svnUrl);
    }

/**
获取svn指定子目录的最后提交版本。
*/
    public long getRepVersion() {
        try {
            log.info("getRepVersion");
            BasicAuthenticationManager authManager = new BasicAuthenticationManager(getUsername(), getPassword());
            SVNRepository repository = SVNRepositoryFactory.create(SVNURL.parseURIEncoded(getRepUrl()));
            log.info("getRepVersion repository.getLocation():{}", repository.getLocation().toString());
            repository.setAuthenticationManager(authManager);
            long version = repository.getLatestRevision();
            log.info("getRepVersion version:{}", version);
            File versionFile = new File(getRepLocalBasePath() + getSvnVersionPath());
            SVNStatus status = SVNClientManager.newInstance(null, authManager)
                    .getStatusClient().doStatus(versionFile, false);
            if (status != null) {
                version = status.getCommittedRevision().getNumber();
            }
            return version;
        } catch (Exception e) {
            log.error("getRepVersion error", e);
        }
        return -1;
    }

/**
获取svn指定版本的日志信息.
*/
    public String getLogInfo(long revision) {
        try {
            BasicAuthenticationManager authManager = new BasicAuthenticationManager(getUsername(), getPassword());
            SVNRepository repository = SVNRepositoryFactory.create(SVNURL.parseURIEncoded(getRepUrl()));
            log.info("getRepVersion repository.getLocation():{}", repository.getLocation().toString());
            repository.setAuthenticationManager(authManager);
            log.info("getRepVersion version:{}", revision);
            File versionFile = new File(getRepLocalBasePath() + getSvnVersionPath());
            StringBuffer logInfoBuf = new StringBuffer();
            ISVNLogEntryHandler handler = logEntry -> {
                String logInfo = String.format("%s %s",
                        DateUtil.format(logEntry.getDate(), "yyyyMMddHH:mm:ss"),
                        logEntry.getMessage());
                logInfoBuf.append(logInfo);
                log.info("logInfo {}: {}", logEntry.getRevision(), logInfo);
            };
            SVNLogClient logClient = new SVNLogClient(authManager, null);
            logClient.doLog(new File[]{versionFile},
                    SVNRevision.create(revision), SVNRevision.create(revision),
                    true, true,
                    1, handler);
            return logInfoBuf.toString();
        } catch (Exception e) {
           log.error("getLogInfo error", e);
        }
        return "";
    }
# ccs编译命令
@echo off
set ccs_home=E:\programe\ccs124
set workspace=yyyy
set proj_home=xxxx

set eclipsec="%ccs_home%\ccs\eclipse\eclipsec"
set proj_name=zzz

rem rmdir /S /Q "%proj_home%"\Release
rem TortoiseProc.exe /command:remove /y /path:"%proj_home%\Release\"
 
 
 rmdir /S /Q "%workspace%"

 mkdir "%workspace%"

rem 导入项目
 "%eclipsec%" -noSplash -data "%workspace%" -application com.ti.ccstudio.apps.projectImport -ccs.location "%proj_home%" -ccs.renameTo "%proj_name%"  >> ./logs/gmakeLog_%date:~0,4%%date:~5,2%%date:~8,2%.log

rem 清空项目.
"%eclipsec%" -noSplash -data "%workspace%" -application com.ti.ccstudio.apps.projectBuild -ccs.projects "%proj_name%" -ccs.clean >> ./logs/gmakeLog_%date:~0,4%%date:~5,2%%date:~8,2%.log

rem 编译.
"%eclipsec%" -noSplash -data "%workspace%" -application com.ti.ccstudio.apps.projectBuild -ccs.projects "%proj_name%" -ccs.configuration Release >> ./logs/gmakeLog_%date:~0,4%%date:~5,2%%date:~8,2%.log

到了这里,关于CCS项目持续集成的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【git】CI/CD持续集成与部署C++示例

    😏 ★,° :.☆( ̄▽ ̄)/$: .°★ 😏 这篇文章主要介绍CI/CD持续集成与部署C++示例。 学其所用,用其所学。——梁启超 欢迎来到我的博客,一起学习,共同进步。 喜欢的朋友可以关注一下,下次更新不迷路🥞 CI/CD (持续集成/持续交付)是一种软件开发实践和方法论,旨在通过

    2024年01月19日
    浏览(61)
  • 什么是CI/CD:持续集成与持续交付?(InsCode AI 创作助手)

    在现代软件开发领域,CICD(Continuous Integration and Continuous Delivery)是一种关键性的开发实践,它有助于提高软件交付的质量和效率。本文将深入探讨CICD的定义、原理和重要性,以及如何在项目中实施CICD流程。 什么是CICD? CICD是一种软件开发实践,它将持续集成(CI)和持续交

    2024年02月09日
    浏览(56)
  • 持续集成与持续交付(CI/CD):探讨在云计算中实现快速软件交付的最佳实践

    🎈个人主页:程序员 小侯 🎐CSDN新晋作者 🎉欢迎 👍点赞✍评论⭐收藏 ✨收录专栏:云计算 ✨文章内容:软件交付 🤝希望作者的文章能对你有所帮助,有不足的地方请在评论区留言指正,大家一起学习交流!🤗 持续集成(Continuous Integration,CI)和持续交付(Continuous D

    2024年02月10日
    浏览(60)
  • Jenkins CI/CD 持续集成专题三 Jenkins 使用shell脚本打包组件配置流程

    第六步 查看编译状态和产物 到这里,jenkins 配置shell脚本打包组件的完整配置流程就已经完成

    2024年04月29日
    浏览(54)
  • CCS项目持续集成

    ​ 因工作需要,用户提出希望可以做ccs项目的持续集成,及代码提交后能够自动编译并提交到svn。调研过jenkins之后发现重新手写更有性价比,所以肝了几晚终于搞出来了,现在分享出来。 ​ 先交代背景: ​ 实现功能: git上提交代码时自动触发持续集成 svn上提交代码时,

    2024年04月27日
    浏览(24)
  • CI/CD持续测试的未来...

    如果您想知道为什么持续测试如此重要,请考虑以下几点:在过去,软件测试通常是在编写代码并发送给 QA 部门进行独立测试之后进行的。当发现错误时,代码将返回给开发人员进行更正。虽然这种测试方法有效,但非常耗时。如今,企业想要快速生产出高质量的产品,因此

    2024年02月12日
    浏览(46)
  • 持续交付的力量: 使用Docker Swarm进行CI/CD

    ✅创作者:陈书予 🎉个人主页:陈书予的个人主页 🍁陈书予的个人社区,欢迎你的加入: 陈书予的社区 1.1 Docker Swarm 简介 Docker Swarm 是 Docker 官方的集群管理和编排工具,用于管理多个 Docker 节点和容器,并分发容器到这些节点上运行。Docker Swarm 具有可扩展性、故障转移和负

    2023年04月26日
    浏览(59)
  • 实践:devops之云主机模式持续部署(ci-cd)

    https://www.yuque.com/xyy-onlyone/aevhhf?# 《玩转Typora》 2条Jenkins pipeline CI pipeline CD pipeline 标准规范 项目规范与总体设计 公司里面要使用流水线要做持续集成CI/CD的项目越来越多,这对流水线的设计和开发有不同的要求。我们经常听到用户的反馈: 各种 不同语言的技术栈, 如何使流

    2024年02月12日
    浏览(44)
  • CI/CD工具中的CI和CD的含义

    CI/CD 是现代软件开发方法中广泛使用的一种方法。其中,CI 代表持续集成(Continuous Integration),CD 则有两层含义,一是持续交付(Continuous Delivery),二是持续部署(Continuous Deployment)。下面是这些术语的详细解释: 持续集成(Continuous Integration):CI 是一种开发实践,开发人

    2024年02月07日
    浏览(47)
  • CI/CD:GitLab-CI 自动化集成/部署 JAVA微服务的应用合集

    日常开发中,每次代码编写完成后,都需要手动打包,并且上传服务器,无论本地打包的时间或者上传文件到服务器都需要花费大量的时间来完成,都是重复的并且毫无意义,应该将时间花费在更有价值的时间上;所以编写这篇文章,将自己收集、搭建、测试的步骤或经验汇

    2024年02月08日
    浏览(48)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包