Commit 5d7c4150 authored by shengnan hu's avatar shengnan hu
Browse files

init

parents
Pipeline #4715 failed with stage
in 30 seconds
default:
tags:
- test # runner 需配置相同tag
interruptible: true # 任务可被后来pipeline打断
stages:
- upload-mr-analysis
- schedule-analyze-stage
workflow:
rules:
- if: $CI_MERGE_REQUEST_IID
- if: $CI_PIPELINE_SOURCE == "schedule"
variables:
MERGE_REQUEST_PARAM: "{mergeRequestId:$CI_MERGE_REQUEST_IID,projectId:$CI_PROJECT_ID,jobId:$CI_JOB_ID}"
JAVA_MAIN_SOURCE: "src/main/java" # 检索差异文件脚本变量,表示只检查main文件,不检查test文件
SCANNER_SCRIPT: "/root/analysis-tool/bin/scanner" # 套件命令执行文件
SCANNER_JAVA_LICENSE_PATH: "/root/analysis-tool/Hub-ci-java.txt" # JAVA授权文件
SCANNER_C_LICENSE_PATH: "/root/analysis-tool/Hub-ci-c.txt" # C授权文件
# 根据项目进行配置
HUB_LOGIN_NAME: "admin" # 登录名
HUB_PASSWORD: "1234qwer" # 密码
HUB_URL: "http://192.168.68.153:9521" # 平台URL
HUB_PROJECT_ID: "10" # 对应平台项目Id
REPOSITORY_FULL_PATH: "/builds/hub-gitlab/root/arthas" # 项目绝对路径,供套件分析
REPOSITORY_NAME: "arthas" # 项目名称
JAVA_SUFFIX: ".java"
ANALYSIS_PARAM: "MR_IID:$CI_MERGE_REQUEST_IID,JOB_ID:$CI_JOB_ID,false" # 分析名称 描述 是否为项目分析
ANALYSIS_PARAM_SCHEDULE: "定时项目分析,任务ID:$CI_JOB_ID,true" # 分析名称 描述 是否为项目分析
upload-job:
stage: upload-mr-analysis
# 包含分析工具运行所需环境
# 需要设置 runner config: pull_policy = "if-not-present"
# 使用本地镜像,本地需要有这个镜像
# 需要设置 runner config:mac_address(固定IP 工具授权需要)
image: docker.ustchcs.com/ubuntu-javacli-quality:v3.0
allow_failure: false
rules:
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
before_script:
# 授权
- locale-gen zh_CN
- export LANG=zh_CN.UTF-8
- export LC_ALL=zh_CN.UTF-8
- export LANGUAGE=zh_CN.UTF-8
- $SCANNER_SCRIPT authorize -n cafehunter $SCANNER_JAVA_LICENSE_PATH
# - $SCANNER_SCRIPT authorize -n seahunter $SCANNER_C_LICENSE_PATH
# 将游离分支转换为正常分支 以供套件分析
- cd $REPOSITORY_FULL_PATH
- git fetch
- git branch tmp-$CI_JOB_ID-$CI_JOB_NAME $CI_COMMIT_SHA
- git checkout -b $CI_COMMIT_REF_NAME
- git merge tmp-$CI_JOB_ID-$CI_JOB_NAME
# 获取分析文件
- chmod 777 $REPOSITORY_FULL_PATH/getCommittedFiles.sh
- export COMMITTED_FILES=$($REPOSITORY_FULL_PATH/getCommittedFiles.sh)
script:
# 分析
- echo "SCANNER_SCRIPT scan $COMMITTED_FILES -umr $REPOSITORY_NAME $HUB_LOGIN_NAME $HUB_PASSWORD $HUB_URL $HUB_PROJECT_ID $ANALYSIS_PARAM $MERGE_REQUEST_PARAM"
- $SCANNER_SCRIPT scan $COMMITTED_FILES -umr $REPOSITORY_NAME $HUB_LOGIN_NAME $HUB_PASSWORD $HUB_URL $HUB_PROJECT_ID $ANALYSIS_PARAM $MERGE_REQUEST_PARAM
# 删除过程中用到的分支
- "git branch -d tmp-$CI_JOB_ID-$CI_JOB_NAME"
- "git checkout $CI_COMMIT_SHA"
- "git branch -D $CI_COMMIT_REF_NAME"
after_script:
- "git branch -d tmp-$CI_JOB_ID-$CI_JOB_NAME"
- "git checkout $CI_COMMIT_SHA"
- "git branch -D $CI_COMMIT_REF_NAME"
schedule-analyze:
stage: schedule-analyze-stage
image: docker.ustchcs.com/ubuntu-javacli-quality:v3.0
allow_failure: false
only:
- schedules
before_script:
- locale-gen zh_CN
- export LANG=zh_CN.UTF-8
- export LC_ALL=zh_CN.UTF-8
- export LANGUAGE=zh_CN.UTF-8
- $SCANNER_SCRIPT authorize -n cafehunter $SCANNER_JAVA_LICENSE_PATH
- "cd $REPOSITORY_FULL_PATH"
- "git fetch"
- "git checkout develop"
- "git pull origin develop"
- "git branch"
- "git log"
- "locale-gen zh_CN"
- "export LANG=zh_CN.UTF-8"
- "export LC_ALL=zh_CN.UTF-8"
- "export LANGUAGE=zh_CN.UTF-8"
script:
- echo 'cafehunter-cli install complete.'
- echo "$SCANNER_SCRIPT scan $REPOSITORY_FULL_PATH/arthas-vmtool -u $REPOSITORY_NAME $HUB_LOGIN_NAME $HUB_PASSWORD $HUB_URL $HUB_PROJECT_ID $ANALYSIS_PARAM_SCHEDULE"
- "$SCANNER_SCRIPT scan $REPOSITORY_FULL_PATH/arthas-vmtool -u $REPOSITORY_NAME $HUB_LOGIN_NAME $HUB_PASSWORD $HUB_URL $HUB_PROJECT_ID $ANALYSIS_PARAM_SCHEDULE"
<?xml version="1.0"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.taobao.arthas</groupId>
<artifactId>arthas-all</artifactId>
<version>${revision}</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>arthas-agent</artifactId>
<name>arthas-agent</name>
<dependencies>
<dependency>
<groupId>com.taobao.arthas</groupId>
<artifactId>arthas-spy</artifactId>
<version>${project.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<finalName>arthas-agent</finalName>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.6</source>
<target>1.6</target>
<encoding>UTF-8</encoding>
<showDeprecation>true</showDeprecation>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>single</goal>
</goals>
<phase>package</phase>
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
<archive>
<manifestEntries>
<Premain-Class>com.taobao.arthas.agent334.AgentBootstrap</Premain-Class>
<Agent-Class>com.taobao.arthas.agent334.AgentBootstrap</Agent-Class>
<Can-Redefine-Classes>true</Can-Redefine-Classes>
<Can-Retransform-Classes>true</Can-Retransform-Classes>
<Specification-Title>${project.name}</Specification-Title>
<Specification-Version>${project.version}</Specification-Version>
<Implementation-Title>${project.name}</Implementation-Title>
<Implementation-Version>${project.version}</Implementation-Version>
</manifestEntries>
</archive>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
package com.taobao.arthas.agent;
import java.net.URL;
import java.net.URLClassLoader;
/**
* @author beiwei30 on 09/12/2016.
*/
public class ArthasClassloader extends URLClassLoader {
public ArthasClassloader(URL[] urls) {
super(urls, ClassLoader.getSystemClassLoader().getParent());
}
@Override
protected synchronized Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {
final Class<?> loadedClass = findLoadedClass(name);
if (loadedClass != null) {
return loadedClass;
}
// 优先从parent(SystemClassLoader)里加载系统类,避免抛出ClassNotFoundException
if (name != null && (name.startsWith("sun.") || name.startsWith("java."))) {
return super.loadClass(name, resolve);
}
try {
Class<?> aClass = findClass(name);
if (resolve) {
resolveClass(aClass);
}
return aClass;
} catch (Exception e) {
// ignore
}
return super.loadClass(name, resolve);
}
}
package com.taobao.arthas.agent334;
import java.arthas.SpyAPI;
import java.io.File;
import java.io.FileOutputStream;
import java.io.PrintStream;
import java.io.UnsupportedEncodingException;
import java.lang.instrument.Instrumentation;
import java.net.URL;
import java.net.URLDecoder;
import java.security.CodeSource;
import com.taobao.arthas.agent.ArthasClassloader;
/**
* 代理启动类
*
* @author vlinux on 15/5/19.
*/
public class AgentBootstrap {
private static final String ARTHAS_CORE_JAR = "arthas-core.jar";
private static final String ARTHAS_BOOTSTRAP = "com.taobao.arthas.core.server.ArthasBootstrap";
private static final String GET_INSTANCE = "getInstance";
private static final String IS_BIND = "isBind";
private static PrintStream ps = System.err;
static {
try {
File arthasLogDir = new File(System.getProperty("user.home") + File.separator + "logs" + File.separator
+ "arthas" + File.separator);
if (!arthasLogDir.exists()) {
arthasLogDir.mkdirs();
}
if (!arthasLogDir.exists()) {
// #572
arthasLogDir = new File(System.getProperty("java.io.tmpdir") + File.separator + "logs" + File.separator
+ "arthas" + File.separator);
if (!arthasLogDir.exists()) {
arthasLogDir.mkdirs();
}
}
File log = new File(arthasLogDir, "arthas.log");
if (!log.exists()) {
log.createNewFile();
}
ps = new PrintStream(new FileOutputStream(log, true));
} catch (Throwable t) {
t.printStackTrace(ps);
}
}
/**
* <pre>
* 1. 全局持有classloader用于隔离 Arthas 实现,防止多次attach重复初始化
* 2. ClassLoader在arthas停止时会被reset
* 3. 如果ClassLoader一直没变,则 com.taobao.arthas.core.server.ArthasBootstrap#getInstance 返回结果一直是一样的
* </pre>
*/
private static volatile ClassLoader arthasClassLoader;
public static void premain(String args, Instrumentation inst) {
main(args, inst);
}
public static void agentmain(String args, Instrumentation inst) {
main(args, inst);
}
/**
* 让下次再次启动时有机会重新加载
*/
public static void resetArthasClassLoader() {
arthasClassLoader = null;
}
private static ClassLoader getClassLoader(Instrumentation inst, File arthasCoreJarFile) throws Throwable {
// 构造自定义的类加载器,尽量减少Arthas对现有工程的侵蚀
return loadOrDefineClassLoader(arthasCoreJarFile);
}
private static ClassLoader loadOrDefineClassLoader(File arthasCoreJarFile) throws Throwable {
if (arthasClassLoader == null) {
arthasClassLoader = new ArthasClassloader(new URL[]{arthasCoreJarFile.toURI().toURL()});
}
return arthasClassLoader;
}
private static synchronized void main(String args, final Instrumentation inst) {
// 尝试判断arthas是否已在运行,如果是的话,直接就退出
try {
Class.forName("java.arthas.SpyAPI"); // 加载不到会抛异常
if (SpyAPI.isInited()) {
ps.println("Arthas server already stared, skip attach.");
ps.flush();
return;
}
} catch (Throwable e) {
// ignore
}
try {
ps.println("Arthas server agent start...");
// 传递的args参数分两个部分:arthasCoreJar路径和agentArgs, 分别是Agent的JAR包路径和期望传递到服务端的参数
if (args == null) {
args = "";
}
args = decodeArg(args);
String arthasCoreJar;
final String agentArgs;
int index = args.indexOf(';');
if (index != -1) {
arthasCoreJar = args.substring(0, index);
agentArgs = args.substring(index);
} else {
arthasCoreJar = "";
agentArgs = args;
}
File arthasCoreJarFile = new File(arthasCoreJar);
if (!arthasCoreJarFile.exists()) {
ps.println("Can not find arthas-core jar file from args: " + arthasCoreJarFile);
// try to find from arthas-agent.jar directory
CodeSource codeSource = AgentBootstrap.class.getProtectionDomain().getCodeSource();
if (codeSource != null) {
try {
File arthasAgentJarFile = new File(codeSource.getLocation().toURI().getSchemeSpecificPart());
arthasCoreJarFile = new File(arthasAgentJarFile.getParentFile(), ARTHAS_CORE_JAR);
if (!arthasCoreJarFile.exists()) {
ps.println("Can not find arthas-core jar file from agent jar directory: " + arthasAgentJarFile);
}
} catch (Throwable e) {
ps.println("Can not find arthas-core jar file from " + codeSource.getLocation());
e.printStackTrace(ps);
}
}
}
if (!arthasCoreJarFile.exists()) {
return;
}
/**
* Use a dedicated thread to run the binding logic to prevent possible memory leak. #195
*/
final ClassLoader agentLoader = getClassLoader(inst, arthasCoreJarFile);
Thread bindingThread = new Thread() {
@Override
public void run() {
try {
bind(inst, agentLoader, agentArgs);
} catch (Throwable throwable) {
throwable.printStackTrace(ps);
}
}
};
bindingThread.setName("arthas-binding-thread");
bindingThread.start();
bindingThread.join();
} catch (Throwable t) {
t.printStackTrace(ps);
try {
if (ps != System.err) {
ps.close();
}
} catch (Throwable tt) {
// ignore
}
throw new RuntimeException(t);
}
}
private static void bind(Instrumentation inst, ClassLoader agentLoader, String args) throws Throwable {
/**
* <pre>
* ArthasBootstrap bootstrap = ArthasBootstrap.getInstance(inst);
* </pre>
*/
Class<?> bootstrapClass = agentLoader.loadClass(ARTHAS_BOOTSTRAP);
Object bootstrap = bootstrapClass.getMethod(GET_INSTANCE, Instrumentation.class, String.class).invoke(null, inst, args);
boolean isBind = (Boolean) bootstrapClass.getMethod(IS_BIND).invoke(bootstrap);
if (!isBind) {
String errorMsg = "Arthas server port binding failed! Please check $HOME/logs/arthas/arthas.log for more details.";
ps.println(errorMsg);
throw new RuntimeException(errorMsg);
}
ps.println("Arthas server already bind.");
}
private static String decodeArg(String arg) {
try {
return URLDecoder.decode(arg, "utf-8");
} catch (UnsupportedEncodingException e) {
return arg;
}
}
}
#Generated by Git-Commit-Id-Plugin
git.build.version=3.6.4
git.closest.tag.commit.count=
git.closest.tag.name=
git.commit.id=35f73a652cf4efc30cc57df74dbab7d5c1de757a
git.commit.id.abbrev=35f73a6
git.commit.id.describe=35f73a6
git.commit.id.describe-short=35f73a6
git.commit.message.full=ci-set-3
git.commit.message.short=ci-set-3
git.commit.user.email=shengnan.hu@ustchcs.com
git.commit.user.name=shengnan.hu
git.dirty=false
<?xml version="1.0"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.taobao.arthas</groupId>
<artifactId>arthas-all</artifactId>
<version>${revision}</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>arthas-agent-attach</artifactId>
<name>arthas-agent-attach</name>
<dependencies>
<dependency>
<groupId>com.taobao.arthas</groupId>
<artifactId>arthas-spy</artifactId>
<version>${project.version}</version>
<scope>provided</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>net.bytebuddy</groupId>
<artifactId>byte-buddy-agent</artifactId>
</dependency>
<dependency>
<groupId>org.zeroturnaround</groupId>
<artifactId>zt-zip</artifactId>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.6</source>
<target>1.6</target>
<encoding>UTF-8</encoding>
<showDeprecation>true</showDeprecation>
</configuration>
</plugin>
</plugins>
</build>
</project>
package com.taobao.arthas.agent.attach;
import java.arthas.SpyAPI;
import java.io.File;
import java.lang.instrument.Instrumentation;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;
import org.zeroturnaround.zip.ZipUtil;
import net.bytebuddy.agent.ByteBuddyAgent;
/**
*
* @author hengyunabc 2020-06-22
*
*/
public class ArthasAgent {
private static final int TEMP_DIR_ATTEMPTS = 10000;
private static final String ARTHAS_CORE_JAR = "arthas-core.jar";
private static final String ARTHAS_BOOTSTRAP = "com.taobao.arthas.core.server.ArthasBootstrap";
private static final String GET_INSTANCE = "getInstance";
private static final String IS_BIND = "isBind";
private String errorMessage;
private Map<String, String> configMap = new HashMap<String, String>();
private String arthasHome;
private boolean slientInit;
private Instrumentation instrumentation;
public ArthasAgent() {
this(null, null, false, null);
}
public ArthasAgent(Map<String, String> configMap) {
this(configMap, null, false, null);
}
public ArthasAgent(String arthasHome) {
this(null, arthasHome, false, null);
}
public ArthasAgent(Map<String, String> configMap, String arthasHome, boolean slientInit,
Instrumentation instrumentation) {
if (configMap != null) {
this.configMap = configMap;
}
this.arthasHome = arthasHome;
this.slientInit = slientInit;
this.instrumentation = instrumentation;
}
public static void attach() {
new ArthasAgent().init();
}
/**
* @see https://arthas.aliyun.com/doc/arthas-properties.html
* @param configMap
*/
public static void attach(Map<String, String> configMap) {
new ArthasAgent(configMap).init();
}
/**
* use the specified arthas
* @param arthasHome arthas directory
*/
public static void attach(String arthasHome) {
new ArthasAgent().init();
}
public void init() throws IllegalStateException {
// 尝试判断arthas是否已在运行,如果是的话,直接就退出
try {
Class.forName("java.arthas.SpyAPI"); // 加载不到会抛异常
if (SpyAPI.isInited()) {
return;
}
} catch (Throwable e) {
// ignore
}
try {
if (instrumentation == null) {
instrumentation = ByteBuddyAgent.install();
}
// 检查 arthasHome
if (arthasHome == null || arthasHome.trim().isEmpty()) {
// 解压出 arthasHome
URL coreJarUrl = this.getClass().getClassLoader().getResource("arthas-bin.zip");
if (coreJarUrl != null) {
File tempArthasDir = createTempDir();
ZipUtil.unpack(coreJarUrl.openStream(), tempArthasDir);
arthasHome = tempArthasDir.getAbsolutePath();
} else {
throw new IllegalArgumentException("can not getResources arthas-bin.zip from classloader: "
+ this.getClass().getClassLoader());
}
}
// find arthas-core.jar
File arthasCoreJarFile = new File(arthasHome, ARTHAS_CORE_JAR);
if (!arthasCoreJarFile.exists()) {
throw new IllegalStateException("can not find arthas-core.jar under arthasHome: " + arthasHome);
}
AttachArthasClassloader arthasClassLoader = new AttachArthasClassloader(
new URL[] { arthasCoreJarFile.toURI().toURL() });
/**
* <pre>
* ArthasBootstrap bootstrap = ArthasBootstrap.getInstance(inst);
* </pre>
*/
Class<?> bootstrapClass = arthasClassLoader.loadClass(ARTHAS_BOOTSTRAP);
Object bootstrap = bootstrapClass.getMethod(GET_INSTANCE, Instrumentation.class, Map.class).invoke(null,
instrumentation, configMap);
boolean isBind = (Boolean) bootstrapClass.getMethod(IS_BIND).invoke(bootstrap);
if (!isBind) {
String errorMsg = "Arthas server port binding failed! Please check $HOME/logs/arthas/arthas.log for more details.";
throw new RuntimeException(errorMsg);
}
} catch (Throwable e) {
errorMessage = e.getMessage();
if (!slientInit) {
throw new IllegalStateException(e);
}
}
}
private static File createTempDir() {
File baseDir = new File(System.getProperty("java.io.tmpdir"));
String baseName = "arthas-" + System.currentTimeMillis() + "-";
for (int counter = 0; counter < TEMP_DIR_ATTEMPTS; counter++) {
File tempDir = new File(baseDir, baseName + counter);
if (tempDir.mkdir()) {
return tempDir;
}
}
throw new IllegalStateException("Failed to create directory within " + TEMP_DIR_ATTEMPTS + " attempts (tried "
+ baseName + "0 to " + baseName + (TEMP_DIR_ATTEMPTS - 1) + ')');
}
public String getErrorMessage() {
return errorMessage;
}
public void setErrorMessage(String errorMessage) {
this.errorMessage = errorMessage;
}
}
package com.taobao.arthas.agent.attach;
import java.net.URL;
import java.net.URLClassLoader;
/**
*
* @author hengyunabc 2020-06-22
*
*/
public class AttachArthasClassloader extends URLClassLoader {
public AttachArthasClassloader(URL[] urls) {
super(urls, ClassLoader.getSystemClassLoader().getParent());
}
@Override
protected synchronized Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {
final Class<?> loadedClass = findLoadedClass(name);
if (loadedClass != null) {
return loadedClass;
}
// 优先从parent(SystemClassLoader)里加载系统类,避免抛出ClassNotFoundException
if (name != null && (name.startsWith("sun.") || name.startsWith("java."))) {
return super.loadClass(name, resolve);
}
try {
Class<?> aClass = findClass(name);
if (resolve) {
resolveClass(aClass);
}
return aClass;
} catch (Exception e) {
// ignore
}
return super.loadClass(name, resolve);
}
}
#Generated by Git-Commit-Id-Plugin
git.build.version=3.6.4
git.closest.tag.commit.count=
git.closest.tag.name=
git.commit.id=35f73a652cf4efc30cc57df74dbab7d5c1de757a
git.commit.id.abbrev=35f73a6
git.commit.id.describe=35f73a6
git.commit.id.describe-short=35f73a6
git.commit.message.full=ci-set-3
git.commit.message.short=ci-set-3
git.commit.user.email=shengnan.hu@ustchcs.com
git.commit.user.name=shengnan.hu
git.dirty=false
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.taobao.arthas</groupId>
<artifactId>arthas-all</artifactId>
<version>${revision}</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>arthas-spring-boot-starter</artifactId>
<packaging>jar</packaging>
<name>${project.artifactId}</name>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${spring-boot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>com.taobao.arthas</groupId>
<artifactId>arthas-agent-attach</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.taobao.arthas</groupId>
<artifactId>arthas-packaging</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
<scope>provided</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<scope>provided</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<artifactId>maven-invoker-plugin</artifactId>
<version>${maven-invoker-plugin.version}</version>
<configuration>
<!-- <debug>true</debug> -->
<cloneProjectsTo>${project.build.directory}/it</cloneProjectsTo>
<projectsDirectory>src/it</projectsDirectory>
<settingsFile>src/it/settings.xml</settingsFile>
<localRepositoryPath>${project.build.directory}/local-repo</localRepositoryPath>
<skipInvocation>${skipTests}</skipInvocation>
<streamLogs>true</streamLogs>
<preBuildHookScript>setup</preBuildHookScript>
<postBuildHookScript>verify</postBuildHookScript>
</configuration>
<executions>
<execution>
<id>integration-test</id>
<goals>
<goal>install</goal>
<goal>run</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
# A comma or space separated list of goals/phases to execute, may
# specify an empty list to execute the default goal of the IT project.
# Environment variables used by maven plugins can be added here
invoker.goals = clean spring-boot:run
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>@spring-boot.version@</version>
<relativePath /> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>arthas-spring-boot-starter-example</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>arthas-spring-boot-starter-example</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>@project.groupId@</groupId>
<artifactId>@project.artifactId@</artifactId>
<version>@project.version@</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
package com.example.arthasspringbootstarterexample;
import java.util.concurrent.TimeUnit;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class ArthasSpringBootStarterExampleApplication {
public static void main(String[] args) throws InterruptedException {
SpringApplication.run(ArthasSpringBootStarterExampleApplication.class, args);
System.out.println("xxxxxxxxxxxxxxxxxx");
TimeUnit.SECONDS.sleep(3);
System.exit(0);
}
}
package com.example.arthasspringbootstarterexample;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
class ArthasSpringBootStarterExampleApplicationTests {
@Test
void contextLoads() {
}
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment