From cd69685e1cc9b4070f4a52c766e306892fbce860 Mon Sep 17 00:00:00 2001 From: raylax Date: Thu, 6 Jun 2019 11:28:59 +0800 Subject: [PATCH] update --- README.md | 64 ++++++++++++- image/step1.png | Bin 0 -> 14534 bytes image/step2.png | Bin 0 -> 35311 bytes .../inurl/jenkins/plugin/OSSPublisher.java | 41 +++++++- .../inurl/jenkins/plugin/Messages.properties | 3 +- .../jenkins/plugin/Messages_zh.properties | 3 +- .../jenkins/plugin/OSSPublisher/config.jelly | 5 +- .../plugin/OSSPublisher/config.properties | 4 +- .../plugin/OSSPublisher/config_zh.properties | 4 +- .../OSSPublisher/help-accessKeyId_zh.html | 4 + .../OSSPublisher/help-accessKeySecret_zh.html | 4 + .../OSSPublisher/help-bucketName_zh.html | 4 + .../plugin/OSSPublisher/help-endpoint_zh.html | 4 + .../OSSPublisher/help-localPath_zh.html | 3 + .../OSSPublisher/help-remotePath_zh.html | 3 + .../jenkins/plugin/OSSPublisherTest.java | 90 ++++++++++++++++++ 16 files changed, 225 insertions(+), 11 deletions(-) create mode 100644 image/step1.png create mode 100644 image/step2.png create mode 100644 src/main/resources/org/inurl/jenkins/plugin/OSSPublisher/help-accessKeyId_zh.html create mode 100644 src/main/resources/org/inurl/jenkins/plugin/OSSPublisher/help-accessKeySecret_zh.html create mode 100644 src/main/resources/org/inurl/jenkins/plugin/OSSPublisher/help-bucketName_zh.html create mode 100644 src/main/resources/org/inurl/jenkins/plugin/OSSPublisher/help-endpoint_zh.html create mode 100644 src/main/resources/org/inurl/jenkins/plugin/OSSPublisher/help-localPath_zh.html create mode 100644 src/main/resources/org/inurl/jenkins/plugin/OSSPublisher/help-remotePath_zh.html create mode 100644 src/test/java/org/inurl/jenkins/plugin/OSSPublisherTest.java diff --git a/README.md b/README.md index 7148a59..e7b126f 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,62 @@ -# jenkins-aliyun-oss-plugin -jenkins阿里云OSS上传插件 +# jenkins阿里云OSS上传插件 + +## 使用 + +1.增加`构建后操作`,选择`阿里云OSS上传` + +![](https://github.com/raylax/jenkins-aliyun-oss-plugin/raw/master/image/step1.png) + +2.填写阿里云OSS配置信息 + +![](https://github.com/raylax/jenkins-aliyun-oss-plugin/raw/master/image/step2.png) + +> 本地路径为相对于workspace的路径,例如填写为`/abc`,则本地路径为`${WORKSPACE}/abc` +本地路径可以设置为文件或目录 + +## 构建 + +1. 修改`${USER}/.m2/settings.xml`中的maven配置文件 + +在`mirrors`节点中增加 +```xml + + repo.jenkins-ci.org + https://repo.jenkins-ci.org/public/ + m.g.o-public + +``` +在`pluginGroups`节点中增加 +```xml +org.jenkins-ci.tools +``` +在`profiles`节点中增加 +```xml + + jenkins + + true + + + + repo.jenkins-ci.org + https://repo.jenkins-ci.org/public/ + + + + + repo.jenkins-ci.org + https://repo.jenkins-ci.org/public/ + + + +``` + +2. 打包 +```bash +mvn package +``` + +3. 运行 +```bash +mvn hpi:run +``` \ No newline at end of file diff --git a/image/step1.png b/image/step1.png new file mode 100644 index 0000000000000000000000000000000000000000..bd94b15c110df85376bf4efb2f680c6b8677615e GIT binary patch literal 14534 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 literal 0 HcmV?d00001 diff --git a/image/step2.png b/image/step2.png new file mode 100644 index 0000000000000000000000000000000000000000..b781500a77a636e4eeeb90ac19b1dd8a94d1695b GIT binary patch literal 35311 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®Rb9 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 literal 0 HcmV?d00001 diff --git a/src/main/java/org/inurl/jenkins/plugin/OSSPublisher.java b/src/main/java/org/inurl/jenkins/plugin/OSSPublisher.java index 9045e7e..cefaceb 100644 --- a/src/main/java/org/inurl/jenkins/plugin/OSSPublisher.java +++ b/src/main/java/org/inurl/jenkins/plugin/OSSPublisher.java @@ -12,7 +12,9 @@ import hudson.tasks.BuildStepMonitor; import hudson.tasks.Publisher; import hudson.util.FormValidation; import jenkins.tasks.SimpleBuildStep; +import jnr.ffi.annotations.In; import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang.math.NumberUtils; import org.kohsuke.stapler.DataBoundConstructor; import org.kohsuke.stapler.QueryParameter; @@ -36,6 +38,8 @@ public class OSSPublisher extends Publisher implements SimpleBuildStep { private final String remotePath; + private final String maxRetries; + public String getEndpoint() { return endpoint; @@ -61,14 +65,19 @@ public class OSSPublisher extends Publisher implements SimpleBuildStep { return remotePath; } + public int getMaxRetries() { + return StringUtils.isEmpty(maxRetries) ? 3 : Integer.parseInt(maxRetries); + } + @DataBoundConstructor - public OSSPublisher(String endpoint, String accessKeyId, String accessKeySecret, String bucketName, String localPath, String remotePath) { + public OSSPublisher(String endpoint, String accessKeyId, String accessKeySecret, String bucketName, String localPath, String remotePath, String maxRetries) { this.endpoint = endpoint; this.accessKeyId = accessKeyId; this.accessKeySecret = accessKeySecret; this.bucketName = bucketName; this.localPath = localPath; this.remotePath = remotePath; + this.maxRetries = maxRetries; } @Override @@ -82,15 +91,17 @@ public class OSSPublisher extends Publisher implements SimpleBuildStep { OSSClient client = new OSSClient(endpoint, accessKeyId, accessKeySecret); String local = localPath.substring(1); String remote = remotePath.substring(1); - logger.println("workspace => " + workspace); FilePath p = new FilePath(workspace, local); if (p.isDirectory()) { logger.println("upload dir => " + p); upload(client, logger, remote, p, true); + logger.println("upload dir success"); } else { logger.println("upload file => " + p); uploadFile(client, logger, remote, p); + logger.println("upload file success"); } + } private void upload(OSSClient client, PrintStream logger, String base, FilePath path, boolean root) throws InterruptedException, IOException { @@ -104,6 +115,23 @@ public class OSSPublisher extends Publisher implements SimpleBuildStep { } private void uploadFile(OSSClient client, PrintStream logger, String key, FilePath path) throws InterruptedException, IOException { + int maxRetries = getMaxRetries(); + int retries = 0; + do { + if (retries > 0) { + logger.println("upload retrying (" + retries + "/" + maxRetries +")"); + } + try { + uploadFile0(client, logger, key, path); + return; + } catch (Exception e) { + e.printStackTrace(logger); + } + } while ((++retries) <= maxRetries); + throw new RuntimeException("upload fail, more than the max of retries"); + } + + private void uploadFile0(OSSClient client, PrintStream logger, String key, FilePath path) throws InterruptedException, IOException { String realKey = key; if (realKey.startsWith("/")) { realKey = realKey.substring(1); @@ -118,6 +146,15 @@ public class OSSPublisher extends Publisher implements SimpleBuildStep { @Extension public static final class DescriptorImpl extends BuildStepDescriptor { + public FormValidation doCheckMaxRetries(@QueryParameter String value) { + try { + Integer.parseInt(value); + } catch (Exception e) { + return FormValidation.error(Messages.OSSPublish_MaxRetiesMustBeNumbers()); + } + return FormValidation.ok(); + } + public FormValidation doCheckEndpoint(@QueryParameter(required = true) String value) { return checkValue(value, Messages.OSSPublish_MissingEndpoint()); } diff --git a/src/main/resources/org/inurl/jenkins/plugin/Messages.properties b/src/main/resources/org/inurl/jenkins/plugin/Messages.properties index 0fa2fe0..09d0f31 100644 --- a/src/main/resources/org/inurl/jenkins/plugin/Messages.properties +++ b/src/main/resources/org/inurl/jenkins/plugin/Messages.properties @@ -5,4 +5,5 @@ OSSPublish.MissingAccessKeyId=Please set AccessKeyId OSSPublish.MissingAccessKeySecret=Please set AccessKeySecret OSSPublish.MissingBucketName=Please set BucketName OSSPublish.MissingLocalPath=Please set LocalPath -OSSPublish.MissingRemotePath=Please set RemotePath \ No newline at end of file +OSSPublish.MissingRemotePath=Please set RemotePath +OSSPublish.MaxRetiesMustBeNumbers=Must be number \ No newline at end of file diff --git a/src/main/resources/org/inurl/jenkins/plugin/Messages_zh.properties b/src/main/resources/org/inurl/jenkins/plugin/Messages_zh.properties index abb1222..b5df8f6 100644 --- a/src/main/resources/org/inurl/jenkins/plugin/Messages_zh.properties +++ b/src/main/resources/org/inurl/jenkins/plugin/Messages_zh.properties @@ -5,4 +5,5 @@ OSSPublish.MissingAccessKeyId=\u8bf7\u8bbe\u7f6eAccessKeyId OSSPublish.MissingAccessKeySecret=\u8bf7\u8bbe\u7f6eAccessKeySecret OSSPublish.MissingBucketName=\u8bf7\u8bbe\u7f6eBucketName OSSPublish.MissingLocalPath=\u8bf7\u8bbe\u7f6e\u672c\u5730\u8def\u5f84 -OSSPublish.MissingRemotePath=\u8bf7\u8bbe\u7f6e\u8fdc\u7a0b\u8def\u5f84 \ No newline at end of file +OSSPublish.MissingRemotePath=\u8bf7\u8bbe\u7f6e\u8fdc\u7a0b\u8def\u5f84 +OSSPublish.MaxRetiesMustBeNumbers=\u6700\u5927\u91cd\u8bd5\u6b21\u6570\u5fc5\u987b\u4e3a\u6570\u5b57 \ No newline at end of file diff --git a/src/main/resources/org/inurl/jenkins/plugin/OSSPublisher/config.jelly b/src/main/resources/org/inurl/jenkins/plugin/OSSPublisher/config.jelly index c1cd62c..b439156 100644 --- a/src/main/resources/org/inurl/jenkins/plugin/OSSPublisher/config.jelly +++ b/src/main/resources/org/inurl/jenkins/plugin/OSSPublisher/config.jelly @@ -19,9 +19,8 @@ - - + + diff --git a/src/main/resources/org/inurl/jenkins/plugin/OSSPublisher/config.properties b/src/main/resources/org/inurl/jenkins/plugin/OSSPublisher/config.properties index f4865b9..13ce9cd 100644 --- a/src/main/resources/org/inurl/jenkins/plugin/OSSPublisher/config.properties +++ b/src/main/resources/org/inurl/jenkins/plugin/OSSPublisher/config.properties @@ -3,4 +3,6 @@ AccessKeyId=AccessKeyId AccessKeySecret=AccessKeySecret BucketName=BucketName LocalPath=Local Path -RemotePath=Remote Path \ No newline at end of file +RemotePath=Remote Path + +MaxRetries=max retries \ No newline at end of file diff --git a/src/main/resources/org/inurl/jenkins/plugin/OSSPublisher/config_zh.properties b/src/main/resources/org/inurl/jenkins/plugin/OSSPublisher/config_zh.properties index 598951e..4e83625 100644 --- a/src/main/resources/org/inurl/jenkins/plugin/OSSPublisher/config_zh.properties +++ b/src/main/resources/org/inurl/jenkins/plugin/OSSPublisher/config_zh.properties @@ -3,4 +3,6 @@ AccessKeyId=AccessKeyId AccessKeySecret=AccessKeySecret BucketName=BucketName LocalPath=\u672c\u5730\u8def\u5f84 -RemotePath=\u8fdc\u7a0b\u8def\u5f84 \ No newline at end of file +RemotePath=\u8fdc\u7a0b\u8def\u5f84 + +MaxRetries=\u6700\u5927\u91cd\u8bd5\u6b21\u6570 \ No newline at end of file diff --git a/src/main/resources/org/inurl/jenkins/plugin/OSSPublisher/help-accessKeyId_zh.html b/src/main/resources/org/inurl/jenkins/plugin/OSSPublisher/help-accessKeyId_zh.html new file mode 100644 index 0000000..56b3890 --- /dev/null +++ b/src/main/resources/org/inurl/jenkins/plugin/OSSPublisher/help-accessKeyId_zh.html @@ -0,0 +1,4 @@ +
+ 阿里云 AccessKey
+ 去配置 +
diff --git a/src/main/resources/org/inurl/jenkins/plugin/OSSPublisher/help-accessKeySecret_zh.html b/src/main/resources/org/inurl/jenkins/plugin/OSSPublisher/help-accessKeySecret_zh.html new file mode 100644 index 0000000..a6b013f --- /dev/null +++ b/src/main/resources/org/inurl/jenkins/plugin/OSSPublisher/help-accessKeySecret_zh.html @@ -0,0 +1,4 @@ +
+ 阿里云 AccessKeySecret
+ 去配置 +
diff --git a/src/main/resources/org/inurl/jenkins/plugin/OSSPublisher/help-bucketName_zh.html b/src/main/resources/org/inurl/jenkins/plugin/OSSPublisher/help-bucketName_zh.html new file mode 100644 index 0000000..7e88780 --- /dev/null +++ b/src/main/resources/org/inurl/jenkins/plugin/OSSPublisher/help-bucketName_zh.html @@ -0,0 +1,4 @@ +
+ 阿里云 OSS BucketName
+ 去配置 +
diff --git a/src/main/resources/org/inurl/jenkins/plugin/OSSPublisher/help-endpoint_zh.html b/src/main/resources/org/inurl/jenkins/plugin/OSSPublisher/help-endpoint_zh.html new file mode 100644 index 0000000..94bd0bf --- /dev/null +++ b/src/main/resources/org/inurl/jenkins/plugin/OSSPublisher/help-endpoint_zh.html @@ -0,0 +1,4 @@ +
+ 阿里云 OSS Endpoint
+ 去配置 +
diff --git a/src/main/resources/org/inurl/jenkins/plugin/OSSPublisher/help-localPath_zh.html b/src/main/resources/org/inurl/jenkins/plugin/OSSPublisher/help-localPath_zh.html new file mode 100644 index 0000000..974f4d0 --- /dev/null +++ b/src/main/resources/org/inurl/jenkins/plugin/OSSPublisher/help-localPath_zh.html @@ -0,0 +1,3 @@ +
+ 本地路径,必须以`/`开头 +
\ No newline at end of file diff --git a/src/main/resources/org/inurl/jenkins/plugin/OSSPublisher/help-remotePath_zh.html b/src/main/resources/org/inurl/jenkins/plugin/OSSPublisher/help-remotePath_zh.html new file mode 100644 index 0000000..f307115 --- /dev/null +++ b/src/main/resources/org/inurl/jenkins/plugin/OSSPublisher/help-remotePath_zh.html @@ -0,0 +1,3 @@ +
+ 远程路径,必须以`/`开头 +
\ No newline at end of file diff --git a/src/test/java/org/inurl/jenkins/plugin/OSSPublisherTest.java b/src/test/java/org/inurl/jenkins/plugin/OSSPublisherTest.java new file mode 100644 index 0000000..bed631f --- /dev/null +++ b/src/test/java/org/inurl/jenkins/plugin/OSSPublisherTest.java @@ -0,0 +1,90 @@ +package org.inurl.jenkins.plugin; + +import com.aliyun.oss.OSSClient; +import hudson.model.FreeStyleBuild; +import hudson.model.FreeStyleProject; +import hudson.tasks.Shell; +import org.junit.Rule; +import org.junit.Test; +import org.jvnet.hudson.test.JenkinsRule; + +import static org.junit.Assert.assertTrue; + +public class OSSPublisherTest { + + @Rule + public JenkinsRule jenkins = new JenkinsRule(); + + private final String name = "Test"; + + private final String endpoint = System.getenv("OSS_ENDPOINT"); + private final String accessKeyId = System.getenv("OSS_ACCESS_KEY_ID"); + private final String accessKeySecret = System.getenv("OSS_ACCESS_KEY_SECRET"); + private final String bucketName = System.getenv("OSS_BUCKET_NAME"); + private final String maxRetries = "10"; + + public static void main(String[] args) { + System.out.println(System.getenv("os").contains("Windows")); + } + + @Test + public void testOSS() { + OSSClient client = new OSSClient(endpoint, accessKeyId, accessKeySecret); + client.getBucketInfo(bucketName); + assertTrue(true); + } + + @Test + public void testConfigRoundtrip() throws Exception { + FreeStyleProject project = jenkins.createFreeStyleProject(name); + String localPath = "/"; + String remotePath = "/"; + project.getPublishersList().add(new OSSPublisher(endpoint, accessKeyId, accessKeySecret, bucketName, localPath, remotePath, maxRetries)); + project = jenkins.configRoundtrip(project); + jenkins.assertEqualDataBoundBeans( + new OSSPublisher(endpoint, accessKeyId, accessKeySecret, bucketName, localPath, remotePath, maxRetries), + project.getPublishersList().get(0)); + } + + + @Test + public void testBuildDir() throws Exception { + FreeStyleProject project = jenkins.createFreeStyleProject(name); + Shell shell = createFileShell(); + project.getBuildersList().add(shell); + project.getPublishersList().add(new OSSPublisher(endpoint, accessKeyId, accessKeySecret, bucketName, "/", "/", maxRetries)); + FreeStyleBuild build = jenkins.buildAndAssertSuccess(project); + jenkins.assertLogContains("upload dir success", build); + } + + @Test + public void testBuildFile() throws Exception { + FreeStyleProject project = jenkins.createFreeStyleProject(name); + project.getPublishersList().add(new OSSPublisher(endpoint, accessKeyId, accessKeySecret, bucketName, "/n/3", "/remoteFile", maxRetries)); + FreeStyleBuild build = jenkins.buildAndAssertSuccess(project); + jenkins.assertLogContains("upload file success", build); + } + + private static Shell createFileShell() { + //language=Bash + String del = + "if [[ -e \"a\" ]];then rm -f a fi\n" + + "if [[ -e \"b\" ]];then rm -f b fi\n" + + "if [[ -e \"c\" ]];then rm -f c fi\n" + + "if [[ -e \"n/1\" ]];then rm -f n/1 fi\n" + + "if [[ -e \"n/2\" ]];then rm -f n/2 fi\n" + + "if [[ -e \"n/3\" ]];then rm -f n/3 fi\n"; + //language=Bash + String create = + "echo a > a\n" + + "echo b > b\n" + + "echo c > c\n" + + "mkdir n\n" + + "echo 1 > n/1\n" + + "echo 2 > n/2\n" + + "echo 3 > n/3"; + return new Shell(del + "\n" + create); + } + + +} \ No newline at end of file -- GitLab