Using actions
As a reminder, to be able to use an action, you have to know its owner, name and version, e.g. actions/checkout@v3
.
The library comes bundled with some popular actions, but you can consume any action you want. Read on to learn about
your possibilities.
Built-in actions
Take a look here: Supported actions.
These are actions ready to use, grouped by owners. For actions/checkout@v3
, there's CheckoutV3
accepting all inputs defined in its metadata file, along with some basic typing. You may notice that for each major
version, a separate class exists. It's because it's assumed Semantic Versioning is used to
version the actions, as recommended by GitHub.
Each new major version means a breaking change, and it usually means that the Kotlin binding for the action needs a
breaking change as well.
Requirements for adding a new action
An action is eligible to be added to this library (i.e. have its Kotlin binding generated and maintained by the library) if the following conditions are fulfilled:
- follows Semantic Versioning, with exceptions for pre-releases (like
v0.2
) - provides major version tags, as described here.
An example valid tag is
v2
that points to the newest release with major version number 2. Example invalid tags arev2.1.0
,latest
ormain
Nice to have:
- provides typings using github-actions-typing
User-defined actions
If your action is not bundled with the library, you are in a hurry and contributing to the library now is not an option, you have two ways to proceed.
Typed binding
When to use this approach
It lets you create an action binding in a similar manner that is provided by the built-in action bindings in this
library, i.e. a class that takes some constructor arguments with types of your choice, and maps them to strings
inside toYamlArguments
. Use it to have better type-safety when using the binding.
Repository based actions
In case of a repository based action which most GitHub actions are, inherit from RegularAction
and in case of actions without explicit outputs, use the Actions.Outputs
class as type argument:
class MyCoolActionV3(
private val someArgument: String,
) : RegularAction<Action.Outputs>("acmecorp", "cool-action", "v3") {
override fun toYamlArguments() =
linkedMapOf(
"some-argument" to someArgument,
)
override fun buildOutputObject(stepId: String) = Outputs(stepId)
}
or, in case of actions with explicit outputs, create a subclass of Action.Outputs
for the type argument:
class MyCoolActionV3(
private val someArgument: String,
) : RegularAction<MyCoolActionV3.Outputs>("acmecorp", "cool-action", "v3") {
override fun toYamlArguments() =
linkedMapOf(
"some-argument" to someArgument,
)
override fun buildOutputObject(stepId: String) = Outputs(stepId)
class Outputs(stepId: String) : Action.Outputs(stepId) {
public val coolOutput: String = "steps.$stepId.outputs.coolOutput"
}
}
Once you've got your action, it's now as simple as using it like this:
uses(
name = "FooBar",
action = MyCoolActionV3(someArgument = "foobar"),
)
Local actions
In case of a local action you have available in your repository or cloned from a private repository,
inherit from LocalAction
instead:
class MyCoolLocalActionV3(
private val someArgument: String,
) : LocalAction<Action.Outputs>("./.github/actions/cool-action") {
override fun toYamlArguments() =
linkedMapOf(
"some-argument" to someArgument,
)
override fun buildOutputObject(stepId: String) = Outputs(stepId)
}
Published Docker actions
In case of a published Docker action, inherit from DockerAction
instead:
class MyCoolDockerActionV3(
private val someArgument: String,
) : DockerAction<Action.Outputs>("alpine", "latest") {
override fun toYamlArguments() =
linkedMapOf(
"some-argument" to someArgument,
)
override fun buildOutputObject(stepId: String) = Outputs(stepId)
}
Untyped binding
When to use this approach
It omits typing entirely, and both inputs and outputs are referenced using strings. Use it if you don't care about types because you're in the middle of experimenting. It's also more convenient to produce such code by a code generator.
Repository based actions
In case of a repository based action which most GitHub actions are, use a CustomAction
:
val customAction =
CustomAction(
actionOwner = "xu-cheng",
actionName = "latex-action",
actionVersion = "v2",
inputs =
linkedMapOf(
"root_file" to "report.tex",
"compiler" to "latexmk",
),
)
If your custom action has outputs, you can access them, albeit in a type-unsafe manner:
job(id = "test_job", runsOn = RunnerType.UbuntuLatest) {
val customActionStep =
uses(
name = "Some step with output",
action = customAction,
)
// use your outputs:
println(expr(customActionStep.outputs["custom-output"]))
}
Local actions
In case of a local action you have available in your repository or cloned from a private repository,
use a CustomLocalAction
instead:
val customAction =
CustomLocalAction(
actionPath = "./.github/actions/setup-build-env",
)
Published Docker actions
In case of a published Docker action, use a CustomDockerAction
instead:
val customAction =
CustomDockerAction(
actionImage = "alpine",
actionTag = "latest",
)