summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--README.md6
-rw-r--r--cmd/root.go104
-rw-r--r--pkg/model/planner.go15
3 files changed, 94 insertions, 31 deletions
diff --git a/README.md b/README.md
index 823c04b..8fe500e 100644
--- a/README.md
+++ b/README.md
@@ -128,13 +128,17 @@ Download the [latest release](https://github.com/nektos/act/releases/latest) and
# Command structure:
act [<event>] [options]
If no event name passed, will default to "on: push"
+If actions handles only one event it will be used as default instead of "on: push"
-# List the actions for the default event:
+# List all actions for all events:
act -l
# List the actions for a specific event:
act workflow_dispatch -l
+# List the actions for a specific job:
+act -j test -l
+
# Run the default (`push`) event:
act
diff --git a/cmd/root.go b/cmd/root.go
index 646ca99..d56d2bb 100644
--- a/cmd/root.go
+++ b/cmd/root.go
@@ -30,7 +30,7 @@ import (
func Execute(ctx context.Context, version string) {
input := new(Input)
var rootCmd = &cobra.Command{
- Use: "act [event name to run]\nIf no event name passed, will default to \"on: push\"",
+ Use: "act [event name to run] [flags]\n\nIf no event name passed, will default to \"on: push\"\nIf actions handles only one event it will be used as default instead of \"on: push\"",
Short: "Run GitHub actions locally by specifying the event name (e.g. `push`) or an action name directly.",
Args: cobra.MaximumNArgs(1),
RunE: newRunCommand(ctx, input),
@@ -304,48 +304,92 @@ func newRunCommand(ctx context.Context, input *Input) func(*cobra.Command, []str
return err
}
- // Determine the event name
- var eventName string
+ jobID, err := cmd.Flags().GetString("job")
+ if err != nil {
+ return err
+ }
+
+ // check if we should just list the workflows
+ list, err := cmd.Flags().GetBool("list")
+ if err != nil {
+ return err
+ }
+
+ // check if we should just draw the graph
+ graph, err := cmd.Flags().GetBool("graph")
+ if err != nil {
+ return err
+ }
+
+ // collect all events from loaded workflows
events := planner.GetEvents()
- if input.autodetectEvent && len(events) > 0 {
- // set default event type to first event
+
+ // plan with filtered jobs - to be used for filtering only
+ var filterPlan *model.Plan
+
+ // Determine the event name to be filtered
+ var filterEventName string = ""
+
+ if len(args) > 0 {
+ log.Debugf("Using first passed in arguments event for filtering: %s", args[0])
+ filterEventName = args[0]
+ } else if input.autodetectEvent && len(events) > 0 && len(events[0]) > 0 {
+ // set default event type to first event from many available
+ // this way user dont have to specify the event.
+ log.Debugf("Using first detected workflow event for filtering: %s", events[0])
+ filterEventName = events[0]
+ }
+
+ if jobID != "" {
+ log.Debugf("Preparing plan with a job: %s", jobID)
+ filterPlan = planner.PlanJob(jobID)
+ } else if filterEventName != "" {
+ log.Debugf("Preparing plan for a event: %s", filterEventName)
+ filterPlan = planner.PlanEvent(filterEventName)
+ } else {
+ log.Debugf("Preparing plan with all jobs")
+ filterPlan = planner.PlanAll()
+ }
+
+ if list {
+ return printList(filterPlan)
+ }
+
+ if graph {
+ return drawGraph(filterPlan)
+ }
+
+ // plan with triggered jobs
+ var plan *model.Plan
+
+ // Determine the event name to be triggered
+ var eventName string
+
+ if len(args) > 0 {
+ log.Debugf("Using first passed in arguments event: %s", args[0])
+ eventName = args[0]
+ } else if len(events) == 1 && len(events[0]) > 0 {
+ log.Debugf("Using the only detected workflow event: %s", events[0])
+ eventName = events[0]
+ } else if input.autodetectEvent && len(events) > 0 && len(events[0]) > 0 {
+ // set default event type to first event from many available
// this way user dont have to specify the event.
- log.Debugf("Using detected workflow event: %s", events[0])
+ log.Debugf("Using first detected workflow event: %s", events[0])
eventName = events[0]
} else {
- if len(args) > 0 {
- eventName = args[0]
- } else if plan := planner.PlanEvent("push"); plan != nil {
- eventName = "push"
- }
+ log.Debugf("Using default workflow event: push")
+ eventName = "push"
}
// build the plan for this run
- var plan *model.Plan
- if jobID, err := cmd.Flags().GetString("job"); err != nil {
- return err
- } else if jobID != "" {
+ if jobID != "" {
log.Debugf("Planning job: %s", jobID)
plan = planner.PlanJob(jobID)
} else {
- log.Debugf("Planning event: %s", eventName)
+ log.Debugf("Planning jobs for event: %s", eventName)
plan = planner.PlanEvent(eventName)
}
- // check if we should just list the workflows
- if list, err := cmd.Flags().GetBool("list"); err != nil {
- return err
- } else if list {
- return printList(plan)
- }
-
- // check if we should just print the graph
- if list, err := cmd.Flags().GetBool("graph"); err != nil {
- return err
- } else if list {
- return drawGraph(plan)
- }
-
// check to see if the main branch was defined
defaultbranch, err := cmd.Flags().GetString("defaultbranch")
if err != nil {
diff --git a/pkg/model/planner.go b/pkg/model/planner.go
index 16c8928..7f8af6f 100644
--- a/pkg/model/planner.go
+++ b/pkg/model/planner.go
@@ -17,6 +17,7 @@ import (
type WorkflowPlanner interface {
PlanEvent(eventName string) *Plan
PlanJob(jobName string) *Plan
+ PlanAll() *Plan
GetEvents() []string
}
@@ -196,6 +197,20 @@ func (wp *workflowPlanner) PlanJob(jobName string) *Plan {
return plan
}
+// PlanAll builds a new run to execute in parallel all
+func (wp *workflowPlanner) PlanAll() *Plan {
+ plan := new(Plan)
+ if len(wp.workflows) == 0 {
+ log.Debugf("no jobs found for loaded workflows")
+ }
+
+ for _, w := range wp.workflows {
+ plan.mergeStages(createStages(w, w.GetJobIDs()...))
+ }
+
+ return plan
+}
+
// GetEvents gets all the events in the workflows file
func (wp *workflowPlanner) GetEvents() []string {
events := make([]string, 0)