Creating an Action¶
This guide walks through implementing a GithubAction from scratch.
Step 1: Choose Your Event Type¶
Each action handles a specific GitHub event. Pick the context type that matches your use case:
| Context | Event | Use Case |
|---|---|---|
PushContext |
push |
Validate commits, update badges |
PullRequestContext |
pull_request |
Run checks, post comments |
IssueContext |
issues |
Auto-label, notify |
ReleaseContext |
release |
Deploy, notify |
WorkflowDispatchContext |
workflow_dispatch |
Manual triggers |
ScheduleContext |
schedule |
Cron jobs |
CreateContext |
create |
Branch/tag creation events |
Step 2: Implement GithubAction¶
Create a class that implements GithubAction with your chosen context type:
package com.example
import ir.amirroid.workflowkt.ActionResult
import ir.amirroid.workflowkt.GithubAction
import ir.amirroid.workflowkt.context.PushContext
import ir.amirroid.workflowkt.environment.GithubEnvironment
class ValidateCommitsAction : GithubAction<PushContext> {
override fun run(
context: PushContext,
environment: GithubEnvironment
): ActionResult {
// Your logic here
return ActionResult.Success()
}
}
Step 3: Implement Your Logic¶
Use the typed context and environment to access event data:
override fun run(
context: PushContext,
environment: GithubEnvironment
): ActionResult {
// Access push event data
val branch = context.ref
val commits = context.commits
val sender = context.sender.login
val repo = context.repository.fullName
// Access environment variables
val sha = environment.sha
val token = environment["GITHUB_TOKEN"]
// Validate commits
val invalid = commits.filter { commit ->
!commit.message.startsWith("feat:") &&
!commit.message.startsWith("fix:") &&
!commit.message.startsWith("chore:")
}
return if (invalid.isEmpty()) {
ActionResult.Success()
} else {
ActionResult.Failure("Found ${invalid.size} commits without conventional format")
}
}
Step 4: Return Results¶
Success with Outputs¶
return ActionResult.Success(
mapOf(
"VALIDATED" to "true",
"COMMIT_COUNT" to commits.size.toString()
)
)
Failure with Reason¶
return ActionResult.Failure(
"Commit '${commit.id.take(7)}' has invalid message: '${commit.message}'"
)
Complete Example¶
package com.example
import ir.amirroid.workflowkt.ActionResult
import ir.amirroid.workflowkt.GithubAction
import ir.amirroid.workflowkt.context.IssueContext
import ir.amirroid.workflowkt.environment.GithubEnvironment
class AutoLabelAction : GithubAction<IssueContext> {
override fun run(
context: IssueContext,
environment: GithubEnvironment
): ActionResult {
// Only run on newly opened issues
if (context.action != "opened") {
return ActionResult.Success()
}
val issue = context.issue
val text = "${issue.title} ${issue.body ?: ""}".lowercase()
val labels = mutableListOf<String>()
if (text.contains("bug") || text.contains("error")) {
labels.add("bug")
}
if (text.contains("feature") || text.contains("enhancement")) {
labels.add("enhancement")
}
if (labels.isEmpty()) {
return ActionResult.Success()
}
println("Would add labels to issue #${issue.number}: $labels")
return ActionResult.Success(
mapOf("LABELS" to labels.joinToString(","))
)
}
}
Requirements¶
- Class must have a no-arg constructor (or be a Kotlin
object) - Must implement
GithubAction<C>whereCis a concreteActionContexttype - The
runmethod receives both the typed context and the environment