Jenkins Workflow PluginのDSLを拡張する試み
Jenkins Workflow PluginのDSLを拡張する仕組みを調べたのでメモします.
Workflow basic stepsを参考にする
Workflow Pluginはbasic stepsという基礎的な命令セットと一緒にリリースされています.basic stepsには下記が含まれます.
- ArtifactArchiverStep
- ArtifactArchiverStepExecution
- ArtifactUnarchiverStep
- ArtifactUnarchiverStepExecution
- CatchErrorStep
- CoreStep
- EchoStep
- ErrorStep
- MailStep
- PushdStep
- PwdStep
- ReadFileStep
- RetryStep
- RetryStepExecution
- SleepStep
- TimeoutStep
- TimeoutStepExecution
- ToolStep
- WaitForConditionStep
- WriteFileStep
ここではEchoStepの実装を参考にします.echo
という名前は下記のDescriptorクラスで定義されています.
@Extension public static class DescriptorImpl extends AbstractStepDescriptorImpl { public DescriptorImpl() { super(Execution.class); } @Override public String getFunctionName() { return "echo"; } }
Workflowスクリプトでecho
を実行した場合,コンストラクタが実行されます.echo
の引数はコンストラクタに渡されます.
@DataBoundConstructor public EchoStep(String message) { this.message = message; }
そして,Executionクラスのrun()
メソッドが実行されます.
public static class Execution extends AbstractSynchronousStepExecution<Void> { @Override protected Void run() throws Exception { listener.getLogger().println(step.getMessage()); return null; } }
おおまかな処理の流れが分かったところで,プラグインを実装してみましょう.
プラグインでStepを実装する
Stepの定義をプラグインに書いて,Workflowの動作を確認します.
Jenkinsプラグインの作り方は Plugin tutorial - Jenkins - Jenkins Wiki を参考にします.ここでは,Archetypeで自動生成されたコードを使います.なお,自動生成されたコードはIntelliJ IDEAで読み込めます.
まず,pom.xmlにWorkflow Step APIの依存関係を追加します.
<dependencies> <dependency> <groupId>org.jenkins-ci.plugins.workflow</groupId> <artifactId>workflow-step-api</artifactId> <version>1.2</version> </dependency> <dependency> <groupId>org.jenkins-ci.plugins.workflow</groupId> <artifactId>workflow-step-api</artifactId> <version>1.2</version> <classifier>tests</classifier> <scope>test</scope> </dependency> </dependencies>
次に,EchoStepのコードをそのまま貼り付けて,名前をカスタマイズします.
@Extension public static class DescriptorImpl extends AbstractStepDescriptorImpl { public DescriptorImpl() { super(Execution.class); } @Override public String getFunctionName() { return "something"; } }
コンストラクタはあらゆる引数を受け取れるようにしてみます.
@DataBoundConstructor public EchoStep(Object arg) { this.arg = arg; }
Executionクラスのrun()
メソッドでは,引数をtoString()
したものを出力してみます.
public static class Execution extends AbstractSynchronousStepExecution<Void> { @Override protected Void run() throws Exception { listener.getLogger().println(step.getArg().toString()); return null; } }
コードを書いたら実際に動作させてみましょう.下記のコマンドでプラグインが組み込まれたJenkinsが起動します.
mvn hpi:run
初期状態ではプラグインが足りないため,追加でWorkflow: Aggregateプラグインをインストールします.
新しいWorkflowジョブを作成して実行してみましょう.Workflowスクリプトは下記とします.
something 'D・S・L!!'
ジョブを実行したら引数が表示されると思います.また,somethingの引数をクロージャなどに変えたらクラス名が表示されるはずです.
まとめ
本エントリでは,WorkflowのDSLを拡張する基礎的な方法を説明しました.この仕組みを応用することで,既存のプラグインをWorkflowに対応させたり,新しい語彙をDSLに追加したりすることが可能です.
参考文献: