CCS项目持续集成

2024-04-23 22:04
文章标签 项目 集成 持续 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 (下面的配置需要使用管理员的账号)

    在这里插入图片描述

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

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

    整体逻辑是:

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

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

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

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

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

    先将其关键代码展示:

    // 操作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=xxxxset eclipsec="%ccs_home%\ccs\eclipse\eclipsec"
set proj_name=zzzrem 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%.logrem 清空项目.
"%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%.logrem 编译.
"%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项目持续集成的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/930002

相关文章

深度解析Java项目中包和包之间的联系

《深度解析Java项目中包和包之间的联系》文章浏览阅读850次,点赞13次,收藏8次。本文详细介绍了Java分层架构中的几个关键包:DTO、Controller、Service和Mapper。_jav... 目录前言一、各大包1.DTO1.1、DTO的核心用途1.2. DTO与实体类(Entity)的区别1

在Spring Boot中集成RabbitMQ的实战记录

《在SpringBoot中集成RabbitMQ的实战记录》本文介绍SpringBoot集成RabbitMQ的步骤,涵盖配置连接、消息发送与接收,并对比两种定义Exchange与队列的方式:手动声明(... 目录前言准备工作1. 安装 RabbitMQ2. 消息发送者(Producer)配置1. 创建 Spr

如何在Spring Boot项目中集成MQTT协议

《如何在SpringBoot项目中集成MQTT协议》本文介绍在SpringBoot中集成MQTT的步骤,包括安装Broker、添加EclipsePaho依赖、配置连接参数、实现消息发布订阅、测试接口... 目录1. 准备工作2. 引入依赖3. 配置MQTT连接4. 创建MQTT配置类5. 实现消息发布与订阅

springboot项目打jar制作成镜像并指定配置文件位置方式

《springboot项目打jar制作成镜像并指定配置文件位置方式》:本文主要介绍springboot项目打jar制作成镜像并指定配置文件位置方式,具有很好的参考价值,希望对大家有所帮助,如有错误... 目录一、上传jar到服务器二、编写dockerfile三、新建对应配置文件所存放的数据卷目录四、将配置文

SpringBoot集成LiteFlow工作流引擎的完整指南

《SpringBoot集成LiteFlow工作流引擎的完整指南》LiteFlow作为一款国产轻量级规则引擎/流程引擎,以其零学习成本、高可扩展性和极致性能成为微服务架构下的理想选择,本文将详细讲解Sp... 目录一、LiteFlow核心优势二、SpringBoot集成实战三、高级特性应用1. 异步并行执行2

怎么用idea创建一个SpringBoot项目

《怎么用idea创建一个SpringBoot项目》本文介绍了在IDEA中创建SpringBoot项目的步骤,包括环境准备(JDK1.8+、Maven3.2.5+)、使用SpringInitializr... 目录如何在idea中创建一个SpringBoot项目环境准备1.1打开IDEA,点击New新建一个项

springboot项目中整合高德地图的实践

《springboot项目中整合高德地图的实践》:本文主要介绍springboot项目中整合高德地图的实践,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一:高德开放平台的使用二:创建数据库(我是用的是mysql)三:Springboot所需的依赖(根据你的需求再

SpringBoot3应用中集成和使用Spring Retry的实践记录

《SpringBoot3应用中集成和使用SpringRetry的实践记录》SpringRetry为SpringBoot3提供重试机制,支持注解和编程式两种方式,可配置重试策略与监听器,适用于临时性故... 目录1. 简介2. 环境准备3. 使用方式3.1 注解方式 基础使用自定义重试策略失败恢复机制注意事项

一文详解如何在idea中快速搭建一个Spring Boot项目

《一文详解如何在idea中快速搭建一个SpringBoot项目》IntelliJIDEA作为Java开发者的‌首选IDE‌,深度集成SpringBoot支持,可一键生成项目骨架、智能配置依赖,这篇文... 目录前言1、创建项目名称2、勾选需要的依赖3、在setting中检查maven4、编写数据源5、开启热

SpringBoot项目配置logback-spring.xml屏蔽特定路径的日志

《SpringBoot项目配置logback-spring.xml屏蔽特定路径的日志》在SpringBoot项目中,使用logback-spring.xml配置屏蔽特定路径的日志有两种常用方式,文中的... 目录方案一:基础配置(直接关闭目标路径日志)方案二:结合 Spring Profile 按环境屏蔽关