【Gradle-13】SNAPSHOT版本检查

1、什么是SNAPSHOT

SNAPSHOT版本是指尚未发布的版本,是一个「动态版本」,它始终指向最新的发布工件(gav),也就是说同一个SNAPSHOT版本可以反复用来发布。
这种情况在大型app多团队的开发中比较常见,比如user模块依赖base模块,因为是在开发阶段,base模块可能会不断的修bug或者提供新能力,这时候就可以不断的发布SNAPSHOT版本提供给user模块使用,而不用发正式版本,也达不到正式版本的要求,而user模块也不用频繁的去改版本就能拉到最新的base代码了。

2、为什么要检测

这种开发效率的提升也带来一定的风险,因为SNAPSHOT版本是开发阶段的动态版本,反复发布具有覆盖的特性,如果在打release包的时候拉到最新的SNAPSHOT版本中有未验证的代码,轻则编译错误,万一带到线上去可是非常危险的。

3、检测思路

SNAPSHOT版本通常用版本号后缀表示:

gradle:
    classpath('com.github.yechaoa.GradleX:plugin:1.3-SNAPSHOT')

maven:
    <version>1.3-SNAPSHOT</version>
  1. 获取项目中参与编译的所有依赖项;
  2. 校验依赖项的版本号;
    1. 有SNAPSHOT依赖,打印出来,并打断构建流程(可选);
    2. 无 则继续;

听起来并不复杂,实际上也很简单,下面来实战一下。

4、实战

4.1、获取所有依赖

  1. 先获取AppExtension。
AppExtension androidExtension = project.getExtensions().getByType(AppExtension.class);
  • 简单理解它对应的是build.gradle,而build.gradle里面有dependencies{ }
  1. 通过Variants获取Configuration。
androidExtension.getApplicationVariants().all(applicationVariant -> {
    // debug/release也可以加配置
    System.out.println(TAG + "applicationVariant.getName() = " + applicationVariant.getName());
    Configuration configuration = project.getConfigurations().getByName(applicationVariant.getName() + "CompileClasspath");
    // ...
});
  • 不同的build type它的依赖是有区别的,比如implementation和debugImplementation;
  • 获取Configuration对象是因为依赖项是在配置阶段解析的;

4.2、遍历依赖项

configuration.getResolvedConfiguration().getLenientConfiguration().getAllModuleDependencies().forEach(resolvedDependency -> {
    ModuleVersionIdentifier identifier = resolvedDependency.getModule().getId();
    if (isSnapshot(identifier.getVersion())) {
        snapshotList.add(identifier.getGroup() + ":" + identifier.getName() + ":" + identifier.getVersion());
    }
});
  • 这里我们要用getResolvedConfiguration()来获取版本决议后的依赖项;
  • 然后通过getLenientConfiguration().getAllModuleDependencies()获取所有依赖,包括依赖中的子依赖;
  • 在遍历中,我们还要获取ModuleVersionIdentifier对象,通过它获取依赖项的坐标GAV;

4.3、Snapshot校验

    private boolean isSnapshot(String version) {
        String checkRules = "SNAPSHOT";
        return version.endsWith(checkRules) || version.contains(checkRules);
    }
  • 校验规则比较简单,就是判断是否包含SNAPSHOT字符串;
  • 符合规则的就添加到集合中,然后打印出来;

4.4、打断编译

    private void blockBuilding() {
        String errorMassage = "检测到有SNAPSHOT版本依赖";
        throw new GradleException(errorMassage, new Exception(errorMassage));
    }

打断编译也比较简单,直接抛个异常就好了。

4.4.1、异常类型

  • GradleException:一般用于在Gradle构建过程中抛出异常,比如自定义Plugin中的逻辑错误等;
  • GradleScriptException:一般表示构建脚本(build script)执行异常,比如语法错误、解析错误等;
  • StopActionException:一般用在Task里面,表示当前Action执行异常,但是还可以继续执行下一个;
  • InvalidUserDataException:这个也是经常遇到和经常用的,一般表示无效的参数或者选项;

更多的可以去翻下源码,一般编译过程中的异常都是继承自RuntimeException

4.5、完整代码

    private void checkSnapshot(Project project, boolean blockSnapshot) {
        AppExtension androidExtension = project.getExtensions().getByType(AppExtension.class);
        androidExtension.getApplicationVariants().all(applicationVariant -> {
            // debug/release也可以加配置
            System.out.println(TAG + "applicationVariant.getName() = " + applicationVariant.getName());
            Configuration configuration = project.getConfigurations().getByName(applicationVariant.getName() + "CompileClasspath");

            List<String> snapshotList = new ArrayList<>();

            // 所有的依赖,包括依赖中的依赖
            configuration.getResolvedConfiguration().getLenientConfiguration().getAllModuleDependencies().forEach(resolvedDependency -> {
                ModuleVersionIdentifier identifier = resolvedDependency.getModule().getId();
                if (isSnapshot(identifier.getVersion())) {
                    snapshotList.add(identifier.getGroup() + ":" + identifier.getName() + ":" + identifier.getVersion());
                }
            });

            if (snapshotList.size() > 0) {
                snapshotList.forEach(System.out::println);
                if (blockSnapshot) {
                    blockBuilding();
                }
            } else {
                System.out.println(TAG + "无SNAPSHOT版本依赖");
            }
        });
    }

    private void blockBuilding() {
        String errorMassage = "检测到有SNAPSHOT版本依赖";
        throw new GradleException(errorMassage, new Exception(errorMassage));
    }

    private boolean isSnapshot(String version) {
        String checkRules = "SNAPSHOT";
        return version.endsWith(checkRules) || version.contains(checkRules);
    }

4.6、验证

测试找了一个androidx.core的beta版本,然后把检测规则改成beta来验证。

implementation 'androidx.core:core:1.9.0-beta01'

然后在插件配置中加上Snapshot检查和编译打断(默认关)。

gradleX {
    checkSnapshot = true
    blockSnapshot = true
}

最终效果:
效果.png
是不是还挺简单的~

在实际开发中,如果有CI/CD流程可以添加一个后置执行卡口,再补一个白名单和审批流,如果没有,也可以整个构建报告。

5、最后

如果你不想自己写,这个插件我也发布远端了,按照下面三步走,即可使用。
Step 1. Add the JitPack repository to your build file

repositories {
	...
	maven { url 'https://jitpack.io' }
}

Step 2. Add the dependency

dependencies {
    classpath('com.github.yechaoa.GradleX:plugin:1.5')
}

Step 3. Add the Plugin Id to your build file and configure the gradleX{ } dsl

plugins {
    id 'com.yechaoa.plugin.gradleX'
}

gradleX {
    printDependencies = false
    analysisSo = true
    checkSnapshot = true
    blockSnapshot = false
}

ok,以上即是本文介绍内容,学废了吗,快来三连~

6、GitHub

https://github.com/yechaoa/GradleX

7、相关文档

  • 【Gradle-8】Gradle插件开发指南
  • GradleException

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/165737.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

ROS参数服务器(Param):通信模型、Hello World与拓展

参数服务器在ROS中主要用于实现不同节点之间的数据共享。 参数服务器相当于是独立于所有节点的一个公共容器&#xff0c;可以将数据存储在该容器中&#xff0c;被不同的节点调用&#xff0c;当然不同的节点也可以往其中存储数据。 使用场景一般存储一些机器人的固有参数&…

系列四、强引用、软引用、弱引用、虚引用分别是什么?

一、整体架构 二、强引用&#xff08;默认支持模式&#xff09; 2.1、概述 当内存不足时&#xff0c;JVM开始垃圾回收&#xff0c;对于强引用的对象&#xff0c;就算是出现了OOM也不会对该对象进行回收&#xff0c;死都不收。 强引用是我们最常见的普通对象引用&#xff0c;只…

Gin框架源码解析

概要 目录 Gin路由详解 Gin框架路由之Radix Tree 一、路由树节点 二、请求方法树 三、路由注册以及匹配 中间件含义 Gin框架中的中间件 主要讲述Gin框架路由和中间件的详细解释。本文章将从Radix树&#xff08;基数树或者压缩前缀树&#xff09;、请求处理、路由方法树…

hypermesh学习总结(一)

1、hypermesh导入导出 2、hypermesh如何使用拓扑命令,连接多个几何体为一个? 3、hypermesh模式选择 分别有显示动力学模式explicit,标准模式Standard3D(静力学及模态等)

Linux之进程概念(一)

&#x1f4d8;北尘_&#xff1a;个人主页 &#x1f30e;个人专栏:《Linux操作系统》《经典算法试题 》《C》 《数据结构与算法》 ☀️走在路上&#xff0c;不忘来时的初心 文章目录 一、冯诺依曼体系结构二、操作系统(Operator System)1、概念2、设计OS的目的3、定位4、如何理…

2024年csdn最新最全的Postman接口测试: postman实现参数化

什么时候会用到参数化 比如&#xff1a;一个模块要用多组不同数据进行测试 验证业务的正确性 Login模块&#xff1a;正确的用户名&#xff0c;密码 成功&#xff1b;错误的用户名&#xff0c;正确的密码 失败 postman实现参数化 在实际的接口测试中&#xff0c;部分参数…

弗洛伊德算法(C++)

目录 介绍&#xff1a; 代码&#xff1a; 结果&#xff1a; 介绍&#xff1a; 弗洛伊德算法&#xff08;Floyd algorithm&#xff09;也称为Floyd-Warshall算法&#xff0c;是一种用于求解所有节点对之间的最短路径的动态规划算法。它使用了一个二维数组来存储所有节点…

深入解析具名导入es6规范中的具名导入是在做解构吗

先说答案&#xff0c;不是 尽管es6的具名导入和语法非常相似 es6赋值解构 const obj {a: 1,f() {this.a}}const { a, f } objes6具名导入 //导出文件代码export let a 1export function f() {a}export default {a,f}//导入文件代码import { a, f } from ./tsVolution可以看出…

Unity2021及以上 启动或者禁用自动刷新

Unity 2021以以上启动自动刷新 Edit---> Preferences--> Asset Pipline --> Auto Refresh 禁用的结果 如果不启动自动刷新在Project面板选择Refresh是不会刷新已经修改后的脚本的。

10_6 input输入子系统,流程解析

简单分层 应用层 内核层 --------------------------- input handler 数据处理层 driver/input/evdev.c1.和用户空间交互,实现fops2.不知道数据怎么得到的,但是可以把数据上传给用户--------------------------- input core层1.维护上面和下面的两个链表2.为上下两层提供接口--…

智慧路灯控制系统设计方案思路及设计原则

智慧路灯系统依托于智慧路灯综合管理平台&#xff0c;实现点&#xff08;智慧路灯&#xff09;、线&#xff08;道路&#xff09;、面&#xff08;城市&#xff09;的三级监控&#xff0c;实现灯控、屏控、视频监控、数据采集、联动的统一。 1&#xff09;一个城市的智慧路灯系…

Shell判断:流程控制—if(三)

一、调试脚本 1、调试脚本的其他方法&#xff1a; [rootlocalhost ~] # sh -n useradd.sh 仅调试脚本中的语法错误。 [rootlocalhost ~]# sh -vx useradd.sh 以调试的方式执行&#xff0c;查询整个执行过程。 2、示例&#xff1a; [rootlocalhost ~]# sh -n useradd.sh #调…

【数据结构&C++】二叉平衡搜索树-AVL树(25)

前言 大家好吖&#xff0c;欢迎来到 YY 滴C系列 &#xff0c;热烈欢迎&#xff01; 本章主要内容面向接触过C的老铁 主要内容含&#xff1a; 欢迎订阅 YY滴C专栏&#xff01;更多干货持续更新&#xff01;以下是传送门&#xff01; 目录 一.AVL树的概念二.AVL树节点的定义(代码…

OpenHarmony源码下载

OpenHarmony源码下载 现在的 OpenHarmony 4.0 源码已经有了&#xff0c;在 https://gitee.com/openharmony 地址中&#xff0c;描述了源码获取的方式&#xff0c;但那是基于 ubuntu 或者说是 Linux 的下载方式。在 windows 平台下的下载方式没有做出介绍。 我自己尝试了 wind…

linux文件IO

文件IO截断 截断对文件的偏移量没有影响。

【Go入门】 Go如何使得Web工作

【Go入门】 Go如何使得Web工作 前面小节介绍了如何通过Go搭建一个Web服务&#xff0c;我们可以看到简单应用一个net/http包就方便的搭建起来了。那么Go在底层到底是怎么做的呢&#xff1f;万变不离其宗&#xff0c;Go的Web服务工作也离不开我们第一小节介绍的Web工作方式。 w…

简单聊一聊幂等和防重

大家好&#xff0c;我是G探险者。 每年的双十一&#xff0c;618&#xff0c;电商系统都会面临这超高的流量&#xff0c;如果一个订单被反复提交&#xff0c;那电商系统如何保证这个订单之后执行一次减库存&#xff0c;扣款的操作&#xff1f; 这里就引入两个概念&#xff0c;…

python-opencv 培训课程笔记(1)

python-opencv 培训课程笔记&#xff08;1&#xff09; 博主参加了一次opencv库的培训课程&#xff0c;把课程所学整理成笔记&#xff0c;供大家学习&#xff0c;第一次课程包括如下内容&#xff1a; 1.读取图像 2.保存图像 3.使用opencv库显示图像 4.读取图像为灰度图像 …

常见树种(贵州省):003柏类

摘要&#xff1a;本专栏树种介绍图片来源于PPBC中国植物图像库&#xff08;下附网址&#xff09;&#xff0c;本文整理仅做交流学习使用&#xff0c;同时便于查找&#xff0c;如有侵权请联系删除。 图片网址&#xff1a;PPBC中国植物图像库——最大的植物分类图片库 一、柏木 …

【Go入门】Web工作方式

【Go入门】 Web工作方式 我们平时浏览网页的时候,会打开浏览器&#xff0c;输入网址后按下回车键&#xff0c;然后就会显示出你想要浏览的内容。在这个看似简单的用户行为背后&#xff0c;到底隐藏了些什么呢&#xff1f; 对于普通的上网过程&#xff0c;系统其实是这样做的&…