* fix: show workflow info even if on.push is not defined (#1329) To fix listing of workflows in such cases list/graph filtering was split with planning. Now act supports one of the following list (-l)/graph (-g) cases: * show all jobs of loaded workflows: act -l * show specific job JOBNAME: act -l -j JOBNAME * show jobs of loaded workflows in which event EVENTNAME is set up: act -l EVENTNAME * show jobs of loaded workflows in which first defined workflow event is set up: act -l --detect-event For planning it supports: * running specific job JOBNAME with triggered event determined from: ** CLI argument: act -j JOBNAME EVENTNAME ** first defined in loaded workflows event: act -j JOBNAME --detect-event ** only defined in loaded workflows event: act -j JOBNAME ** push event by default: act -j JOBNAME * running jobs of loaded workflows in which event is set up, event is determined from: ** CLI argument: act EVENTNAME ** first defined in loaded workflows event: act --detect-event ** only defined in loaded workflows event: act ** push event by default: act Except #1329 this PR fixes #1332, #1318 * Update docs/help
This commit is contained in:
parent
13d530302e
commit
21484b5c1e
3 changed files with 97 additions and 34 deletions
|
@ -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
|
||||
|
||||
|
|
110
cmd/root.go
110
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,46 +304,90 @@ func newRunCommand(ctx context.Context, input *Input) func(*cobra.Command, []str
|
|||
return err
|
||||
}
|
||||
|
||||
// Determine the event name
|
||||
var eventName string
|
||||
events := planner.GetEvents()
|
||||
if input.autodetectEvent && len(events) > 0 {
|
||||
// set default event type to first event
|
||||
// this way user dont have to specify the event.
|
||||
log.Debugf("Using 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"
|
||||
}
|
||||
}
|
||||
|
||||
// build the plan for this run
|
||||
var plan *model.Plan
|
||||
if jobID, err := cmd.Flags().GetString("job"); err != nil {
|
||||
jobID, err := cmd.Flags().GetString("job")
|
||||
if err != nil {
|
||||
return err
|
||||
} else if jobID != "" {
|
||||
log.Debugf("Planning job: %s", jobID)
|
||||
plan = planner.PlanJob(jobID)
|
||||
} else {
|
||||
log.Debugf("Planning event: %s", eventName)
|
||||
plan = planner.PlanEvent(eventName)
|
||||
}
|
||||
|
||||
// check if we should just list the workflows
|
||||
if list, err := cmd.Flags().GetBool("list"); err != nil {
|
||||
list, err := cmd.Flags().GetBool("list")
|
||||
if 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 {
|
||||
// check if we should just draw the graph
|
||||
graph, err := cmd.Flags().GetBool("graph")
|
||||
if err != nil {
|
||||
return err
|
||||
} else if list {
|
||||
return drawGraph(plan)
|
||||
}
|
||||
|
||||
// collect all events from loaded workflows
|
||||
events := planner.GetEvents()
|
||||
|
||||
// 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 first detected workflow event: %s", events[0])
|
||||
eventName = events[0]
|
||||
} else {
|
||||
log.Debugf("Using default workflow event: push")
|
||||
eventName = "push"
|
||||
}
|
||||
|
||||
// build the plan for this run
|
||||
if jobID != "" {
|
||||
log.Debugf("Planning job: %s", jobID)
|
||||
plan = planner.PlanJob(jobID)
|
||||
} else {
|
||||
log.Debugf("Planning jobs for event: %s", eventName)
|
||||
plan = planner.PlanEvent(eventName)
|
||||
}
|
||||
|
||||
// check to see if the main branch was defined
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in a new issue