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

相关文章

Spring Boot项目部署命令java -jar的各种参数及作用详解

《SpringBoot项目部署命令java-jar的各种参数及作用详解》:本文主要介绍SpringBoot项目部署命令java-jar的各种参数及作用的相关资料,包括设置内存大小、垃圾回收... 目录前言一、基础命令结构二、常见的 Java 命令参数1. 设置内存大小2. 配置垃圾回收器3. 配置线程栈大小

Spring Boot项目中结合MyBatis实现MySQL的自动主从切换功能

《SpringBoot项目中结合MyBatis实现MySQL的自动主从切换功能》:本文主要介绍SpringBoot项目中结合MyBatis实现MySQL的自动主从切换功能,本文分步骤给大家介绍的... 目录原理解析1. mysql主从复制(Master-Slave Replication)2. 读写分离3.

springboot简单集成Security配置的教程

《springboot简单集成Security配置的教程》:本文主要介绍springboot简单集成Security配置的教程,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,... 目录集成Security安全框架引入依赖编写配置类WebSecurityConfig(自定义资源权限规则

一文教你如何将maven项目转成web项目

《一文教你如何将maven项目转成web项目》在软件开发过程中,有时我们需要将一个普通的Maven项目转换为Web项目,以便能够部署到Web容器中运行,本文将详细介绍如何通过简单的步骤完成这一转换过程... 目录准备工作步骤一:修改​​pom.XML​​1.1 添加​​packaging​​标签1.2 添加

tomcat多实例部署的项目实践

《tomcat多实例部署的项目实践》Tomcat多实例是指在一台设备上运行多个Tomcat服务,这些Tomcat相互独立,本文主要介绍了tomcat多实例部署的项目实践,具有一定的参考价值,感兴趣的可... 目录1.创建项目目录,测试文China编程件2js.创建实例的安装目录3.准备实例的配置文件4.编辑实例的

springboot集成Deepseek4j的项目实践

《springboot集成Deepseek4j的项目实践》本文主要介绍了springboot集成Deepseek4j的项目实践,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价... 目录Deepseek4j快速开始Maven 依js赖基础配置基础使用示例1. 流式返回示例2. 进阶

SpringBoot项目启动报错"找不到或无法加载主类"的解决方法

《SpringBoot项目启动报错找不到或无法加载主类的解决方法》在使用IntelliJIDEA开发基于SpringBoot框架的Java程序时,可能会出现找不到或无法加载主类com.example.... 目录一、问题描述二、排查过程三、解决方案一、问题描述在使用 IntelliJ IDEA 开发基于

SpringBoot项目使用MDC给日志增加唯一标识的实现步骤

《SpringBoot项目使用MDC给日志增加唯一标识的实现步骤》本文介绍了如何在SpringBoot项目中使用MDC(MappedDiagnosticContext)为日志增加唯一标识,以便于日... 目录【Java】SpringBoot项目使用MDC给日志增加唯一标识,方便日志追踪1.日志效果2.实现步

Spring Boot 集成 Quartz 使用Cron 表达式实现定时任务

《SpringBoot集成Quartz使用Cron表达式实现定时任务》本文介绍了如何在SpringBoot项目中集成Quartz并使用Cron表达式进行任务调度,通过添加Quartz依赖、创... 目录前言1. 添加 Quartz 依赖2. 创建 Quartz 任务3. 配置 Quartz 任务调度4. 启

Ubuntu中Nginx虚拟主机设置的项目实践

《Ubuntu中Nginx虚拟主机设置的项目实践》通过配置虚拟主机,可以在同一台服务器上运行多个独立的网站,本文主要介绍了Ubuntu中Nginx虚拟主机设置的项目实践,具有一定的参考价值,感兴趣的可... 目录简介安装 Nginx创建虚拟主机1. 创建网站目录2. 创建默认索引文件3. 配置 Nginx4