Commit cd69685e authored by raylax's avatar raylax

update

parent 70b61a25
# 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
<mirror>
<id>repo.jenkins-ci.org</id>
<url>https://repo.jenkins-ci.org/public/</url>
<mirrorOf>m.g.o-public</mirrorOf>
</mirror>
```
`pluginGroups`节点中增加
```xml
<pluginGroup>org.jenkins-ci.tools</pluginGroup>
```
`profiles`节点中增加
```xml
<profile>
<id>jenkins</id>
<activation>
<activeByDefault>true</activeByDefault> <!-- change this to false, if you don't like to have it on per default -->
</activation>
<repositories>
<repository>
<id>repo.jenkins-ci.org</id>
<url>https://repo.jenkins-ci.org/public/</url>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>repo.jenkins-ci.org</id>
<url>https://repo.jenkins-ci.org/public/</url>
</pluginRepository>
</pluginRepositories>
</profile>
```
2. 打包
```bash
mvn package
```
3. 运行
```bash
mvn hpi:run
```
\ No newline at end of file
...@@ -12,7 +12,9 @@ import hudson.tasks.BuildStepMonitor; ...@@ -12,7 +12,9 @@ import hudson.tasks.BuildStepMonitor;
import hudson.tasks.Publisher; import hudson.tasks.Publisher;
import hudson.util.FormValidation; import hudson.util.FormValidation;
import jenkins.tasks.SimpleBuildStep; import jenkins.tasks.SimpleBuildStep;
import jnr.ffi.annotations.In;
import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.math.NumberUtils;
import org.kohsuke.stapler.DataBoundConstructor; import org.kohsuke.stapler.DataBoundConstructor;
import org.kohsuke.stapler.QueryParameter; import org.kohsuke.stapler.QueryParameter;
...@@ -36,6 +38,8 @@ public class OSSPublisher extends Publisher implements SimpleBuildStep { ...@@ -36,6 +38,8 @@ public class OSSPublisher extends Publisher implements SimpleBuildStep {
private final String remotePath; private final String remotePath;
private final String maxRetries;
public String getEndpoint() { public String getEndpoint() {
return endpoint; return endpoint;
...@@ -61,14 +65,19 @@ public class OSSPublisher extends Publisher implements SimpleBuildStep { ...@@ -61,14 +65,19 @@ public class OSSPublisher extends Publisher implements SimpleBuildStep {
return remotePath; return remotePath;
} }
public int getMaxRetries() {
return StringUtils.isEmpty(maxRetries) ? 3 : Integer.parseInt(maxRetries);
}
@DataBoundConstructor @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.endpoint = endpoint;
this.accessKeyId = accessKeyId; this.accessKeyId = accessKeyId;
this.accessKeySecret = accessKeySecret; this.accessKeySecret = accessKeySecret;
this.bucketName = bucketName; this.bucketName = bucketName;
this.localPath = localPath; this.localPath = localPath;
this.remotePath = remotePath; this.remotePath = remotePath;
this.maxRetries = maxRetries;
} }
@Override @Override
...@@ -82,15 +91,17 @@ public class OSSPublisher extends Publisher implements SimpleBuildStep { ...@@ -82,15 +91,17 @@ public class OSSPublisher extends Publisher implements SimpleBuildStep {
OSSClient client = new OSSClient(endpoint, accessKeyId, accessKeySecret); OSSClient client = new OSSClient(endpoint, accessKeyId, accessKeySecret);
String local = localPath.substring(1); String local = localPath.substring(1);
String remote = remotePath.substring(1); String remote = remotePath.substring(1);
logger.println("workspace => " + workspace);
FilePath p = new FilePath(workspace, local); FilePath p = new FilePath(workspace, local);
if (p.isDirectory()) { if (p.isDirectory()) {
logger.println("upload dir => " + p); logger.println("upload dir => " + p);
upload(client, logger, remote, p, true); upload(client, logger, remote, p, true);
logger.println("upload dir success");
} else { } else {
logger.println("upload file => " + p); logger.println("upload file => " + p);
uploadFile(client, logger, remote, 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 { 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 { ...@@ -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 { 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; String realKey = key;
if (realKey.startsWith("/")) { if (realKey.startsWith("/")) {
realKey = realKey.substring(1); realKey = realKey.substring(1);
...@@ -118,6 +146,15 @@ public class OSSPublisher extends Publisher implements SimpleBuildStep { ...@@ -118,6 +146,15 @@ public class OSSPublisher extends Publisher implements SimpleBuildStep {
@Extension @Extension
public static final class DescriptorImpl extends BuildStepDescriptor<Publisher> { public static final class DescriptorImpl extends BuildStepDescriptor<Publisher> {
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) { public FormValidation doCheckEndpoint(@QueryParameter(required = true) String value) {
return checkValue(value, Messages.OSSPublish_MissingEndpoint()); return checkValue(value, Messages.OSSPublish_MissingEndpoint());
} }
......
...@@ -5,4 +5,5 @@ OSSPublish.MissingAccessKeyId=Please set AccessKeyId ...@@ -5,4 +5,5 @@ OSSPublish.MissingAccessKeyId=Please set AccessKeyId
OSSPublish.MissingAccessKeySecret=Please set AccessKeySecret OSSPublish.MissingAccessKeySecret=Please set AccessKeySecret
OSSPublish.MissingBucketName=Please set BucketName OSSPublish.MissingBucketName=Please set BucketName
OSSPublish.MissingLocalPath=Please set LocalPath OSSPublish.MissingLocalPath=Please set LocalPath
OSSPublish.MissingRemotePath=Please set RemotePath OSSPublish.MissingRemotePath=Please set RemotePath
\ No newline at end of file OSSPublish.MaxRetiesMustBeNumbers=Must be number
\ No newline at end of file
...@@ -5,4 +5,5 @@ OSSPublish.MissingAccessKeyId=\u8bf7\u8bbe\u7f6eAccessKeyId ...@@ -5,4 +5,5 @@ OSSPublish.MissingAccessKeyId=\u8bf7\u8bbe\u7f6eAccessKeyId
OSSPublish.MissingAccessKeySecret=\u8bf7\u8bbe\u7f6eAccessKeySecret OSSPublish.MissingAccessKeySecret=\u8bf7\u8bbe\u7f6eAccessKeySecret
OSSPublish.MissingBucketName=\u8bf7\u8bbe\u7f6eBucketName OSSPublish.MissingBucketName=\u8bf7\u8bbe\u7f6eBucketName
OSSPublish.MissingLocalPath=\u8bf7\u8bbe\u7f6e\u672c\u5730\u8def\u5f84 OSSPublish.MissingLocalPath=\u8bf7\u8bbe\u7f6e\u672c\u5730\u8def\u5f84
OSSPublish.MissingRemotePath=\u8bf7\u8bbe\u7f6e\u8fdc\u7a0b\u8def\u5f84 OSSPublish.MissingRemotePath=\u8bf7\u8bbe\u7f6e\u8fdc\u7a0b\u8def\u5f84
\ No newline at end of file OSSPublish.MaxRetiesMustBeNumbers=\u6700\u5927\u91cd\u8bd5\u6b21\u6570\u5fc5\u987b\u4e3a\u6570\u5b57
\ No newline at end of file
...@@ -19,9 +19,8 @@ ...@@ -19,9 +19,8 @@
<f:textbox /> <f:textbox />
</f:entry> </f:entry>
<f:advanced> <f:advanced>
<f:entry title="${%French}" field="useFrench" <f:entry title="${%MaxRetries}" field="maxRetries">
description="${%FrenchDescr}"> <f:textbox />
<f:checkbox />
</f:entry> </f:entry>
</f:advanced> </f:advanced>
</j:jelly> </j:jelly>
...@@ -3,4 +3,6 @@ AccessKeyId=AccessKeyId ...@@ -3,4 +3,6 @@ AccessKeyId=AccessKeyId
AccessKeySecret=AccessKeySecret AccessKeySecret=AccessKeySecret
BucketName=BucketName BucketName=BucketName
LocalPath=Local Path LocalPath=Local Path
RemotePath=Remote Path RemotePath=Remote Path
\ No newline at end of file
MaxRetries=max retries
\ No newline at end of file
...@@ -3,4 +3,6 @@ AccessKeyId=AccessKeyId ...@@ -3,4 +3,6 @@ AccessKeyId=AccessKeyId
AccessKeySecret=AccessKeySecret AccessKeySecret=AccessKeySecret
BucketName=BucketName BucketName=BucketName
LocalPath=\u672c\u5730\u8def\u5f84 LocalPath=\u672c\u5730\u8def\u5f84
RemotePath=\u8fdc\u7a0b\u8def\u5f84 RemotePath=\u8fdc\u7a0b\u8def\u5f84
\ No newline at end of file
MaxRetries=\u6700\u5927\u91cd\u8bd5\u6b21\u6570
\ No newline at end of file
<div>
阿里云 AccessKey<br/>
<a target="_blank" href="https://usercenter.console.aliyun.com/#/manage/ak">去配置</a>
</div>
<div>
阿里云 AccessKeySecret<br/>
<a target="_blank" href="https://usercenter.console.aliyun.com/#/manage/ak">去配置</a>
</div>
<div>
阿里云 OSS BucketName<br/>
<a target="_blank" href="https://oss.console.aliyun.com">去配置</a>
</div>
<div>
阿里云 OSS Endpoint<br/>
<a target="_blank" href="https://oss.console.aliyun.com">去配置</a>
</div>
<div>
本地路径,必须以`/`开头
</div>
\ No newline at end of file
<div>
远程路径,必须以`/`开头
</div>
\ No newline at end of file
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
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