From 7c5400d75b25024c2ddf59e49072f85e8020dd95 Mon Sep 17 00:00:00 2001
From: Lunny Xiao <xiaolunwen@gmail.com>
Date: Fri, 24 Mar 2023 20:15:46 +0800
Subject: [PATCH] ParseRawOn support schedules (#29)

Fix gitea/act_runner#71

Reviewed-on: https://gitea.com/gitea/act/pulls/29
Reviewed-by: Jason Song <i@wolfogre.com>
Reviewed-by: Zettat123 <zettat123@noreply.gitea.io>
Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com>
Co-committed-by: Lunny Xiao <xiaolunwen@gmail.com>
---
 pkg/jobparser/model.go      | 50 ++++++++++++++++++++++++++++++++-----
 pkg/jobparser/model_test.go | 31 ++++++++++++++++-------
 2 files changed, 66 insertions(+), 15 deletions(-)

diff --git a/pkg/jobparser/model.go b/pkg/jobparser/model.go
index 9e9a97c..a0bc61a 100644
--- a/pkg/jobparser/model.go
+++ b/pkg/jobparser/model.go
@@ -125,8 +125,21 @@ type RunDefaults struct {
 }
 
 type Event struct {
-	Name string
-	Acts map[string][]string
+	Name      string
+	acts      map[string][]string
+	schedules []map[string]string
+}
+
+func (evt *Event) IsSchedule() bool {
+	return evt.schedules != nil
+}
+
+func (evt *Event) Acts() map[string][]string {
+	return evt.acts
+}
+
+func (evt *Event) Schedules() []map[string]string {
+	return evt.schedules
 }
 
 func ParseRawOn(rawOn *yaml.Node) ([]*Event, error) {
@@ -168,12 +181,12 @@ func ParseRawOn(rawOn *yaml.Node) ([]*Event, error) {
 			case string:
 				res = append(res, &Event{
 					Name: k,
-					Acts: map[string][]string{},
+					acts: map[string][]string{},
 				})
 			case []string:
 				res = append(res, &Event{
 					Name: k,
-					Acts: map[string][]string{},
+					acts: map[string][]string{},
 				})
 			case map[string]interface{}:
 				acts := make(map[string][]string, len(t))
@@ -186,7 +199,10 @@ func ParseRawOn(rawOn *yaml.Node) ([]*Event, error) {
 					case []interface{}:
 						acts[act] = make([]string, len(b))
 						for i, v := range b {
-							acts[act][i] = v.(string)
+							var ok bool
+							if acts[act][i], ok = v.(string); !ok {
+								return nil, fmt.Errorf("unknown on type: %#v", branches)
+							}
 						}
 					default:
 						return nil, fmt.Errorf("unknown on type: %#v", branches)
@@ -194,7 +210,29 @@ func ParseRawOn(rawOn *yaml.Node) ([]*Event, error) {
 				}
 				res = append(res, &Event{
 					Name: k,
-					Acts: acts,
+					acts: acts,
+				})
+			case []interface{}:
+				if k != "schedule" {
+					return nil, fmt.Errorf("unknown on type: %#v", v)
+				}
+				schedules := make([]map[string]string, len(t))
+				for i, tt := range t {
+					vv, ok := tt.(map[string]interface{})
+					if !ok {
+						return nil, fmt.Errorf("unknown on type: %#v", v)
+					}
+					schedules[i] = make(map[string]string, len(vv))
+					for k, vvv := range vv {
+						var ok bool
+						if schedules[i][k], ok = vvv.(string); !ok {
+							return nil, fmt.Errorf("unknown on type: %#v", v)
+						}
+					}
+				}
+				res = append(res, &Event{
+					Name:      k,
+					schedules: schedules,
 				})
 			default:
 				return nil, fmt.Errorf("unknown on type: %#v", v)
diff --git a/pkg/jobparser/model_test.go b/pkg/jobparser/model_test.go
index 9293d25..3ee13e7 100644
--- a/pkg/jobparser/model_test.go
+++ b/pkg/jobparser/model_test.go
@@ -47,7 +47,7 @@ func TestParseRawOn(t *testing.T) {
 			result: []*Event{
 				{
 					Name: "push",
-					Acts: map[string][]string{
+					acts: map[string][]string{
 						"branches": {
 							"master",
 						},
@@ -60,7 +60,7 @@ func TestParseRawOn(t *testing.T) {
 			result: []*Event{
 				{
 					Name: "branch_protection_rule",
-					Acts: map[string][]string{
+					acts: map[string][]string{
 						"types": {
 							"created",
 							"deleted",
@@ -74,7 +74,7 @@ func TestParseRawOn(t *testing.T) {
 			result: []*Event{
 				{
 					Name: "project",
-					Acts: map[string][]string{
+					acts: map[string][]string{
 						"types": {
 							"created",
 							"deleted",
@@ -83,7 +83,7 @@ func TestParseRawOn(t *testing.T) {
 				},
 				{
 					Name: "milestone",
-					Acts: map[string][]string{
+					acts: map[string][]string{
 						"types": {
 							"opened",
 							"deleted",
@@ -97,7 +97,7 @@ func TestParseRawOn(t *testing.T) {
 			result: []*Event{
 				{
 					Name: "pull_request",
-					Acts: map[string][]string{
+					acts: map[string][]string{
 						"types": {
 							"opened",
 						},
@@ -113,7 +113,7 @@ func TestParseRawOn(t *testing.T) {
 			result: []*Event{
 				{
 					Name: "push",
-					Acts: map[string][]string{
+					acts: map[string][]string{
 						"branches": {
 							"main",
 						},
@@ -121,7 +121,7 @@ func TestParseRawOn(t *testing.T) {
 				},
 				{
 					Name: "pull_request",
-					Acts: map[string][]string{
+					acts: map[string][]string{
 						"types": {
 							"opened",
 						},
@@ -137,7 +137,7 @@ func TestParseRawOn(t *testing.T) {
 			result: []*Event{
 				{
 					Name: "push",
-					Acts: map[string][]string{
+					acts: map[string][]string{
 						"branches": {
 							"main",
 							"releases/**",
@@ -151,7 +151,7 @@ func TestParseRawOn(t *testing.T) {
 			result: []*Event{
 				{
 					Name: "push",
-					Acts: map[string][]string{
+					acts: map[string][]string{
 						"tags": {
 							"v1.**",
 						},
@@ -170,6 +170,19 @@ func TestParseRawOn(t *testing.T) {
 				},
 			},
 		},
+		{
+			input: "on:\n  schedule:\n    - cron: '20 6 * * *'",
+			result: []*Event{
+				{
+					Name: "schedule",
+					schedules: []map[string]string{
+						{
+							"cron": "20 6 * * *",
+						},
+					},
+				},
+			},
+		},
 	}
 	for _, kase := range kases {
 		t.Run(kase.input, func(t *testing.T) {