谁说大象不能跳舞?ABAP 开发也能实现持续集成

简介: 谁说大象不能跳舞?ABAP 开发也能实现持续集成

本世纪过去的十年里,计算机软件敏捷开发领域中的持续集成(Continuous Integration,简称 CI)理念,几乎已经渗透到了各个领域的软件开发中。

诞生于上世纪 80 年代的 ABAP 编程语言,论辈分,算是现在很多主流编程语言爷爷级的存在了。因为 ABAP 独特的技术栈,以及用来开发的都是复杂度极其高的企业管理软件,其软件实施周期动辄就是数年甚至十数年,使得不少人都觉得 ABAP 开发肯定与敏捷开发中的持续集成不然。

其实不然,笔者近年来工作的团队,就成功地使用了 ABAP 完成了持续集成的工作。

本文将笔者团队进行 ABAP 持续集成的实践分享给大家。

我们首先来简单了解一下 abaplint.

使用 SAP UI5 开发的朋友们,想必都接触过 ESLint,一款 JavaScript 代码检测工具。

笔者每天用 Angular 开发 SAP Commerce Cloud UI,也借助了 Visual Studio Code 名为 TSLint 的扩展,来对 TypeScript 代码进行检测。

同样,abaplint 也是一款对 ABAP 代码根据指定的规则进行检测的开源工具,基于 TypeScript 编写。

下面是它的一个 demo 网站:

https://playground.abaplint.org/

其中 abaplint.json 是配置文件,定义了检测规则。违反规则的代码,会通过红色波浪线高亮出来:

我按照 abaplint 检测出来的提示对代码进行了调整,之后警告信息都消失了。

注意,abaplint 对代码的检测和 ABAP 服务器上的代码语法检查(Syntax Check)完全是两回事。后者由位于 ABAP 内核的 Compiler 完成,而前者只是 TypeScript 实现的基于源代码文本级别的检测,abaplint 本身并不能从语法层面识别 ABAP 语言,只是机械地基于文本静态分析,完成 abaplint.json 里定义的检测任务而已。

下面介绍如何配置 abapGit 和 abaplint 实现最简单的 ABAP 持续集成。这个例子不需要任何开发,仅仅包含一些配置工作,不超过半小时即可完成。

(1) 创建一个 Github 仓库存放 ABAP 代码。我选择把所有的 ABAP 代码放置在 src 文件夹内。

注意:abaplint 只能扫描特殊格式的 ABAP 代码文件,即经过 abapGit 提交的 ABAP 代码。

新建一个 .github 文件夹,里面放一个子文件夹 workflows, 包含一个 abaplint.yml 文件。

name: abaplint
categories:
  - linter
tags:
  - abap
license: MIT License
types:
  - cli
  - service
  - ide-plugin  
source: 'https://github.com/abaplint/abaplint'
homepage: 'https://abaplint.org'
description: 'Linter for ABAP, written in TypeScript.'

这个 abaplint.yml 文件,负责指定当该代码仓库有新的代码提交时,通过 Github Workflow 执行的操作内容。其中第2行开始的 on 指令,告诉 Github,当 main 分支有 push 或者 pull request 到来时,执行名为 abaplint 的 job. 而后者的工作内容,其具体步骤从第14行的 steps 指令开始定义。

第15行的 uses 指令,意思是重用 Github 自带的名为 setup-node action,完成 Node.js 运行环境的准备。

setup-node 这个 action 实现于如下的 Github 仓库:

https://github.com/actions/setup-node

name: 'Setup Node.js environment'
description: 'Setup a Node.js environment by adding problem matchers and optionally downloading and adding it to the PATH.'
author: 'GitHub'
inputs:
  always-auth:
    description: 'Set always-auth in npmrc.'
    default: 'false'
  node-version:
    description: 'Version Spec of the version to use. Examples: 12.x, 10.15.1, >=10.15.0.'
  node-version-file:
    description: 'File containing the version Spec of the version to use.  Examples: package.json, .nvmrc, .node-version, .tool-versions.'
  architecture:
    description: 'Target architecture for Node to use. Examples: x86, x64. Will use system architecture by default.'
  check-latest:
    description: 'Set this option if you want the action to check for the latest available version that satisfies the version spec.'
    default: false
  registry-url:
    description: 'Optional registry to set up for auth. Will set the registry in a project level .npmrc and .yarnrc file, and set up auth to read in from env.NODE_AUTH_TOKEN.'
  scope:
    description: 'Optional scope for authenticating against scoped registries. Will fall back to the repository owner when using the GitHub Packages registry (https://npm.pkg.github.com/).'
  token:
    description: Used to pull node distributions from node-versions. Since there's a default, this is typically not supplied by the user. When running this action on github.com, the default value is sufficient. When running on GHES, you can pass a personal access token for github.com if you are experiencing rate limiting.
    default: ${{ github.server_url == 'https://github.com' && github.token || '' }}
  cache:
    description: 'Used to specify a package manager for caching in the default directory. Supported values: npm, yarn, pnpm.'
  cache-dependency-path:
    description: 'Used to specify the path to a dependency file: package-lock.json, yarn.lock, etc. Supports wildcards or a list of file names for caching multiple dependencies.'
# TODO: add input to control forcing to pull from cloud or dist.
#       escape valve for someone having issues or needing the absolute latest which isn't cached yet
outputs:
  cache-hit: 
    description: 'A boolean value to indicate if a cache was hit.'
  node-version:
    description: 'The installed node version.'
runs:
  using: 'node20'
  main: 'dist/setup/index.js'
  post: 'dist/cache-save/index.js'
  post-if: success()

而 run 命令里维护的如下命令行,意思是 Node.js 运行环境准备好之后,安装 abaplint 命令行工具并执行。

npm -g install @abaplint/cli
abaplint

(2) 根目录下新建 abaplint.json,定义 ABAP 代码检测规则。为了演示起见,我只启用了如下图所示的几条简单规则。关于 abaplint.json 支持的所有检测规则,请查阅这个链接:

https://github.com/abapGit/abapGit/blob/main/abaplint.json

完成 abaplint.yml 和 abaplint.json 两个文件的创建之后,提交任意代码到 main 分支,即可在代码仓库的 Actions 标签页里,看到针对这些代码提交,自动执行的 abaplint 检测记录:

单击一条进去,能查看到引起当前工作流执行失败的原因——代码违反了我自定义的 abaplint 检测规则:定义的关键字需要小写,使用了被标注为 obsolete 的关键字 ADD 等等。

目前开源社区里用于持续集成的构建和测试的自动化工具层出不穷,笔者工作的 SAP Commerce Cloud Spartacus UI 开发团队使用的是 Travis.

Travis 支持绑定 Github 的代码仓库,只要有新的代码提交,就会自动抓取。然后提供一个运行环境,执行测试,完成构建。

为了让我的 ABAP 代码仓库提交的代码能够被 Travis 抓取,我在项目根目录下创建了 .travis.yml 文件,内容如下图所示,其 script 区域的命令行和前文介绍的 abaplint.yml 内包含的内容完全一致,这里不再赘述。

完成 .travis.yml 文件的编辑之后,重新提交,登录 Travis 控制台,发现这次提交触发了一次新的 Travis 构建:

https://app.travis-ci.com/github/wangzixi-diablo/abap-ci-test

构建失败,原因还是因为违反了 abaplint.json 定义的那几条规则:

老老实实按照 abaplint 输出的结果把 ABAP 代码里所有违反规则之处修复,重新提交,这次 Github 工作流和 Travis 里的构建日志终于都显示绿灯了。

本文演示用的 ABAP 代码仓库地址如下:

https://github.com/wangzixi-diablo/abap-ci-test

总结

本文通过一个具体的例子,介绍了如何利用 abapGit 和 abaplint,以及 Travis,实现 ABAP 持续集成场景里基于新的代码提交,自动进行代码检测的步骤。

相关文章
|
2天前
|
存储 资源调度 应用服务中间件
浅谈本地开发好的 Web 应用部署到 ABAP 应用服务器上的几种方式
浅谈本地开发好的 Web 应用部署到 ABAP 应用服务器上的几种方式
33 0
|
2天前
|
JSON API 数据处理
【Swift开发专栏】Swift中的RESTful API集成实战
【4月更文挑战第30天】本文探讨了在Swift中集成RESTful API的方法,涉及RESTful API的基础概念,如HTTP方法和设计原则,以及Swift的网络请求技术,如`URLSession`、`Alamofire`和`SwiftyJSON`。此外,还强调了数据处理、错误管理和异步操作的重要性。通过合理利用这些工具和策略,开发者能实现高效、稳定的API集成,提升应用性能和用户体验。
|
2天前
|
IDE 测试技术 项目管理
集成开发环境(IDE)的使用:提升Visual Basic开发效率的工具和技巧
【4月更文挑战第27天】本文探讨了如何使用Visual Basic IDE提升开发效率,包括理解IDE组件、利用代码编辑器的智能功能、通过界面设计器设计GUI、使用调试和测试工具、有效管理项目与版本控制、掌握快捷键和宏、定制IDE以及利用学习资源。通过充分利用这些工具和技巧,开发者能更快地编写高质量代码,高效管理项目,从而提升整体开发效率。随着IDE的持续发展,开发者应不断学习新特性以适应进步。
|
2天前
|
前端开发 JavaScript 数据挖掘
《Solidity 简易速速上手小册》第9章:DApp 开发与 Solidity 集成(2024 最新版)(下)
《Solidity 简易速速上手小册》第9章:DApp 开发与 Solidity 集成(2024 最新版)
30 1
|
2天前
|
算法 Linux Windows
FFmpeg开发笔记(十七)Windows环境给FFmpeg集成字幕库libass
在Windows环境下为FFmpeg集成字幕渲染库libass涉及多个步骤,包括安装freetype、libxml2、gperf、fontconfig、fribidi、harfbuzz和libass。每个库的安装都需要下载源码、配置、编译和安装,并更新PKG_CONFIG_PATH环境变量。最后,重新配置并编译FFmpeg以启用libass及相关依赖。完成上述步骤后,通过`ffmpeg -version`确认libass已成功集成。
21 1
FFmpeg开发笔记(十七)Windows环境给FFmpeg集成字幕库libass
|
2天前
|
缓存 NoSQL Java
springboot业务开发--springboot集成redis解决缓存雪崩穿透问题
该文介绍了缓存使用中可能出现的三个问题及解决方案:缓存穿透、缓存击穿和缓存雪崩。为防止缓存穿透,可校验请求数据并缓存空值;缓存击穿可采用限流、热点数据预加载或加锁策略;缓存雪崩则需避免同一时间大量缓存失效,可设置随机过期时间。文章还提及了Spring Boot中Redis缓存的配置,包括缓存null值、使用前缀和自定义过期时间,并提供了改造代码以实现缓存到期时间的个性化设置。
|
2天前
|
前端开发 定位技术 API
【Flutter前端技术开发专栏】Flutter中的第三方服务集成(如支付、地图等)
【4月更文挑战第30天】本文介绍了在Flutter中集成第三方服务,如支付和地图,以增强应用功能和用户体验。开发者可通过官方或社区插件集成服务,关注服务选择、API调用、错误处理和用户体验。支付集成涉及选择服务、获取API密钥、引入插件、调用API及处理结果。地图集成则需选择地图服务、获取API密钥、初始化地图并添加交互功能。集成时注意选择稳定插件、阅读文档、处理异常、优化性能和遵循安全规范。随着Flutter生态发展,更多第三方服务将可供选择。
【Flutter前端技术开发专栏】Flutter中的第三方服务集成(如支付、地图等)
|
2天前
|
Dart 前端开发 Android开发
【Flutter前端技术开发专栏】Flutter与原生代码的集成与交互
【4月更文挑战第30天】本文探讨了如何在Flutter中集成和交互原生代码,以利用特定平台的API和库。当需要访问如蓝牙、特定支付SDK或复杂动画时,集成原生代码能提升效率和性能。集成方法包括:使用Platform Channel进行通信,借助现有Flutter插件,以及Android和iOS的Embedding。文中通过一个电池信息获取的例子展示了如何使用`MethodChannel`在Dart和原生代码间传递调用。这些技术使开发者能充分利用原生功能,加速开发进程。
【Flutter前端技术开发专栏】Flutter与原生代码的集成与交互
|
2天前
|
传感器 前端开发 Android开发
【Flutter 前端技术开发专栏】Flutter 中的插件开发与集成
【4月更文挑战第30天】本文探讨了Flutter插件开发的关键技术和实践,包括插件作为连接Flutter与原生功能桥梁的角色,开发流程(定义接口、实现原生代码、打包发布),以及集成方法(添加依赖、初始化)。文中提到了多媒体、传感器和文件系统等常见插件类型,并以相机插件为例说明开发步骤。此外,还强调了版本兼容性、性能优化和错误处理的注意事项,推荐了开发工具和资源。随着Flutter的发展,插件开发将更加重要,未来有望形成更丰富的生态系统。
【Flutter 前端技术开发专栏】Flutter 中的插件开发与集成
|
2天前
|
持续交付 开发工具 Swift
【Swift开发专栏】Swift与第三方库和框架的集成
【4月更文挑战第30天】本文探讨了Swift中集成第三方库和框架的策略,包括选择有功能需求、社区支持、丰富文档和合适许可证的库。集成步骤涉及使用CocoaPods等工具安装,`import`导入库,遵循错误处理和性能优化。建议遵循代码组织、单一职责原则,做好错误处理和日志记录,使用版本控制和CI/CD,以提升项目稳定性和用户体验。

热门文章

最新文章