Top / Java / Jenkins / プラグイン開発のTIPS集

config.jellyでデフォルト値を設定する。

Basic guide to Jelly usage in Jenkins - Jenkins - Jenkins Wiki に説明がありましたが、

 <f:entry title="${%Port}" field="port">
   <f:textbox default="80" />
 </f:entry>

このように直接値を指定したり、

 <f:entry title="メール送信先" field="addresses" description="チェック結果をメール送信する宛先をカンマ区切りで指定してください。">
   <f:textarea default="${descriptor.defaultSamples()}"/>
 </f:entry>

このようにdescriptor#defaultSamples() メソッドを呼び出すとしてそのビルダーのDescriptorクラスの実装で

public String defaultSamples() {
    StringBuffer buf = new StringBuffer();
    buf.append("hoge@example.com");
    buf.append("\n");
    buf.append("fuga@example.com");
    buf.append("\n");
    return new String(buf);
}

などと記述すればOKです。

スクリプトコンソールをうまく使う。

たとえば自分が開発したビルダーをセットしているプロジェクトを探してくるような処理を書きたいとして、コードを書きながらちょこちょこ稼動確認をしたいなんて事があります。

こんな時はスクリプトコンソールを使うことで、プラグイン内で利用するコードの確認を素早く行うことができます。たとえばこんな感じ。

import nu.mine.kino.jenkins.plugins.projectmanagement.utils.PMUtils;
import nu.mine.kino.jenkins.plugins.projectmanagement.EVMToolsBuilder;
import hudson.util.DescribableList;

List items = Jenkins.getInstance().getItems();
for (TopLevelItem item : items) {
    if (item instanceof FreeStyleProject) {
        DescribableList buildersList = ((FreeStyleProject) item)
                .getBuildersList();
        EVMToolsBuilder builder = buildersList      // このビルダが自分で書いたプラグインだとして。。
                .get(EVMToolsBuilder.class);
        if (builder != null) {
          println item.name
        }
    }
}

実際はGroovyなのですが、どーしてもJavaになってしまうのはご愛敬として。。 こんな感じでコードを書いていくことが可能です。

プラグイン開発で使用する、Jenkins起動時のMAVEN_OPTS

export MAVEN_OPTS="-Xdebug -Xrunjdwp:transport=dt_socket,server=y,address=8000,suspend=n -Xmx1024m -XX:MaxPermSize=128m"

Windowsだと

set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,address=8000,suspend=n -Xmx1024m -XX:MaxPermSize=128m

こうかな?

プラグイン開発で出てくる、ビルド関連のパス(FilePath?/File)の結果

System.out.println(build.getModuleRoot()); //FilePath ワークスペースのルート?リモートの場合もある。。
System.out.println(build.getRootDir()); //File このビルド自体のルート?
System.out.println(build.getWorkspace()); //FilePath
System.out.println(build.getArtifactsDir()); ←@Deprecated //File

の結果ですが、ビルドはローカル(マスター)で実行されるかスレーブで実行されるか分からないので、実行される環境によって下記のように結果が異なります。

  • ローカル(マスター)の結果(Windows) TESTというジョブを走らせた場合。
    D:\workspace_palette\project-management\work\jobs\TEST\workspace
    D:\workspace_palette\project-management\.\work\jobs\TEST\builds\2014-10-17_12-46-07
    D:\workspace_palette\project-management\work\jobs\TEST\workspace
    D:\workspace_palette\project-management\.\work\jobs\TEST\builds\2014-10-17_12-46-07\archive
  • スレーブの結果(Linux) TESTというジョブを走らせた場合。スレーブのトップディレクトリは
     /opt/jenkins/
    に設定してあります。結果は以下
    /opt/jenkins/workspace/TEST
    D:\workspace_palette\project-management\.\work\jobs\TEST\builds\2014-10-17_12-50-37
    /opt/jenkins/workspace/TEST
    D:\workspace_palette\project-management\.\work\jobs\TEST\builds\2014-10-17_12-50-37\archive

Jenkinsのソース検索

GitHub にアクセスして 「検索文字列」 repo:jenkinsci/jenkins [検索文字]といれて検索を行えばOK

ビルダーが追加したアクションのアイコンを指定する。

XXBuilderクラスないで

action = new XXAction(build);
build.addAction(action);

などとしてアクションを追加すると、そのビルド画面の左メニューにアイコンが表示されます。

menu.png

このアイコンを独自のモノにするには、

@Override
public String getIconFileName() {
  return "/plugin/project-management/images/24x24/user_suit.png";  <- project-management はプラグイン名。
}

などとしてファイル名を絶対パスで指定します。 この場所はプロジェクト上は

icon.png

あたりに解釈されるので、ココにファイルを配置してビルドすればOKです。

Jenkins users - Plugin image location

アクションの画面でのリンク

index.jelly 内のリンク設定:

<a href="documents/hogehoge.tsv">hogehoge.tsv</a>

だった場合、クリックするとアクションクラスの

public void doDynamic(StaplerRequest req, StaplerResponse res)
        throws IOException, ServletException {
}

メソッドがコールされます。引数は通常のサーブレットのReq/Resのインタフェースになっています。 なので下記のようにResponseにデータを流し込んで

String filePath = req.getRestOfPath();  filePathは documents/hogehoge.tsv
File file = new File(owner.getRootDir(), filePath);  ← rootDirはビルドのディレクトリ
FileInputStream in = null;
ServletOutputStream out = res.getOutputStream();
try {
    in = new FileInputStream(file);
    int i;
    while ((i = in.read()) != -1) {
        out.write(i);
    }
} finally {
    out.close();
    in.close();
}

ビルドしたディレクトリにあるファイルを引っぱってきて直接表示したり、

res.sendRedirect2(req.getContextPath() + req.getRestOfPath()); /[contextpath]/documents/hogehoge.tsv

などとして指定した画面へリダイレクトしたりすることができます。

ビルドのトリガーとなったコミット情報にアクセスする。

public boolean perform(AbstractBuild build, Launcher launcher, BuildListener listener) 

ないで、以下のようにアクセスすることができます。

if (build.getChangeSet() instanceof SubversionChangeLogSet) {
    SubversionChangeLogSet changeSet = (SubversionChangeLogSet) build
            .getChangeSet();
    List<LogEntry> logs = changeSet.getLogs();  // 一回のコミットのログ
    for (LogEntry logEntry : logs) {
        List<Path> paths = logEntry.getPaths();     // 一回のコミットで複数のコミットファイルがある
        for (Path path : paths) {
            listener.getLogger().printf("[%s][%s][%s][%s]\n",
                    path.getKind(), path.getValue(), path.getPath(),
                    path.getEditType().getName());
        }
    }
}

実行結果:

A         test.dat
At revision 347
[unknown][/trunk/test/test.dat][/trunk/test/test.dat][add]

ビルドのトリガーとなったコミット情報*1へアクセスすることができました。

あ pom.xml に

   <dependency>
     <groupId>org.jenkins-ci.plugins</groupId>
     <artifactId>subversion</artifactId>
     <version>1.45</version>
   </dependency>

の追加が必要です。。

Jenkinsの設定を使ってE-Mailを送信する。

まずこんな感じにメールを送信するメソッドを定義します。

   public static void sendMail(String[] addresses, String subject,
           String message) throws UnsupportedEncodingException,
           MessagingException {

       MimeMessage mimeMessage = new MimeMessage(Mailer.descriptor()
               .createSession());

       InternetAddress[] to = new InternetAddress[addresses.length];
       String adminAddress = JenkinsLocationConfiguration.get()
               .getAdminAddress();
       for (int i = 0; i < addresses.length; i++) {
           to[i] = new InternetAddress(addresses[i], true);
       }
       mimeMessage.setSender(new InternetAddress(adminAddress));
       mimeMessage.setRecipients(Message.RecipientType.TO, to);
       mimeMessage.setSubject(subject, "ISO-2022-JP");
       mimeMessage.setText(message, "ISO-2022-JP");
       Transport.send(mimeMessage);
   }

基本的にはコレだけでJenkinsにあらかじめ設定されているメール送信設定を用いてメールを送ることができます。

あとは

public boolean perform(AbstractBuild build, Launcher launcher, BuildListener listener) 

内で、以下のようにメール送信ができます。

 listener.getLogger().printf("宛先: %s \n", addresses);
 listener.getLogger().printf("題名: %s \n", subject);
 listener.getLogger().printf("メッセージ: %s \n", message);

 String[] addressArray = StringUtils.stripAll(StringUtils.split(
         addresses, ',' ));
 try {
     sendMail(addressArray, subject, message);
 } catch (UnsupportedEncodingException e) {
     e.printStackTrace();
 } catch (MessagingException e) {
     e.printStackTrace();
 }

あ、pom.xml に

<dependency>
  <groupId>org.jenkins-ci.plugins</groupId>
  <artifactId>mailer</artifactId>
  <version>1.5</version>
</dependency>

の追加が必要です。。


この記事は

選択肢 投票
おもしろかった 0  
そうでもない 0  
  • こうみると、ワークスペースはスレーブにも存在するが、ビルドのディレクトリはマスターにしか存在しないってことになりますね。。スレーブで処理されてワークスペースになんかを出力した場合、それはスレーブに出力されるので、スレーブのワークスペースからビルドディレクトリにコピーする必要がありそうです。 -- きの? 2014-11-27 (木) 16:52:44

Top / Java / Jenkins / プラグイン開発のTIPS集

現在のアクセス:2377


*1 というか、そのビルドでUpdateされたコミット情報

添付ファイル: fileicon.png 357件 [詳細] filemenu.png 350件 [詳細]

トップ   編集 凍結 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS
Last-modified: 2015-10-13 (火) 09:45:13 (1491d)