# workflow-step-api-plugin **Repository Path**: linuxsuren/workflow-step-api-plugin ## Basic Information - **Project Name**: workflow-step-api-plugin - **Description**: No description available - **Primary Language**: Java - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2018-04-28 - **Last Updated**: 2020-12-19 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # Writing Pipeline steps Plugins can implement custom Pipeline steps with specialized behavior by adding a dependency on `workflow-step-api`. Remember to ensure that your baseline Jenkins version is at least as new as that required by the versions of various Pipeline component plugins you are depending on. (The plugin wikis will note these baselines.) ## Creating a basic synchronous step When a Pipeline step does something quick and nonblocking, you can make a “synchronous” step. The Groovy execution waits for it to finish. Extend `Step`. Define mandatory parameters in a `@DataBoundConstructor`. Define optional parameters using `@DataBoundSetter`. (Both need matching getters.) Create a class, conventionally a nested `private static class Execution`, and extend `SynchronousNonBlockingStepExecution` (or `SynchronousStepExecution` for certain trivial steps). Parameterize it with the desired return value of the step (or `Void` if it need not return a value). The `run` method should do the work of the step. You can pass the `Step` object to the `StepExecution` constructor to access its configuration. Use `StepContext.get` to obtain contextual objects you require; commonly required types include `Run`, `TaskListener`, `FilePath`, `EnvVars`, and `Launcher` (these will be enumerated in `StepDescriptor.getRequiredContext`). Extend `StepDescriptor`. Besides a display name, pick a function name which will be used from Groovy scripts. Create a `config.jelly` form with databinding for all the parameters, for use from _Snippet Generator_. You can use the `StepConfigTester` test utility in `workflow-step-api` (`tests` classifier) to verify that all fields are correctly bound. The descriptor can also have the usual methods complementing `config.jelly` for field validation, etc. Note: older versions of Pipeline used Guice for injecting step configuration and contextual objects into the execution. This is still possible, but not recommended. If you must depend on an old version of `workflow-step-api`, *and* you are creating a non-blocking synchronous step, you will be obliged to use `AbstractStepImpl`, `AbstractStepDescriptorImpl`, `AbstractSynchronousNonBlockingStepExecution`, `@Inject`, and `@StepContextParameter`. ## Creating an asynchronous step For the more general case that a Pipeline step might block in network or disk I/O, and might need to survive Jenkins restarts, you can use a more powerful API. This relies on a callback system: the Pipeline engine tells your step when to start, and your step tells Pipeline when it is done. Extend `StepExecution` rather than `SynchronousStepExecution` or `SynchronousNonBlockingStepExecution`. You will be implementing a `start` method. Normally it should do any quick setup work and then return `false`, meaning the step is still running. Later you can call `getContext().onSuccess(returnValue)` (once) to make the step complete normally. Or, `getContext().onFailure(error)` to make the step throw an exception. You can keep `transient` fields for caching purposes; override `onResume` to recreate transient state after a Jenkins restart if you need to. You can also keep non-`transient` fields, assuming they are `Serializable`. Do not forget to declare ```java private static final long serialVersionUID = 1L; ``` You should also implement `stop` to terminate the step. It could simply read ```java getContext().onFailure(cause); ``` but generally it will need to interrupt whatever process you started. ## Creating a block-scoped step Pipeline steps can also take “closures”: a code block which they may run zero or more times, optionally with some added context. Override `takesImplicitBlockArgument` in your descriptor. In `start`, or thereafter, call ```java getContext().newBodyInvoker(). withContext(…something…). withCallback(BodyExecutionCallback.wrap(getContext())). start(); ``` The above returns the same value as the block. The callback may also be a `TailCall` to do some cleanup, or any other `BodyExecutionCallback` to customize handling of the end of the block. You can pass various contextual objects, as per `StepContext.get` above. `stop` is optional. ## Using more APIs You can also add a dependency on `workflow-api` which brings in more Pipeline-specific features. For example you can then receive a `FlowNode` from `StepContext.get` and call `addAction` to customize the _Pipeline Steps_ view.